Files
Reactive-Resume/docs/contributing/deployment-checks.mdx
T
Amruth Pillai 725be158c0 feat(deploy): deploy Vercel as frontend and backend services
Vercel now deploys Reactive Resume as two services in one project:
`frontend` serves the static Vite build from apps/web/dist, and
`backend` runs the Hono server Function from apps/server. Top-level
rewrites send server-owned paths (/api, /uploads, /mcp, /.well-known,
robots.txt, sitemap.xml, llms.txt, schema.json, index.html) and every
path without a file extension to `backend`, so HTML shells keep their
injected SEO metadata. Paths with a file extension go to `frontend`.

The service builder needs a few accommodations:

- apps/server/vercel.mjs replaces api/index.mjs as the entrypoint,
  because a service entrypoint must exist before the build runs.
- `outputDirectory: "."` stops the builder from using the Docker
  entrypoint in dist/ as the Function handler.
- The builder loads external CommonJS dependencies through pnpm links
  that it leaves out of the Function. ioredis and react-reconciler are
  now bundled with their dependencies, and bcrypt is replaced with
  bcryptjs, which reads and writes the same $2b$ hashes.

The Vercel compatibility workflow now builds with the services
framework and loads a copy of the backend Function outside the
checkout, so a dependency missing from the Function fails CI. The stale
PDFKit trace checks are removed.

Existing Vercel installations must set Framework Preset to Services
before redeploying; the self-hosting guide documents this.
2026-09-30 00:17:24 +02:00

52 lines
2.4 KiB
Plaintext

---
title: "Deployment checks"
description: "How CI verifies the Vercel build artifact, and how to run the deployment smoke test against Vercel or Docker."
---
The **Vercel compatibility** workflow (`.github/workflows/vercel.yml`) has two jobs.
## Artifact build
Runs on every pull request and every push to `main`. It needs no Vercel account and no secrets, so fork pull requests run it safely.
The job:
1. Starts an isolated PostgreSQL service.
2. Writes a local `.vercel/project.json` with the `services` framework and runs `vercel build --prod` offline, with placeholder Blob credentials. This also applies migrations to the isolated database.
3. Checks the `backend` service Function:
- runtime is `nodejs24.x`, `maxDuration` is `300`, and the handler is `apps/server/vercel.mjs`;
- a copy of the Function outside the checkout loads with `--no-experimental-require-module`, which matches the Vercel runtime, so a dependency the build left out fails the job;
- the copy rejects an unauthenticated staging request and serves the prerendered homepage.
If a new server dependency fails the loading check, add it and its own dependencies to `bundledInteropPackages` in `apps/server/tsdown.config.ts`. CommonJS dependencies need this: Vercel's service builder loads them through pnpm links that it leaves out of the Function.
## Live smoke test
Runs only when started manually (`workflow_dispatch`). It uses the `vercel-smoke` GitHub environment and runs `tooling/deployment/smoke.mjs` against `VERCEL_SMOKE_URL`.
<Warning>
Point the smoke test only at a dedicated test installation. It creates an account, a public resume, and files, then deletes them.
</Warning>
The script checks health, public pages, signup, resume CRUD, public PDF rendering, a 10 MiB upload and download, and one-time use of staged requests.
To also check a 25 MiB agent attachment, configure a deterministic OpenAI-compatible test provider that serves the model `smoke-model`:
| Name | Kind | Value |
| --- | --- | --- |
| `VERCEL_SMOKE_URL` | Variable | Test installation origin |
| `VERCEL_SMOKE_AI_BASE_URL` | Variable | Test provider base URL |
| `VERCEL_SMOKE_AI_API_KEY` | Secret | Test provider API key |
No paid AI model is needed.
## Run the smoke test locally
Against a local Docker installation:
```bash
SMOKE_URL=http://localhost:3000 node tooling/deployment/smoke.mjs
```
Add `SMOKE_AI_BASE_URL` and `SMOKE_AI_API_KEY` to include the attachment check.