Installation
cfstack has three runtime lanes:
| Lane | Default URL | Purpose |
|---|---|---|
local-app | http://localhost:3101 | Fast Next.js development and the canonical Playwright lane |
local-worker | http://localhost:8787 | Local Wrangler runtime for Worker-fidelity checks |
remote-cloudflare | your preview or production domain | Real Cloudflare deploys |
Tracked wrangler.toml stays template-safe and local-development friendly. The canonical Worker runtime is the tracked source-owned custom-worker entrypoint, and your private preview and production tenant identity belongs in wrangler.remote.toml.
Prerequisites
Before you begin, ensure you have the following installed:
- Node.js 20.x or later
- npm 10.x or later (comes with Node.js)
- Git for version control
- Wrangler CLI if you want the
local-workerlane or remote Cloudflare deploys
Clone the Repository
First, clone the repository to your local machine:
git clone https://github.com/aigotowork/cfstack.git
cd cfstackInstall Dependencies
Install all required dependencies using npm:
npm installThis will install all packages listed in package.json, including:
- Next.js framework
- Drizzle ORM for database
- NextAuth.js for authentication
- Stripe for payments
- shadcn/ui components
Bootstrap the local-app lane
Copy the tracked local app example:
cp .env.local.example .env.localOpen .env.local and set the values you actually need:
APP_URL="http://localhost:3101"
AUTH_SECRET="replace-me-with-a-local-secret"
DATABASE_URL="file:./dev.db"
XADMIN_SECRET="replace-me-for-local-seeding"Use .env.example as the full variable catalog when you need optional integrations. Do not bootstrap day-to-day development by copying it directly.
Generate AUTH_SECRET
Generate a secure random string for AUTH_SECRET:
npx auth secretOptional: bootstrap the local-worker lane
If you want to run the app inside local Wrangler, create the Wrangler-local vars file:
cp .dev.vars.example .dev.vars.devThe key difference is the lane URL:
APP_URL="http://localhost:8787"
AUTH_SECRET="replace-me-with-a-local-worker-secret"
XADMIN_SECRET="replace-me-for-local-worker-seeding"
CRON_SECRET="replace-me-for-local-worker-cron"
TRIGGER_SECRET="replace-me-for-local-worker-triggers"Keep .env.local on the local-app lane. Keep .dev.vars.dev on the local-worker lane.
The local-worker lane exists so you can verify the real Worker runtime explicitly. It does not replace the default local-app development and Playwright lane.
Optional: bootstrap the remote-cloudflare lane
For preview or production Cloudflare deploys:
cp wrangler.remote.example.toml wrangler.remote.toml
cp .env.cloudflare.example .env.cloudflare
cp .env.cloudflare.example .env.cloudflare.preview- Fill
wrangler.remote.tomlwith your private account, route, D1, KV, and R2 identifiers. - Use
.env.cloudflare*for remote helper, seeding, and Cloudflare API credentials only. - Do not edit tracked
wrangler.tomlwith live tenant IDs.
Database setup
Initialize your database with Drizzle:
# Generate migrations
npm run db:generate
# Apply migrations
npm run db:pushRun the local-app lane
Start the development server:
npm run dev -- --port 3101Open http://localhost:3101 in your browser to see your application.
Run the local-worker lane
If you bootstrapped .dev.vars.dev, start the Worker-fidelity lane separately:
npm run cf:previewOpen http://localhost:8787 to confirm Wrangler is serving the Worker locally.
The local Worker process should be backed by the tracked custom-worker entrypoint. Scheduled behavior is owned in that source boundary and continues through /api/cron; it is not meant to depend on patching generated .open-next output.
Verify the runtime lanes
Use the default Playwright lane for the app server:
npm run test:e2eIf you want Worker-runtime fidelity, opt into the dedicated worker smoke lane:
npm run test:e2e:worker
npm run test:e2e:worker:headedKeep those lanes mentally separate:
local-appstays on3101and remains the default Playwright lane.local-workerstays on8787and is the explicit Wrangler-based smoke lane.
Verify installation
To verify everything is working correctly:
- Visit http://localhost:3101 and confirm the home page renders.
- Navigate to /register and confirm the registration page loads.
- If you started the worker lane, visit http://localhost:8787 and confirm Wrangler serves the same app shell.
- Run
npm run test:e2efor the default app-lane smoke check. - If you opted into the worker lane, run
npm run test:e2e:workerto confirm the explicit Worker smoke path. - Check the terminal output for any missing env warnings.
Next Steps
Now that you have everything installed, proceed to:
- Configuration - Configure your application
- Deployment - Deploy to Cloudflare Workers
Troubleshooting
Port Already in Use
The canonical local-app lane intentionally uses port 3101 to stay aligned with the repo’s Playwright lane. If you intentionally create a different app lane, update APP_URL in .env.local to match:
npm run dev -- --port 3201The local-worker lane stays separate on Wrangler’s default 8787 port through .dev.vars.dev.
Do not point the default npm run test:e2e lane at 8787. Use npm run test:e2e:worker when you intentionally want Worker-runtime verification.
Database Connection Errors
If you encounter database connection errors:
- Ensure
DATABASE_URLis correctly set in.env.local. - Delete
dev.dband runnpm run db:pushagain. - Check file permissions
Module Not Found Errors
If you see “module not found” errors:
- Delete
node_modulesandpackage-lock.json - Run
npm installagain - Restart your development server
Wrong Cloudflare File
If a Cloudflare deploy or helper command complains about missing account, route, or binding IDs:
- Check
wrangler.remote.toml, not trackedwrangler.toml. - Check
.env.cloudflareor.env.cloudflare.previewfor helper/API credentials. - Keep
.dev.vars.devlocal-only and do not reuse it for preview or production.