AnonMessage is built on the Next.js 14 App Router. Every page, API handler, and shared utility lives underDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/dev0302/nextjs-project-1/llms.txt
Use this file to discover all available pages before exploring further.
src/, with route groups providing logical separation between authenticated pages, authentication flows, and public-facing profiles — all without affecting the URL structure.
Annotated Directory Tree
Route Groups
Next.js treats any folder name wrapped in parentheses as a route group. The parentheses are stripped from the URL, so the folders exist purely for code organisation and to allow separate layouts.(app) group
Contains
dashboard/ and u/[username]/. Both pages share the same authenticated layout. The URL paths are /dashboard and /u/[username] — the (app) segment never appears in the browser.(auth) group
Contains
sign-in/, sign-up/, and verify-otp/. These three pages share an auth-focused layout. URL paths are /sign-in, /sign-up, and /verify-otp.Because route group names are invisible to the router, you can have
/dashboard (inside (app)) and /sign-in (inside (auth)) without any URL prefix from the group folders themselves.API Routes
All API handlers live undersrc/app/api/. Each folder contains a route.ts (or route.tsx) file that exports named HTTP method functions.
| Route | Method(s) | Purpose |
|---|---|---|
/api/auth/[...nextauth] | GET, POST | NextAuth catch-all — handles sign-in, sign-out, session, and callbacks |
/api/sign-up | POST | Verifies OTP, hashes password with bcrypt, creates the user document |
/api/send-otp | POST | Generates a 6-digit OTP via otp-generator, creates an OTP document (pre-save hook emails it) |
/api/check-username-unique | GET | Accepts ?username= query param, checks uniqueness against MongoDB |
/api/accept-messages | GET, POST | GET returns isAcceptingMessages status; POST updates it |
/api/send-message | POST | Pushes a new anonymous message onto the recipient user’s messages array |
/api/get-messages | GET | Runs a Mongoose aggregation pipeline ($match → $unwind → $sort → $group) and returns messages sorted by newest first |
/api/delete-message | PATCH | Uses $pull to remove a specific message subdocument by _id |
/api/suggest-messages | GET | Calls Google Gemini (gemini-1.5-flash) with a few-shot prompt and returns three suggested questions separated by || |
Components
components/ui/
shadcn/ui primitives:
Button, Input, Label, Avatar, AlertDialog, and Sonner (toast notifications). These are generated and owned by the project — not imported from an external package at runtime.components/navbar/
Navbar is the shell; NavbarAuthButtons shows Sign In / Sign Up links for guests; NavbarUserMenu shows the logged-in avatar and sign-out option; NavbarMiddleLink renders nav links for authenticated users.Feature components
MessageCard — renders content + delete button. MessageGrid — responsive grid. MessageToogle — shadcn Switch bound to the accept-messages toggle. CopyLink — copies the /u/[username] URL to clipboard. SendMessageProfile — anonymous message submission form on the public profile page.Utility components
DeleteMessageButton — wraps AlertDialog to confirm deletion before calling PATCH /api/delete-message. RefreshButton — client component that triggers a router refresh or manual re-fetch. email-client-card — shown post-OTP to prompt the user to check their inbox.Lib Utilities
auth.ts — NextAuth configuration
Exports
NEXT_AUTH_CONFIG: AuthOptions, which defines a single CredentialsProvider. The authorize callback connects to MongoDB, looks up the user by email, and compares the password with bcrypt.compare. Two callbacks (jwt and session) copy _id, isVerified, isAcceptingMessages, and username into the JWT and then into the session object.dbConnect.ts — Singleton Mongoose connection
Maintains a module-level
connection object with an isConnected flag. If isConnected is truthy the function returns immediately, preventing duplicate connections during Next.js hot-module reloads. On failure it calls process.exit(1) to fail loudly at startup rather than silently later.Zod Validation Schemas
All form and API input validation is centralised insrc/app/schemas/. Each schema is a named export so it can be reused in both client-side form hooks (react-hook-form + zodResolver) and server-side route handlers.
| File | Schema | Key rules |
|---|---|---|
signUpSchema.ts | signUpSchema | username 2–20 chars, alphanumeric + underscores; email valid format; password min 3 chars |
signInSchema.ts | signInSchema | username string, password string (no extra constraints — auth logic handles failures) |
messageSchema.ts | messageSchema | content 10–300 characters |
acceptMessageSchema.ts | acceptMessageSchema | acceptMessage must be a boolean |
verifySchema.ts | verifySchema | code exactly 6 characters |
Types
ApiResponse<T> — generic response envelope
ApiResponse<T> — generic response envelope
T defaults to null, making data optional for responses that carry no payload (e.g., a simple success/failure acknowledgement).SafeUser — non-sensitive user subset
SafeUser — non-sensitive user subset
data field in sign-up and delete-message responses. The password field is intentionally excluded.next-auth.d.ts — module augmentation
next-auth.d.ts — module augmentation
User, Session, and JWT interfaces. The & DefaultSession['user'] intersection preserves the original name, email, and image fields.