For whoever runs MakerLab Tools at the Cornell Tech MakerLAB. It covers accounts, keys, routine tasks, and what to do when something breaks.
You do not need to be able to write code to use most of this guide. The sections that need a developer are marked [dev].
How the code works is in
architecture-guide.md.
A website that lists the lab's machines and answers questions about them. The data lives in Notion — seven databases that staff edit directly. The website reads from Notion and adds an AI assistant on top.
Editing the catalogue means editing Notion. There is no admin login and no dashboard, by design. If a machine's description is wrong, you fix it in Notion, and the website catches up within minutes.
Three moving parts, and it is worth knowing which is which when something is wrong:
| Part | What it is | Who provides it |
|---|---|---|
| The website | The app itself | Hosted on Vercel |
| The data | Seven databases | Notion workspace |
| The assistant | The AI | Anthropic API (Claude) |
This section is the handover. Until it is filled in with real names, the system has no owner.
| Thing | Where | Who owns it | Notes |
|---|---|---|---|
| Vercel project | vercel.com | ⬜ TBD | Hosting, deploys, env vars, logs |
| Notion workspace | notion.so | ⬜ TBD | The seven databases |
| Notion integration token | Notion settings | ⬜ TBD | NOTION_API_KEY |
AI_GATEWAY_API_KEY |
Vercel → AI Gateway | ⬜ TBD | The intended production path. Model spend on the hosting invoice, with a platform spend limit |
| Anthropic API key | console.anthropic.com | ⬜ TBD | Fallback. Costs money per use. Keep it — it is the lever back if the gateway fails |
| GitHub repository | github.com | ⬜ TBD | The code |
| Domain / DNS | ⬜ | ⬜ TBD | |
ADMIN_REVALIDATE_SECRET |
Vercel env vars | ⬜ TBD | Forces the site to refresh |
| Vercel Blob store | Vercel → Storage | ⬜ TBD | Holds the nightly Notion backup. Sets BLOB_READ_WRITE_TOKEN. Contains student PII — keep private |
CRON_SECRET |
Vercel env vars | ⬜ TBD | Lets the nightly backup cron prove it is Vercel (§3) |
Warning
Inference is a live bill and the only cost here that scales with use. Every question a student asks costs a small amount. Whichever path you run, it must be owned by the institution rather than an individual, and it must have a spend limit.
Run the gateway. Set AI_GATEWAY_API_KEY and every model call routes through the Vercel
AI Gateway: spend lands on the invoice you already pay, a platform-enforced ceiling replaces
a promise to watch the dashboard, and whoever operates the app can see usage without holding
the Anthropic key.
Keep the Anthropic key anyway. Set both and the gateway wins — but do not revoke the direct one. It is a one-env-var lever back to a working assistant if the gateway has an outage, if billing lapses, or if the model id turns out wrong during a demo. It costs nothing to keep and it is the only fallback the app has.
Important
The gateway path has never made a live call. It is written and unit-tested, but nobody
has held a key. The gateway spells model versions with dots (anthropic/claude-sonnet-4.6)
where Anthropic's own API uses dashes, and the two are not interchangeable. Send one
message through a preview deploy before production. A wrong id fails loudly with
GatewayModelNotFoundError on the first request — it does not silently fall back.
Note
Routing through the gateway means student questions, and any photos they attach, transit Vercel's infrastructure. That is a genuine change in data flow and worth an explicit answer from the university rather than an assumption.
Two things a person has to do, neither of which is code:
- Create the key in the Vercel dashboard (AI Gateway → API keys) and set a monthly spend limit and an alert threshold at the same time. A key without a limit is the whole financial risk of this app in one credential.
- Confirm with the university that routing student questions — and the photos they upload — through Vercel's infrastructure is acceptable. This is a real change in where data flows, not a formality.
The gateway path has never been exercised against a live gateway; see
specs/2026-07-29-ai-gateway-migration-design.md
for what remains to verify before production traffic goes through it.
- In Notion, add a row to the Tools database.
- Fill in at least: name, description, category, location.
- Add units in the Units database, linked to the tool — one row per physical machine, with serial and status.
- Add manuals or SOPs to Resources, linked to the tool.
- Tick published. Until you do, it will not appear on the site.
- Wait a few minutes, or force a refresh (§4).
The assistant picks it up automatically. No deploy, no developer.
Change the unit's status in the Units database to Under Maintenance or Out of Service. The site shows it as offline, and the assistant stops recommending it.
Tickets from the assistant land in Maintenance_Logs, with photos if the student attached
any. Work them in Notion: set status to In Progress, then Resolved, and fill in
resolution.
Nothing in the app enforces this. A ticket queue nobody reads is worse than no ticket queue — students stop reporting after a couple of unanswered reports. Decide who checks it and how often, and write that down here:
Ticket owner: ⬜ TBD · Checked: ⬜ TBD
Almost always a data problem, not an AI problem. The assistant answers from Notion, so a wrong answer usually means a wrong or empty field. Fix the record; the answer changes.
If it is wrong and the Notion record is right, that is a real bug — see §6.
Environment variables in Vercel, no code change: NEXT_PUBLIC_SITE_NAME,
NEXT_PUBLIC_INSTITUTION, NEXT_PUBLIC_TAGLINE, NEXT_PUBLIC_LOGO,
NEXT_PUBLIC_COLOR_PRIMARY, NEXT_PUBLIC_COLOR_PRIMARY_DARK,
NEXT_PUBLIC_CHAT_ASSISTANT_NAME, and AUDIENCE. Full explanations in
v5/.env.example. Redeploy after changing them.
Every night at 07:17 UTC (about 03:17 New York) the site backs up Notion. Vercel Cron
calls /api/admin/backup, which reads every Notion database and writes one file to private
Vercel Blob storage as backups/YYYY-MM-DD.json. Files older than 30 days are deleted
by the same job, so the store holds roughly a month at any time.
This is the only copy of the Notion data outside Notion. Before it existed, one deleted database meant ~100 machines of staff work was gone for good.
Three settings in Vercel make it work, and it does nothing without all three:
| Setting | Where | What it is |
|---|---|---|
| A Blob store linked to the project | Vercel → Storage | Sets BLOB_READ_WRITE_TOKEN automatically |
CRON_SECRET |
Vercel env vars | Vercel sends it so the route knows the nightly call is genuine |
ADMIN_REVALIDATE_SECRET |
Vercel env vars | Lets a person trigger a backup by hand (same secret as §4) |
How to check it, once a month: Vercel dashboard → your project → Cron Jobs. A green run means a file was written. A red run means the backup did not happen — the route deliberately fails loudly rather than reporting success, because a backup that fails quietly is discovered on the day you need it. The failure reason is in the run's log.
To run one by hand, or to confirm it works after changing anything:
GET https://<your-site>/api/admin/backup
Header: x-admin-secret: <ADMIN_REVALIDATE_SECRET>
It answers with the file it wrote, how many rows came from each database, and which old
files it deleted. Anything other than 200 is a real failure.
Warning
The backup contains student names and email addresses from Maintenance_Logs. It is written to private blob storage and must stay that way — never make the store public, never share a download link, and list it in whatever data inventory the university keeps.
To restore: download the file from Vercel → Storage → Blob, and re-import the affected database. The file holds the raw Notion rows, so a person can read it and rebuild from it. There is no automated restore, on purpose — it is far more work than the failure justifies. [dev] for anything beyond reading the file.
The site caches Notion data for a few minutes. To make a change appear immediately:
POST https://<your-site>/api/admin/revalidate
Header: x-admin-secret: <ADMIN_REVALIDATE_SECRET>
Body: {"tag": "catalog"}
Any HTTP client works. If you would rather not use one, waiting a few minutes has the same effect.
| Where | What | How often |
|---|---|---|
| Anthropic console | Spend. Set a limit and an alert. | Weekly, at minimum |
| Vercel dashboard | Failed deploys, function errors | When something looks wrong |
| Vercel logs | Falling back to mock catalog |
Whenever the catalogue looks odd |
| Vercel → Cron Jobs | The nightly backup ran green | Monthly — see §3 |
| Notion: Maintenance_Logs | Open tickets | Per §3 |
The one alert that matters: an Anthropic spend threshold. Everything else is recoverable; an unbounded bill is not.
Most likely cause, and it is not obvious. The app falls back to a built-in demo catalogue whenever it cannot reach Notion — a missing or misspelled environment variable, an expired integration token, or a database that stopped being shared with the integration.
The site does not show an error. It looks perfectly healthy while serving fictional equipment.
- Check the Vercel logs for
Falling back to mock catalog. - Check every
NOTION_DB_*variable andNOTION_API_KEYin Vercel. - In Notion, confirm each database is still shared with the integration.
Check published is ticked in Notion. Then force a refresh (§4).
Someone probably renamed the property in Notion. The app matches property names and cannot
follow a rename. Compare against v5/.env.example and the other rows. [dev] if unclear.
- Check status.anthropic.com.
- Check the Anthropic key has not expired or hit its spend limit.
- Check Vercel logs for errors on
/api/chat.
The catalogue keeps working while the assistant is down — they fail independently.
Check the Vercel dashboard. A failed deploy leaves the previous version running, so a total outage is usually a platform incident or a domain problem rather than a bad deploy.
Vercel dashboard → Deployments → find the last good one → Promote to Production. No code or command line required. Do this first and diagnose afterwards.
git clone <repo> && cd makerlab-tools/v5
npm install
npm run dev # works with no credentials, using the demo catalogue
npm run test:all # must pass before mergingRead docs/constitution.md first — it is short and it is the rules.
Every feature starts with a spec in docs/specs/ that merges before the code.
The live app is v5/. The root src/ directory is the old v4 app and is not used.
Full step-by-step for a first deployment:
deploy.md.
Nothing about Cornell is hardcoded.
- Duplicate the seven Notion databases into the new workspace.
- Create a Notion integration and share all seven databases with it.
- Deploy the repo to Vercel.
- Set
NOTION_API_KEY, the sevenNOTION_DB_*IDs, andANTHROPIC_API_KEY. - Override the
NEXT_PUBLIC_*branding variables. - Replace the logo in
v5/public/.
Full variable list with explanations: v5/.env.example.
- No sign-in yet. The assistant is open to anyone with the URL. Specced, not built.
- The fallback is silent (§6). Fix specced in the operational-hardening spec.
- No analytics. Notion cannot aggregate, so there is no way to see which machines get asked about most. This is the main reason a successor project exists.
- No backup beyond Notion's own version history. Notion keeps page history; there is no separate export. Consider a periodic manual export of the databases.
- One person built this. That is the risk this document exists to reduce. If something here is unclear, that is a bug in the document — fix it while you still have someone to ask.
- Fill in every owner in §2
- Set an Anthropic spend limit and alert
- Name a maintenance-ticket owner and cadence (§3)
- Confirm who can deploy and who administers the Vercel project
- Decide whether student email in Notion is acceptable to the university (see the auth spec's open questions)
- Agree a periodic Notion export for backup