Architecture
Frequency is built as a multi-repo ecosystem with shared packages, consistent patterns, and clear boundaries between infrastructure and application code.
Repositories
frequency-sites
Monorepo for all documentation and branding sites. Shared packages for auth, database, and data models. Where this standards site lives.
frequency-platform
The main product application. Full-stack Next.js with feature modules, API routes, and the complete Supabase integration.
npm packages
@frequencyads/brand (theme, typography, colors) and @frequencyads/components (Hero, AudioPlayer, CodeBlock, etc.) are published to npm and shared across all repos.
.ai-drivers
AI agent orchestration system. 9 specialist agents, quality gates, and slash commands. Linked into repos as a git submodule. See AI Development.
Monorepo Structure (frequency-sites)
frequency-sites/
├── apps/
│ ├── public/ # No auth required
│ │ ├── brand/ # Brand guidelines & component showcase
│ │ ├── template-public/ # Public documentation template
│ │ └── landing/ # Landing page
│ └── private/ # Auth required (Supabase OAuth)
│ ├── template-private/ # Private documentation template
│ └── standards/ # This site — engineering standards
├── packages/
│ ├── auth/ # Supabase auth middleware & components
│ ├── db/ # Database client & utilities
│ └── models/ # Data models (LinkML → TypeScript)
├── .ai-drivers/ # AI agent orchestration (submodule)
├── supabase/ # Local Supabase config & migrations
├── turbo.json # Turborepo task orchestration
└── pnpm-workspace.yaml # Workspace package definitionsShared Packages
@frequencyads/auth
Authentication and route protection using Supabase SSR.
| Export | Purpose |
|---|---|
./client | Browser Supabase client |
./server | Server Supabase client (SSR, cookie-based sessions) |
./middleware | Auth middleware (protects routes, redirects to login) |
./components/login | Login page with Google OAuth |
./components/auth-provider | <AuthProvider> context + useAuth() hook |
./callback | OAuth callback handler (GET /auth/callback) |
Usage in private apps:
// middleware.ts — protect all routes
export { middleware } from '@frequencyads/auth/middleware';
// providers.tsx — wrap app in auth context
import { AuthProvider } from '@frequencyads/auth/components/auth-provider';
// components — access user session
const { user, supabase, loading } = useAuth();@frequencyads/models
Data models defined in LinkML (YAML), with generated TypeScript types and SQL migrations.
| Export | Purpose |
|---|---|
./schemas/* | Raw LinkML YAML schema files |
./generated/* | Auto-generated TypeScript interfaces |
See Data & Schemas for the full pipeline.
@frequencyads/db
Database client factory and multi-tenancy utilities.
| Export | Purpose |
|---|---|
./client | createBrowserClient() / createServerClient() |
./prefix | prefixTable() for multi-tenancy |
./types | Database TypeScript types |
App Architecture Pattern
Every app in the monorepo follows the same structure:
app/
├── content/ # MDX content pages (Nextra)
│ ├── _meta.ts # Navigation structure
│ └── *.mdx # Content pages
├── src/app/ # Next.js App Router
│ ├── layout.tsx # Root layout (fonts, providers, Nextra)
│ ├── page.tsx # Homepage
│ ├── providers.tsx # Client-side providers (Mantine, Auth)
│ ├── navbar.tsx # Custom navigation bar
│ ├── globals.css # Global styles
│ ├── auth/callback/route.ts # OAuth callback (private apps only)
│ ├── login/page.tsx # Login page (private apps only)
│ └── docs/[[...mdxPath]]/ # Nextra dynamic routing
│ └── page.tsx
├── mdx-components.tsx # MDX component registration
├── middleware.ts # Auth middleware (private apps only)
├── next.config.mjs # Next.js + Nextra config
└── package.jsonRoot Layout Pattern
All apps share a consistent layout structure:
// Server component — layout.tsx
export default async function RootLayout({ children }) {
const pageMap = await getPageMap();
return (
<html lang="en" dir="ltr" suppressHydrationWarning>
<head>
<ColorSchemeScript />
<link rel="stylesheet" href={googleFontsUrl} />
</head>
<body>
<Providers>
<Layout navbar={<CustomNavbar />} footer={<Footer>...</Footer>}
pageMap={pageMap}>
{/* Private apps wrap children in <RequireAuth> */}
{children}
</Layout>
</Providers>
</body>
</html>
);
}Provider Stack
// Client component — providers.tsx
'use client';
export function Providers({ children }) {
return (
<MantineProvider theme={frequencyTheme}>
<AuthProvider>{children}</AuthProvider> {/* Private apps only */}
</MantineProvider>
);
}Feature Module Pattern
For larger applications (like frequency-platform), features are organized as self-contained modules:
// src/features/invoices/index.ts — the public API
export { InvoiceList } from './components/InvoiceList';
export { InvoiceDetail } from './components/InvoiceDetail';
export { useInvoices, useInvoice } from './hooks/useInvoices';
export { invoiceSchema, type Invoice } from './schemas/invoice';Feature Module Rules
- One feature, one directory — never spread a feature across multiple top-level folders
- Export through index.ts — other code imports from the feature’s index, never from internal files
- Keep it self-contained — a feature should be deletable without breaking unrelated code
- Shared code goes to
packages/— if it’s used across apps, make it a workspace package
Import Boundaries
// ✅ CORRECT — import from package
import { createClient } from '@frequencyads/auth/client';
import type { Organization } from '@frequencyads/models';
// ✅ CORRECT — import from feature's public API
import { InvoiceList } from '@/features/invoices';
// ❌ WRONG — reaching into feature internals
import { InvoiceList } from '@/features/invoices/components/InvoiceList';
// ❌ WRONG — cross-feature internal imports
import { formatAmount } from '@/features/billing/utils/format';Key Architecture Decisions
- pnpm workspaces + Turborepo — fast, cache-aware builds across the monorepo
- Nextra for documentation — MDX-based, works with App Router, full-text search via Pagefind
- Supabase for backend — PostgreSQL + RLS, OAuth out-of-box, SSR-friendly
- Mantine for UI — CSS Modules, no runtime CSS-in-JS, 100+ components
- LinkML for data modeling — single source of truth, generates SQL + TypeScript
- AI Drivers for quality — automated security and code review gates
See ADRs for the full decision records.