Skip to content

Conversation

@reckziegelwilliam
Copy link

Upgrade apps/web into an authentication-aware router using Cloudflare Service Bindings. The root URL (/) now serves different content based on user auth state:

  • Unauthenticated users → marketing site (static assets)
  • Authenticated users → app dashboard (proxied from apps/app)

This creates a seamless GitHub-like experience where the home page intelligently adapts based on user authentication state.

Service Bindings Configuration

Added service bindings in wrangler.jsonc to connect workers:

  • APP_SERVICE → example-app (main application worker)
  • API_SERVICE → example-api (backend API worker)
  • Configured across all environments (dev, staging, preview, production)

Critical Configurations

  • Added run_worker_first: ["/"] to assets config Forces worker execution for / before serving static index.html Without this, static assets would bypass authentication logic entirely

  • Set assets.binding: "ASSETS" for explicit static asset serving

  • Set main: "./worker.ts" as worker entrypoint

Worker Implementation (worker.ts)

Created Hono-based worker with priority-ordered routing:

  1. PRIORITY 1 - API routes: Proxy /api/* → API_SERVICE Fixes 500 errors when app makes API calls

  2. PRIORITY 2 - App routes: Proxy to APP_SERVICE

    • /_app/* (app internal routes)
    • /login*, /signup* (authentication pages)
    • /settings*, /analytics*, /reports* (app features)
  3. PRIORITY 3 - Home page (/) with auth-aware logic:

    • Check for better-auth.session_token cookie (supports __Secure- prefix)
    • Forward full cookie header to API service binding
    • Validate session via GET /api/auth/get-session
    • On valid session → proxy to APP_SERVICE
    • Otherwise → serve marketing site from ASSETS
  4. PRIORITY 4 - Wildcard: Serve marketing pages from ASSETS Ensures /about, /features, /pricing work normally

Supports both GET and HEAD methods for proper HTTP compliance All / responses include cache control headers to prevent auth-state mixing

Helper Functions (lib/auth-helpers.ts)

Extracted reusable authentication utilities:

  • setCacheHeaders(response) - Prevents CDN/browser from caching auth-dependent content Sets Cache-Control: private, no-store and Vary: Cookie headers

  • extractSession(json) - Robust session extraction from Better Auth responses Handles multiple response formats from different plugins/wrappers

  • COOKIE_NAMES - Constants for Better Auth cookie names Supports both regular and __Secure- prefixed cookies for HTTPS

Type Definitions (types/env.d.ts)

Added comprehensive TypeScript interfaces:

  • Env - Cloudflare Workers environment bindings ASSETS, APP_SERVICE, API_SERVICE, ENVIRONMENT

  • BetterAuthApiResponse - API response structure Handles varying response shapes from Better Auth

  • BetterAuthSession - Session object structure Standard fields: id, userId, expiresAt

All interfaces exported for reusability across modules

Security & Performance

Security:

  • Session validation via API service (not just cookie presence)
  • Cache headers prevent authenticated content mixing
  • Graceful fallback to marketing site on all errors
  • Full cookie header forwarding (supports all Better Auth cookies)
  • No internal service URLs exposed

Performance:

  • Service bindings provide zero-latency inter-worker communication
  • Minimal code in hot path (cookie check before API call)
  • Cache headers prevent unnecessary processing
  • Route priority ensures fast static asset serving

Testing

  • ✅ TypeScript compilation verified (tsc --noEmit)
  • ✅ Build succeeds (astro build)
  • ✅ No linter errors
  • ✅ All workers start successfully
  • ✅ Code follows repo patterns (matches apps/api/ structure)

Runtime testing requires wrangler dev or production deployment to verify service binding execution.

Files Changed

  • apps/web/worker.ts (new) - Main worker entrypoint with routing logic
  • apps/web/lib/auth-helpers.ts (new) - Reusable auth utility functions
  • apps/web/types/env.d.ts (new) - TypeScript type definitions
  • apps/web/wrangler.jsonc (modified) - Added service bindings and run_worker_first
  • apps/web/package.json (modified) - Added hono dependency
  • apps/web/tsconfig.json (modified) - Include types directory and Cloudflare types

Upgrade apps/web into an authentication-aware router using Cloudflare Service
Bindings. The root URL (/) now serves different content based on user auth state:
- Unauthenticated users → marketing site (static assets)
- Authenticated users → app dashboard (proxied from apps/app)

This creates a seamless GitHub-like experience where the home page intelligently
adapts based on user authentication state.

## Service Bindings Configuration

Added service bindings in wrangler.jsonc to connect workers:
- APP_SERVICE → example-app (main application worker)
- API_SERVICE → example-api (backend API worker)
- Configured across all environments (dev, staging, preview, production)

## Critical Configurations

- Added `run_worker_first: ["/"]` to assets config
  Forces worker execution for / before serving static index.html
  Without this, static assets would bypass authentication logic entirely

- Set `assets.binding: "ASSETS"` for explicit static asset serving

- Set `main: "./worker.ts"` as worker entrypoint

## Worker Implementation (worker.ts)

Created Hono-based worker with priority-ordered routing:

1. PRIORITY 1 - API routes: Proxy /api/* → API_SERVICE
   Fixes 500 errors when app makes API calls

2. PRIORITY 2 - App routes: Proxy to APP_SERVICE
   - /_app/* (app internal routes)
   - /login*, /signup* (authentication pages)
   - /settings*, /analytics*, /reports* (app features)

3. PRIORITY 3 - Home page (/) with auth-aware logic:
   - Check for better-auth.session_token cookie (supports __Secure- prefix)
   - Forward full cookie header to API service binding
   - Validate session via GET /api/auth/get-session
   - On valid session → proxy to APP_SERVICE
   - Otherwise → serve marketing site from ASSETS

4. PRIORITY 4 - Wildcard: Serve marketing pages from ASSETS
   Ensures /about, /features, /pricing work normally

Supports both GET and HEAD methods for proper HTTP compliance
All / responses include cache control headers to prevent auth-state mixing

## Helper Functions (lib/auth-helpers.ts)

Extracted reusable authentication utilities:

- `setCacheHeaders(response)` - Prevents CDN/browser from caching auth-dependent content
  Sets Cache-Control: private, no-store and Vary: Cookie headers

- `extractSession(json)` - Robust session extraction from Better Auth responses
  Handles multiple response formats from different plugins/wrappers

- `COOKIE_NAMES` - Constants for Better Auth cookie names
  Supports both regular and __Secure- prefixed cookies for HTTPS

## Type Definitions (types/env.d.ts)

Added comprehensive TypeScript interfaces:

- `Env` - Cloudflare Workers environment bindings
  ASSETS, APP_SERVICE, API_SERVICE, ENVIRONMENT

- `BetterAuthApiResponse` - API response structure
  Handles varying response shapes from Better Auth

- `BetterAuthSession` - Session object structure
  Standard fields: id, userId, expiresAt

All interfaces exported for reusability across modules

## Security & Performance

Security:
- Session validation via API service (not just cookie presence)
- Cache headers prevent authenticated content mixing
- Graceful fallback to marketing site on all errors
- Full cookie header forwarding (supports all Better Auth cookies)
- No internal service URLs exposed

Performance:
- Service bindings provide zero-latency inter-worker communication
- Minimal code in hot path (cookie check before API call)
- Cache headers prevent unnecessary processing
- Route priority ensures fast static asset serving

## Testing

- ✅ TypeScript compilation verified (tsc --noEmit)
- ✅ Build succeeds (astro build)
- ✅ No linter errors
- ✅ All workers start successfully
- ✅ Code follows repo patterns (matches apps/api/ structure)

Runtime testing requires wrangler dev or production deployment
to verify service binding execution.

## Files Changed

- apps/web/worker.ts (new) - Main worker entrypoint with routing logic
- apps/web/lib/auth-helpers.ts (new) - Reusable auth utility functions
- apps/web/types/env.d.ts (new) - TypeScript type definitions
- apps/web/wrangler.jsonc (modified) - Added service bindings and run_worker_first
- apps/web/package.json (modified) - Added hono dependency
- apps/web/tsconfig.json (modified) - Include types directory and Cloudflare types
@koistya
Copy link
Member

koistya commented Dec 16, 2025

Thanks @reckziegelwilliam Give me some time to review and I'll get back to you.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants