Skip to content

oscabriel/better-cloud

Repository files navigation

Better-Cloud

Hello! Thank you for checking out this project. If you like what you see and want to see more production-ready projects and blog posts about those projects, check out my personal site: oscargabriel.dev.

Better-Cloud is a comprehensive full-stack application demonstrating modern web development on Cloudflare's edge platform. This production-ready web app showcases real-time features, user authentication, and persistent data management using Cloudflare Workers, Durable Objects, D1, and KV, making use of Alchemy for its infrastructure-as-code configuration.

Live Demo Features

  • πŸ”’ Global Counter: Real-time synchronized counter with persistent state
  • πŸ“ Guestbook: Traditional guestbook with user profiles and country field
  • πŸ‘€ User Authentication: Email OTP and social OAauth login (Google, GitHub)
  • πŸ”„ Real-time Updates: WebSocket connections with hibernation API
  • πŸ“Š Connection Monitoring: Live connection count tracking

Better-Cloud Preview

Table of Contents


Application Features

🏠 Landing Page

  • ASCII banner header
  • Real-time API health check with tRPC

πŸ”’ Counter Demo (/counter)

  • Global State Management: SQLite-backed persistent counter
  • Real-time Synchronization: WebSocket updates across all users
  • Rich Metrics: Tracks total increments, decrements, last updater
  • Connection Status: Live WebSocket connection monitoring
  • Technical Diagrams: Interactive flow charts explaining the architecture

πŸ“ Guestbook (/guestbook)

  • User Messages: Create and view community messages
  • Profile Integration: Automatic name population from user profiles

πŸ‘€ User Management (/profile)

  • Profile Settings: Update display name and preferences
  • Session Management: View and terminate sessions on other devices

πŸ” Authentication (/sign-in)

  • Email OTP: Passwordless authentication via verification codes
  • Social OAuth: Google and GitHub provider integration

Tech Stack

Frontend

  • React 19: Latest React with concurrent features
  • TypeScript: Full type safety throughout the application
  • Vite: Fast development builds and hot module replacement
  • TanStack Router: File-based routing with type-safe navigation
  • TanStack Query: Server state management and caching
  • TanStack Form: Type-safe form validation and handling
  • Tailwind CSS v4: Modern utility-first styling
  • shadcn/ui: Accessible component library
  • Sonner: Toast notifications

Backend & Infrastructure

  • Cloudflare Workers: Serverless edge computing platform
  • Hono: Lightweight web framework for Workers
  • tRPC: End-to-end type-safe API with client-server sync
  • Zod: Runtime type validation and schema parsing
  • Cloudflare D1: Distributed SQLite database
  • Drizzle ORM: Type-safe database queries and migrations
  • Cloudflare KV: Key-value storage for sessions and caching
  • Better Auth: Modern authentication with email OTP and OAuth
  • Resend: Transactional email delivery

Real-time & State Management

  • Durable Objects: Stateful serverless objects with strong consistency
  • WebSocket Hibernation API: Cost-effective real-time connections
  • SQLite Storage: ACID transactions within Durable Objects
  • Connection Pooling: Efficient WebSocket connection management

Development & Deployment

  • Bun: Fast package manager and JavaScript runtime
  • Biome: Modern linting and formatting (replaces ESLint + Prettier)
  • Alchemy: Infrastructure-as-code for Cloudflare resources
  • Wrangler: Cloudflare Workers development and deployment CLI

Project Structure

