Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
181 changes: 151 additions & 30 deletions .agents/skills/constructive-starter-kits/references/nextjs-app.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
---
name: constructive-boilerplate-nextjs-app
description: Set up and develop with the Constructive App frontend boilerplate — a Next.js application with authentication, organization management, invites, members, and a GraphQL SDK. Use when scaffolding a new Constructive frontend application from the boilerplate.
description: Set up and develop with the Constructive App frontend boilerplate — a Next.js application with authentication, organization management, invites, members, and a per-DB GraphQL SDK architecture. Use when scaffolding a new Constructive frontend application from the boilerplate.
---

Set up and develop with the Constructive App frontend boilerplate — a Next.js application with authentication, organization management, invites, members, and a GraphQL SDK.
Set up and develop with the Constructive App frontend boilerplate — a Next.js application with authentication, organization management, invites, members, and a per-DB GraphQL SDK architecture.

## When to Apply

Expand All @@ -15,7 +15,7 @@ Use this skill when:

## Overview

The Constructive App boilerplate is a **frontend-only** Next.js application that connects to a Constructive backend. It provides production-ready authentication flows, organization management, invite handling, member management, and account settings — all powered by a generated GraphQL SDK.
The Constructive App boilerplate is a **frontend-only** Next.js application that connects to a Constructive backend using a **per-database architecture**. It provides production-ready authentication flows, organization management, invite handling, member management, and account settings — all powered by three generated GraphQL SDKs (admin, auth, app).

## Setup

Expand Down Expand Up @@ -66,7 +66,7 @@ pgpm init \
--moduleName <module-name>
```

**Required arguments for existing workspace :**
**Required arguments for existing workspace:**

| Argument | Description |
|----------|-------------|
Expand All @@ -76,7 +76,7 @@ This creates the module at `packages/<module-name>/` within your existing worksp

> **Note:** You must run this from the workspace root or a valid `packages/` subdirectory. If you are not inside a pnpm workspace, pgpm will error with "Not inside a PNPM workspace." Use the `-w` flag (see above) to create a new workspace and module together.

> **Interactive mode (for humans):** :
> **Interactive mode (for humans):**
> ```bash
> pgpm init --repo constructive-io/sandbox-templates --template nextjs/constructive-app
> ```
Expand All @@ -90,34 +90,52 @@ pnpm install

### 3. Configure Environment

Create or verify `.env.local`:
Create `.env.local` from `.env.example`:

```bash
# GraphQL endpoint (must point to a running Constructive backend)
NEXT_PUBLIC_SCHEMA_BUILDER_GRAPHQL_ENDPOINT=http://api.localhost:3000/graphql
# Database name — REQUIRED
# This single value derives all GraphQL endpoints:
# admin-{db}.localhost:3000 → organizations, members, permissions
# auth-{db}.localhost:3000 → users, authentication
# app-public-{db}.localhost:3000 → your business data
NEXT_PUBLIC_DB_NAME=your-db-name

# Optional: Override the default API port (default: 3000)
# NEXT_PUBLIC_API_PORT=3000

# Optional: Override individual endpoints (bypasses DB_NAME derivation)
# NEXT_PUBLIC_ADMIN_ENDPOINT=http://admin-mydb.localhost:3000/graphql
# NEXT_PUBLIC_AUTH_ENDPOINT=http://auth-mydb.localhost:3000/graphql
# NEXT_PUBLIC_APP_ENDPOINT=http://app-public-mydb.localhost:3000/graphql
```

### 4. Generate GraphQL SDK

The SDK must be generated against a running backend:
The SDK must be generated against a running backend with your per-DB endpoints:

```bash
pnpm codegen
```

This runs `@constructive-io/graphql-codegen` using `graphql-codegen.config.ts` and outputs the SDK to `src/graphql/schema-builder-sdk/api`.
This runs `@constructive-io/graphql-codegen` using `graphql-codegen.config.ts` and outputs **three SDKs**:

| SDK | Output | Endpoint | Purpose |
|-----|--------|----------|---------|
| `admin` | `src/graphql/sdk/admin/` | `http://admin-{db}.localhost:3000/graphql` | Organizations, members, permissions, invites (44 tables) |
| `auth` | `src/graphql/sdk/auth/` | `http://auth-{db}.localhost:3000/graphql` | Users, emails, authentication (6 tables) |
| `app` | `src/graphql/sdk/app/` | `http://app-public-{db}.localhost:3000/graphql` | Your business data |

### 5. Start Development

```bash
pnpm dev
```

