Imported from RavishankarDuMCA10/AI_IN_SDLC_Linkshortener (
AGENTS.md). Install upstream withnpx skills add RavishankarDuMCA10/AI_IN_SDLC_Linkshortener. Copyright stays with the author.
This is NOT the Next.js you know
This version has breaking changes — APIs, conventions, and file structure may all differ from your training data. Read the relevant guide in node_modules/next/dist/docs/ before writing any code. Heed deprecation notices.
Agent Instructions
[!CAUTION] STOP. DO NOT WRITE A SINGLE LINE OF CODE UNTIL YOU HAVE READ THE RELEVANT
/docsFILE(S) LISTED BELOW. Skipping this step will cause broken, incorrect, or insecure output. There are no exceptions. Docs are indocs/auth.mdanddocs/ui-components.md.
This file is the entry point for LLM coding agents working in this repository.
For detailed guidelines on specific topics, refer to the modular documentation in the /docs directory. Reading the relevant .md file(s) BEFORE generating ANY code is mandatory — not optional, not skippable. Every topic area has a dedicated guide; use it:
Rule: If your task touches a topic in the table below, you MUST open and read the corresponding file in full before writing or modifying any code.
[!IMPORTANT] MANDATORY REQUIREMENT: Reading the relevant
/docsfile(s) is not a suggestion — it is a hard prerequisite. Any agent that skips this step and generates code directly is violating these instructions. The docs exist because this project uses versions and conventions that differ from general training data. They are the single source of truth.
Docs Index
YOU MUST READ THE RELEVANT FILE(S) BELOW BEFORE WRITING ANY CODE. These docs contain project-specific APIs, conventions, and breaking changes that differ from general training data. Failure to read them will result in incorrect code.
| Topic | File | When to read |
|---|---|---|
| Authentication (Clerk v7) | docs/auth.md | Any time you work with auth, protected routes, sign-in/sign-up UI, or user identity |
| UI Components (shadcn/ui) | docs/ui-components.md | Any time you build or modify UI — buttons, forms, dialogs, tables, or any visual element |
Workflow: (1) Identify which doc(s) apply to your task. (2) Read them in full. (3) Only then begin writing code.
Critical Rules (Summary)
The following rules are the most likely to trip up an agent relying on outdated training data. Violating any of these will break the application.
-
Middleware is
proxy.ts— Next.js 16 renamedmiddleware.tstoproxy.ts. Do not create or referencemiddleware.ts. -
paramsandsearchParamsare Promises — Alwaysawaitthem in page/layout components before accessing properties. -
No
tailwind.config.js— Tailwind v4 is configured via@theme inlineinapp/globals.css. Do not create a config file. -
Clerk v7 auth is async —
auth()andcurrentUser()from@clerk/nextjs/servermust beawaited in server contexts. -
DB access is server-only — Never import
dbfrom@/dbinside a Client Component ('use client'). Use Server Components, Server Functions, or Route Handlers. -
Use
cn()for class names — Always merge Tailwind classes withcn()from@/lib/utilsto avoid conflicts. -
shadcn components live in
components/ui/— Add vianpx shadcn add <component>. Do not hand-write or move them. -
Clerk is the only auth provider — Do not implement or suggest any other authentication method. See docs/auth.md.
-
/dashboardis a protected route — Unauthenticated users must be blocked at the middleware level inproxy.ts. See docs/auth.md. -
Authenticated users visiting
/are redirected to/dashboard— Handle inproxy.ts. See docs/auth.md. -
Sign in and sign up are always modals — Use
<SignInButton mode="modal">and<SignUpButton mode="modal">. Never create/sign-inor/sign-uppages. See docs/auth.md.
Project Architecture
Data Flow
Browser
└── Client Component (interaction, state)
└── Server Action / Route Handler ← "use server" boundary
└── db (Drizzle + Neon) ← server-only
User-triggered mutations flow from Client Components through Server Actions. Data reads happen directly in Server Components without an API layer.
Layer Responsibilities
| Layer | Location | Responsibility |
|---|---|---|
| Pages | app/**/page.tsx |
Fetch data, compose layout, no business logic |
| Layouts | app/**/layout.tsx |
Persistent UI shell; fetch session-scoped data once |
| Server Components | app/**/*.tsx (no directive) |
Data access, auth checks, pass data down as props |
| Client Components | 'use client' files |
Interactivity, state, browser APIs only |
| Server Actions | app/lib/actions.ts or co-located actions.ts |
Mutations, form handling, always auth-gated |
| Route Handlers | app/api/**/route.ts |
Public-facing REST endpoints (webhooks, redirects) |
| DB schema | db/schema.ts |
Single source of truth for all table shapes |
| DB client | db/index.ts |
Singleton Drizzle instance; never re-instantiate |
| Shared utilities | lib/ |
Pure functions; no framework imports |
| UI primitives | components/ui/ |
shadcn-generated; minimal edits, no moves |
| App components | components/ |
Composed application UI; can be Server or Client |
URL Shortener Core Flow
- Create link — authenticated user submits a URL → Server Action validates, generates a unique slug, inserts into
url_links, revalidates the dashboard cache. - Redirect — visitor hits
/:slug→ a Route Handler (orpage.tsxwithredirect()) looks up the slug in the DB, incrementsclick_count, and issues a 307/308 redirect. - Dashboard — authenticated user views their links → Server Component fetches links scoped to
userId, renders a Client Component table with copy/delete actions.
File Naming at a Glance
app/
├── layout.tsx # Root layout (ClerkProvider, fonts)
├── page.tsx # Landing / marketing page
├── globals.css # Tailwind v4 theme config
├── [slug]/
│ └── page.tsx # Redirect handler
├── dashboard/
│ ├── layout.tsx # Auth-protected shell
│ ├── page.tsx # Link list page
│ └── _components/ # Route-private components
├── api/
│ └── webhooks/
│ └── clerk/
│ └── route.ts # Clerk webhook handler (if needed)
└── lib/
└── actions.ts # All Server Actions
components/
├── ui/ # shadcn primitives (auto-generated)
├── LinkCard.tsx
├── LinkTable.tsx
└── CreateLinkForm.tsx
db/
├── index.ts # Drizzle client
└── schema.ts # Table definitions
lib/
└── utils.ts # cn() and other pure helpers
proxy.ts # Clerk middleware (Next.js 16)
Best Practices
Security
- Authenticate inside every Server Action. Server Actions are reachable via direct POST requests — never assume the caller is authenticated.
- Scope all DB queries to
userIdreturned fromauth(). Never acceptuserIdas a client-side input. - Validate all user input before writing to the database (length, format, URL validity).
- Never expose raw DB errors to the client. Catch errors in Server Actions and return safe user-facing messages.
- Environment variables: access via
process.env.VAR_NAMEonly. Never commit.env.local. Never exposeCLERK_SECRET_KEYorDATABASE_URLto the client bundle (noNEXT_PUBLIC_prefix on secrets).
Performance
- Keep the
'use client'boundary as deep as possible. Fetching data in Server Components avoids round-trip latency and keeps secrets off the client. - Use
Promise.allwhen fetching multiple independent data sources in a Server Component to avoid sequential waterfalls. - Use
loading.tsxfiles to stream UI progressively — wrap expensive async components in<Suspense>. - Export
unstable_instant = truefrom routes that feel slow on client-side navigation (seedocs/nextjs.md). - Use
next/imagefor all images — never raw<img>tags.
Code Quality
- One concern per file. Components render UI. Actions mutate data. Schema defines shape. Utilities are pure.
- No business logic in layouts or pages. Extract to Server Actions (
lib/actions.ts) or pure utility functions (lib/). - Avoid prop drilling beyond 2 levels. Lift data fetching to the nearest Server Component ancestor that can pass it directly.
- TypeScript strict: no
any, no@ts-ignore, no casting awaynull/undefinedwithout a real check. - Lint must pass (
npm run lint) before considering a change complete.
Mutations Checklist
Before shipping any Server Action:
-
await auth()is called anduserIdis checked - All user-supplied values are validated (type, length, format)
- DB query is scoped to the authenticated user's data
-
revalidatePathorrevalidateTagis called after mutating so the UI reflects the change - Errors are caught and surfaced as user-friendly messages, not stack traces
Adding a New Feature
- Read docs/project-overview.md to confirm where the feature fits.
- If it touches the DB: update
db/schema.ts, runnpx drizzle-kit generate && npx drizzle-kit migrate. - If it needs a new UI component:
npx shadcn add <component>— do not hand-write primitive components. - Build the data layer first (schema → action/query), then the UI.
- Default new components to Server Components; add
'use client'only when interactivity is required. - Run
npm run lintand fix all errors before finishing.