|
1 | | -# CLAUDE.md |
2 | | - |
3 | | -This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. |
4 | | - |
5 | | -## Project Overview |
6 | | - |
7 | | -This is a recruitment website for Beijing Institute of Technology (BIT), targeted at Indonesian students. It is an **unofficial** site managed by BIND (BIT Indonesian Community). The site uses Next.js 16 with App Router, React 19, TypeScript, Tailwind CSS v4, and Framer Motion for animations. |
8 | | - |
9 | | -The site is configured for **static export** (`output: "export"` in `next.config.ts`), which means it builds as pure static HTML/CSS/JS with no server-side rendering. |
10 | | - |
11 | | -## Commands |
12 | | - |
13 | | -```bash |
14 | | -# Development |
15 | | -bun run dev # Start dev server (http://localhost:3000) |
16 | | - |
17 | | -# Build & Deploy |
18 | | -bun run build # Build for production (outputs to `out/` directory) |
19 | | -bun run start # Preview production build (requires build first) |
20 | | - |
21 | | -# Linting |
22 | | -bun run lint # Run ESLint |
23 | | -``` |
24 | | - |
25 | | -## Architecture |
26 | | - |
27 | | -### Directory Structure |
28 | | - |
29 | | -``` |
30 | | -app/ # Next.js App Router pages |
31 | | -├── layout.tsx # Root layout with fonts (Plus Jakarta Sans, Syne) |
32 | | -├── page.tsx # Home page |
33 | | -├── globals.css # Global styles with Tailwind v4 + custom utilities |
34 | | -├── admissions/ # Admissions & scholarships page |
35 | | -├── campus-life/ # Campus life page |
36 | | -├── community/ # Indonesian community page |
37 | | -├── faq/ # FAQ page with search |
38 | | -└── why-bit/ # Why BIT page |
39 | | -
|
40 | | -components/ |
41 | | -├── layout/ # Layout components (Navbar, Footer) |
42 | | -├── features/ # Feature components (e.g., CostCalculator) |
43 | | -└── ui/ # Reusable UI components (shadcn/base-nova) |
44 | | -
|
45 | | -lib/ |
46 | | -├── content.ts # Site content, stats, features, scholarships data |
47 | | -└── utils.ts # Utility functions (cn for className merging) |
48 | | -``` |
49 | | - |
50 | | -### Content Management |
51 | | - |
52 | | -Site content is centralized in `lib/content.ts`: |
53 | | -- `hero` - Hero section content |
54 | | -- `stats` - Statistics displayed on homepage |
55 | | -- `features` - Value proposition cards |
56 | | -- `contact` - WhatsApp and contact info |
57 | | -- `scholarships` - Scholarship data for CostCalculator |
58 | | -- `costs` - Cost basis for calculator (tuition, dorm, living) |
59 | | - |
60 | | -When updating content, prefer editing `lib/content.ts` over hardcoding values in components. |
61 | | - |
62 | | -### Styling System |
63 | | - |
64 | | -**Tailwind CSS v4** with a custom design system defined in `app/globals.css`: |
65 | | - |
66 | | -- **Primary color**: Emerald green (`oklch(0.596 0.17 163.7)`) |
67 | | -- **Fonts**: Plus Jakarta Sans (body), Syne (display/headings) |
68 | | -- **Radius**: Base 12px with scale (`--radius-*` CSS variables) |
69 | | -- **Custom utilities**: |
70 | | - - `.glass` - Frosted glass effect (bg-white/70 + backdrop-blur) |
71 | | - - `.glass-pill` - Pill-shaped glass navbar |
72 | | - - `.bg-gradient-warm`, `.bg-gradient-cool` - Gradient backgrounds |
73 | | - - `.text-gradient-warm`, `.text-gradient-cool` - Gradient text |
74 | | - |
75 | | -The site is **light mode primary** but retains dark mode variables for future use. |
76 | | - |
77 | | -### Key Components |
78 | | - |
79 | | -- **Navbar** (`components/layout/Navbar.tsx`): Floating pill design with scroll-based shrink, mobile menu overlay |
80 | | -- **Footer** (`components/layout/Footer.tsx`): Multi-column layout |
81 | | -- **GradientBlob** (`components/ui/GradientBlob.tsx`): Animated background blobs with variants (cool, warm, accent) |
82 | | -- **WhatsAppButton** (`components/ui/WhatsAppButton.tsx`): Primary CTA linking to WhatsApp consultation |
83 | | - |
84 | | -### UI Component Library |
85 | | - |
86 | | -Uses **shadcn (base-nova style)** with components in `components/ui/`. To add new components: |
87 | | - |
88 | | -```bash |
89 | | -# Use shadcn CLI (configured in components.json) |
90 | | -bunx shadcn add [component-name] |
91 | | -``` |
92 | | - |
93 | | -Component aliases (from `components.json`): |
94 | | -- `@/components` → components |
95 | | -- `@/lib/utils` → lib/utils |
96 | | -- `@/components/ui` → components/ui |
97 | | - |
98 | | -### Animations |
99 | | - |
100 | | -**Framer Motion** is used for page animations and micro-interactions: |
101 | | -- Page transitions with `AnimatePresence` and `mode="wait"` |
102 | | -- Scroll-triggered animations with `whileInView` and `viewport` |
103 | | -- Staggered children animations using `staggerChildren` |
104 | | - |
105 | | -## Important Notes |
106 | | - |
107 | | -1. **Static Export Limitations**: Since `output: "export"` is used, avoid: |
108 | | - - Dynamic routes with `generateStaticParams` |
109 | | - - Server Actions |
110 | | - - Route Handlers (API routes) |
111 | | - - `headers()`, `cookies()`, or other server-only APIs |
112 | | - |
113 | | -2. **Images**: Use `next/image` with `placeholder="blur"` for better UX. See `components/ui/blur-image.tsx`. |
114 | | - |
115 | | -3. **Icons**: Lucide React via `lucide-react` package. |
116 | | - |
117 | | -4. **Path Alias**: `@/*` maps to project root (configured in `tsconfig.json`). |
118 | | - |
119 | | -5. **WhatsApp Contact**: Primary contact method is WhatsApp (`https://wa.me/6281388577873`). |
120 | | - |
121 | | -6. **Package Manager - BUN ONLY**: |
122 | | - - This project **EXCLUSIVELY** uses [Bun](https://bun.sh) as the package manager and runtime |
123 | | - - **NEVER** use `npm`, `yarn`, `pnpm`, `node`, or `npx` commands |
124 | | - - **NEVER** create or modify `package-lock.json`, `yarn.lock`, or `pnpm-lock.yaml` |
125 | | - - Only `bun.lock` should exist for dependency locking |
126 | | - |
127 | | - **For Claude Code**: |
128 | | - - Always use `bun` instead of `npm`/`yarn`/`pnpm` |
129 | | - - Use `bunx` instead of `npx` |
130 | | - - Example: `bunx shadcn add button` NOT `npx shadcn add button` |
131 | | - |
132 | | - **For Contributors without Bun**: |
133 | | - If you don't have Bun installed, install it first: |
134 | | - ```bash |
135 | | - # macOS/Linux |
136 | | - curl -fsSL https://bun.sh/install | bash |
137 | | - |
138 | | - # Windows (PowerShell) |
139 | | - powershell -c "irm bun.sh/install.ps1 | iex" |
140 | | - |
141 | | - # Or via npm (one-time only to install Bun) |
142 | | - npm install -g bun |
143 | | - ``` |
144 | | - |
145 | | - Then use these Bun commands: |
146 | | - ```bash |
147 | | - bun install # Instead of: npm install |
148 | | - bun add <package> # Instead of: npm install <package> |
149 | | - bun remove <package> # Instead of: npm uninstall <package> |
150 | | - bun run dev # Instead of: npm run dev |
151 | | - bunx <command> # Instead of: npx <command> |
152 | | - ``` |
153 | | - |
154 | | -7. **Linting**: |
155 | | - - Run `bun run lint` after making any code changes |
156 | | - - Fix all linting errors before considering the task complete |
157 | | - - Do not finish work with linting errors |
158 | | - - If lint errors occur, fix them immediately and re-run `bun run lint` to verify |
159 | | - |
160 | | -8. **React Best Practices - Avoid useEffect**: |
161 | | - - Most `useEffect` usage can be replaced with better patterns: |
162 | | - - **Event handlers**: For user interactions (clicks, form submissions) |
163 | | - - **Server Components**: For data fetching (when not using static export) |
164 | | - - **Props/State**: For derived state (calculate during render) |
165 | | - - **useMemo/useCallback**: For expensive computations |
166 | | - - **React Query/SWR**: For data fetching and caching |
167 | | - - **Framer Motion callbacks**: For animation-related side effects |
168 | | - - Only use `useEffect` as a last resort for: |
169 | | - - Syncing with external systems (non-React libraries) |
170 | | - - Browser APIs (localStorage, window listeners) - but prefer event handlers |
171 | | - - Truly unavoidable imperative operations |
172 | | - - If you must use `useEffect`, document why it's necessary in a comment |
| 1 | +# CLAUDE.md |
| 2 | + |
| 3 | +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. |
| 4 | + |
| 5 | +## Project Overview |
| 6 | + |
| 7 | +This is a recruitment website for Beijing Institute of Technology (BIT), targeted at Indonesian students. It is an **unofficial** site managed by BIND (BIT Indonesian Community). The site uses Next.js 16 with App Router, React 19, TypeScript, Tailwind CSS v4, and Framer Motion for animations. |
| 8 | + |
| 9 | +The site is configured for **static export** (`output: "export"` in `next.config.ts`), which means it builds as pure static HTML/CSS/JS with no server-side rendering. |
| 10 | + |
| 11 | +## Commands |
| 12 | + |
| 13 | +```bash |
| 14 | +# Development |
| 15 | +bun run dev # Start dev server (http://localhost:3000) |
| 16 | + |
| 17 | +# Build & Deploy |
| 18 | +bun run build # Build for production (outputs to `out/` directory) |
| 19 | +bun run start # Preview production build (requires build first) |
| 20 | + |
| 21 | +# Linting |
| 22 | +bun run lint # Run ESLint |
| 23 | +``` |
| 24 | + |
| 25 | +## Architecture |
| 26 | + |
| 27 | +### Directory Structure |
| 28 | + |
| 29 | +``` |
| 30 | +app/ # Next.js App Router pages |
| 31 | +├── layout.tsx # Root layout with fonts (Plus Jakarta Sans, Syne) |
| 32 | +├── page.tsx # Home page |
| 33 | +├── globals.css # Global styles with Tailwind v4 + custom utilities |
| 34 | +├── admissions/ # Admissions & scholarships page |
| 35 | +├── campus-life/ # Campus life page |
| 36 | +├── community/ # Indonesian community page |
| 37 | +├── faq/ # FAQ page with search |
| 38 | +└── why-bit/ # Why BIT page |
| 39 | +
|
| 40 | +components/ |
| 41 | +├── layout/ # Layout components (Navbar, Footer) |
| 42 | +├── features/ # Feature components (e.g., CostCalculator) |
| 43 | +└── ui/ # Reusable UI components (shadcn/base-nova) |
| 44 | +
|
| 45 | +lib/ |
| 46 | +├── content.ts # Site content, stats, features, scholarships data |
| 47 | +└── utils.ts # Utility functions (cn for className merging) |
| 48 | +``` |
| 49 | + |
| 50 | +### Content Management |
| 51 | + |
| 52 | +Site content is centralized in `lib/content.ts`: |
| 53 | +- `hero` - Hero section content |
| 54 | +- `stats` - Statistics displayed on homepage |
| 55 | +- `features` - Value proposition cards |
| 56 | +- `contact` - WhatsApp and contact info |
| 57 | +- `scholarships` - Scholarship data for CostCalculator |
| 58 | +- `costs` - Cost basis for calculator (tuition, dorm, living) |
| 59 | + |
| 60 | +When updating content, prefer editing `lib/content.ts` over hardcoding values in components. |
| 61 | + |
| 62 | +### Styling System |
| 63 | + |
| 64 | +**Tailwind CSS v4** with a custom design system defined in `app/globals.css`: |
| 65 | + |
| 66 | +- **Primary color**: Emerald green (`oklch(0.596 0.17 163.7)`) |
| 67 | +- **Fonts**: Plus Jakarta Sans (body), Syne (display/headings) |
| 68 | +- **Radius**: Base 12px with scale (`--radius-*` CSS variables) |
| 69 | +- **Custom utilities**: |
| 70 | + - `.glass` - Frosted glass effect (bg-white/70 + backdrop-blur) |
| 71 | + - `.glass-pill` - Pill-shaped glass navbar |
| 72 | + - `.bg-gradient-warm`, `.bg-gradient-cool` - Gradient backgrounds |
| 73 | + - `.text-gradient-warm`, `.text-gradient-cool` - Gradient text |
| 74 | + |
| 75 | +The site is **light mode primary** but retains dark mode variables for future use. |
| 76 | + |
| 77 | +### Key Components |
| 78 | + |
| 79 | +- **Navbar** (`components/layout/Navbar.tsx`): Floating pill design with scroll-based shrink, mobile menu overlay |
| 80 | +- **Footer** (`components/layout/Footer.tsx`): Multi-column layout |
| 81 | +- **GradientBlob** (`components/ui/GradientBlob.tsx`): Animated background blobs with variants (cool, warm, accent) |
| 82 | +- **WhatsAppButton** (`components/ui/WhatsAppButton.tsx`): Primary CTA linking to WhatsApp consultation |
| 83 | + |
| 84 | +### UI Component Library |
| 85 | + |
| 86 | +Uses **shadcn (base-nova style)** with components in `components/ui/`. To add new components: |
| 87 | + |
| 88 | +```bash |
| 89 | +# Use shadcn CLI (configured in components.json) |
| 90 | +bunx shadcn add [component-name] |
| 91 | +``` |
| 92 | + |
| 93 | +Component aliases (from `components.json`): |
| 94 | +- `@/components` → components |
| 95 | +- `@/lib/utils` → lib/utils |
| 96 | +- `@/components/ui` → components/ui |
| 97 | + |
| 98 | +### Animations |
| 99 | + |
| 100 | +**Framer Motion** is used for page animations and micro-interactions: |
| 101 | +- Page transitions with `AnimatePresence` and `mode="wait"` |
| 102 | +- Scroll-triggered animations with `whileInView` and `viewport` |
| 103 | +- Staggered children animations using `staggerChildren` |
| 104 | + |
| 105 | +## Important Notes |
| 106 | + |
| 107 | +1. **Static Export Limitations**: Since `output: "export"` is used, avoid: |
| 108 | + - Dynamic routes with `generateStaticParams` |
| 109 | + - Server Actions |
| 110 | + - Route Handlers (API routes) |
| 111 | + - `headers()`, `cookies()`, or other server-only APIs |
| 112 | + |
| 113 | +2. **Images**: Use `next/image` with `placeholder="blur"` for better UX. See `components/ui/blur-image.tsx`. |
| 114 | + |
| 115 | +3. **Icons**: Lucide React via `lucide-react` package. |
| 116 | + |
| 117 | +4. **Path Alias**: `@/*` maps to project root (configured in `tsconfig.json`). |
| 118 | + |
| 119 | +5. **WhatsApp Contact**: Primary contact method is WhatsApp (`https://wa.me/8618810362679`). |
| 120 | + |
| 121 | +6. **Package Manager - BUN ONLY**: |
| 122 | + - This project **EXCLUSIVELY** uses [Bun](https://bun.sh) as the package manager and runtime |
| 123 | + - **NEVER** use `npm`, `yarn`, `pnpm`, `node`, or `npx` commands |
| 124 | + - **NEVER** create or modify `package-lock.json`, `yarn.lock`, or `pnpm-lock.yaml` |
| 125 | + - Only `bun.lock` should exist for dependency locking |
| 126 | + |
| 127 | + **For Claude Code**: |
| 128 | + - Always use `bun` instead of `npm`/`yarn`/`pnpm` |
| 129 | + - Use `bunx` instead of `npx` |
| 130 | + - Example: `bunx shadcn add button` NOT `npx shadcn add button` |
| 131 | + |
| 132 | + **For Contributors without Bun**: |
| 133 | + If you don't have Bun installed, install it first: |
| 134 | + ```bash |
| 135 | + # macOS/Linux |
| 136 | + curl -fsSL https://bun.sh/install | bash |
| 137 | + |
| 138 | + # Windows (PowerShell) |
| 139 | + powershell -c "irm bun.sh/install.ps1 | iex" |
| 140 | + |
| 141 | + # Or via npm (one-time only to install Bun) |
| 142 | + npm install -g bun |
| 143 | + ``` |
| 144 | + |
| 145 | + Then use these Bun commands: |
| 146 | + ```bash |
| 147 | + bun install # Instead of: npm install |
| 148 | + bun add <package> # Instead of: npm install <package> |
| 149 | + bun remove <package> # Instead of: npm uninstall <package> |
| 150 | + bun run dev # Instead of: npm run dev |
| 151 | + bunx <command> # Instead of: npx <command> |
| 152 | + ``` |
| 153 | + |
| 154 | +7. **Linting**: |
| 155 | + - Run `bun run lint` after making any code changes |
| 156 | + - Fix all linting errors before considering the task complete |
| 157 | + - Do not finish work with linting errors |
| 158 | + - If lint errors occur, fix them immediately and re-run `bun run lint` to verify |
| 159 | + |
| 160 | +8. **React Best Practices - Avoid useEffect**: |
| 161 | + - Most `useEffect` usage can be replaced with better patterns: |
| 162 | + - **Event handlers**: For user interactions (clicks, form submissions) |
| 163 | + - **Server Components**: For data fetching (when not using static export) |
| 164 | + - **Props/State**: For derived state (calculate during render) |
| 165 | + - **useMemo/useCallback**: For expensive computations |
| 166 | + - **React Query/SWR**: For data fetching and caching |
| 167 | + - **Framer Motion callbacks**: For animation-related side effects |
| 168 | + - Only use `useEffect` as a last resort for: |
| 169 | + - Syncing with external systems (non-React libraries) |
| 170 | + - Browser APIs (localStorage, window listeners) - but prefer event handlers |
| 171 | + - Truly unavoidable imperative operations |
| 172 | + - If you must use `useEffect`, document why it's necessary in a comment |
173 | 173 | - Reference: [You Might Not Need an Effect](https://react.dev/learn/you-might-not-need-an-effect) |
0 commit comments