Skip to content

Latest commit

 

History

History
122 lines (89 loc) · 6.08 KB

File metadata and controls

122 lines (89 loc) · 6.08 KB

Capabilities — The Installed Toolbox

Everything below is already installed and wired. Check here before writing code that needs a capability, and never install a package that duplicates one of these.

At a Glance

Need Use Not
Forms react-hook-form + zod + @hookform/resolvers formik, custom form state
Validation zod (v4) joi, yup, hand-rolled checks
UI components shadcn/ui via npx shadcn add MUI, Chakra, custom modals
Icons lucide-react emoji in UI, other icon packs
Client state zustand (v5) Redux, context spaghetti
Server state @tanstack/react-query (v5) useEffect-fetch patterns
HTTP axios node-fetch, superagent
Auth next-auth v5 (Auth.js) + @auth/prisma-adapter custom sessions, JWT rolls
Database prisma (v7) + @prisma/client raw SQL, other ORMs
Dates date-fns (v4) moment, dayjs
Animation motion (import { motion } from "motion/react") framer-motion (old name), GSAP
Toasts sonner (v2) react-hot-toast, custom toasts
File upload UI react-dropzone hand-rolled drag/drop
Dark mode next-themes (.dark class strategy) media-query-only hacks
IDs nanoid uuid, Math.random
Env vars @t3-oss/env-nextjs raw process.env reads
SEO Next.js Metadata API (built in) next-seo or any package
Styling tailwindcss v4 + tokens in globals.css CSS modules, styled-components
Class merging clsx + tailwind-merge via cn() string concatenation
Testing vitest v4 + @testing-library/react jest

Database: Prisma 7

Prisma 7 uses a config file and driver adapters — this is already set up:

  • prisma.config.ts — CLI config, loads .env via dotenv
  • prisma/schema.prisma — generator outputs to src/generated/prisma (gitignored)
  • @prisma/adapter-better-sqlite3 — SQLite driver adapter (swap for @prisma/adapter-pg on Postgres)

The client singleton pattern for this project:

// src/lib/prisma.ts
import { PrismaClient } from "@/generated/prisma/client";
import { PrismaBetterSQLite3 } from "@prisma/adapter-better-sqlite3";

const adapter = new PrismaBetterSQLite3({ url: process.env.DATABASE_URL! });

const globalForPrisma = globalThis as unknown as { prisma?: PrismaClient };

export const prisma = globalForPrisma.prisma ?? new PrismaClient({ adapter });

if (process.env.NODE_ENV !== "production") globalForPrisma.prisma = prisma;

Commands: npm run db:generate, npm run db:push, npm run db:migrate, npm run db:studio.

Auth: NextAuth v5 (Auth.js)

The v5 pattern — one config, exported helpers, thin route handler:

// src/lib/auth.ts
import NextAuth from "next-auth";
import GitHub from "next-auth/providers/github";
import { PrismaAdapter } from "@auth/prisma-adapter";
import { prisma } from "@/lib/prisma";

export const { handlers, auth, signIn, signOut } = NextAuth({
  adapter: PrismaAdapter(prisma),
  providers: [GitHub],
});

Env vars use the AUTH_* convention (AUTH_SECRET, AUTH_GITHUB_ID, …) — see .env.example. Generate a secret with npx auth secret.

UI: shadcn/ui on Tailwind v4

Components are copied into the repo, not installed as dependencies — you own the code:

npx shadcn@latest add button card input label form dialog table

components.json is generated by /2-setup-foundation (Tailwind v4 style: css-based config, no tailwind.config.js). Installed parts land in src/components/ui/. Compose with the cn() helper from src/lib/utils.ts and design tokens only:

import { Button } from "@/components/ui/button";
import { cn } from "@/lib/utils";

<Button className={cn("font-body", isUrgent && "bg-destructive")}>
  Send quote
</Button>;

The Radix primitives shadcn depends on (dialog, select, dropdown-menu, tabs, popover, toast, checkbox, switch, slot) are pre-installed.

Styling: Tailwind CSS v4

Config is CSS-first. src/app/globals.css (generated by /2-setup-foundation) holds:

  • @import "tailwindcss" and tw-animate-css
  • OKLCH color variables for light (:root) and dark (.dark)
  • @theme inline mapping every token to a utility — including font-heading, font-body, and the ds-1ds-6 spacing steps

DESIGN_SYSTEM.md documents the full vocabulary. Off-system values are blocked by both ESLint rules and the PostToolUse hook.

Data Flow Patterns

  • Reads: server components fetch directly via Prisma; client-side refetching goes through TanStack Query
  • Writes: server actions validated with zod; route handlers (src/app/api/*/route.ts) for webhooks/external consumers
  • Client state: zustand stores in src/stores/, one store per domain
  • External APIs: axios, called from the server side whenever a key is involved

Dev Toolchain

  • npm run dev / build / start — Next.js 16 with Turbopack
  • npm run lint / lint:fix — ESLint 9 flat config with design-system rules
  • npm run type-check — strict TypeScript
  • npm test / test:ui / test:coverage — vitest + Testing Library (jsdom)
  • npm run format — Prettier (with Tailwind class sorting)
  • npm run analyze — bundle analysis
  • npm run validate-design-system — self-test of the enforcement layers
  • husky + lint-staged run lint and format on every commit