Public Site Deployment
The public marketing and docs site is an Astro hybrid site in packages/site. It is separate from the Randal runtime, dashboard, Railway deployments, and self-hosted randal serve process.
Use this guide when you want a hosted marketing/docs preview or production site. Do not use it to deploy an agent runtime.
What Gets Deployed
- Source package:
packages/site - Build command:
bun run site:build - Output mode: Astro hybrid output with
@astrojs/vercel/serverless - Static pages: marketing/docs pages are prerendered by Astro
- Server route:
/api/personalizeis a Vercel serverless function when classifier personalization is configured - Docs content source:
README.mdand allowlisteddocs/*.mdfiles read at build time
The site does not run the Bun/Hono agent runtime in production. Vercel serves prerendered pages from its output and runs only the site API routes that are explicitly marked server-side.
Separation From Runtime Deployments
The public site is only the marketing/docs surface:
- It does not start
randal serve. - It does not host the dashboard or gateway runtime.
- It does not require
RANDAL_API_TOKEN, Discord secrets, LiveKit, Twilio, or Railway variables. - It only needs a model provider key if generated landing-page classification is intentionally enabled.
- It does not change self-host or Railway runtime deploy behavior.
- PostHog, when enabled, is included only in
packages/sitestatic pages.
Use docs/deployment-guide.md for local, Railway, Docker, and imported-service runtime deployments.
Recommended Vercel Setup
Use the Vercel GitHub integration for PR previews and production deploys. This keeps site deploys in Vercel and avoids a duplicate GitHub Actions deploy path.
- Create or log in to a Vercel account, ideally under the Hassion Studio team or org.
- Import the GitHub repository
Hassion-Studio/randal. - Configure the Vercel project with these settings:
| Setting | Value |
|---|---|
| Framework preset | Astro |
| Install command | bun install |
| Build command | bun run site:build:vercel |
| Output mode | Vercel Build Output API via the Astro Vercel adapter, promoted from packages/site/.vercel/output to .vercel/output |
| Node runtime | Node 20 (package.json sets engines.node to 20.x) |
The repo includes vercel.json with the same settings. The extra Vercel build script exists because the Astro app lives in packages/site, while Vercel's Build Output API expects .vercel/output at the deployed project root. Normal self-host users can ignore this file; it is inert unless the repo is connected to Vercel or a deploy command is run.
For local verification, use Node 20 before running bun run site:build if you need generated Vercel function metadata to match production. The adapter derives the function runtime from the Node process that runs the build.
Environment Variables
Copy packages/site/.env.example for local site development or set the same variables in Vercel.
| Variable | Required | Description |
|---|---|---|
PUBLIC_SITE_URL | Recommended | Canonical site origin, for example https://randal.bot or a Vercel preview URL. |
PUBLIC_POSTHOG_ENABLED | Optional | Set to true to enable PostHog on the public site. Any other value disables it. |
PUBLIC_POSTHOG_KEY | Optional | Public PostHog project key. Analytics stay disabled if this is missing. |
PUBLIC_POSTHOG_HOST | Optional | PostHog ingest host. Defaults to https://us.i.posthog.com; use the EU host if needed. |
OPENROUTER_API_KEY | Optional | Server-only key for landing-page classifier personalization. Leave unset to use static presets only. |
RANDAL_PERSONALIZATION_MODEL | Optional | Classifier model ID. Defaults to openai/gpt-4.1-mini. |
PUBLIC_TURNSTILE_SITE_KEY | Required with Turnstile | Public Cloudflare Turnstile site key for protected classifier requests. |
TURNSTILE_SECRET_KEY | Required in production if classifier is enabled | Server-only Turnstile secret. When set, /api/personalize verifies tokens server-side before any model call. |
RANDAL_PERSONALIZE_ALLOW_UNPROTECTED | Emergency/internal only | Set to true only to intentionally allow production classifier requests without Turnstile. Default behavior fails closed. |
Do not set runtime secrets such as ANTHROPIC_API_KEY, OPENAI_API_KEY, RANDAL_API_TOKEN, DATABASE_URL, legacy migration keys, or any agent runtime credential on the public site project. If OPENROUTER_API_KEY is set for the landing classifier, keep it server-only and configure Turnstile protection or the explicit unprotected override.
Landing Personalization Deployment
The homepage personalization endpoint is intentionally narrow:
- It is a classifier/router only. Model output can select a static preset id, but rich homepage copy, CTAs, quote, FAQ, feature rows, and workflow cards all come from static site-owned preset data.
- The endpoint rejects production requests without an exact allowed
Originheader based onPUBLIC_SITE_URL. - If
TURNSTILE_SECRET_KEYis set, requests must include a valid Cloudflare Turnstile token verified server-side. - In production, if no Turnstile secret is configured, the endpoint fails closed unless
RANDAL_PERSONALIZE_ALLOW_UNPROTECTED=trueis explicitly set. - If no model key is configured, the browser uses deterministic static presets and the site remains useful.
Safe rollout order:
- Deploy the hybrid site with
OPENROUTER_API_KEYunset and verify static preset personalization works. - Set
PUBLIC_SITE_URLto the production origin and redeploy. - Add Turnstile keys and verify challenge-protected requests in preview.
- Add
OPENROUTER_API_KEYonly after the protection path is verified. - If anything fails, remove
OPENROUTER_API_KEY; the site falls back to static presets.
PostHog Setup
PostHog is opt-in and public-site-only.
- Create a PostHog project.
- Copy the public project key.
- In Vercel, set
PUBLIC_POSTHOG_ENABLED=true. - Set
PUBLIC_POSTHOG_KEY=phc_.... - Set
PUBLIC_POSTHOG_HOST=https://us.i.posthog.comor the EU ingest host. - Redeploy the site.
If PUBLIC_POSTHOG_ENABLED is absent, not true, or PUBLIC_POSTHOG_KEY is empty, the built site does not include the PostHog snippet.
Domain Setup
- In Vercel, open the site project settings.
- Add the production domain, for example
randal.bot. - Follow Vercel's DNS instructions for your registrar.
- Set
PUBLIC_SITE_URLto the final production origin. - Trigger a production redeploy so canonical URLs use the production domain.
Preview deployments can use Vercel's generated preview URLs. If you need exact canonical preview URLs, set PUBLIC_SITE_URL in the Vercel preview environment.
GitHub Actions Deployment
Do not configure a GitHub Actions Vercel deploy workflow by default. The current deployment path is the Vercel GitHub app, which owns PR previews and production deploys without repo-managed Vercel tokens.
A GitHub Actions deploy could be added later for a specific need, but it should remain an explicit alternative to the Vercel integration, not a second active deploy path for the same site.
Local Verification
Before pushing deployment changes, run:
bun run site:build
bun run test:site
bun run lint
To verify PostHog is disabled by default, build without public PostHog env vars and confirm the generated HTML has no PostHog snippet. To verify opt-in behavior, run a build with PUBLIC_POSTHOG_ENABLED=true and PUBLIC_POSTHOG_KEY=phc_test and confirm the static pages include the public-site snippet.