A modern Next.js 16 application for coaching and sports management with TypeScript, Tailwind CSS v4, shadcn/ui, Drizzle ORM, tRPC, better-auth, Convex, and next-intl.
- Framework: Next.js 16 (App Router, Turbopack)
- Language: TypeScript + React 19
- Styling: Tailwind CSS v4, shadcn/ui (Radix UI), class-variance-authority
- Database: PostgreSQL with Drizzle ORM
- API: tRPC + Next.js route handlers
- Auth: better-auth (email/password, magic link, social)
- Realtime: Convex (chat + notifications)
- File uploads: UploadThing
- Maps: Mapbox GL + MapQuest geocoding
- State Management: TanStack Query
- Validation: Zod
- Internationalization: next-intl
- Package Manager: Bun
- Data Access Layer (DAL) in
src/db/dalwith shared Zod schemas insrc/schemas - shadcn/ui components under
src/components/ui/shadcn(seecomponents.json) - better-auth integration in
src/lib/authwith a Drizzle adapter - Convex realtime chat and notifications in
convex/andsrc/lib/convex - AI assistant endpoint at
/api/assistant(Gemini or HuggingFace viasrc/lib/llm)
- Node.js 18+ or Bun
- PostgreSQL database
- Optional: Mapbox/MapQuest keys, UploadThing, Convex, and LLM provider keys
-
Clone the repository
-
Install dependencies:
bun install
-
Copy
.env.exampleto.envand fill required values (seesrc/env.tsfor the full list) -
Run the development server:
bun run dev
-
Open http://localhost:3000 in your browser
This project uses next-intl for internationalization with the following setup:
- French (fr) - Default language
- English (en) - Secondary language
src/i18n.ts: Main i18n configurationmessages/fr.json: French translationsmessages/en.json: English translationssrc/app/layout.tsx: Loads messages intoNextIntlClientProvider
import { useTranslations } from "next-intl";
export function MyComponent() {
const t = useTranslations();
return (
<div>
<h1>{t("home.title")}</h1>
<p>{t("home.subtitle")}</p>
</div>
);
}The app includes a LanguageSwitcher component:
import LanguageSwitcher from "@/components/LanguageSwitcher";
<LanguageSwitcher />;This project uses tRPC for type-safe APIs:
src/lib/trpc/server.ts: tRPC context and helperssrc/server/api/root.ts: Root router combining sub-routerssrc/server/api/routers/: Individual route handlerssrc/app/api/trpc/[trpc]/route.ts: Next.js API route handler
src/lib/trpc/client.ts: tRPC client configurationsrc/lib/trpc/provider.tsx: React Query provider wrappersrc/app/layout.tsx: Root layout with tRPC and i18n providers
import { trpc } from "@/lib/trpc/client";
export function MyComponent() {
const users = trpc.user.list.useQuery({ limit: 10 });
const createUser = trpc.user.create.useMutation();
if (users.isLoading) return <div>Loading...</div>;
return (
<div>
{users.data?.map((user) => (
<div key={user.id}>{user.name}</div>
))}
</div>
);
}The DAL provides typed database operations and is paired with shared Zod schemas:
- DAL:
src/db/dal - Schemas:
src/schemas - Guide:
docs/dal-guide.md
convex/ # Convex functions and schema
docs/ # Internal guides
drizzle/ # Drizzle migrations
messages/ # i18n translations
src/
├── app/ # Next.js App Router pages
├── actions/ # Server actions
├── components/ # UI and feature components
│ └── ui/shadcn/ # shadcn/ui components
├── db/
│ ├── dal/ # Data Access Layer
│ ├── schema/ # Drizzle schema definitions
│ └── index.ts # Database connection
├── lib/
│ ├── auth/ # better-auth client/server helpers
│ ├── convex/ # Convex client/server helpers
│ ├── llm/ # Assistant integrations
│ └── trpc/ # tRPC configuration
├── schemas/ # Shared Zod schemas
└── i18n.ts # Internationalization config
- Dev:
bun run dev - Build:
bun run build - Lint:
bun run lint - Lint (all):
bun run lint:all - Typecheck:
bun run tsc - Format:
bun run format
The project uses Drizzle ORM with PostgreSQL:
- Schema:
src/db/schema - Migrations:
drizzle/ - DAL:
src/db/dal
docs/dal-guide.mddocs/error-handling-guide.md
- Follow the TypeScript and tRPC patterns established in the codebase
- Use the shared Zod schemas in
src/schemasfor inputs - Route all database access through the DAL in
src/db/dal - Add translations for all new text content
- Test thoroughly before submitting changes