Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
6 changes: 3 additions & 3 deletions .coderabbit.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ reviews:
- "!**/gen/**"
- "!**/*.gen.ts"
- "!**/*.gen.js"
- "!apps/fastify/src/db/migrations/**"
- "!apps/api/src/db/migrations/**"

# Documentation assets
- "!**/*.png"
Expand Down Expand Up @@ -90,7 +90,7 @@ reviews:
- .cursor/rules/frontend/react.mdc
- .cursor/rules/base/typescript.mdc

- path: "apps/next/**"
- path: "apps/web/**"
instructions: |
- Verify Next.js App Router conventions and React Server Components usage
- Follow all coding standards defined in:
Expand All @@ -111,7 +111,7 @@ reviews:
- .cursor/rules/base/docs.mdc
- .cursor/rules/base/typescript.mdc

- path: "apps/fastify/**"
- path: "apps/api/**"
instructions: |
- CRITICAL: never edit db/migrations, openapi schema files directly. All migrations must be created through the typical Drizzle flow and OpenAPI is autogenerated. Always validate no discrepancies.
- Verify Fastify functional patterns and TypeBox schema usage
Expand Down
2 changes: 1 addition & 1 deletion .cursor/rules/backend/fastify.mdc
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
description: Fastify backend development standards and patterns
glob: "apps/fastify/**/*"
glob: "apps/api/**/*"
alwaysApply: true
---

Expand Down
2 changes: 1 addition & 1 deletion .cursor/rules/frontend/auth.mdc
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
description: Next.js auth patterns—single cookie, core client modes, refresh flow
glob: "apps/next/**/*,packages/core/**/*,packages/react/**/*"
glob: "apps/web/**/*,packages/core/**/*,packages/react/**/*"
alwaysApply: false
---

Expand Down
4 changes: 2 additions & 2 deletions .cursor/rules/frontend/e2e-playwright.mdc
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
---
description: Playwright E2E patterns for Next.js and Fastify API
glob: "apps/next/e2e/**/*, apps/next/playwright.config.ts, apps/fastify/test/**/*, apps/fastify/playwright.config.ts"
glob: "apps/web/e2e/**/*, apps/web/playwright.config.ts, apps/api/test/**/*, apps/api/playwright.config.ts"
---

## Config
- Frontend apps (`apps/next`) use **Playwright E2E only** — no Vitest/Testing Library unit or integration tests
- Frontend apps (`apps/web`) use **Playwright E2E only** — no Vitest/Testing Library unit or integration tests
- No webServer; URLs from `PLAYWRIGHT_APP_URL` / `PLAYWRIGHT_API_URL` (env or `--app` / `--api` params)
- Fastify: only `--api` param; `test:e2e` = URL-based, `test:e2e:local` = spawn API, poll, run, cleanup
- Param format: `--app=URL` or `--app URL`, `--api=URL` or `--api URL`
Expand Down
2 changes: 1 addition & 1 deletion .cursor/rules/web3/wagmi.mdc
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
description: Web3 integration patterns using Wagmi v3
glob: "apps/next/**/*.{ts,tsx}"
glob: "apps/web/**/*.{ts,tsx}"
alwaysApply: false
---

Expand Down
14 changes: 7 additions & 7 deletions .github/workflows/api-e2e.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ name: API (E2E)
on:
pull_request:
paths:
- 'apps/fastify/**'
- 'apps/api/**'
- 'packages/email/**'
- 'packages/sentry/**'
- 'packages/utils/**'
Expand Down Expand Up @@ -48,17 +48,17 @@ jobs:
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Build
run: pnpm turbo run build --filter=@repo/fastify...
run: pnpm turbo run build --filter=@repo/api...
- name: Unit tests
run: pnpm turbo run test --filter=@repo/fastify
run: pnpm turbo run test --filter=@repo/api
- name: Install Playwright
run: pnpm --filter @repo/fastify exec playwright install chromium --with-deps
run: pnpm --filter @repo/api exec playwright install chromium --with-deps
- name: E2E tests (local)
run: pnpm --filter @repo/fastify test:e2e:local
run: pnpm --filter @repo/api test:e2e:local
- name: Upload Playwright report
if: always()
uses: actions/upload-artifact@v4
with:
name: playwright-report-fastify
path: apps/fastify/playwright-report/
name: playwright-report-api
path: apps/api/playwright-report/
retention-days: 30
6 changes: 3 additions & 3 deletions .github/workflows/packages-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,8 @@ jobs:
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Generate OpenAPI (for @repo/core)
run: pnpm turbo run generate:openapi --filter=@repo/fastify
run: pnpm turbo run generate:openapi --filter=@repo/api
- name: Build packages
run: pnpm turbo run build --filter='!@repo/next' --filter='!@repo/fastify' --filter='!@repo/docu'
run: pnpm turbo run build --filter='!@repo/web' --filter='!@repo/api' --filter='!@repo/docu'
- name: Unit tests (packages only)
run: pnpm turbo run test --filter='!@repo/next' --filter='!@repo/fastify' --filter='!@repo/docu'
run: pnpm turbo run test --filter='!@repo/web' --filter='!@repo/api' --filter='!@repo/docu'
20 changes: 10 additions & 10 deletions .github/workflows/next-e2e.yml → .github/workflows/web-e2e.yml
Original file line number Diff line number Diff line change
@@ -1,23 +1,23 @@
name: Next (E2E)
name: Web (E2E)

