-
Notifications
You must be signed in to change notification settings - Fork 15
Expand file tree
/
Copy path.cursorrules
More file actions
157 lines (121 loc) · 6.83 KB
/
.cursorrules
File metadata and controls
157 lines (121 loc) · 6.83 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
# Berkeleytime Codebase Rules
## Project Overview
Berkeleytime is a course discovery and planning tool for UC Berkeley students. It combines academic information from UC Berkeley's Office of the Registrar and Engineering Integration Services (EIS) to provide students with course data, schedules, ratings, and planning tools.
## Architecture
This is a **monorepo** using Turbo for build orchestration. The codebase is organized into:
- **Apps**: All stored in the `app/` directory (backend, frontend, datapuller are the main ones)
- **Packages**: Shared code in `packages/` (theme, common, gql-typedefs, sis-api, shared, etc.)
- **Infrastructure**: Kubernetes/Helm charts in `infra/`
## Tech Stack
### Backend (`apps/backend`)
- **Runtime**: Node.js (>=22.12.0) with TypeScript
- **Framework**: Express.js
- **API**: Apollo GraphQL Server
- **Database**: MongoDB (Mongoose ORM)
- **Cache**: Redis
- **Auth**: Passport.js
### Frontend (`apps/frontend`)
- **Framework**: React with TypeScript
- **Build Tool**: Vite
- **GraphQL Client**: Apollo Client
- **Styling**: SCSS Modules
- **UI Components**: Custom components from `@repo/theme` (Radix UI based)
- **Routing**: React Router
### Other Services
- **Datapuller**: Service for pulling data from UC Berkeley APIs
- **Docs**: mdBook documentation site
- **Staff/AG Frontends**: Admin interfaces
## Code Organization Patterns
### Backend Modules (`apps/backend/src/modules/`)
Backend follows a **module-based architecture**. Each module represents a domain (User, Course, Rating, etc.) and follows this structure:
```
modules/[domain]/
├── typedefs/ # GraphQL schema definitions
├── generated-types/ # Generated TypeScript types (DO NOT EDIT)
├── controller.ts # Database querying functions (Mongoose)
├── formatter.ts # Optional: DB models → GraphQL types
├── resolver.ts # GraphQL resolvers
└── index.ts # Module entrypoint
```
**Pipeline**: Request → Resolver → Controller → Database → Formatter → Response
- **DO NOT** edit files in `generated-types/` directories - they are auto-generated
- Use GraphQL Code Generation: run `npm run generate` in backend after schema changes
- Controllers use Mongoose to query MongoDB
- Formatters translate DB models to GraphQL types (only if types differ)
### Frontend Structure (`apps/frontend/src/`)
```
src/
├── app/ # Views, pages, and scoped components
├── components/ # Reusable React components
├── contexts/ # React contexts
├── hooks/ # React hooks
├── lib/ # Utility functions and logic
│ └── api/ # GraphQL queries, mutations, and types
└── utils/ # Utility functions
```
- Use **SCSS Modules** for component styling: `[Component].module.scss`
- Component folders: `index.tsx` + `[Component].module.scss`
- Child components should be extracted when logic becomes complex or reusable
- Reusable Berkeleytime-specific components (such as a ClassCard) should be put in `components/`
- Reusable generic components (like a Select) should be put in the parent `packages/theme/src/components` folder
## Conventions
### TypeScript
- Use strict TypeScript
- Generate types from GraphQL schemas - don't write them manually for API query related types
- Use generated types from `generated-types/` directories
### GraphQL
- Overall schemas defined in `packages/gql-typedefs`
- **Backend**: Resolvers are defined in in `resolver.ts`
- **Frontend**: Define queries/mutations in `lib/api/`, use Apollo Client hooks
- Always run `npm run generate` after GraphQL schema changes
- Use GraphQL Code Generation for type safety
### Styling
- Use SCSS Modules (`.module.scss`) for component styles
- Use Bootstrap utility classes (`m-*`, `p-*`) for simple spacing when appropriate
- Import styles: `import styles from "./Component.module.scss"`
- Use/extend `@repo/theme` components when available instead of building custom ones
### File Naming
- Components: PascalCase (`RatingButton.tsx`)
- Utilities/hooks: camelCase (`ratingErrorMessages.ts`, `useReadClass.ts`)
- SCSS modules: `[Component].module.scss`
## Shared Packages
- **`@repo/theme`**: UI component library (Radix UI primitives + Berkeleytime-specific)
- **`@repo/common`**: Shared utilities and types
- **`@repo/gql-typedefs`**: Shared GraphQL type definitions
- **`@repo/sis-api`**: Auto-generated TypeScript clients for UC Berkeley APIs
- **`@repo/shared`**: Shared business logic
Use these packages rather than duplicating code across apps.
## Development Workflow
1. **Type Generation**: Always run `npm run generate` after GraphQL changes
2. **Type-Check**: Uses `tsc` (`npm run type-check`)
3. **Linting**: Use ESLint (configured in `packages/eslint-config`, `npm run lint`)
4. **Formatting**: Prettier with import sorting (configured in `.prettierrc`)
5. **Docker**: Development uses Docker Compose. `docker compose up` will setup all services. Use the `--build` flag after significant changes, otherwise hot-reload is enabled.
6. **Turbo**: Use `npm run dev`, `npm run build`, etc. from root (Turbo handles orchestration)
## Important Notes
- **Generated Code**: Never edit `generated-types/`, `generated-typedefs/`, or `generated/` directories
- **Database Models**: Defined in `packages/common/src/models/` (Mongoose schemas)
- **Environment Variables**: Use `.env` files (see `.env.template`)
- **Monorepo**: Changes to packages may require rebuilding dependent apps
- **GraphQL Playground**: Available at `http://localhost:[DEV_PORT_BASE]/api/graphql` in dev mode
## When Adding Features
### Backend (GraphQL API)
1. Add GraphQL type definitions in module's `typedefs/`
2. Add controller functions for database queries
3. Add resolver functions that call controllers
4. Add formatter if DB model differs from GraphQL type
5. Run `npm run generate` to generate types
6. Export module in `src/modules/index.ts`
### Frontend (React Components)
1. Add GraphQL queries/mutations in `lib/api/`
2. Create components in `app/` (page-specific) or `components/` (reusable)
3. Use Apollo Client hooks (`useQuery`, `useMutation`). With these, always use the generated `...Document` types, NEVER the raw exported string.
4. Use SCSS Modules for styling
5. Use components from `@repo/theme` when possible
6. Try to use Apollo GraphQL's caching patterns when possible
7. Use color CSS variables defined in `packages/theme/src/components/ThemeProvider/ThemeProvider.scss` for consistency with light and dark mode
## Common Patterns
- **Error Handling**: Use GraphQL error codes (UNAUTHENTICATED, BAD_USER_INPUT, etc.)
- **Authentication**: Handled by Passport.js in backend, check auth status in resolvers
- **Caching**: Redis is used for caching - check backend code for cache patterns
- **Data Sources**: UC Berkeley APIs accessed via `@repo/sis-api` package