Imported from Elevate-Foundation/elevate-learning-platform-web (
AGENTS.md). Install upstream withnpx skills add Elevate-Foundation/elevate-learning-platform-web. Copyright stays with the author.
Elevate E-Learning Platform — Web Frontend
Project Overview
This is the web frontend for Elevate, an e-learning platform. It is built with Next.js (App Router) and serves two main areas:
- Website (
/) — Public-facing marketing pages (home, landing, etc.) - Dashboard (
/dashboard) — Authenticated area (sign-in, sign-up, course management, etc.)
Tech Stack
| Category | Tool / Library |
|---|---|
| Framework | Next.js 15 (App Router, Turbopack dev server) |
| Language | TypeScript (strict mode) |
| React | React 19 |
| Styling | Tailwind CSS v4 (@import 'tailwindcss' syntax) |
| UI Components | shadcn/ui (Radix UI primitives + CVA + tailwind-merge) |
| Data Fetching | TanStack Query (React Query) |
| Forms | React Hook Form + Zod (via @hookform/resolvers) |
| Icons | Lucide React |
| Font | Lato (via next/font/google) |
| Package Manager | pnpm (v9+, enforced via only-allow pnpm preinstall hook) |
| Linting | ESLint 9 (flat config, next/core-web-vitals + next/typescript) |
| Formatting | Prettier (single quotes, trailing commas, 80 char width) |
| Git Hooks | Husky + lint-staged (lint on pre-commit, commitlint on commit-msg) |
| Commit Standard | Conventional Commits (enforced via commitlint + Commitizen) |
| Animations | tw-animate-css |
Project Structure
src/
├── app/
│ ├── layout.tsx # Root layout (font, global styles)
│ ├── globals.css # Tailwind config, CSS variables, theming
│ ├── (website)/ # Route group: public website
│ │ ├── layout.tsx # Website layout (nav, header, main, footer)
│ │ ├── page.tsx # Root website page (/)
│ │ ├── home/
│ │ │ ├── page.tsx
│ │ │ └── _components/ # Page-scoped components
│ │ └── _components/ # Shared website layout components
│ │ └── layout/
│ │ ├── nav/ # Nav (desktop, mobile, links, dropdown)
│ │ └── footer/
│ └── dashboard/ # Route group: authenticated dashboard
│ └── (auth)/ # Auth-related pages
│ ├── layout.tsx
│ ├── sign-in/
│ ├── sign-up/
│ ├── forgot-password/
│ ├── reset-password/
│ └── _components/ # Shared auth components (Google/Facebook buttons)
│ └── index.ts # Barrel file for re-exports
├── components/
│ └── ui/ # shadcn/ui components (Button, Card, Input, Form, etc.)
└── lib/
└── utils.ts # cn() helper (clsx + tailwind-merge)
Coding Conventions
General
- Use TypeScript for all files. Enable strict mode.
- Use the
@/*path alias for imports fromsrc/(e.g.,import { cn } from '@/lib/utils'). - Default to client components (
'use client'). This project uses TanStack Query for data fetching, so most components are client-side. Only omit the directive for purely static/layout components that have no interactivity or data fetching. - Use named exports for components (e.g.,
export const Hero = () => {}). Page components are the exception — they useexport default function. - Use arrow functions for components; use regular
functiondeclarations for page-level default exports.
File & Folder Naming
- Use kebab-case for all file and folder names (e.g.,
google-button.tsx,forgot-password/). - Use PascalCase for component names and types.
- Prefix private/internal route folders with
_(e.g.,_components/). - Use Next.js route groups with parentheses (e.g.,
(website),(auth)) to organize routes without affecting URL paths.
Component Organization
- Page-scoped components live in
_components/next to their page (e.g.,home/_components/hero.tsx). - Shared layout components live in the nearest shared
_components/layout/directory. - Reusable UI primitives (shadcn/ui) live in
src/components/ui/. - Use barrel files (
index.ts) to re-export related components from_components/directories.
Styling
- Use Tailwind CSS v4 — styles are configured via
@theme inlineand CSS custom properties inglobals.css. - Use the
cn()utility (@/lib/utils) to merge class names conditionally. - Use shadcn/ui conventions: CVA (class-variance-authority) for component variants,
data-slotattributes for component identification. - Color tokens use oklch color space via CSS custom properties (e.g.,
--primary,--background). - The project supports light/dark mode via the
.darkclass strategy. - Avoid hardcoding colors — use semantic tokens (
primary,secondary,muted,destructive, etc.).
Forms & Validation
- Use React Hook Form with Zod schemas for form validation.
- Use
zodResolverfrom@hookform/resolversto connect Zod schemas to React Hook Form. - Define Zod schemas in the same file as the form component (co-location).
- Use shadcn
<Form>,<FormField>,<FormItem>,<FormLabel>,<FormControl>,<FormMessage>wrappers.
Data Fetching
- Use TanStack Query for all server state management and data fetching.
- Prefer client-side data fetching with TanStack Query hooks (
useQuery,useMutation) over Next.js server-side patterns.
Images
- Use Next.js
<Image>component for all images. - Store static images in
public/images/. - Brand assets go in
public/brand/.
Git & Commit Conventions
Commit Messages
Commits follow the Conventional Commits standard, enforced by commitlint. Use the pnpm commit script (Commitizen) for interactive commits.
Allowed types: feat, fix, docs, style, refactor, perf, test, chore, ci, build, revert, wip
Rules:
- Subject must be lowercase
- Subject max length: 100 characters
- Type and subject are required
Examples:
feat: add hero component and home page
fix: build error
chore: install and setup commitizen
refactor: update folder structure
Git Hooks
- pre-commit: Runs
lint-staged(ESLint fix on.ts/.tsx, Prettier on.json/.md/.css) - commit-msg: Runs commitlint to validate commit message format
Commands
| Command | Description |
|---|---|
pnpm dev |
Start dev server (Turbopack) |
pnpm build |
Production build |
pnpm lint |
Run ESLint |
pnpm lint:fix |
Run ESLint with auto-fix |
pnpm format |
Format all files with Prettier |
pnpm format:check |
Check formatting without writing |
pnpm commit |
Interactive commit (Commitizen) |
Prettier Config
- Single quotes
- Trailing commas (ES5)
- Print width: 80
- Tab width: 2 (spaces, not tabs)
- Semicolons: yes
Best Practices
- Client components by default — This project uses TanStack Query for data fetching. Add
'use client'to components. Only use server components for purely static layouts with zero interactivity. - Co-locate code — Keep components, styles, and logic close to where they're used. Only lift to shared locations when reuse is needed.
- Use the design system — Prefer shadcn/ui components and semantic color tokens over custom styles. Extend variants via CVA when needed.
- Validate at the boundary — Use Zod schemas for form inputs and API responses. Don't over-validate internal data flows.
- Keep components small — Extract sub-components into the same
_components/directory when a file grows large. - Semantic HTML — Use proper HTML elements (
<nav>,<header>,<main>,<section>, etc.). - Accessibility — Use Radix UI primitives (via shadcn) which handle ARIA attributes, focus management, and keyboard navigation.
- Optimized images — Always use
next/imagewith appropriatealttext. Usepriorityfor above-the-fold images. - No hardcoded URLs in components — Use Next.js
<Link>for internal navigation. - Type safety — Prefer inferred types from Zod schemas (
z.infer<typeof schema>) over manually duplicated type definitions.