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
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .mise.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,9 @@ ga = "git add ."
gb = "git branch"
gco = "git checkout"
gs = "git status"
gc = "git commit -m"
gc = "git commit"
gp = "git push"
gpl = "git pull"
gr = "git rebase --merge"

[tasks.init]
Expand Down
61 changes: 35 additions & 26 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -1,18 +1,20 @@
# Agents.md

## 1. Project Overview
cur8d is a production-ready Next.js starter optimized for data integration and scalability.
cur8d is a production-ready Next.js starter optimized for performance, accessibility, and type safety.

## 2. Tech Stack
- Next.js 16.2.6: App Router, Server Components.
- HeroUI v3.0.5: Compound components with dot notation.
- Tailwind CSS v4: CSS-first configuration.
- Vitest 4.1.6 & Playwright 1.59.1: Testing.
- Supabase & Vercel Blob: Data and storage stubs.
- Next.js 16 (App Router, Turbopack, Server Components, React 19).
- HeroUI v3: Accessible compound components with dot notation.
- Tailwind CSS v4: CSS-first configuration and theme variables.
- Vitest & Playwright: Unit, E2E, and accessibility (`@axe-core/playwright`) testing.
- Vercel Blob & Observability: Storage stub and centralized error reporting.

## 3. Directory Structure
- `app`: Routes, layouts, components, hooks, and logic/data layer.
- `docs`: Nextra v4 documentation.
- `app`: Routes, layouts, components, hooks, and logic layer (`app/lib`).
- `docs`: Nextra v4 documentation site.
- `scripts`: Template initialization and utility scripts (`scripts/init.ts`).
- `tests`: Test suites (`tests/unit/` for Vitest, `tests/e2e/` for Playwright).

## 4. Toolchain Management
Managed via `mise`. Update `.mise.toml` to change Node.js or pnpm versions.
Expand All @@ -23,43 +25,50 @@ Managed via `mise`. Update `.mise.toml` to change Node.js or pnpm versions.
- Explicit interfaces for all component props.

## 6. Coding Conventions
- Named imports for icons.
- Barrel exports (`index.ts`) in component folders.
- Server Components by default.
- Named imports for icons (`lucide-react`, `@icons-pack/react-simple-icons`).
- Component folders in `app/components/ComponentName/index.tsx`.
- Server Components by default; `"use client"` for interactive leaf components.

## 7. How to add a new page
Add directory to `app/` with `page.tsx`.

## 8. How to add a new component
Create folder in `app/components/` with `index.tsx`, types, and tests.
Create folder in `app/components/ComponentName/` with `index.tsx`, explicit prop interface, and unit test in `tests/unit/components/ComponentName/index.test.tsx`.

## 9. How to add a keyboard shortcut
Register in `app/config/shortcuts.ts`, use `useShortcuts` hook, add UI hint.
## 9. State Management & Hooks
Custom hooks in `app/hooks/` (e.g., `useSearchState` via `SearchProvider` context).

## 10. Testing Guide
- Unit: `pnpm test`
- E2E: `pnpm test:e2e`
- 80% coverage required.
- Complete Verification: `mise run verify` (alias: `v`)
- Unit: `mise run test` (alias: `t` or `pnpm test`)
- Coverage: `mise run test:coverage` (80% coverage required)
- E2E: `mise run test:e2e`
- Install Playwright Browsers: `mise run playwright:install`

## 11. Environment Variables
Validated via Zod in `app/lib/env.ts`.

## 12. Local Development Commands
- `pnpm dev`: Start dev server.
- `pnpm build`: Production build.
- `pnpm lint`: Run linting.
- `mise run dev` (alias: `d` or `pnpm dev`): Start Turbopack dev server.
- `mise run build` (alias: `b` or `pnpm build`): Production build.
- `mise run lint` (alias: `l` or `pnpm lint`): Run linting.
- `mise run docs:dev`: Start documentation server.
- `mise run docs:build`: Build static documentation.

## 13. Deployment
Vercel for SSR, GitHub Pages for static export.
- Vercel: Primary target for SSR site (`mise run deploy:vercel` / `deploy.yml`).
- Firebase Hosting: Alternative target for site and docs (`mise run deploy:firebase`).
- GitHub Pages: Static documentation hosting (`docs.yml`).

## 14. HeroUI v3 usage
Use compound component pattern (e.g., `<Table.Header>`).
Use compound component pattern (e.g., `<Card.Header>`, `<Tooltip.Trigger>`).