on:
pull_request:
paths:
- 'apps/next/**'
- 'apps/web/**'
- 'scripts/**'
- 'packages/core/**'
- 'packages/react/**'
- 'packages/ui/**'
- 'packages/utils/**'
- 'packages/eslint-config/**'
- 'packages/typescript-config/**'
- 'apps/fastify/openapi/**'
- 'apps/api/openapi/**'
- 'pnpm-lock.yaml'
- 'package.json'
- 'turbo.json'

concurrency:
group: next-e2e-${{ github.ref }}
group: web-e2e-${{ github.ref }}
cancel-in-progress: false

env:
Expand Down Expand Up @@ -52,19 +52,19 @@ jobs:
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Build
run: pnpm turbo run build --filter=@repo/next...
run: pnpm turbo run build --filter=@repo/web...
- name: Unit tests
run: pnpm turbo run test --filter=@repo/next
run: pnpm turbo run test --filter=@repo/web
- name: Install Playwright
run: pnpm --filter @repo/next exec playwright install chromium --with-deps
run: pnpm --filter @repo/web exec playwright install chromium --with-deps
- name: E2E tests (local)
env:
SKIP_BUILD: '1'
run: pnpm --filter @repo/next test:e2e:local
run: pnpm --filter @repo/web test:e2e:local
- name: Upload Playwright report
if: always()
uses: actions/upload-artifact@v4
with:
name: playwright-report-next
path: apps/next/playwright-report/
name: playwright-report-web
path: apps/web/playwright-report/
retention-days: 30
6 changes: 3 additions & 3 deletions .gitleaks.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,12 @@ useDefault = true
[allowlist]
description = "Allowlist for test fixtures and example files"
paths = [
'''apps/next/e2e/wallet-setup/.*\.(ts|js|mjs)$''',
'''apps/web/e2e/wallet-setup/.*\.(ts|js|mjs)$''',
'''\.env-example$''',
'''\.env\.example$''',
'''\.env\.test\.example$''',
'''\.env-sample$''',
'''^apps/next/\.env\.local\.example$''',
'''^apps/web/\.env\.local\.example$''',
'''\.env\.sample$''',
'''\.env\.schema$''',
'''\.env\.test$''',
Expand All @@ -28,7 +28,7 @@ paths = [
'''fixtures/''',
'''examples/''',
'''docs/''',
'''apps/fastify/scripts/generate-openapi\.ts$''',
'''apps/api/scripts/generate-openapi\.ts$''',
'''scripts/run-qa\.mjs$''',
]

Expand Down
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ Fastify • OpenAPI • Next.js • Expo — one stack, multiple platforms.

## Apps

- **[API](apps/fastify/README.md)** — Type-safe REST API built with Fastify & OpenAPI
- **[Web App](apps/next/README.md)** — Next.js app with monorepo integration
- **[API](apps/api/README.md)** — Type-safe REST API built with Fastify & OpenAPI
- **[Web App](apps/web/README.md)** — Next.js app with monorepo integration
- **[Documentation](apps/docu/README.md)** — Fumadocs-based docs site for architecture, ADRs, and development workflows

## Packages
Expand All @@ -55,7 +55,7 @@ Run with `pnpm <script>`.
- `setup:database` — Database tools
**Primary**
- `build` — Build packages and apps
- `dev` — Start dev (core, react, error, utils, fastify, next)
- `dev` — Start dev (core, react, error, utils, api, web)
- `qa` — Full check: install → checktypes → lint → build → test (unit) → test:e2e (Fastify + Next, local spawn)
**Format / Lint**
- `checktypes` — Type-check all packages
Expand All @@ -68,7 +68,7 @@ Run with `pnpm <script>`.
- `test` — Run unit tests (packages + apps)
- `test:e2e` — E2E (Fastify + Next)
**CI**
- Lint and security run on every PR. App E2E (`next-e2e`, `api-e2e`) and package tests (`packages-test`) run only when relevant code changes. See [GitHub Actions](https://basilic-docs.vercel.app/docs/deployment/github-actions).
- Lint and security run on every PR. App E2E (`web-e2e`, `api-e2e`) and package tests (`packages-test`) run only when relevant code changes. See [GitHub Actions](https://basilic-docs.vercel.app/docs/deployment/github-actions).
**Security**
- `security:block-files` — Block sensitive file patterns
- `security:secrets` — Scan staged files for secrets
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
2 changes: 1 addition & 1 deletion apps/fastify/README.md → apps/api/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ Uses `framework: "fastify"` in vercel.json. Vercel auto-detects `server.ts` as t

**OPTIONS Allowlist (CORS preflight):** When Deployment Protection is enabled on preview deployments, add `/` (or `/auth`) to **Project Settings > Deployment Protection > OPTIONS Allowlist**. Otherwise, preflight OPTIONS requests are blocked before reaching Fastify and CORS fails for cross-origin clients.

**CI & Builds** (`api-e2e.yml`): Unit tests and E2E run on PR when `apps/fastify` or its dependencies change. Spawns API locally via `test:e2e:local`; no Vercel deploy required.
**CI & Builds** (`api-e2e.yml`): Unit tests and E2E run on PR when `apps/api` or its dependencies change. Spawns API locally via `test:e2e:local`; no Vercel deploy required.

## Testing

Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
2 changes: 1 addition & 1 deletion apps/fastify/package.json → apps/api/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"type": "module",
"name": "@repo/fastify",
"name": "@repo/api",
"version": "1.0.0",
"description": "This project was bootstrapped with Fastify-CLI.",
"main": "dist/server.js",
Expand Down
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ try {
} else if (isTableExistsError) {
logger.warn(
{ context: 'migrate', err: migrationError },
'Migration failed due to existing tables. Tables appear to match schema. For clean state, run: pnpm --filter @repo/fastify db:reset',
'Migration failed due to existing tables. Tables appear to match schema. For clean state, run: pnpm --filter @repo/api db:reset',
)
// In development/build, allow this to pass if tables exist and match schema
// In production, this should fail to ensure proper migration tracking
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ const fastifyDir = dirname(scriptDir)
const repoRoot = dirname(dirname(fastifyDir))

function loadEnvTest() {
const path = join(repoRoot, 'apps/fastify/.env.test')
const path = join(repoRoot, 'apps/api/.env.test')
if (!existsSync(path)) return {}
const lines = readFileSync(path, 'utf8').split('\n')
const out = {}
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@ import { getTestDatabase, truncateAllTables } from './db.js'

const setupFile = fileURLToPath(import.meta.url)
const setupDir = dirname(setupFile)
// setupDir is apps/fastify/test/utils
// projectRoot is apps/fastify
// setupDir is apps/api/test/utils
// projectRoot is apps/api
const projectRoot = dirname(dirname(setupDir))

// Track if migrations have been run in this worker
Expand Down
4 changes: 2 additions & 2 deletions apps/fastify/test/utils/db.ts → apps/api/test/utils/db.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
* ## Important Notes
*
* - Per-worker pattern: Each Vitest worker gets its own database directory
* - Database directory: `/tmp/basilic-fastify-test-db-{workerId}`
* - Database directory: `/tmp/basilic-api-test-db-{workerId}`
* - Instance created once per worker before tests in that worker execute
* - Instance deleted once per worker after all tests in that worker complete
* - Workers are isolated - no shared state/data across workers
Expand Down Expand Up @@ -52,7 +52,7 @@ export const TEST_DATABASE_URL = 'postgresql://localhost/test'
function getWorkerDbDir(): string {
// Vitest sets VITEST_WORKER_ID for each worker thread
const workerId = process.env.VITEST_WORKER_ID || process.pid.toString()
return join(tmpdir(), `basilic-fastify-test-db-${workerId}`)
return join(tmpdir(), `basilic-api-test-db-${workerId}`)
}

/**
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
6 changes: 3 additions & 3 deletions apps/fastify/vercel.json → apps/api/vercel.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
{
"$schema": "https://openapi.vercel.sh/vercel.json",
"framework": "fastify",
"ignoreCommand": "npx turbo-ignore @repo/fastify --fallback=HEAD^1",
"buildCommand": "cd ../.. && pnpm turbo run build --filter=@repo/fastify...",
"ignoreCommand": "npx turbo-ignore @repo/api --fallback=HEAD^1",
"buildCommand": "cd ../.. && pnpm turbo run build --filter=@repo/api...",
"installCommand": "cd ../.. && pnpm install",
"devCommand": "cd ../.. && pnpm dev --filter=@repo/fastify",
"devCommand": "cd ../.. && pnpm dev --filter=@repo/api",
"git": { "deploymentEnabled": { "main": true, "develop": true } },
"headers": [
{
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
4 changes: 2 additions & 2 deletions apps/docu/content/docs/adrs/005-package-manager.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ Mature, workspace-optimized package manager.
**Pros**

- Correctly hoists and resolves dependencies across workspace packages
- Handles complex scenarios like `@tailwindcss/postcss` in `@repo/ui` being accessible to `apps/next`
- Handles complex scenarios like `@tailwindcss/postcss` in `@repo/ui` being accessible to `apps/web`
- Uses symlinks and proper node_modules structure for workspace packages
- Well-tested with Next.js, Fastify, and Turbo
- Mature support for monorepo patterns
Expand Down Expand Up @@ -79,7 +79,7 @@ We will use **pnpm** as our package manager.

**Main reasons:**

- **Reliable workspace resolution**: Correctly hoists and resolves dependencies across workspace packages, handling complex scenarios like `@tailwindcss/postcss` in `@repo/ui` being accessible to `apps/next`
- **Reliable workspace resolution**: Correctly hoists and resolves dependencies across workspace packages, handling complex scenarios like `@tailwindcss/postcss` in `@repo/ui` being accessible to `apps/web`
- **Monorepo maturity**: Well-tested with Next.js, Fastify, and Turbo with mature support for monorepo patterns
- **Production stability**: Battle-tested in production environments with reliable builds and no module resolution issues
- **Ecosystem support**: Extensive community adoption, documentation, and better tooling support for debugging, monitoring, and CI/CD
Expand Down
4 changes: 2 additions & 2 deletions apps/docu/content/docs/adrs/009-api-architecture.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ We will use **Fastify REST API** with **OpenAPI spec generation from routes** an

### OpenAPI Specification

OpenAPI specs are generated in `apps/fastify/openapi/openapi.json` from Fastify routes via `generate-openapi.ts`:
OpenAPI specs are generated in `apps/api/openapi/openapi.json` from Fastify routes via `generate-openapi.ts`:

```json
{
Expand Down Expand Up @@ -188,7 +188,7 @@ TypeScript clients are generated using `@hey-api/openapi-ts`:

Fastify routes are the source of truth:

- Routes implemented in `apps/fastify/src/routes/` with TypeBox schemas (native JSON Schema)
- Routes implemented in `apps/api/src/routes/` with TypeBox schemas (native JSON Schema)
- OpenAPI spec automatically generated from route definitions via `generate-openapi.ts`
- Type-safe request/response handling via route schemas with TypeBox type provider
- Validation uses TypeBox schemas defined in routes (no conversion overhead)
Expand Down
8 changes: 4 additions & 4 deletions apps/docu/content/docs/architecture/api.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ Data flow: TypeBox (backend) → OpenAPI spec → generated types & Zod schemas

## How it works

1. **Author routes** with TypeBox schemas (in `apps/fastify/src/routes/`; Fastify uses them for validation)
1. **Author routes** with TypeBox schemas (in `apps/api/src/routes/`; Fastify uses them for validation)
2. **Generate OpenAPI** from route definitions
3. **Generate SDKs** from OpenAPI (TypeScript client + Zod schemas + React Query hooks)

Expand Down Expand Up @@ -60,10 +60,10 @@ fastify.get('/health', {

### Generate OpenAPI

The OpenAPI spec is generated from route definitions and written to `apps/fastify/openapi/openapi.json`.
The OpenAPI spec is generated from route definitions and written to `apps/api/openapi/openapi.json`.

```bash
pnpm --filter @repo/fastify generate:openapi
pnpm --filter @repo/api generate:openapi
```

### Generate TypeScript client
Expand Down Expand Up @@ -110,7 +110,7 @@ const { data } = useHealthCheck()

## OpenAPI Integration

- **Generation**: `apps/fastify/openapi/openapi.json` (generated from routes via `generate-openapi.ts`)
- **Generation**: `apps/api/openapi/openapi.json` (generated from routes via `generate-openapi.ts`)
- **Serving**: `/reference/openapi.json` (programmatic access)
- **Docs UI**: `/reference` (Scalar)
- **AI tooling**: MCP integration can consume the spec for agent workflows
Expand Down
Loading
Loading