Vercel Deployment
Deploy the LinkDen web app on Vercel with the API running on Cloudflare Workers or another platform.
Vercel Deployment
Vercel is the company behind Next.js and provides an optimized hosting platform for Next.js applications. This guide covers deploying the LinkDen web app to Vercel while running the API on a separate platform (typically Cloudflare Workers).
Important: Split Architecture
Vercel hosts only the web app (Next.js frontend). The API server (Hono) must run separately because:
- The Hono API uses Cloudflare Workers-specific APIs (D1 bindings, Workers runtime).
- Vercel Functions use a different runtime and do not support D1.
- LinkDen's API is a standalone Hono server, not a Next.js API route.
┌──────────────────┐ ┌────────────────────────┐ ┌──────────────┐
│ Vercel │────▶│ Cloudflare Workers │────▶│ Cloudflare D1│
│ (Next.js static │ │ (Hono API server) │ │ (SQLite DB) │
│ export) │ │ -- OR -- │ │ │
│ │ │ Railway / Docker / etc. │ │ │
└──────────────────┘ └────────────────────────┘ └──────────────┘Recommended API hosting options:
| Platform | Database | Best For |
|---|---|---|
| Cloudflare Workers | D1 | Best performance, free tier |
| Railway | SQLite volume | Simple managed hosting |
| Docker (any VPS) | SQLite file | Full control |
See the respective guides for deploying the API: Cloudflare, Railway, or Docker.
Prerequisites
- A Vercel account (free Hobby plan is sufficient).
- The LinkDen repository on GitHub (Vercel connects directly to your GitHub repo).
- The API server already deployed and accessible at a public URL.
- Clerk API keys from clerk.com.
Step 1: Deploy the API First
Before setting up Vercel, deploy the API server using one of the supported platforms. You need the API's public URL for the web app's environment variables.
For example, if deploying the API on Cloudflare Workers:
# From the LinkDen repo root
pnpm cf:deployNote the Worker URL (e.g., https://linkden-api.your-subdomain.workers.dev).
Step 2: Import the Project to Vercel
- Log in to the Vercel dashboard.
- Click Add New > Project.
- Select Import Git Repository and choose the LinkDen repository.
- Vercel detects the monorepo structure.
Configure Build Settings
| Setting | Value |
|---|---|
| Framework Preset | Next.js |
| Root Directory | apps/web |
| Build Command | cd ../.. && pnpm --filter @linkden/web build |
| Output Directory | out |
| Install Command | cd ../.. && pnpm install --frozen-lockfile |
The output: "export" setting in next.config.ts tells Next.js to produce a static export, which Vercel serves as static files with its global CDN.
Alternative: Use Vercel's Monorepo Support
Vercel has built-in monorepo support. You can also configure via vercel.json in the repo root:
{
"buildCommand": "pnpm --filter @linkden/web build",
"installCommand": "pnpm install --frozen-lockfile",
"outputDirectory": "apps/web/out",
"framework": "nextjs"
}Step 3: Configure Environment Variables
In the Vercel dashboard, go to your project's Settings > Environment Variables and add:
Required Variables
| Variable | Value | Environment |
|---|---|---|
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY | pk_live_... | Production |
CLERK_SECRET_KEY | sk_live_... | Production |
NEXT_PUBLIC_API_URL | https://api.yourdomain.com | Production |
NEXT_PUBLIC_SITE_URL | https://yourdomain.com | Production |
Optional Variables
| Variable | Value | Environment |
|---|---|---|
NEXT_PUBLIC_SITE_NAME | My Links | Production |
NEXT_PUBLIC_TURNSTILE_SITE_KEY | 0x... | Production |
NEXT_PUBLIC_CLERK_SIGN_IN_URL | /sign-in | Production |
NEXT_PUBLIC_CLERK_SIGN_UP_URL | /sign-up | Production |
Development Environment
For preview deployments (pull request previews), add development values:
| Variable | Value | Environment |
|---|---|---|
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY | pk_test_... | Preview |
CLERK_SECRET_KEY | sk_test_... | Preview |
NEXT_PUBLIC_API_URL | Your staging API URL | Preview |
NEXT_PUBLIC_SITE_URL | (Vercel provides this automatically) | Preview |
Step 4: Deploy
Click Deploy. Vercel:
- Clones the repository.
- Installs dependencies with pnpm.
- Runs the Next.js build (which produces a static export in
apps/web/out). - Deploys the static files to Vercel's global edge network.
The first deploy takes 2-3 minutes. Subsequent deploys are faster due to caching.
Your site is live at https://your-project.vercel.app.
Step 5: Set Up a Custom Domain
- Go to your project's Settings > Domains.
- Enter your domain (e.g.,
yourdomain.com). - Vercel shows the DNS records to add.
For Apex Domains
Add an A record at your DNS provider:
| Type | Name | Target |
|---|---|---|
| A | @ | 76.76.21.21 |
For Subdomains
Add a CNAME record:
| Type | Name | Target |
|---|---|---|
| CNAME | links | cname.vercel-dns.com |
After DNS Setup
- Vercel automatically provisions an SSL certificate.
- Verify by visiting
https://yourdomain.com. - Update
NEXT_PUBLIC_SITE_URLin Vercel's environment variables to match your custom domain. - Update
CORS_ORIGINandAPP_URLon the API server. - Redeploy for the URL change to take effect.
Using Both Vercel and Cloudflare DNS
If your domain uses Cloudflare DNS and you want to point it to Vercel:
- Add the CNAME record in Cloudflare DNS.
- Set the proxy status to DNS only (grey cloud) -- not proxied. Vercel needs direct DNS resolution for SSL provisioning.
- Alternatively, if you want Cloudflare's proxy (orange cloud), add your domain in Vercel and follow their guide for Cloudflare integration.
Step 6: Configure Clerk
Update your Clerk application settings:
- Go to the Clerk dashboard.
- Under Domains, add your Vercel production domain.
- If using preview deployments, add
*.vercel.appas an allowed domain for development.
Automatic Deployments
Vercel automatically deploys when you push to your connected branch:
- Production: Pushes to
maintrigger a production deployment. - Preview: Pull requests get a unique preview URL for testing.
Configuring Deployment Branches
By default, Vercel deploys the main branch to production. To change this:
- Go to Settings > Git.
- Change the Production Branch.
Skipping Deployments
To skip unnecessary builds when only non-web files change, add to vercel.json:
{
"ignoreCommand": "git diff --quiet HEAD^ HEAD -- apps/web/ packages/ui/ packages/validators/"
}This skips the build if no files in the web app or its dependencies changed.
Edge Functions Considerations
LinkDen's web app is a static export (output: "export" in next.config.ts), which means:
- No server-side rendering (SSR): All pages are pre-rendered at build time.
- No API routes: The Hono API runs separately.
- No Edge Functions needed: The static export does not use Vercel's Edge or Serverless Functions.
- No Middleware: Clerk middleware runs at build time only.
This makes the Vercel deployment very simple and cost-effective -- it is essentially static file hosting with a global CDN.
If you ever need SSR features (such as dynamic server-side rendering or API routes within the Next.js app), you would need to change output: "export" to output: "standalone" in next.config.ts. This is a significant architectural change and is not covered in this guide.
Performance Optimization
CDN and Caching
Vercel serves static assets from its global edge network. For optimal caching:
- Static assets (
_next/static/*) are automatically cached with longCache-Controlheaders. - HTML pages are served with appropriate revalidation headers.
Image Optimization
Since the web app uses images.unoptimized: true in next.config.ts (required for static export), consider:
- Optimizing images before uploading them to LinkDen.
- Using external image optimization services.
- Serving images via Cloudflare's Image Optimization if your images are on a Cloudflare-proxied domain.
Costs
Vercel pricing:
| Plan | Cost | Includes |
|---|---|---|
| Hobby | Free | 100 GB bandwidth, unlimited sites, automatic SSL |
| Pro | $20/month per member | 1 TB bandwidth, advanced analytics, password protection |
| Enterprise | Custom | SLA, SAML SSO, audit logs |
For a static LinkDen site, the Hobby plan (free) is more than sufficient. The 100 GB bandwidth limit translates to millions of page views.
Total cost for Vercel + Cloudflare Workers stack:
- Vercel Hobby: $0/month
- Cloudflare Workers free tier: $0/month
- Total: $0/month for most personal link pages
Troubleshooting
Build fails with "Cannot find module"
- Ensure the
Install Commandruns from the monorepo root:cd ../.. && pnpm install --frozen-lockfile. - Check that
pnpm-workspace.yamlincludes the web app and its dependencies.
"NEXT_PUBLIC_API_URL is undefined"
NEXT_PUBLIC_*variables must be set before the build runs.- Verify the variables are added in Vercel's Environment Variables settings, not just locally.
- Trigger a new deployment after adding variables (Vercel does not automatically redeploy).
CORS errors when calling the API
- The API's
CORS_ORIGINmust include the Vercel domain. - If using both
*.vercel.appand a custom domain, add both toCORS_ORIGIN(comma-separated).
Custom domain shows "Invalid configuration"
- Verify DNS records are correct.
- If using Cloudflare DNS, set the proxy to DNS only (grey cloud).
- Wait for DNS propagation and retry.
Preview deployments fail on Clerk auth
- Clerk needs the preview deployment URL in its allowed domains.
- Add
*.vercel.appas an allowed domain in Clerk for development. - Use separate Clerk development keys for preview environments.
Static export does not include dynamic pages
- The
output: "export"mode pre-renders all pages at build time. - Dynamic routes like
/[slug]needgenerateStaticParams()to define which paths to generate. - If a page is missing, check the build output for warnings about ungenerated routes.