Self-Hosting
Typeroll is open-source (MIT) and can be self-hosted. This guide covers running the portal on your own infrastructure.
Architecture
Section titled “Architecture”Portal (Astro SSR) ──────▶ Firestore (content) │ R2 / S3 (media CDN) ▼ Cloudflare Pages (static site output) Static site builder (Astro SSG)Prerequisites
Section titled “Prerequisites”- Node.js 20+
- Firebase project with Firestore and Authentication enabled
- Cloudflare account with R2 for media storage and Pages for site output
- Anthropic API key for the AI chat feature
Quick start (local dev)
Section titled “Quick start (local dev)”Clone the repository and install dependencies:
git clone https://github.com/typeroll/typerollcd typerollnpm installThe portal includes a fixtures backend — a JSON file store that replaces Firestore for local development. No Firebase configuration needed to run locally:
npm run dev:portalOpen http://localhost:4321. You’ll be logged in as a dev user with access to the sample content in packages/portal/fixtures/.
Environment variables
Section titled “Environment variables”For production, create a .env file in packages/portal/:
# Firebase (required for auth in production)FIREBASE_SERVICE_ACCOUNT={"type":"service_account","project_id":"..."}
# AI chatANTHROPIC_API_KEY=sk-ant-...
# Media CDN (Cloudflare R2 or any S3-compatible store)R2_ACCOUNT_ID=...R2_ACCESS_KEY_ID=...R2_SECRET_ACCESS_KEY=...R2_BUCKET=typeroll-mediaR2_PUBLIC_BASE_URL=https://cdn.yourdomain.com
# Static site output (Cloudflare Pages)CLOUDFLARE_ACCOUNT_ID=...CLOUDFLARE_API_TOKEN=...CLOUDFLARE_PAGES_PROJECT=your-pages-project
# SecurityFORMS_HMAC_SECRET=a-random-64-char-hex-stringPREVIEW_HMAC_SECRET=another-random-64-char-hex-string
# Portal URL (used in deploy output and preview links)PORTAL_PUBLIC_URL=https://app.yourdomain.comSITES_BASE_DOMAIN=sites.yourdomain.com
# Deploy queue (in_process for single-server; cloud_tasks for production scale)DEPLOY_QUEUE=in_processFirebase setup
Section titled “Firebase setup”- Create a Firebase project at console.firebase.google.com
- Enable Firestore (Native mode) and Authentication (Email/Password)
- Create a service account: Project Settings → Service Accounts → Generate new private key
- Set
FIREBASE_SERVICE_ACCOUNTto the full JSON content (one line) - For each user, set an
org_idcustom claim via the Firebase Admin SDK:
await admin.auth().setCustomUserClaims(uid, { org_id: "your-org-id" });All content is scoped under organizations/{org_id}/ in Firestore.
Docker
Section titled “Docker”A Dockerfile is included at the repo root:
docker build -t typeroll-portal .docker run -p 4321:4321 --env-file .env typeroll-portalDeploy to Cloud Run
Section titled “Deploy to Cloud Run”The included GitHub Actions workflow (.github/workflows/deploy.yml) deploys to Google Cloud Run. See the workflow file for the full configuration — it uses Workload Identity Federation (no long-lived service account keys).
For other platforms (Fly.io, Railway, etc.), the portal is a standard Node.js SSR application. Set all the environment variables and run node dist/server/entry.mjs.