better-cloud/
β”œβ”€β”€ src/
β”‚   β”œβ”€β”€ client/                   # React frontend application
β”‚   β”‚   β”œβ”€β”€ components/           # Reusable UI components
β”‚   β”‚   β”‚   β”œβ”€β”€ navbar/           # Header, theme toggle, user menu
β”‚   β”‚   β”‚   └── ui/               # shadcn/ui component library
β”‚   β”‚   β”œβ”€β”€ hooks/                # Custom React hooks
β”‚   β”‚   β”‚   β”œβ”€β”€ use-counter-query.ts    # Counter state management
β”‚   β”‚   β”‚   └── use-dual-websocket.ts   # WebSocket connections
β”‚   β”‚   β”œβ”€β”€ lib/                  # Client-side utilities
β”‚   β”‚   β”‚   β”œβ”€β”€ auth-client.ts    # Better Auth client setup
β”‚   β”‚   β”‚   β”œβ”€β”€ trpc-client.ts    # tRPC client configuration
β”‚   β”‚   β”‚   └── theme-provider.tsx # Dark/light theme context
β”‚   β”‚   β”œβ”€β”€ routes/               # File-based routing (TanStack Router)
β”‚   β”‚   β”‚   β”œβ”€β”€ _authLayout/      # Authentication pages
β”‚   β”‚   β”‚   β”‚   └── sign-in.tsx   # Email OTP and social login
β”‚   β”‚   β”‚   β”œβ”€β”€ _protectedLayout/ # Authenticated user pages
β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ counter.tsx   # Global counter demo
β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ guestbook.tsx # Community guestbook
β”‚   β”‚   β”‚   β”‚   └── profile.tsx   # User profile management
β”‚   β”‚   β”‚   β”œβ”€β”€ __root.tsx        # Root layout component
β”‚   β”‚   β”‚   └── index.tsx         # Landing page
β”‚   β”‚   └── routeTree.gen.ts      # Auto-generated route definitions
β”‚   β”‚
β”‚   └── server/                   # Cloudflare Workers backend
β”‚       β”œβ”€β”€ db/                   # Database layer
β”‚       β”‚   β”œβ”€β”€ schema/           # Drizzle ORM schemas
β”‚       β”‚   β”‚   β”œβ”€β”€ auth.ts       # Authentication tables
β”‚       β”‚   β”‚   └── guestbook.ts  # Guestbook messages
β”‚       β”‚   β”œβ”€β”€ migrations/       # Database migration files
β”‚       β”‚   └── index.ts          # Database connection setup
β”‚       β”œβ”€β”€ durable-objects/      # Stateful serverless objects
β”‚       β”‚   β”œβ”€β”€ counter.ts        # Global counter with SQLite
β”‚       β”‚   └── connection-counter.ts # WebSocket connection tracking
β”‚       β”œβ”€β”€ lib/                  # Server-side utilities
β”‚       β”‚   β”œβ”€β”€ auth.ts           # Better Auth configuration
β”‚       β”‚   β”œβ”€β”€ context.ts        # tRPC context setup
β”‚       β”‚   └── types.ts          # Shared TypeScript types
β”‚       β”œβ”€β”€ routers/              # tRPC API routes
β”‚       β”‚   β”œβ”€β”€ counter.ts        # Counter operations
β”‚       β”‚   β”œβ”€β”€ guestbook.ts      # Guestbook CRUD
β”‚       β”‚   β”œβ”€β”€ user.ts           # User profile management
β”‚       β”‚   └── index.ts          # Router composition
β”‚       └── index.ts              # Worker entry point
β”‚
β”œβ”€β”€ types/                        # Global TypeScript definitions
β”‚   β”œβ”€β”€ env.d.ts                  # Alchemy augmented env types
β”‚   └── vite.d.ts                 # Vite types
β”œβ”€β”€ public/                       # Static assets
β”œβ”€β”€ alchemy.run.ts                # Infrastructure-as-code (Alchemy)
β”œβ”€β”€ vite.config.ts                # Vite configuration
β”œβ”€β”€ drizzle.config.ts             # Database migration config
β”œβ”€β”€ biome.json                    # Linting and formatting rules
└── package.json                  # Dependencies and scripts

Database

The application uses Cloudflare D1 (distributed SQLite) with Drizzle ORM for type-safe database operations.

Database Commands

Command Description
bun db:generate Generate migration files from schema changes
bun db:push Push schema changes directly (development only)
bun db:migrate Apply pending migrations to database
bun db:studio Launch Drizzle Studio for local database
bun db:studio:prod Launch Drizzle Studio for production database

Durable Objects

Durable Objects provide stateful, globally-consistent serverless computing with persistent storage and real-time WebSocket capabilities.

Counter Durable Object (counter.ts)

State Management

  • Persistent counter value with increment/decrement operations
  • Comprehensive metrics: total increments, decrements, last updater, timestamps
  • SQLite-backed storage with ACID transaction guarantees
  • Automatic state restoration after hibernation

WebSocket Features

  • Real-time updates broadcast to all connected clients
  • Hibernation API for cost-effective WebSocket connections
  • Support for up to 32,768 concurrent connections per object
  • Ping/pong keepalive and connection health monitoring

