Introduction
Welcome to the developer documentation for the Mood project. This guide provides a deep dive into the architecture, technical choices, and core principles that define this application.
Project Goal
Mood is a self-hostable polling platform designed for teams to gather feedback with a core focus on 100% anonymity and a single-administrator security model. It allows one admin to create campaigns and distribute unique polling links to managers, ensuring that all responses remain untraceable to the individual.
Core Architectural Principles
The application is built on several key principles that guide its structure and development:
End-to-End Type Safety: By combining Next.js, tRPC, Zod, and Prisma, the entire data flow is strongly typed. This eliminates a massive class of potential bugs between the frontend and backend and provides an exceptional developer experience with autocompletion.
Defense in Depth Security: The application employs a multi-layered security model:
- Edge Protection: A
middleware.tsfile protects the entire/adminroute group at the network edge, redirecting unauthenticated users before any application code is rendered. - API Protection: Every sensitive API endpoint is a
protectedProcedure, verifying the user's session on the server for every single request. - Single-Admin Model: The authentication logic (
src/auth.ts) is hard-coded to allow registration only for the very first user, secured by a mandatoryINVITATION_KEY.
- Edge Protection: A
Optimized User Experience: The architecture is designed to be fast and responsive.
- "Server Component Shell" Pattern: Complex pages use a Server Component shell to enable instant loading and UI streaming via React Suspense, while a core Client Component handles all interactivity.
- Consistent Feedback: Every user action (especially mutations) provides immediate visual feedback through toasts and loading states, ensuring the user is never left guessing.
Technical Stack
- Framework: Next.js 15 (App Router) with Turbopack
- API: tRPC (for end-to-end typesafe APIs)
- Database: PostgreSQL with Prisma ORM
- Authentication: Better Auth (configured for a single-admin system)
- UI: Tailwind CSS with shadcn/ui components
- Visuals: Custom WebGL shaders via
react-three-fiber&ogl - Validation: Zod (for API input validation)
Application Data Flow
A typical request to a protected page follows this comprehensive path:
- A user attempts to access an admin URL (e.g.,
/admin/campaigns/active). - The Next.js Middleware (
src/middleware.ts) intercepts the request at the edge and verifies the session cookie. If invalid, it redirects to/login. - The request proceeds. React renders the page, starting with the Root Layout and the Admin Layout.
- The
AdminLayoutwraps the page in aTRPCProvider, making the authenticated tRPC client available. - The page's Client Component (e.g.,
ActiveCampaignsPage.tsx) mounts and calls a tRPC hook, liketrpc.campaign.list.useQuery(). - The tRPC client sends an HTTP request to the API route at
/api/trpc. Data is serialized usingsuperjson. - The tRPC Context (
src/server/context.ts) is created on the server, attaching theprismaclient and the usersessionto the request. - The
protectedProcedureinsrc/server/trpc.tsruns its middleware, validating thatctx.session.userexists. - The router logic in
src/server/routers/campaign.tsfinally executes, using Prisma to query the database. - The fully typed response is returned to the client, where React Query manages caching and renders the data.