Web Platform
The web platform uses Next.js 14+ with App Router, providing a modern React web application that shares authentication with your mobile app.
Overview
| Feature | Description |
|---|---|
| Framework | Next.js 14+ with App Router |
| Styling | Tailwind CSS + shadcn/ui |
| Authentication | Cookie-based sessions (shared with mobile) |
| Dark Mode | next-themes with system preference |
Shared Backend
Both web and mobile apps connect to the same Fastify backend, sharing the user database and authentication system.
Project Structure
web/
├── src/
│ ├── app/ # Next.js App Router
│ │ ├── (auth)/ # Auth pages (login, register, etc.)
│ │ ├── (app)/ # Protected app pages (dashboard, settings)
│ │ ├── auth/ # OAuth callback routes
│ │ ├── globals.css # Global styles with dark mode
│ │ └── layout.tsx # Root layout with providers
│ ├── components/
│ │ ├── ui/ # shadcn/ui components
│ │ ├── auth/ # Auth forms and buttons
│ │ ├── settings/ # Settings components
│ │ └── providers/ # Context providers
│ ├── lib/
│ │ ├── auth/ # Auth utilities and actions
│ │ └── utils.ts # Utility functions
│ └── store/ # Zustand stores
├── public/ # Static assets
├── next.config.ts # Next.js configuration
└── package.jsonEnvironment Variables
Create a .env file in the web/ directory:
# Public URL of the web app (used for OAuth callbacks)
NEXT_PUBLIC_APP_URL=http://localhost:3000
# Backend API URL (server-side only, used by server actions)
BACKEND_URL=http://localhost:8080Running the Web App
cd web
bun install
bun run devThe app runs on http://localhost:3000 by default.
Authentication on Web
The web platform uses cookie-based sessions (unlike mobile which uses token storage):
| Feature | Mobile | Web |
|---|---|---|
| Session Storage | AsyncStorage + Secure Store | HTTP-only Cookies |
| Token Refresh | Manual refresh | Automatic via cookies |
| OAuth Flow | Deep links + native SDKs | Browser redirects |
| CSRF Protection | Not needed | Built into Better Auth |
Why Cookies?
Cookie-based sessions are more secure for web applications - they're HTTP-only (no JavaScript access), automatically included in requests, and protected against XSS attacks.
OAuth Configuration
For OAuth to work on web, ensure your OAuth providers have the correct redirect URIs pointing to the backend (Better Auth handles the OAuth callback):
Google Cloud Console
# Development
http://localhost:8080/api/auth/callback/google
# Production
https://api.yourdomain.com/api/auth/callback/googleApple Developer Console
HTTPS Required
Apple Sign In requires HTTPS for redirect URIs. It will not work with http://localhost
in development. You must either use a tunneling service (ngrok, Cloudflare Tunnel),
test in production/staging, or use the mobile app for Apple Sign In testing.
# Production only - HTTPS required
https://api.yourdomain.com/api/auth/callback/appleGitHub OAuth App
# Development
http://localhost:8080/api/auth/callback/github
# Production
https://api.yourdomain.com/api/auth/callback/githubCORS Configuration
The backend must allow web origins. In backend/.env:
# Comma-separated list of allowed origins
CORS_ORIGINS=http://localhost:3000,https://yourdomain.comDark Mode
The web app includes full dark mode support:
- Uses
next-themesfor theme management - Theme persists in localStorage
- Respects system preference by default
- Toggle via the
ThemeTogglecomponent
Deploying Web
See Deployment for detailed deployment instructions for Vercel, Netlify, Docker, and Node.js hosting.