## 15. Dark mode
Wiring via `next-themes` and Tailwind v4 variables.
Wiring via `next-themes` (`Providers` component) and Tailwind v4 CSS variables.

## 16. Icon usage
`lucide-react` named imports with Tailwind `size-*` utilities.
Named imports with Tailwind `size-*` or `h-* w-*` utilities.

## 17. Logic & Data layer
Logic, Zod schemas, structured metadata (`json-ld.ts`), and centralized error reporting (`error-reporting.ts`) in `app/lib/`.

## 17. Data layer
Mock data in `app/lib/data/mock.ts`, migration path to Supabase documented in `app/lib/data/README.md`.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ This project is organized as a monorepo workspace managed by `pnpm`:
```text
├── app/ # Main Next.js App Router application
│ ├── components/ # Reusable React components (with barrel exports)
│ ├── hooks/ # Custom React hooks (e.g., keyboard shortcuts)
│ ├── lib/ # Logic layer, Zod environment schema, SEO JSON-LD helpers
│ ├── hooks/ # Custom React hooks (e.g., search state)
│ ├── lib/ # Logic layer, Zod environment schema, SEO JSON-LD helpers, error reporting
│ ├── layout.tsx # Root layout with providers configured
│ └── globals.css # Tailwind CSS v4 directives and variables
├── docs/ # Nextra v4 documentation site (pnpm workspace package)
Expand Down
8 changes: 8 additions & 0 deletions docs/app/[[...mdxPath]]/globals.css
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,14 @@
}

@layer base {
:root,
:host {
--x-font-sans: var(--font-geist-sans);
--x-font-mono: var(--font-geist-mono);
--x-default-font-family: var(--font-geist-sans);
--x-default-mono-font-family: var(--font-geist-mono);
}

:root {
--background: 0 0% 100%;
--foreground: 240 10% 3.9%;
Expand Down
20 changes: 16 additions & 4 deletions docs/app/[[...mdxPath]]/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { Geist, Geist_Mono } from 'next/font/google'
import 'nextra-theme-docs/style.css'
import './globals.css'
import { ReactNode } from 'react'
import Link from 'next/link'

const geistSans = Geist({
variable: '--font-geist-sans',
Expand Down Expand Up @@ -34,12 +35,23 @@ export default async function RootLayout({ children }: { children: ReactNode })
/>
<meta name="referrer" content="strict-origin-when-cross-origin" />
</Head>
<body className="font-sans antialiased">
<body className={`${geistSans.variable} ${geistMono.variable} font-sans antialiased`}>
<Layout
navbar={<Navbar logo={
navbar={<Navbar logoLink={false} logo={
<div className="flex items-center gap-2">
<span className="font-bold text-xl tracking-tight">Cur8d</span>
<span className="text-muted-foreground text-sm font-medium uppercase tracking-wider">Docs</span>
<Link
href="https://tsx.cur8d.dev"
className="font-bold text-xl tracking-tight hover:opacity-75 transition-opacity"
>
cur8d
</Link>
<span className="text-muted-foreground select-none">/</span>
<Link
href="/"
className="text-muted-foreground hover:text-foreground text-sm font-medium tracking-wider transition-colors"
>
docs
</Link>
</div>
} />}
footer={<Footer>
Expand Down
7 changes: 4 additions & 3 deletions docs/content/adr/_meta.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ export default {
"adr-003-vitest": "ADR 003: Vitest",
"adr-004-playwright": "ADR 004: Playwright",
"adr-005-mise": "ADR 005: Mise",
"adr-006-tailwind-v4": "ADR 006: Tailwind v4",
"adr-007-data-layer": "ADR 007: Data Layer",
"adr-008-vercel": "ADR 008: Vercel"
"adr-006-tailwind-v4": "ADR 006: Tailwind CSS v4",
"adr-007-data-layer": "ADR 007: Logic & Data Layer",
"adr-008-vercel": "ADR 008: Deployment Architecture"
}

9 changes: 5 additions & 4 deletions docs/content/adr/adr-001-nextjs-16.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@
Status: Accepted

## Context
We need a modern, performant, and developer-friendly framework for the cur8d template.
We need a modern, performant, and developer-friendly React framework for the cur8d starter template.

## Decision
We chose Next.js 16.2.6 (App Router).
We chose Next.js 16 (App Router) with Turbopack and React 19.

## Rationale
Next.js provides excellent support for Server Components, SSR, and built-in optimization. Version 16 brings latest performance improvements and React 19 support.
Next.js provides first-class support for React Server Components, Streaming SSR, and built-in optimization. Version 16 brings cutting-edge performance improvements, Turbopack dev acceleration, and seamless React 19 integration.

## Consequences
All development must follow App Router conventions. Leaf nodes needing interactivity should use `"use client"`.
All page routing and layouts follow App Router conventions. Server Components are used by default, and client-side interactivity is isolated in `"use client"` leaf components.

9 changes: 5 additions & 4 deletions docs/content/adr/adr-002-heroui-v3.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@
Status: Accepted

## Context
We need a robust, accessible, and themeable UI component library.
We need a robust, accessible, and themeable UI component library that integrates cleanly with Tailwind CSS.

## Decision
We chose HeroUI v3.0.5.
We chose HeroUI v3.

## Rationale
HeroUI v3 offers a wide range of compound components with dot notation, built-in accessibility, and seamless integration with Tailwind CSS.
HeroUI v3 offers accessible compound components with dot notation, built-in ARIA support, keyboard navigation, and seamless styling compatibility with Tailwind CSS.

## Consequences
Component usage must strictly follow v3 APIs (e.g., `<Table.Header>` instead of legacy v2 structures).
Component usage follows v3 compound component APIs (e.g., `<Card.Header>`, `<Tooltip.Trigger>` instead of legacy monolithic component wrappers).

9 changes: 5 additions & 4 deletions docs/content/adr/adr-003-vitest.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@
Status: Accepted

## Context
We need a fast and modern unit testing framework compatible with Vite-based tooling.
We need a fast, modern, and ESM-native unit testing framework with built-in code coverage support.

## Decision
We chose Vitest 4.1.6.
We chose Vitest.

## Rationale
Vitest is significantly faster than Jest, provides out-of-the-box ESM support, and shares configuration with Vite, simplifying the build pipeline.
Vitest provides native ESM execution, blazing fast test performance with worker threads, seamless Vite plugin integration, and zero-configuration TypeScript support.

## Consequences
Tests are colocated with source files in `__tests__` directories.
Unit and component tests are organized within the top-level `tests/unit/` directory mirroring the application structure. Code coverage is measured using `@vitest/coverage-v8` with an 80% coverage threshold enforced across CI.

9 changes: 5 additions & 4 deletions docs/content/adr/adr-004-playwright.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@
Status: Accepted

## Context
We need a reliable, cross-browser end-to-end testing framework.
We need a reliable, cross-browser end-to-end testing and automated accessibility auditing framework.

## Decision
We chose Playwright 1.59.1.
We chose Playwright.

## Rationale
Playwright offers superior multi-tab/context support, faster execution, and built-in accessibility testing via `@axe-core/playwright`.
Playwright offers multi-browser testing across Chromium, Firefox, and WebKit, isolated browser contexts, parallel execution, and built-in accessibility testing via `@axe-core/playwright`.

## Consequences
E2E tests live in the `tests/e2e/` directory.
E2E and accessibility test suites live in `tests/e2e/`. Playwright browsers are installed via `mise run playwright:install`.

11 changes: 6 additions & 5 deletions docs/content/adr/adr-006-tailwind-v4.mdx
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
# ADR-006: Tailwind v4 CSS-First
# ADR-006: Tailwind CSS v4 CSS-First
Status: Accepted

## Context
We need a powerful and flexible styling solution.
We need a performant, maintainable, and modern styling solution.

## Decision
We chose Tailwind CSS v4.0.0.
We chose Tailwind CSS v4.

## Rationale
Tailwind v4 adopts a CSS-first approach, moving configuration to `@theme` blocks in standard CSS files. This simplifies the toolchain and improves performance.
Tailwind v4 adopts a modern CSS-first configuration model, removing the JavaScript config file in favor of `@theme` directives in standard CSS. This speeds up build times, simplifies dark mode variables, and eliminates build-time plugin overhead.

## Consequences
There is no `tailwind.config.ts`. All customizations live in `app/globals.css`.
There is no `tailwind.config.ts`. All design system customizations and CSS variable bindings are defined in `app/globals.css`.

11 changes: 6 additions & 5 deletions docs/content/adr/adr-007-data-layer.mdx
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
# ADR-007: Data Layer Strategy
# ADR-007: Logic & Data Layer Strategy
Status: Accepted

## Context
The application needs a consistent way to handle data fetching and mutation.
The application requires a decoupled, testable, and robust architecture for logic, environment validation, error reporting, and data handling.

## Decision
We utilize a service-based architecture in `app/lib/data/` for data access.
We centralize business logic, environment validation, and third-party service abstractions in `app/lib/`.

## Rationale
Decoupling data access from UI components improves testability and makes it easier to switch between mock data and real backend services like Supabase.
Decoupling logic, observability, and data access from React UI components maximizes testability, isolates runtime side-effects, and allows seamless evolution from mock data to production storage providers (such as Vercel Blob).

## Consequences
Direct database or API calls should not be made from React components. Always use the provided data services.
Components focus purely on rendering and user interaction. All environment parsing (`env.ts`), structured metadata serialization (`json-ld.ts`), and error telemetry (`error-reporting.ts`) are imported from `@/lib/`.

11 changes: 6 additions & 5 deletions docs/content/adr/adr-008-vercel.mdx
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
# ADR-008: Vercel over Firebase Hosting
# ADR-008: Deployment Architecture
Status: Accepted

## Context
We need a hosting provider that fully supports Next.js features.
We need a scalable, automated hosting architecture supporting both Server-Side Rendered (SSR) web applications and static documentation.

## Decision
We chose Vercel.
We chose Vercel as the primary SSR deployment platform, Firebase Hosting as an alternative multi-target host, and GitHub Pages for static documentation.

## Rationale
Vercel is the creator of Next.js and provides the best support for App Router, ISR, and Middleware. Firebase Hosting currently lacks full SSR support for Next.js 16.
Vercel delivers native zero-configuration optimization for Next.js App Router, React Server Components, and Edge Middleware. GitHub Pages provides free, high-availability hosting for Nextra static docs, and Firebase Hosting serves as a battle-tested static and preview environment.

## Consequences
GitHub repository should be connected directly to Vercel for production deployments.
Workflows in `.github/workflows/` are partitioned into `deploy.yml` (application deployment to Vercel/Firebase) and `docs.yml` (documentation deployment to GitHub Pages).

7 changes: 4 additions & 3 deletions docs/content/adr/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ Documentation of key architectural decisions made in the project.
- [ADR 003: Vitest](/adr/adr-003-vitest)
- [ADR 004: Playwright](/adr/adr-004-playwright)
- [ADR 005: Mise](/adr/adr-005-mise)
- [ADR 006: Tailwind v4](/adr/adr-006-tailwind-v4)
- [ADR 007: Data Layer Strategy](/adr/adr-007-data-layer)
- [ADR 008: Vercel](/adr/adr-008-vercel)
- [ADR 006: Tailwind CSS v4](/adr/adr-006-tailwind-v4)
- [ADR 007: Logic & Data Layer Strategy](/adr/adr-007-data-layer)
- [ADR 008: Deployment Architecture](/adr/adr-008-vercel)

1 change: 1 addition & 0 deletions docs/content/deployment/_meta.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
export default {
"index": "Overview",
"vercel": "Vercel",
"firebase": "Firebase Hosting",
"github-pages": "GitHub Pages"
}
34 changes: 34 additions & 0 deletions docs/content/deployment/firebase.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# Firebase Hosting Deployment

Cur8d includes configuration for deploying both the main application (`site`) and the documentation (`docs`) to Firebase Hosting.

## Configuration

Firebase project mapping and hosting rules are defined in:
- [`.firebaserc`](file:///Users/amrabed/Library/CloudStorage/OneDrive-Personal/code/cur8d.tsx/.firebaserc): Maps project aliases to Firebase project IDs.
- [`firebase.json`](file:///Users/amrabed/Library/CloudStorage/OneDrive-Personal/code/cur8d.tsx/firebase.json): Configures hosting targets (`site` and `docs`), clean URLs, custom HTTP security headers (CSP, HSTS, X-Frame-Options), and cache settings.

## Automated CI/CD Deployment

Firebase deployment is configured in `.github/workflows/deploy.yml`:

- Can be triggered manually via `workflow_dispatch` selecting the `firebase` provider.
- Deploys preview channels or live production channels based on the specified environment.

### Setting up Secrets in GitHub

1. Obtain a Firebase CI token via `firebase login:ci`.
2. Add `FIREBASE_TOKEN` as a repository secret (`Settings > Secrets and variables > Actions`).

## Local Deployment via mise

```bash
# Deploy main site to Firebase
export FIREBASE_TOKEN="your_token"
export FIREBASE_ENV="production" # or preview
mise run deploy:firebase

# Or using package.json scripts directly
pnpm run deploy:firebase
pnpm run deploy:firebase:docs
```
Loading