Opens at [http://localhost:3001](http://localhost:3001).
Opens at [http://localhost:3011](http://localhost:3011) by default.

## Backend Requirements

This boilerplate requires a running Constructive backend. The easiest way is via **Constructive Hub**:
This boilerplate requires a running Constructive backend with per-DB endpoints. The easiest way is via **Constructive Hub**:

```bash
# Terminal 1: Start backend infrastructure
Expand All @@ -134,7 +152,7 @@ Required backend services:
| Service | Port | Purpose |
|---------|------|---------|
| PostgreSQL | 5432 | Database with Constructive schema |
| GraphQL Server (Public) | 3000 | API endpoint for app operations |
| GraphQL Server | 3000 | Per-DB endpoints (admin-*, auth-*, app-public-*) |
| GraphQL Server (Private) | 3002 | Admin operations |
| Job Service | 8080 | Background job processing |
| Email Function | 8082 | Email sending via SMTP |
Expand All @@ -157,8 +175,10 @@ src/
│ ├── invite/ # Accept invite flow
│ ├── invites/ # Pending invites list
│ ├── account/ # Account management
│ │ └── settings/ # Account settings + theme
│ ├── settings/ # App settings
│ ├── users/ # User management
│ ├── organizations/ # Organization listing page
│ └── orgs/
│ └── [orgId]/ # Org-scoped pages
│ ├── layout.tsx # Org layout with sidebar
Expand All @@ -167,7 +187,24 @@ src/
│ ├── members/ # Org members management
│ └── settings/ # Org settings
├── components/
│ ├── ui/ # shadcn/ui components (43 components)
│ ├── ui/ # UI components (26 files)
│ │ ├── stack/ # Stack card system (slide-in panels)
│ │ │ ├── stack-card.tsx
│ │ │ ├── stack-context.tsx
│ │ │ ├── stack-viewport.tsx
│ │ │ └── ...
│ │ ├── toast/ # Toast notifications
│ │ │ ├── toast-error.tsx
│ │ │ ├── toast-success.tsx
│ │ │ └── ...
│ │ ├── alert-dialog.tsx
│ │ ├── button.tsx
│ │ ├── card.tsx
│ │ ├── dropdown-menu.tsx
│ │ ├── input.tsx
│ │ ├── select.tsx
│ │ ├── table.tsx
│ │ └── ...
│ ├── auth/ # Auth forms (login, register, reset, etc.)
│ ├── organizations/ # Org CRUD components
│ ├── invites/ # Invite management components
Expand All @@ -179,38 +216,119 @@ src/
│ ├── shared/ # Shared/reusable components
│ └── skeletons/ # Loading skeleton components
├── config/
│ └── branding.ts # App name, logos, legal links
│ └── branding.ts # App name, logos, tagline, legal links
├── graphql/
│ ├── execute.ts # GraphQL execution layer
│ ├── index.ts # GraphQL exports
│ ├── typed-document.ts # Typed document utilities
│ └── schema-builder-sdk/ # Generated SDK (via codegen)
│ └── sdk/ # Generated SDKs (via codegen)
│ ├── admin/ # Admin SDK (orgs, members, permissions)
│ │ ├── hooks/ # React Query hooks
│ │ ├── orm/ # ORM client
│ │ └── README.md
│ ├── auth/ # Auth SDK (users, emails)
│ │ ├── hooks/
│ │ ├── orm/
│ │ └── README.md
│ ├── app/ # App SDK (your business tables)
│ │ ├── hooks/
│ │ ├── orm/
│ │ └── README.md
│ └── README.md
├── hooks/ # Shared React hooks
│ ├── use-character-limit.ts
│ ├── use-debounce.ts
│ ├── use-deferred-mutation.ts
│ ├── use-edit-value.ts
│ ├── use-file-upload.ts
│ ├── use-health-check.ts
│ ├── use-image-status.ts
│ ├── use-in-view.ts
│ ├── use-json-view-scroll.ts
│ ├── use-measure.ts
│ ├── use-mobile.ts
│ ├── use-mounted.ts
│ └── use-scroll-direction.ts
├── lib/
│ ├── auth/ # Auth utilities and context
│ │ ├── auth-context.tsx
│ │ ├── auth-errors.ts
│ │ ├── route-guards.tsx
│ │ ├── token-manager.ts
│ │ └── ...
│ ├── gql/ # GraphQL hooks and query factories
│ │ ├── hooks/
│ │ │ ├── admin/ # Admin hooks (orgs, invites, members)
│ │ │ └── auth/ # Auth hooks (login, register, etc.)
│ │ ├── error-handler.ts
│ │ └── query-error-boundary.tsx
│ ├── navigation/ # Route and navigation helpers
│ │ ├── sidebar-config.ts
│ │ ├── use-entity-params.ts
│ │ └── use-sidebar-navigation.ts
│ ├── permissions/ # Permission checking utilities
│ ├── constants/ # App constants
│ ├── logger/ # Logging utilities
│ ├── runtime/ # Runtime helpers
│ ├── runtime/ # Runtime configuration
│ │ ├── config-core.ts
│ │ ├── env-sync.ts
│ │ ├── get-runtime-config.ts
│ │ └── runtime-config.types.ts
│ ├── motion/ # Animation configuration
│ ├── utils/ # General utilities
│ └── validation/ # Zod schemas and validation
├── store/ # Client state management
│ ├── validation/ # Zod schemas and validation
│ ├── query-client.ts # React Query client
│ ├── schema-context.tsx # Schema context provider
│ └── slot.tsx # Slot utility
├── store/ # Client state management (Zustand)
│ ├── app-store.ts # Main app store
│ ├── auth-slice.ts # Auth state slice
│ ├── env-slice.ts # Environment state slice
│ └── preferences-slice.ts # User preferences slice
├── app-config.ts # App-wide configuration
└── app-routes.ts # Route definitions
```

## SDK Imports

The template provides path aliases for the three SDKs:

```typescript
// Your business data
import { useBoardsQuery, useCreateBoardMutation } from '@sdk/app';

// Users and authentication
import { useCurrentUserQuery, useSignInMutation } from '@sdk/auth';

// Organizations, members, permissions
import { useOrganizationsQuery, useOrgMembersQuery } from '@sdk/admin';
```

## Customization

### Branding

Edit `src/config/branding.ts` to customize:
- App name and tagline
- Logo and wordmark paths (relative to `/public`)
- Company name for legal footer
- Legal links (disclaimer, privacy policy, etc.)
- Home path for logo links

```typescript
export const branding: BrandingConfig = {
name: 'airpage', // App name
tagline: 'powered by Constructive', // Tagline below brand name

logo: '/logo.svg', // Logo mark (collapsed sidebar, auth)
wordmark: '/wordmark.svg', // Full wordmark (expanded sidebar)
logoDark: null, // Dark mode logo override
wordmarkDark: null, // Dark mode wordmark override

companyName: 'Constructive', // Legal footer company name
legalLinks: [ // Auth footer links
{ label: 'Disclaimer', href: '...' },
{ label: 'Privacy Policy', href: '...' },
],

homePath: '/', // Logo link destination
};
```

### Adding UI Components

Expand All @@ -222,15 +340,15 @@ npx shadcn@latest add @constructive/<component>

Registry URL is configured in `components.json`. Components use Base UI primitives, Tailwind CSS 4, and cva for variants.

### GraphQL SDK
### GraphQL SDK Regeneration

The SDK is generated from the running backend schema. After backend schema changes:
After backend schema changes, regenerate the SDKs:

```bash
pnpm codegen
```

Config in `graphql-codegen.config.ts` points to `http://api.localhost:3000/graphql` by default.
Config in `graphql-codegen.config.ts` derives endpoints from `NEXT_PUBLIC_DB_NAME`.

## Features

Expand All @@ -240,11 +358,14 @@ Config in `graphql-codegen.config.ts` points to `http://api.localhost:3000/graph
- **Members** — Manage organization members and roles
- **Account Management** — Profile, email verification, account deletion
- **App Shell** — Sidebar navigation, theme switching, responsive layout
- **Stack Cards** — Slide-in panel system for create/edit flows
- **Permissions** — Role-based access control for org features
- **State Management** — Zustand store with auth, env, and preferences slices

## Troubleshooting

- **GraphQL errors on startup**: Ensure the Constructive backend is running and the endpoint in `.env.local` is correct
- **Empty SDK directory**: Run `pnpm codegen` with the backend running to generate the SDK
- **GraphQL errors on startup**: Ensure the Constructive backend is running and `NEXT_PUBLIC_DB_NAME` in `.env.local` is correct
- **Empty SDK directory**: Run `pnpm codegen` with the backend running to generate the SDKs
- **Password reset emails not arriving**: Requires the full backend stack (job service + email function). Check Mailpit UI at `http://localhost:8025`
- **Port conflicts**: The frontend runs on port 3001 by default. The backend GraphQL server uses port 3000
- **Port conflicts**: The frontend runs on port 3011 by default. The backend GraphQL server uses port 3000
- **SDK import errors**: Ensure path aliases (`@sdk/admin`, `@sdk/auth`, `@sdk/app`) are configured in `tsconfig.json`