This repo contain a fullstack example to build on Cloudflare with the following stack:
- RedwoodSDK: A React framework to run react 19 with SSR/RSC/ServerFunctions/etc.. on Cloudflare
- Drizzle ORM: Lightweight, type-safe SQL ORM with migrations
- Better-auth: Simple, flexible authentication library - The example is setup to use OTP
- Alchemy: Infrastructure-as-Code without the dead weight
- Shadcn: A set of beautifully-designed, accessible components to build your component library
- Bun: a fast JavaScript all-in-one toolkit
- D1 (as main DB)
- R2 (for avatar/file storage)
- Website running on workers using RedwoodSDK
All the required resources are configured via Alchmey in alchemy.run.ts
- Nick Balestra-Foster: This example is a fork of Nick's repo which provided a great foundation to tweak and build on top of.
- MJ Meyer: Nick's example was heavily inspired by MJ's repo, adding little things here and there, mainly Alchemy as IaC.
- Check /types/env.d.ts to see how our IaC help defining our types (no need to generate types with Wrangler)
- Check ./alchemy.run.ts to see how the whole infra is defined as code via Alchemy
git clone https://github.com/oscabriel/red-cloud
cd red-cloud
bun install
cp .env.example .env
bun dev:init
bun dev
The application will be available at the URL displayed in your terminal (typically http://localhost:5173
)
This will provision all the resources needed like db, ... The application will be available at the Cloudflare URL displayed in your terminal.
bun infra:up
This application includes the following key routes:
- / - Landing page with authentication and navigation
- /guestbook - Interactive guestbook where users can leave messages (requires authentication)
- /profile - User profile management with device session control (requires authentication)
- /sign-in - Authentication page with OTP and social login options
- Protected Routes - All authenticated routes use interruptor-based authentication middleware
This example includes a complete authentication system with:
- OTP for signup and login (with email integration via Resend)
- Social authentication (Google & GitHub OAuth)
- Native better-auth session management with database persistence
- Protected routes with interruptor-based authentication
- Multi-device session support with proper logout functionality
The project uses Cloudflare D1 (SQLite) with Drizzle ORM. A local development database will automatically setup when you first run bun dev
in ./wrangler
The authentication schema is defined in src/db/schema
and includes tables for:
- Users
- Sessions
- Accounts
When you need to update your database schema:
- Modify the schema files in
src/db/schema
- Generate a new migration:
bun migrate:new --name="your_migration_name"
- Apply the migration:
bun migrate:dev
To deploy the whole application (app, db, ecc) to Cloudflare:
- Run the infra:up command to spin up and deploy:
bun infra:up
- Run the infra:destroy to tear it down
bun infra:destroy
Everytime you change anything to the infra definition and run infra:up
your whole infra will be updated, that's it.
This project has evolved significantly from a basic implementation to a more production-ready codebase. Here are the major architectural improvements:
We've optimized the session management system to make the most of better-auth's native server-side APIs and db-first session storage:
- Server-Side Session Fetching: Uses
auth.api.getSession()
withdisableCookieCache: true
for fresh session data - SSR Optimization: Pre-fetches session data on the server and passes to client components as props
- Efficient Client Actions: Uses
authClient.signOut()
andauthClient.revokeSession()
for session termination - No Session Caching: We want to maintain fresh session data at all times to align with our realtime functionality
Key Files:
src/middleware/app-middleware.ts
- Server-side session loading using better-auth APIssrc/app/pages/profile/components/session-manager.tsx
- Multi-device session management with native better-auth actions
We implemented a dark/light theme system that prevents hydration errors and FOUCs (Flashes of Unstyled Content) commonly encountered in SSR-first frameworks.
Starting from the default shadcn recommendation, we added:
-
Blocking Theme Script (
public/theme-script.js
):- Executes synchronously in the
<head>
before any React hydration - Reads theme preference from localStorage (
red-cloud-theme
key) - Immediately applies the correct theme class (
light
,dark
) to<html>
- Handles system preference detection via
prefers-color-scheme
- Includes error handling with fallback to system theme
- Executes synchronously in the
-
Separate Theme Hook (
src/app/hooks/use-theme.ts
): Separated hook logic from the theme-provider for better tree-shaking -
Theme Provider (
src/app/components/navigation/theme-provider.tsx
): Manages theme state with SSR-safe initialization -
CSS Variables (
src/app/document/styles.css
): Tailwind v4 with custom properties for light/dark modes -
Hydration Warning Suppression (
src/client.tsx
): Suppresses Radix UI ID mismatch warnings to clean up console output
Achievements:
- Zero flash theme switching
- System preference detection
- Persistent user choice via localStorage
- Hydration-safe SSR compatibility
Migrated from single-file pages to a well-organized, feature-based directory structure:
Pages Reorganization:
src/app/pages/
βββ guestbook/
β βββ guestbook-page.tsx # page component
β βββ functions.ts # server functions
β βββ components/ # specialized components
βββ profile/
β βββ profile-page.tsx
β βββ functions.ts
β βββ components/
βββ sign-in/
βββ sign-in-page.tsx
βββ components/
Library Organization:
src/lib/
βββ auth/ - Better-auth config and utilities
βββ utils/ - Centralized utility functions and constants
βββ validators/ - Zod validation schemas by feature
Authentication Enhancements:
- Centralized config: All better-auth setup in
src/lib/auth/index.ts
- Multi-session Support: Enabled via better-auth plugins for better user experience
- Email OTP Integration: Configured with Resend for reliable email delivery
- Social Providers: Google and GitHub OAuth support
Validation & Type Safety:
- Feature-based Validators: Organized Zod schemas by functionality (auth, guestbook, profile)
- Comprehensive Type Definitions: New
src/types/
directory with API, hooks, session, and UI types - Enhanced TypeScript Coverage: Improved type safety across the entire application
Developer Experience:
- Centralized Constants: Consolidated all reusable constants under
src/lib/utils/constants.ts
- Consistent Error Handling: Standardized error responses using RedwoodSDK patterns
- Improved Logging: Better development-time debugging with structured logging
- Code Quality: Enhanced linting and formatting compliance with Biome.js
User Experience Improvements:
- Onboarding Flow: Modal-based user onboarding for better first-time experience
- Toast Notifications: Sonner integration for user feedback
- Loading States: Skeleton components for better perceived performance
- Form Validation: Enhanced client and server-side validation with better error messages
red-cloud/
ββ .cursor/ # Rules reference for AI
ββ .instructions/ # Planning and task list files for AI
ββ src/ # Central app directory
β ββ api/ # API routes used in worker.tsx
β ββ app/ # UI components and core application logic
β β ββ components/ # Reusable UI components
β β ββ document/ # Root document config
β β ββ hooks/ # Custom React hooks
β β ββ layouts/ # Layout components
β β ββ pages/ # Feature-based page organization
β β β ββ feature/ # Feature page directory
β β β β ββ components/ # Feature-specific components
β β β β ββ functions.ts # Feature-specific server functions
β β β β ββ feature-page.tsx # Feature page component
β β β ββ landing.tsx # Landing page component
β β ββ providers/ # React context providers
β ββ db/ # Database instance/schema/migrations
β ββ lib/ # Shared/auxiliary application logic
β β ββ auth/ # Better-Auth config
β β ββ utils/ # Utility functions, constants, etc
β β ββ validators/ # Zod validation schemas
β ββ middleware/ # Request middleware and rwsdk interruptors
β ββ types/ # Shared app type definitions
β ββ client.tsx # Client-side entry point
β ββ worker.tsx # Server-side entry point
ββ types/ # Global type definitions
ββ public/ # Image/font/script files
ββ alchemy.run.ts # Alchemy Infrastructure-as-Code
ββ biome.json # Biome linter/formatter config
ββ components.json # shadcn/ui config
ββ drizzle.config.ts # Drizzle ORM config
ββ package.json # Dependencies and scripts
ββ tailwind.config.ts # Tailwind CSS config
ββ tsconfig.json # TypeScript config
ββ vite.config.mts # Vite build config
ββ wrangler.jsonc # Wrangler file (generated by Alchemy)