Guidance for working with an Nx monorepo containing a Next.js 15 frontend (Vercel) and Hono.js backend (Cloudflare Workers) with D1 database
This skill provides guidance for working with an Nx monorepo that combines a Next.js 15 frontend (deployed to Vercel) with a Hono.js backend (deployed to Cloudflare Workers) using Cloudflare D1 (SQLite) database.
The monorepo uses pnpm and Nx with three main packages:
When working with this codebase, follow these procedures:
**Starting development servers:**
**Building:**
**Testing and linting:**
**Initial setup:**
1. Create D1 database: `pnpm db:create` (outputs database_id for wrangler.toml)
2. Configure binding in `wrangler.toml`:
```toml
[[d1_databases]]
binding = "DB"
database_name = "backend-db"
database_id = "your-database-id-from-create-command"
```
**Schema changes workflow:**
1. Update `apps/backend/src/db/schema.ts` (Drizzle schema - source of truth)
2. Generate SQL migrations: `pnpm db:generate`
3. Review generated migration in `apps/backend/drizzle/migrations/`
4. Apply to local database: `pnpm db:migrate:local`
5. Update shared types in `packages/shared-types/src/index.ts` if needed
6. Update route validators if schema changes affect validation
7. For production: `pnpm db:migrate` after deployment
**Important:** Drizzle Kit automatically generates SQL migrations from TypeScript schema changes. Never manually edit the schema directly in migration files.
Follow this pattern (reference `apps/backend/src/routes/fruits.ts`):
1. Create Zod schemas inline in route file using `z` from `@hono/zod-openapi`
2. Define routes using `createRoute()` with OpenAPI metadata
3. Implement route handlers using `app.openapi(route, handler)`
4. Create route file in `apps/backend/src/routes/` and export the app
5. Register routes in `apps/backend/src/index.ts` using `app.route('/', yourRoutes)`
6. Define shared types in `packages/shared-types/src/index.ts`
7. Add corresponding methods to `ApiClient` class in `apps/frontend/src/lib/api-client.ts`
**OpenAPIHono route pattern:**
```typescript
import { z } from '@hono/zod-openapi';
import { createRoute } from '@hono/zod-openapi';
// Define schemas
const RequestSchema = z.object({ name: z.string() });
const ResponseSchema = z.object({ id: z.string(), name: z.string() });
// Create route
const createItemRoute = createRoute({
method: 'post',
path: '/api/items',
request: { body: { content: { 'application/json': { schema: RequestSchema } } } },
responses: { 200: { content: { 'application/json': { schema: ResponseSchema } } } }
});
// Implement handler
app.openapi(createItemRoute, async (c) => {
const logger = createLogger(c);
const dbLogger = createDbLogger(logger);
// Implementation
});
```
**Using the logger:**
```typescript
import { createLogger } from '../middleware/logging';
import { createDbLogger } from '../utils/db-logger';
app.openapi(yourRoute, async (c) => {
const logger = createLogger(c);
const dbLogger = createDbLogger(logger);
// Log info
logger.info('Processing request', { customData: 'value' });
// Log database queries with performance tracking
const results = await dbLogger.logQuery('SELECT', 'tableName', async () =>
db.select().from(table)
);
// Log errors with stack traces
try {
// code
} catch (error) {
logger.error('Operation failed', error, { context: 'info' });
throw error;
}
});
```
**Log levels:** DEBUG, INFO, WARN, ERROR
**Best practices:**
**Viewing logs:**
**Frontend (.env.local):**
**Backend (wrangler.toml):**
**Backend (.dev.vars):**
Backend runs on http://localhost:8787 with these endpoints:
**Documentation:**
**Health:**
**Frontend (Vercel):**
**Backend (Cloudflare):**
Leave a review
No reviews yet. Be the first to review this skill!
# Download SKILL.md from killerskills.ai/api/skills/nextjs-honojs-monorepo-guide/raw