Skip to content

Latest commit

 

History

History
170 lines (127 loc) · 4.17 KB

File metadata and controls

170 lines (127 loc) · 4.17 KB

AGENTS.md - Web Coding Academy

Project Overview

Next.js 14 + React 18 + TypeScript educational web portal with Tailwind CSS.

Build Commands

npm run dev      # Start dev server (http://localhost:3000)
npm run build    # Production build
npm run start    # Start production server
npm run lint     # Run ESLint (requires initial setup)

No test framework is configured yet. To add tests, install Jest + React Testing Library.

Code Style Guidelines

Imports

  • Use @/ alias for internal imports (e.g., @/app/components/TopicChecklist)
  • Client components must start with "use client"; directive
  • Group imports: React imports → external libs → internal imports
  • Sort imports alphabetically within groups

TypeScript

  • Strict mode enabled in tsconfig.json
  • Always define prop types using interfaces/type aliases
  • Avoid any - use unknown when type is uncertain
  • Use Record<K, V> for dictionary-like objects

Naming Conventions

  • Components: PascalCase (e.g., TopicChecklist)
  • Functions/variables: camelCase (e.g., toggleTopic, completed)
  • Files: kebab-case (e.g., topic-checklist.tsx)
  • CSS classes: Prefix with fc- (e.g., fc-section, fc-topicItem)

Component Structure

"use client";

import { useState, useEffect } from "react";

type Props = {
  // define props
};

export default function ComponentName({ prop1 }: Props) {
  // hooks first
  // state
  // handlers
  // render
}

Error Handling

  • Wrap JSON.parse() in try/catch
  • Always handle localStorage errors gracefully
  • Use optional chaining (?.) and nullish coalescing (??)
  • Provide fallback values for potentially undefined state

CSS/Styling

  • Uses global CSS in src/app/globals.css
  • All custom classes use fc- prefix (functional component)
  • Tailwind utilities available for rapid styling

File Organization

src/app/
├── components/     # Reusable components
├── data/           # Static data (topics.ts)
├── lib/            # Utilities (storage.ts)
├── topic/[id]/     # Dynamic route pages
├── layout.tsx      # Root layout
├── page.tsx        # Home page
└── globals.css     # Global styles

Cursor/Copilot Rules

None found. Project uses standard Next.js + ESLint configuration.

Key Patterns

Dynamic Routes

// src/app/topic/[id]/page.tsx
type TopicPageProps = {
  params: {
    id: string;
  };
};

export default function TopicPage({ params }: TopicPageProps) {
  const block = topicBlocks.find((item) => item.slug === params.id);
  // ...
}

Client-Side State with localStorage

Use the storage utilities from @/app/lib/storage:

import { getProgress, setProgress, getNotes, setNotes } from "@/app/lib/storage";

Data Models

// src/app/data/topics.ts
export type Topic = {
  id: string;
  title: string;
  shortDescription: string;
  explanation: string;
  example: string;
  glossary: GlossaryItem[];
  difficulty?: "easy" | "medium" | "hard";
  tags?: string[];
};

export type TopicBlock = {
  id: string;
  slug: string;
  emoji: string;
  title: string;
  description: string;
  level: string;
  topics: Topic[];
};

Best Practices

  1. Hydration handling: Always check isHydrated before accessing browser APIs
  2. localStorage: Use try/catch for all localStorage operations
  3. Accessibility: Include proper type attributes on buttons, htmlFor on labels
  4. Keys: Always provide stable keys when mapping arrays
  5. Null checks: Validate dynamic route params before rendering

ESLint Setup

The project needs ESLint configuration. Run npm run lint and select "Strict" when prompted, or create .eslintrc.json manually:

{
  "extends": "next/core-web-vitals"
}

Storage Keys

The project uses these localStorage keys:

  • web-coding-progress - completed topics
  • web-coding-notes - notes by topic
  • web-coding-note-timestamps - timestamps for notes
  • web-coding-last-opened - last opened block slug
  • web-coding-favorites - favorite topics
  • web-coding-theme - theme preference

All storage operations should go through @/app/lib/storage for consistency and easy migration to cloud storage later.