Skip to Content
Getting StartedInstallation

Installation

cfstack has three runtime lanes:

LaneDefault URLPurpose
local-apphttp://localhost:3101Fast Next.js development and the canonical Playwright lane
local-workerhttp://localhost:8787Local Wrangler runtime for Worker-fidelity checks
remote-cloudflareyour preview or production domainReal 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-worker lane or remote Cloudflare deploys

Clone the Repository

First, clone the repository to your local machine:

git clone https://github.com/aigotowork/cfstack.git cd cfstack

Install Dependencies

Install all required dependencies using npm:

npm install

This 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.local

Open .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 secret

Optional: 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.dev

The 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.toml with 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.toml with live tenant IDs.

Database setup

Initialize your database with Drizzle:

# Generate migrations npm run db:generate # Apply migrations npm run db:push

Run the local-app lane

Start the development server:

npm run dev -- --port 3101

Open 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:preview

Open 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:e2e

If you want Worker-runtime fidelity, opt into the dedicated worker smoke lane:

npm run test:e2e:worker npm run test:e2e:worker:headed

Keep those lanes mentally separate:

  • local-app stays on 3101 and remains the default Playwright lane.
  • local-worker stays on 8787 and is the explicit Wrangler-based smoke lane.

Verify installation

To verify everything is working correctly:

  1. Visit http://localhost:3101  and confirm the home page renders.
  2. Navigate to /register and confirm the registration page loads.
  3. If you started the worker lane, visit http://localhost:8787  and confirm Wrangler serves the same app shell.
  4. Run npm run test:e2e for the default app-lane smoke check.
  5. If you opted into the worker lane, run npm run test:e2e:worker to confirm the explicit Worker smoke path.
  6. Check the terminal output for any missing env warnings.

Next Steps

Now that you have everything installed, proceed to:

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 3201

The 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:

  1. Ensure DATABASE_URL is correctly set in .env.local.
  2. Delete dev.db and run npm run db:push again.
  3. Check file permissions

Module Not Found Errors

If you see “module not found” errors:

  1. Delete node_modules and package-lock.json
  2. Run npm install again
  3. Restart your development server

Wrong Cloudflare File

If a Cloudflare deploy or helper command complains about missing account, route, or binding IDs:

  1. Check wrangler.remote.toml, not tracked wrangler.toml.
  2. Check .env.cloudflare or .env.cloudflare.preview for helper/API credentials.
  3. Keep .dev.vars.dev local-only and do not reuse it for preview or production.
Last updated on