.github/workflows/vercel.yml) catches problems that only show up in a deployed build. It has two jobs: an offline artifact build that runs on every pull request, and a live smoke test you start by hand. You can run the same smoke test against your own installation.
Artifact build
Theartifact job runs on every pull request, every push to main, and every manual run. It needs no Vercel account and no secrets, so pull requests from forks run it safely.
The job:
- Starts an isolated PostgreSQL service.
- Writes a local
.vercel/project.jsonwith theservicesframework, then runsvercel build --prod --standaloneoffline with placeholder Blob credentials. Vercel packages dependencies into the Function output; the build applies migrations to the isolated database. - Checks the
backendservice Function:- its runtime is
nodejs24.x,maxDurationis300, and its handler isapps/server/vercel.mjs; - a copy of the Function outside the checkout loads with
--no-experimental-require-module, like the Vercel runtime does, so a dependency the build left out fails the job; - the copy rejects an unauthenticated upload-staging request with
401and serves the prerendered homepage with its JSON-LD metadata.
- its runtime is
When the loading check fails
If a new server dependency breaks the loading check, add it and its own dependencies tobundledInteropPackages in apps/server/tsdown.config.ts. CommonJS dependencies need this, because Vercel’s service builder leaves out the pnpm links they load through.
Live smoke test
Thelive-smoke job runs only when you start the workflow manually (workflow_dispatch). It uses the vercel-smoke GitHub environment and runs tooling/deployment/smoke.mjs against the installation at VERCEL_SMOKE_URL.
The script checks, in order:
/api/healthreportshealthy, and/,/auth/login,/robots.txt,/sitemap.xml, and/.well-known/oauth-protected-resourcerespond. A missing asset returns404.- An email sign-up creates a session.
- A resume created from sample data can be read back and made public, and its public page and server-rendered public PDF load.
- A 10 MiB file uploads, downloads intact, and is deleted. On Vercel the upload goes through a staged request, and the script checks that a staged request can’t be replayed.
- Optionally, a 25 MiB assistant attachment uploads and is deleted (see below).
- The account is deleted, even if an earlier check failed.
FLAG_DISABLE_SIGNUPS and FLAG_DISABLE_EMAIL_AUTH must not be true.
Attachment check
To include the 25 MiB attachment check, configure an OpenAI-compatible test provider that answers a connection test for the modelsmoke-model. No paid AI model is needed; a deterministic stub works.
The installation needs
ENCRYPTION_SECRET set to save the provider. A provider on a private or http:// address also needs FLAG_ALLOW_UNSAFE_AI_BASE_URL=true, which is only safe on an isolated test installation.
Run the smoke test yourself
The script needs only Node.js 24 and a checkout. SetSMOKE_URL to the installation’s origin:
SMOKE_AI_BASE_URL and SMOKE_AI_API_KEY to include the attachment check. The script detects the platform on its own: on Docker, the staging endpoint returns 404 and uploads go directly to the server.
Related pages
- Development setup: run the app and the test suites locally.
- Deploying to Vercel: set up your own Vercel installation.
- Self-hosting with Docker: run the production image.