React + Vite app for real-time anonymous student feedback during lectures. localStorage-based (no real backend). JSX only — no TypeScript.
Always run commands from lecture-pulse/ (the app directory), not the repo root.
npm run dev # Start Vite dev server at http://localhost:5173
npm run build # Production build to dist/
npm run preview # Preview production build locally
npm run lint # ESLint check (all .js/.jsx files)Note: There is no test framework in the project. Do not add tests without explicit instruction.
pre-commitrunscd lecture-pulse && npm run lint— lint must pass.commit-msgenforces Conventional Commits (feat:,fix:,docs:,chore:,refactor:,style:, etc.).- Do NOT skip hooks with
--no-verifyunless explicitly asked.
- Use ES module
import/exportsyntax exclusively. - Use
@/path alias forsrc/(e.g.,import { Button } from "@/components/ui/button"). - Relative imports (
./pages/...) are also acceptable. - Group imports: 3rd-party first, then absolute
@/, then relative./. - Prefer named exports for utilities and small components. Use
export defaultfor page-level components. - Do NOT use
index.js/index.jsxbarrel files — import directly from the file.
| Thing | Convention | Example |
|---|---|---|
| Component files | PascalCase | LectureCard.jsx, AuthContext.jsx |
| Utility/data files | camelCase | storage.js, analytics.js |
| Component functions | PascalCase, function declarations |
function Button() |
| Hooks | use prefix + camelCase |
useAuth, useTheme |
| Variables/functions | camelCase | teacherId, getLectures() |
| Constants (loose) | camelCase | no UPPER_SNAKE convention observed |
- Prefer
function ComponentName(props)overconst Component = (props) =>. - Use
React.forwardReffor reusable UI primitives (button, input, card). - Set
displayNameonforwardRefcomponents. - Destructure props in the function signature.
- Tailwind CSS v4 utility classes — do NOT use external CSS files (except
index.cssfor theme variables). - Use the
cn()helper from@/lib/utilsfor conditional class merging (wrapsclsx+tailwind-merge). - Use CVA (
class-variance-authority) for component variants (seebutton.jsx). - Theme colors use CSS custom properties defined in
index.css— reference them via Tailwind classes likebg-background text-foreground. - Support
.darkclass for dark mode.
- All data is persisted in
localStorage— use the helpers in@/utils/storage.js. - Auth state lives in
AuthContext(@/context/AuthContext.jsx). - Theme state lives in
ThemeContext(@/context/ThemeContext.jsx).
- React Router v7 — define all routes in
App.jsx. - Use
<Link>anduseNavigatefor navigation.
- Use
framer-motionfor animations (motion.div,AnimatePresence,variants).
- Prefer double quotes for JSX attributes and strings (existing convention).
- Use semicolons consistently (existing codebase preference).
- Trailing commas in multiline objects/arrays.
- Simple guard clauses (
if (!data) return) rather than try/catch for expected absences. - Use try/catch around async operations (fetch-like calls, localStorage reads).
- Show errors via
sonnertoast:import { toast } from "sonner"thentoast.error("Message").
- Document function parameters and return values with JSDoc
@param/@returnsfor shared utilities. - Use
@typedefin@/types/lecture.jsfor shared object shapes. - Add a dummy
export const Types = {}when a types file has no runtime export.
src/
pages/ — Route-level page components (one per route)
components/
ui/ — Reusable primitives (button, card, input)
charts/ — Recharts-based chart components
context/ — React context providers (Auth, Theme)
hooks/ — Custom React hooks
lib/ — Shared utilities (cn helper)
utils/ — Domain logic (storage, analytics, pdf, ai)
types/ — JSDoc type definitions
- Do NOT add TypeScript — the project is JSX-only.
- Do NOT add test dependencies or test files unless explicitly requested.
- Do NOT introduce a backend or database — localStorage is the intentional data layer.
- Do NOT add barrel/index files.
- Do NOT convert existing
functiondeclarations to arrow functions or vice versa without reason.