API Endpoints

  • GET / - Retrieve current counter state and metrics
  • POST /increment - Increment counter with optional amount and username
  • POST /decrement - Decrement counter with optional amount and username
  • WebSocket - Real-time counter updates and connection management

Connection Counter Durable Object (connection-counter.ts)

Connection Tracking

  • Real-time monitoring of active WebSocket connections
  • Automatic count updates when clients connect/disconnect
  • Broadcast connection count changes to all subscribers
  • Hibernation-optimized for zero idle costs

Use Cases

  • Live user count display
  • Connection health monitoring
  • Real-time presence indicators
  • System load monitoring

Architecture Benefits

Cost Efficiency

  • Hibernation eliminates memory charges during idle periods
  • Pay only for active compute time and storage
  • Automatic wake-up on incoming requests (sub-millisecond latency)

Strong Consistency

  • Single object instance processes all operations sequentially
  • No race conditions or eventual consistency issues
  • ACID transactions within SQLite storage

Global Performance

  • Deployed to Cloudflare's global edge network
  • Automatic migration to optimal data center locations
  • Sub-100ms response times worldwide

Authentication

Better Auth provides secure, modern authentication with multiple sign-in methods and session management.

Authentication Methods

Email OTP (One-Time Password)

  • Passwordless authentication via email verification codes
  • 6-digit OTP codes sent via Resend email service

Social OAuth Providers

  • Automatic profile creation and linking
  • Secure token management with refresh capabilities

Session Management

Storage Architecture

  • Primary Storage: User accounts and sessions in Cloudflare D1 database
  • Secondary Storage: Session caching in Cloudflare KV for fast access
  • Cross-subdomain Support: Shared sessions across *.example.com

Security Features

  • Secure HTTP-only cookies with SameSite protection
  • Rate limiting on authentication attempts
  • IP address and user agent tracking
  • Automatic session expiry and cleanup

Authentication Flow

  1. Sign In: User enters email or clicks social provider
  2. Verification: OTP sent via email OR OAuth redirect to provider
  3. Account Creation: New users automatically get profiles created
  4. Session Establishment: Secure session created with KV caching
  5. Profile Access: User redirected to protected routes with full access

Cross-Domain & Cross-Subdomain Authentication Setup

This application is configured to handle different domain configurations between development and production environments:

Development Environment (Cross-Domain)

  • Frontend: http://localhost:5173
  • Backend: http://localhost:8787

Production Environment (Cross-Subdomain)

  • Frontend: https://example.com
  • Backend: https://api.example.com

Environment Variables for Domain Configuration

CUSTOM_WEB_DOMAIN & CUSTOM_API_DOMAIN These variables define your production domain configuration:

# Production domains (used by Alchemy for SSL/DNS setup)
CUSTOM_WEB_DOMAIN=example.com         # Your main frontend domain
CUSTOM_API_DOMAIN=api.example.com     # Your API backend subdomain

TRUSTED_ORIGINS Configuration This variable controls which origins Better Auth accepts requests from. It must be properly formatted as a comma-separated string that gets parsed into an array:

# Development
TRUSTED_ORIGINS=http://localhost:5173,http://localhost:8787

# Production
TRUSTED_ORIGINS=https://example.com,https://api.example.com

Important: The TRUSTED_ORIGINS environment variable must be a comma-separated string without spaces. The application parses this using env.TRUSTED_ORIGINS?.split(",") to create an array for Better Auth.

Cookie Configuration Differences

The authentication system uses different cookie settings based on the environment:

Development Settings (ALCHEMY_STAGE=dev)

defaultCookieAttributes: {
  sameSite: "none",    // Required for cross-domain cookies  
}
crossSubDomainCookies: {
  enabled: false,      // Not needed for different domains
}
trustedOrigins: [
  "http://localhost:5173",
  "http://localhost:8787"
]

Production Settings (ALCHEMY_STAGE=prod)

defaultCookieAttributes: {
  sameSite: "lax",     // Safer for same domain, different subdomains
}
crossSubDomainCookies: {
  enabled: true,       // Share cookies across *.example.com
  domain: "example.com"  // Parent domain for subdomain sharing
}
trustedOrigins: [
  "https://example.com",
  "https://api.example.com"
]

Why These Settings Matter

