How do I publish lunch menus?
Go to Manage Food Menus & Data (/menus/admin) — this page picks which source is your school's "primary" (a label only; all three stay usable regardless):
Last updated 2026-11-04
From the School Administrator manual, "Lunch Menus".
Go to Manage Food Menus & Data (/menus/admin) — this page picks which source is your school's
"primary" (a label only; all three stay usable regardless):
- Manual Data Entry — a quick form (
/menus/new) for one date + meal type at a time. - Upload Spreadsheet — download the template, fill in a whole school year of lunch/breakfast/
snack menus at once, and upload it for a preview before it saves (
/menus/import). - Automatic Scraper — self-service: enter your school's School code, Username, and Password for your FACTS Family Portal login, right on this page, and click Save credentials. Once saved, menus sync automatically on a schedule; Update credentials replaces them, Remove takes the scraper connection down. (Your password is encrypted and can never be read back through the app — the fields are always blank when you reopen this page, whether or not credentials are already on file.) Every Senior and Junior Admin gets an in-app notification (see In-App Notifications) after each scheduled sync — either how many menu items were collected (0 or more), or why it failed — so you don't need to check anything to know it's working. The scraper's status box shows when it last ran and, underneath, when it is next scheduled to run (Sundays, Mondays and Wednesdays at about 10:00 AM Eastern in summer, 9:00 AM in winter; the time is approximate because GitHub starts scheduled runs when it can).
Manual entries and scraped/imported entries never silently overwrite each other — if there's a conflict, you'll get a confirmation prompt instead of a silent overwrite. When the scraper finds a different menu for a day you entered or imported yourself, that day is flagged for review; a scrape that matches what you already have is not flagged, and once you choose Keep mine the same scraped menu won't flag that day again (a later, different scrape will).
The weekly view and the day page: each day in the weekly view is a card; today's card has an orange border and a Today label (orange always means today, never green). Each meal has its own color and icon (Breakfast orange, AM Snack pink, Lunch green, PM Snack indigo, Other teal). Jump to Today takes you back to this week. On a day's page, a strip of the week's seven days sits above the menu: the day you are viewing is solid green, today says Today, and a dot means that day has a menu; click another day to switch. Menus never show times.
Lunch illustrations: opening a specific day's menu (click through from the weekly view) shows a fun, automatically generated illustration of that day's lunch, right below the item list — on web and in the SwiftUI app alike. The first time anyone opens a given day, it takes a few seconds to appear (you'll see "Imagining what this looks like…" while it's generated) — after that, everyone sees the same picture instantly. If a picture can't be generated, your school's logo appears instead with "LUNCH" stamped across it banner-style, rather than a blank space. Pictures are generated automatically only for days from about a week ago to two weeks ahead; for a day outside that range, an admin can use Regenerate Image. As a Junior or Senior Admin, you'll also see a Regenerate Image button under the picture — use it if the picture doesn't match the meal, or after you change what's listed for that day. You can change the overall art style used for every generated picture in School Settings → Lunch Image Style (Senior Admin only — see Section 9).
On iPhone/iPad/Mac, opening a day's menu (tap through from the weekly view) shows a pencil icon and a trash icon on each meal card (admin only) — the pencil reveals every field in place (meal type, each item's name/description/category/allergens, and notes) with Save/Cancel (changing the meal type or date moves that meal; if another menu is already there for that meal and day, the save is refused so nothing is overwritten - edit or delete that one instead); the trash asks you to confirm before permanently deleting that meal. Creating a new meal for a day that has none still requires the web app for now (Manual Data Entry or Upload Spreadsheet above).
