Example of Nuxt.js application is located in the apps/nuxt
directory and works as SSR (Server-Side Rendering) application by default.
By default configuration has two environments:
staging
andproduction
.
starter-nuxt-staging | starter-nuxt-production
To run the Nuxt.js application locally, follow these steps:
- Run
pnpm --filter @starter/nuxt run dev
to start the development server.
To deploy the Nuxt.js application, you need to prepare environment:
- Create two workers on Cloudflare. One for
staging
and one forproduction
(e.g.starter-nuxt-staging
andstarter-nuxt-production
). - Connect GitHub repository to those workers and configure build settings:
- Set your default branch as branch control setting in both workers.
- Set build command as
pnpm run build
in both workers. - Set deploy command as
pnpm run deploy:staging
for staging worker. - Set deploy command as
pnpm run deploy:production
for production worker. - Set path as
apps/nuxt
in both workers. - For staging worker enable build for non-production branches with command
pnpm run upload:staging
. It will upload builds for every non-production branch. - Update worker names in
wrangler.jsonc
file accordingly.
To test deployment locally, you can use following commands:
- Build:
pnpm --filter @starter/nuxt run build
- Preview:
pnpm --filter @starter/nuxt run preview
By default, the project uses client bundle mode for icons. It means that icon packs should be installed separately.
To install icons, run the following command: pnpm --filter @starter/nuxt add @iconify-json/streamline-emojis
Example of H3.js worker is located in the workers/h3-example
directory. The worker uses lazy routing to optimize cold start performance by loading route handlers only when needed.
The H3 worker includes full database integration with Drizzle ORM, providing a complete backend solution with PostgreSQL support. It demonstrates how to build scalable serverless APIs with database operations.
- Database Integration - Full PostgreSQL support with Drizzle ORM for type-safe database operations
- Lazy Routing - Route handlers are loaded only when needed for optimal cold start performance
- Environment Validation - Robust validation of environment variables using Valibot
- Demo Endpoints - Example endpoints for KV storage and database operations
GET /
- Welcome endpointGET /kv-test
andPOST /kv-test
- KV storage demonstrationGET /users-count
- Database integration example (returns user count from PostgreSQL)
wrangler.jsonc
- configuration file for Cloudflare Workers.src/
- source code of the worker.src/index.ts
- entry point of the worker..env.example
- example environment variables file.
- Copy
.env.example
to.env
and fill in your values. - Update
wrangler.jsonc
with your worker name and account ID. - Run
pnpm --filter @starter/h3-example run cf:typegen
to generate TypeScript types for Cloudflare Workers.
To run the worker locally, you can use the following commands:
pnpm --filter @starter/h3-example run dev
- run with local bindings (emulated)pnpm --filter @starter/h3-example run dev:remote
- run with remote bindings
To deploy the worker, you can use the following commands:
- For staging:
pnpm --filter @starter/h3-example run deploy:staging
- For production:
pnpm --filter @starter/h3-example run deploy:production
To integrate the worker with GitHub, you can use the following steps:
- Create two workers on Cloudflare or deploy existing one (see above).
- Connect GitHub repository to those workers and configure build settings:
- Set your default branch as branch control setting in both workers.
- Keep build command empty.
- Set deploy command as
pnpm run deploy:staging
for staging worker. - Set deploy command as
pnpm run deploy:production
for production worker. - Set path as
workers/h3-example
in both workers. - For staging worker enable build for non-production branches with command
pnpm run upload:staging
. It will upload builds for every non-production branch.
Cloudflare KV is integrated for both the Nuxt app (server routes) and the H3 worker. The PR #37 added:
- KV namespaces bindings (
KV
) to bothapps/nuxt/wrangler.jsonc
andworkers/h3-example/wrangler.jsonc
(staging + production). - A Nitro storage mapping (
kv-starter-storage
) using thecloudflare-kv-binding
driver for Nuxt app. - Demo API endpoints:
GET /api/kv-storage
andPOST /api/kv-storage
in Nuxt app. - Demo API endpoints:
GET /kv-test
andPOST /kv-test
in H3 worker. - Demo UI page
/test-page/kv-storage
with a Pinia store to read/write a test value. - Shared constants file with storage + key names.
- Local development aid via
nitro-cloudflare-dev
module (environment = staging by default) to emulate KV binding. - HTTP request files in
requests/
directory for testing API endpoints.
In Cloudflare Dashboard create two KV namespaces (or reuse existing): one for staging
, one for production
.
Update (or verify) kv_namespaces
arrays in:
apps/nuxt/wrangler.jsonc
workers/h3-example/wrangler.jsonc
Example GET handler in Nuxt app (apps/nuxt/server/api/kv-storage/index.get.ts
):
const storage = useStorage<string>(kvStarterStorage)
const storedValue = await storage.get(kvTestKeyName)
await storage.set(kvTestKeyName, 'Woof!')
Example handler in H3 worker (workers/h3-example/src/index.ts
):
app.get('/kv-test', async (event) => {
const storedValue = await event.runtime?.cloudflare?.env.KV.get(kvTestKeyName)
await event.runtime?.cloudflare?.env.KV.put(kvTestKeyName, 'Woof!')
})
The Nuxt project uses nitro-cloudflare-dev
module + nitro.cloudflareDev.environment = 'staging'
so running the standard dev command will emulate the staging binding locally.
You can test KV storage using:
- Demo UI at
/test-page/kv-storage
in the Nuxt app - HTTP request files in
requests/kv-save-data.http
for testing endpoints - Direct API calls to the endpoints mentioned above
The project includes a complete PostgreSQL database setup with Drizzle ORM in the @starter/database
package for type-safe database operations across the monorepo.
- PostgreSQL with Docker - Complete database infrastructure with Docker Compose setup
- Drizzle ORM - Type-safe SQL query builder with excellent TypeScript support
- UUID v7 support - Modern UUID generation with timestamp ordering
- Migration system - Automated database schema versioning and updates
- Multi-environment support - Local development with Docker and production with Neon Database
- WebSocket transactions - Full transactional support via WebSocket connections
The database includes predefined tables for common use cases:
users
- User management with admin roles and timestampsoauthProviders
- Authentication provider integrationoauthAccounts
- Linking user accounts with OAuth providers
- Copy
common/database/.env.example
tocommon/database/.env
- Configure your database connection URL
- Set
LOCAL_DATABASE=1
for local Docker development
The project supports both local and production database environments:
- Local Development: Uses Docker PostgreSQL with Neon HTTP/WebSocket proxies for compatibility
- Production: Connects directly to Neon Database or other PostgreSQL providers
- Environment Variables:
DATABASE_URL
- PostgreSQL connection stringLOCAL_DATABASE
- Set to1
for local Docker developmentSESSION_SECRET
- Secure random string for session cookie signing
- Start the database:
pnpm --filter @starter/database run db:start
- Run migrations:
pnpm --filter @starter/database run db:migrate:local
The local setup includes:
- PostgreSQL 17 with custom
pg_uuidv7
extension for modern UUID generation - Neon HTTP Proxy on port 4444 for HTTP-based database queries (compatible with Neon's serverless driver)
- Neon WebSocket Proxy on port 5433 for transactional operations
- Database accessible at
postgres://user:[email protected]:5432/starter
To generate new migrations based on your schema changes, use:
pnpm --filter @starter/database run db:generate
pnpm --filter @starter/database run db:kit
- Run Drizzle Kit commands directlypnpm --filter @starter/database run db:seed
- Seed database with initial data
The Nuxt application includes demo authentication API endpoints that showcase database integration patterns for user management:
GET /api/auth
- Get current user session informationPOST /api/auth
- Create a new user accountDELETE /api/auth
- Delete current user account
These endpoints serve as examples of how to implement authentication with database operations using Drizzle ORM and can be used as a starting point for building your own authentication system.
Server Utilities:
validateSessionUser()
- Utility function to ensure user is authenticated in API routescreateDatabase()
- Creates Drizzle ORM instance with HTTP drivercreateDatabaseWebsocket()
- Creates Drizzle ORM instance with WebSocket support for transactions
You can test the database functionality using:
- Demo UI at
/test-page/database
in the Nuxt app - Interactive page for creating and deleting user accounts - User Store (Pinia) - State management for user authentication with reactive user data
- Session Management - Automatic authentication state persistence across page refreshes
The Nuxt app includes automatic database integration through middleware:
1.session.ts
- Session management middleware for user authentication2.database.ts
- Database connection middleware that provides Drizzle ORM instance to all API routes
The project includes automated database migrations via GitHub Actions:
- Staging migrations - Automatically run on pull requests when
common/database/migrations/**
files change - Production migrations - Automatically run on master branch pushes when migration files change
- Database seeding - Included in staging environment for testing data setup
Both workflows require DATABASE_URL
secret to be configured in GitHub repository environments.
The project includes a dedicated validation package @starter/validation
built on top of Valibot for type-safe data validation across the monorepo.
- Shared validation schemas - Common validation rules that can be reused across apps and workers
- Safe validation - Validators support both throwing (
safe: false
) and non-throwing (safe: true
) modes
import { nonEmptyStringValidator } from '@starter/validation/validators/strings';
// Throwing mode (default)
const result = nonEmptyStringValidator('hello world'); // string
// Safe mode - returns success/error result
const safeResult = nonEmptyStringValidator('hello world', { safe: true });
if (safeResult.success) {
console.log(safeResult.data); // string
} else {
console.log(safeResult.issues); // validation errors
}
The project includes a centralized logging system in the @starter/utils
package that provides structured logging across all applications and workers. The logger is designed following Cloudflare Workers Logs best practices for optimal observability and performance.
- Structured JSON output - All logs are formatted as JSON objects with consistent schema, enabling better filtering and indexing in Workers Logs
- Cloudflare Workers optimized - Follows best practices for Workers Logs with structured data instead of string concatenation
- Tagging system - Each logger instance is tagged (e.g., 'nuxt', 'h3-example') for easy filtering and segmentation
- Multiple log levels - Support for
info
,warn
, anderror
logging levels - Flexible content - Accepts both string messages and object data for rich logging
- Cross-platform - Works seamlessly in Nuxt server routes and Cloudflare Workers
import { createLogger } from '@starter/utils/logger'
// Create logger instance with tag
const logger = createLogger('my-app')
// Log string messages
logger.info('Server started successfully')
logger.warn('Deprecated API endpoint used')
logger.error('Database connection failed')
// Log structured data
logger.info({ userId: 123, action: 'login', timestamp: Date.now() })
logger.error({ error: 'ValidationError', field: 'email', value: 'invalid' })
The requests/
directory contains HTTP request files for testing API endpoints across different services. These files can be used with VS Code REST Client extension or similar tools for quick API testing during development.
Currently includes:
kv-save-data.http
- KV storage endpoints testing for both Nuxt app and H3 workerdatabase-check.http
- Database endpoints testing for H3 worker (/users-count
)- Database API endpoints can be tested directly via the demo UI at
/test-page/database
The project relies on several environment variables for configuration. You can find the example values in the .env.example
files:
apps/nuxt/.env.example
- Nuxt app configuration including database URL and session secretworkers/h3-example/.env.example
- H3 worker configuration for Cloudflare Workers environmentcommon/database/.env.example
- Database-specific configuration for local development
Required variables:
DATABASE_URL
- PostgreSQL connection stringSESSION_SECRET
- Secure random string for session cookie signing (generate withopenssl rand -hex 32
)LOCAL_DATABASE
- Set to1
for local Docker development (optional, defaults to production mode)
- Bleeding-edge technologies and tools.
- Only evergreen browsers are supported
- No legacy code, no outdated libraries.
- TypeScript - static type checker for JavaScript.
- Nuxt.js - web framework.
- Drizzle ORM - TypeScript ORM for SQL databases.
- PostgreSQL - advanced open source relational database.
- Neon Database - serverless PostgreSQL for modern applications.
- Docker - containerization platform for local database setup.
- H3.js - HTTP framework for building web servers.
- Valibot - schema validation library with great TypeScript support.
- pnpm - package manager.
- taze - package update utility.
- Vue Language Tools - High-performance Vue language tooling based-on Volar.js
- Pinia - state management library for Vue.js.
- @nuxt/icon - icon management for Nuxt.js.
- nitro-cloudflare-dev - local development tool for Cloudflare Workers.
- Monorepo with pnpm workspaces.
.editorconfig
for consistent code style.- Code style instructions in
.github/instructions/
directory for consistent development practices. - Dependabot for automatic dependency updates.
- GitHub Copilot for AI-powered code suggestions.
- Cloudflare Workers for serverless functions.
/
- root directory with global scripts/apps
- frontend applications/apps/nuxt
- Nuxt.js application boilerplate/common
- shared packages/common/database
- PostgreSQL database setup with Drizzle ORM, schemas, migrations and Docker configuration/common/utils
- utility functions and helpers including structured logging system/common/validation
- shared validation schemas and utilities using Valibot/requests
- HTTP request files for testing API endpoints across services/scripts
- utility scripts for development and deployment/workers
- worker applications/workers/h3-example
- H3.js example worker/.github/instructions
- coding style and development instructions
update:all
- check package updates in all workspaces in interactive modeupdate:newest
- check package updates in all workspaces and update to the newest versions interactively
pnpm --filter @starter/<workspace> add <package>
- adds apackage
to the@starter/<workspace>
.