mirror of
https://github.com/AmruthPillai/Reactive-Resume.git
synced 2026-10-03 18:23:47 +10:00
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.
165 lines
9.7 KiB
Plaintext
165 lines
9.7 KiB
Plaintext
---
|
|
title: "Self-hosting on Vercel"
|
|
description: "Deploy Reactive Resume on Vercel Hobby with Neon PostgreSQL, private Vercel Blob, and Upstash Redis."
|
|
---
|
|
|
|
This guide deploys Reactive Resume to a Vercel project with the Deploy with Vercel wizard. The wizard provisions a database, file storage, and Redis for you. You supply two secrets.
|
|
|
|
The project deploys as two [Vercel Services](https://vercel.com/docs/services): `frontend` serves the static web app from Vercel's CDN, and `backend` runs the shared Hono server in one Node.js 24 Function. Docker is also supported and uses the same API, authentication, templates, and data format. See [Self-hosting with Docker](/self-hosting/docker) for that option.
|
|
|
|
## Before you start
|
|
|
|
You need:
|
|
|
|
- A Vercel account and a GitHub account.
|
|
- Two independent random secrets, `AUTH_SECRET` and `ENCRYPTION_SECRET`. Generate each one separately:
|
|
|
|
```bash
|
|
openssl rand -hex 32
|
|
```
|
|
|
|
Save both values in a password manager. You must keep the same values for the life of the installation. Losing `ENCRYPTION_SECRET` makes saved AI-provider API keys unreadable.
|
|
|
|
The wizard connects three services through Vercel Marketplace:
|
|
|
|
| Service | Used for |
|
|
| --- | --- |
|
|
| Neon PostgreSQL | Application data |
|
|
| Vercel Blob (**private**) | Uploaded pictures, files, and agent attachments |
|
|
| Upstash Redis | Agent streaming and cancellation, shared rate limits, live resume updates |
|
|
|
|
Quotas and permitted use depend on your Vercel, Neon, and Upstash plans. Review [Vercel limits](https://vercel.com/docs/functions/limitations), [Neon](https://vercel.com/marketplace/neon), and [Upstash](https://vercel.com/marketplace/upstash/upstash-kv) before you choose a plan. Turn off automatic paid upgrades if you want to stay inside a free allowance.
|
|
|
|
<Note>
|
|
Each AI agent run stops active work after four minutes. This keeps the run, plus saving and cleanup, inside Vercel Hobby's five-minute Function limit. The limit applies to each question, not to the whole conversation. Docker uses the same limit.
|
|
</Note>
|
|
|
|
## Deploy
|
|
|
|
<Steps>
|
|
<Step title="Start the wizard">
|
|
Click the button:
|
|
|
|
[](https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2Freactive-resume%2Freactive-resume&project-name=reactive-resume&repository-name=reactive-resume&env=AUTH_SECRET%2CENCRYPTION_SECRET&envDescription=Generate+two+independent+secrets+with+openssl+rand+-hex+32.+Keep+these+values+across+deployments.&envLink=https%3A%2F%2Fdocs.rxresu.me%2Fself-hosting%2Fvercel&stores=%5B%7B%22type%22%3A%22integration%22%2C%22protocol%22%3A%22storage%22%2C%22integrationSlug%22%3A%22neon%22%2C%22productSlug%22%3A%22neon%22%7D%2C%7B%22type%22%3A%22integration%22%2C%22protocol%22%3A%22storage%22%2C%22integrationSlug%22%3A%22upstash%22%2C%22productSlug%22%3A%22upstash-kv%22%7D%2C%7B%22type%22%3A%22blob%22%2C%22access%22%3A%22private%22%7D%5D)
|
|
</Step>
|
|
|
|
<Step title="Choose the Git scope">
|
|
On Hobby, select your **personal GitHub account**. Private repositories owned by a GitHub organization require Vercel Pro.
|
|
</Step>
|
|
|
|
<Step title="Connect the services">
|
|
Approve Neon, Upstash, and Blob. Set Blob access to **private**. Pick nearby regions for all three, ideally close to the Function region (`iad1` by default).
|
|
</Step>
|
|
|
|
<Step title="Enter the secrets">
|
|
Paste `AUTH_SECRET` and `ENCRYPTION_SECRET`.
|
|
</Step>
|
|
|
|
<Step title="Deploy">
|
|
Set **Framework Preset** to **Services**. Keep the project root at the repository root and keep the committed `vercel.json`. Do not select the `apps/web` subdirectory and do not add an SPA fallback rewrite.
|
|
|
|
The build compiles both apps and applies database migrations before the deployment goes live. You do not run migrations yourself.
|
|
</Step>
|
|
</Steps>
|
|
|
|
<Warning>
|
|
Do not paste Docker's `.env.example` into Vercel. Its local URLs and S3 settings select the wrong services.
|
|
</Warning>
|
|
|
|
## Check the deployment
|
|
|
|
1. Open `https://<your-project>.vercel.app/api/health`. `database`, `storage`, and `redis` should all report `healthy`. A sleeping Neon database can fail the first check; retry once.
|
|
2. Open the production domain and create an account.
|
|
3. Optional: add an AI provider under **Settings** to enable AI features.
|
|
4. Optional: configure SMTP for verification and password-reset emails. Without SMTP, emails are written to the Function logs.
|
|
5. Optional: add social or custom OAuth sign-in with the callback URLs in the [SSO guide](/self-hosting/sso).
|
|
|
|
## Use a custom domain
|
|
|
|
1. Add the domain to the Vercel project.
|
|
2. Set `APP_URL` to the full origin, for example `https://resume.example.com`.
|
|
3. Update the callback URLs of every OAuth provider you configured.
|
|
4. Redeploy.
|
|
|
|
Changing the domain does not move stored files. Files stay under the same `DEPLOYMENT_NAMESPACE`.
|
|
|
|
## Update the deployment
|
|
|
|
Redeploy the same project. Keep its connected services and secrets unchanged.
|
|
|
|
<Warning>
|
|
Installations created before Reactive Resume used Vercel Services must switch first. Open **Settings → Build and Deployment**, set **Framework Preset** to **Services**, save, and then redeploy. Vercel builds the `services` configuration only when the project uses this preset.
|
|
</Warning>
|
|
|
|
- Migrations run in the build step, never in runtime Functions. A database advisory lock serializes concurrent deployments.
|
|
- Rolling back to an older deployment does not roll back the database schema. Keep migrations backward-compatible, or restore a database backup.
|
|
|
|
## Preview deployments
|
|
|
|
Preview builds refuse to run migrations by default, so untrusted preview code cannot change your production database.
|
|
|
|
To enable previews:
|
|
|
|
1. Connect separate Neon, Upstash, and Blob resources to the **Preview** environment.
|
|
2. Set `ALLOW_PREVIEW_MIGRATIONS=true` for **Preview** only.
|
|
|
|
A storage namespace does not isolate SQL rows. Never connect the production database to the Preview environment.
|
|
|
|
## Back up your data
|
|
|
|
Back up the Neon database and the Blob store. Store `AUTH_SECRET` and `ENCRYPTION_SECRET` separately from those backups.
|
|
|
|
Moving between Docker and Vercel does not copy the database or files. Migrate them yourself.
|
|
|
|
## Build locally
|
|
|
|
A local Vercel build applies migrations, so run it only against an isolated database.
|
|
|
|
```bash
|
|
vercel pull --environment production
|
|
APP_URL=https://your-project.vercel.app vercel build --prod
|
|
```
|
|
|
|
Replace sensitive pulled values with local-only ones first. The CLI has no deployment hostname before publishing, so `APP_URL` is required here. Cloud builds set it automatically.
|
|
|
|
## Environment variables
|
|
|
|
Explicit variables take precedence over the Marketplace aliases listed here.
|
|
|
|
| Variable | Required | Behavior |
|
|
| --- | --- | --- |
|
|
| `AUTH_SECRET` | Yes | Signs sessions and tokens. Keep it constant. |
|
|
| `ENCRYPTION_SECRET` | Yes | At least 32 characters. Encrypts saved AI-provider API keys. Keep it constant. |
|
|
| `APP_URL` | No | Public origin. Defaults to the production domain in Production and to the deployment domain in Preview. Set it for a custom domain. |
|
|
| `DATABASE_URL` | Injected | Pooled runtime connection. Falls back to `POSTGRES_URL`. |
|
|
| `DATABASE_MIGRATION_URL` | No | Direct connection for migrations. Falls back to `DATABASE_URL_UNPOOLED`, then `POSTGRES_URL_NON_POOLING`, then `DATABASE_URL`. |
|
|
| `DATABASE_POOL_MAX` | No | Maximum database connections per Function instance. Default `10`. |
|
|
| `REDIS_URL` | Injected | Redis TCP/TLS URL. Falls back to Upstash's `KV_URL`. REST credentials alone do not work. |
|
|
| `STORAGE_BACKEND` | No | Must resolve to `blob` on Vercel, which is the default. The build fails with any other value. |
|
|
| `BLOB_READ_WRITE_TOKEN` | Injected | Provided by the connected Blob store. `BLOB_STORE_ID` with Vercel OIDC also works. |
|
|
| `DEPLOYMENT_NAMESPACE` | No | Prefix for Blob objects and Redis keys. Defaults to `production`, or to a per-branch value in Preview. Keep it constant after you store files. Set different values if two installations share one Blob store or Redis database. |
|
|
| `ALLOW_PREVIEW_MIGRATIONS` | No | Set to `true` in Preview only after you connect isolated preview resources. |
|
|
|
|
For SMTP, OAuth providers, and feature flags, use the same variables as Docker. See [Self-hosting with Docker](/self-hosting/docker).
|
|
|
|
## Upload limits
|
|
|
|
Vercel limits Function request bodies to 4.5 MB. The web app sends larger requests through private Blob staging, so these application limits still apply:
|
|
|
|
- General uploads: 10 MB per file.
|
|
- Agent attachments: 25 MiB per file and 100 MiB per thread.
|
|
|
|
Blob objects are never public. The application serves public pictures and authorizes private files itself. API clients that send large RPC requests must follow the [large RPC requests](/guides/large-rpc-requests) protocol. REST (`/api/openapi`) and MCP request bodies stay subject to the 4.5 MB limit.
|
|
|
|
## Troubleshooting
|
|
|
|
| Symptom | Fix |
|
|
| --- | --- |
|
|
| Deployment does not build as services | Set **Framework Preset** to **Services** under **Settings → Build and Deployment**, then redeploy. |
|
|
| First build fails on configuration | Check that all three services are connected to Production and both secrets are set. Remove any `S3_*` variables and any `STORAGE_BACKEND` value other than `blob`. |
|
|
| Preview build refuses to migrate | Connect isolated preview resources, then set `ALLOW_PREVIEW_MIGRATIONS=true` for Preview. |
|
|
| Large upload returns `413` | Use the web app or the [large RPC requests](/guides/large-rpc-requests) protocol. Vercel Pro does not raise the request body limit. |
|
|
| Agent reconnect or stop fails | Check the Upstash TLS URL, the remaining Upstash quota, and that every environment uses the expected `DEPLOYMENT_NAMESPACE`. |
|
|
| Sign-in redirects to another hostname | Set `APP_URL` to the domain you use and redeploy. Do not add wildcard trusted origins. |
|
|
| Files are missing after a configuration change | Restore the original `DEPLOYMENT_NAMESPACE` and Blob connection. |
|