Development Cross-Domain Issues

  • Different ports/domains (localhost:5173 ↔ localhost:8787) require sameSite: "none"
  • Browsers block cross-domain cookies with sameSite: "lax" by default
  • Must use credentials: "include" on all client requests

Production Cross-Subdomain Benefits

  • Same parent domain allows sameSite: "lax" for better security
  • Cookies automatically shared across *.example.com subdomains
  • More secure than sameSite: "none" while maintaining functionality

Configuration

All authentication endpoints are available under /auth/*:

  • /auth/sign-in/email - Email OTP initiation
  • /auth/sign-in/google - Google OAuth redirect
  • /auth/sign-in/github - GitHub OAuth redirect
  • /auth/sign-out - Session termination
  • /auth/callback/* - OAuth return endpoints

Getting Started

Prerequisites

  • Bun v1.2+ - Fast JavaScript runtime and package manager
  • Node.js v18+ - Alternative runtime (if not using Bun)
  • Cloudflare Account - For Workers, D1, KV, and domain management
  • Wrangler CLI - Cloudflare development tool: npm install -g wrangler

Environment Setup

Local Development Environment Create .env.dev.example β†’ .env.dev with:

VITE_CLIENT_URL=http://localhost:5173
VITE_SERVER_URL=http://localhost:8787
TRUSTED_ORIGINS=http://localhost:5173
BETTER_AUTH_URL=http://localhost:8787
BETTER_AUTH_SECRET=your-secret-key
GOOGLE_CLIENT_ID=your-google-oauth-id
GOOGLE_CLIENT_SECRET=your-google-oauth-secret  
GITHUB_CLIENT_ID=your-github-oauth-id
GITHUB_CLIENT_SECRET=your-github-oauth-secret
RESEND_API_KEY=your-resend-key
CUSTOM_WEB_DOMAIN=localhost:5173
CUSTOM_API_DOMAIN=localhost:8787

Production Environment
Create .env.prod.example β†’ .env.prod with:

VITE_CLIENT_URL=https://example.com
VITE_SERVER_URL=https://api.example.com
TRUSTED_ORIGINS=https://example.com,https://api.example.com
BETTER_AUTH_URL=https://api.example.com
BETTER_AUTH_SECRET=your-production-secret-key
GOOGLE_CLIENT_ID=your-google-oauth-id
GOOGLE_CLIENT_SECRET=your-google-oauth-secret
GITHUB_CLIENT_ID=your-github-oauth-id  
GITHUB_CLIENT_SECRET=your-github-oauth-secret
RESEND_API_KEY=your-resend-key
CUSTOM_WEB_DOMAIN=example.com
CUSTOM_API_DOMAIN=api.example.com

Installation

# Install dependencies
bun install

# Generate database migrations (if needed)
bun db:generate

# Push database schema to D1
bun db:push

Development

Single Command Setup (Recommended)

# Start both frontend and backend with Alchemy
bun a:dev            # β†’ Frontend: http://localhost:5173, Backend: http://localhost:8787

Why Alchemy Dev Server?

  • Unified Environment: Single command starts both Vite frontend and Workers backend
  • Proper Database Integration: Uses the D1 database created by alchemy state stored in .alchemy/ directory
  • Resource Management: Automatic setup of KV, Durable Objects, and other Cloudflare resources

Development Commands

bun check            # Lint and format code with Biome  
bun typecheck        # TypeScript type checking
bun db:studio        # Launch database browser interface

Build and Preview

# Build for production
bun build

# Preview production build locally  
bun preview          # β†’ http://localhost:4173

Deployment

Option 1: Alchemy (Recommended)

# Deploy with Alchemy IaC
bun a:deploy         # Deploy to production  

Option 2: Direct Wrangler

# Deploy directly to Cloudflare
bunx wrangler deploy

Infrastructure Management

Alchemy Configuration (alchemy.run.ts)

  • Declarative Resources: D1 database, KV namespaces, Durable Objects
  • Custom Domains: Automatic DNS and SSL certificate management
  • Environment Management: Separate dev/prod configurations
  • Resource Adoption: Import existing Cloudflare resources

Cloudflare Resources Created:

  • Worker: Main application server
  • D1 Database: User data and guestbook messages
  • KV Namespace: Session storage and caching
  • Durable Objects: Counter and connection tracking
  • Custom Domains: Production domain with SSL

License

MIT License

About

Better-Auth 🀝 Cloudflare

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 2

  •  
  •