diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md new file mode 100644 index 0000000..8cb1721 --- /dev/null +++ b/.github/copilot-instructions.md @@ -0,0 +1,305 @@ +# SwitchbackTech Organization - GitHub Copilot Instructions + +## Organization Overview + +**Mission**: Building intentional software that helps people value their time. + +**Primary Product**: Compass Calendar - a minimalist weekly planner that integrates seamlessly with Google Calendar, designed for people who want to reclaim control over their schedule without overwhelming complexity. + +**Philosophy**: +- Intentional software design - every feature serves a clear purpose +- Minimalist user experience - powerful functionality without clutter +- Time-conscious development - respect both user time and developer time +- Open source and community-driven + +## Tech Stack & Architecture + +### Core Technologies +- **Frontend**: React 18+, TypeScript, Styled Components +- **Backend**: Node.js, Express.js, TypeScript +- **Database**: MongoDB with Mongoose ODM +- **Real-time**: Socket.io for live updates +- **Authentication**: Supertokens for session management +- **Testing**: Jest, React Testing Library +- **Build**: Webpack, Yarn workspaces (monorepo) +- **Cloud**: Google Cloud Platform +- **Integration**: Google Calendar API, Google OAuth + +### Architecture Patterns +- **Monorepo Structure**: Use Yarn workspaces with packages/* organization +- **Clean Architecture**: Separate concerns between core business logic, API, and UI +- **Component-Driven**: React components should be reusable and composable +- **Type Safety**: Strict TypeScript configuration with proper type definitions +- **Functional Programming**: Prefer pure functions and immutable data patterns + +## Coding Standards & Conventions + +### General Principles +1. **Clarity over cleverness** - code should be immediately understandable +2. **Consistency** - follow established patterns within each package +3. **Performance-conscious** - especially for calendar rendering and real-time updates +4. **Accessibility** - semantic HTML and ARIA labels for screen readers +5. **Mobile-first** - responsive design starting from mobile viewport + +### TypeScript Guidelines +- Use strict mode with `noImplicitAny` and `strictNullChecks` +- Prefer interfaces over types for object shapes +- Use proper generic types for reusable components +- Export types alongside implementation code +- Use meaningful type names that describe the domain (e.g., `Schema_Event`, `Schema_GridEvent`) +- Use Zod schemas for runtime validation (e.g., `CoreEventSchema`, `GridEventSchema`) +- Extend base schemas when adding functionality (e.g., `GridEventSchema.extend()`) + +### React Best Practices +- Use functional components with hooks +- Keep components small and focused on single responsibility +- Use custom hooks for shared logic +- Prefer composition over inheritance +- Use React.memo() for performance optimization when needed +- Follow the "lift state up" principle for shared state + +### File & Folder Conventions +- Use kebab-case for file names +- Co-locate tests next to source files (not separate test directories) +- Use index.ts files for clean imports +- Group related functionality in feature folders +- Follow the existing package structure: `packages/{backend,core,web,scripts}` + +### Naming Conventions +- **Components**: PascalCase (e.g., `GridEvent`, `SomedayEventContainer`) +- **Functions**: camelCase with descriptive verbs (e.g., `createEvent`, `formatTimeSlot`) +- **Constants**: SCREAMING_SNAKE_CASE (e.g., `DEFAULT_TIME_ZONE`, `SOMEDAY_WEEKLY_LIMIT`) +- **Types/Interfaces**: PascalCase with descriptive names (e.g., `Schema_Event`, `Schema_GridEvent`) +- **Enum Values**: SCREAMING_SNAKE_CASE (e.g., `Priorities.UNASSIGNED`, `Origin.GOOGLE`) +- **Props Interfaces**: ComponentName + "Props" (e.g., `GridEventProps`, `EventFormProps`) + +## Domain-Specific Guidance + +### Domain-Specific Guidance + +### Calendar & Time Management +- Always consider time zones when working with dates +- Use dayjs for consistent date manipulation +- Implement proper handling for recurring events using `recurrence.rule` and `recurrence.eventId` +- Consider performance for large date ranges +- Maintain consistency with Google Calendar conventions +- Use proper field names: `startDate`/`endDate` (not `start`/`end`) +- Handle Google Calendar integration via `gEventId` and `gRecurringEventId` fields + +### User Experience Priorities +1. **Speed**: Calendar operations should feel instantaneous +2. **Simplicity**: Default to the simplest solution that works +3. **Shortcuts**: Power users should have keyboard shortcuts +4. **Offline resilience**: Graceful degradation when offline +5. **Minimal clicks**: Reduce the number of interactions needed + +## Repository-Specific Guidelines + +### `compass` (Main Application) +- Follow the existing monorepo structure with backend, core, and web packages +- Use the established testing patterns with Jest +- Maintain the existing component library patterns +- Consider Google Calendar sync implications for any data changes +- Test thoroughly with the staging environment before production + +### `compass-docs` (Documentation) +- Use Docusaurus conventions and components +- Keep documentation up-to-date with code changes +- Include code examples for complex features +- Maintain consistency with the main app's terminology + +### `.github` (Organization Config) +- Follow GitHub best practices for workflows and templates +- Keep organization-wide configurations minimal and focused +- Test any workflow changes in a fork first + +## Testing Requirements + +### Coverage Expectations +- **Unit Tests**: All business logic functions must have tests +- **Integration Tests**: API endpoints and database operations +- **Component Tests**: React components with user interaction scenarios +- **E2E Tests**: Critical user flows like event creation and sync + +### Testing Patterns +- Use descriptive test names that explain the scenario +- Follow Arrange-Act-Assert pattern +- Mock external dependencies (Google API, database) +- Test error conditions and edge cases +- Use factories or fixtures for test data + +## Performance Considerations + +### Frontend Performance +- Optimize calendar rendering for large date ranges +- Use React.memo() and useMemo() for expensive calculations +- Implement virtual scrolling for long lists +- Minimize re-renders during drag-and-drop operations +- Lazy load non-critical components + +### Backend Performance +- Use database indexes for calendar queries +- Implement proper caching for Google Calendar sync +- Use connection pooling for database operations +- Monitor and optimize API response times +- Consider rate limiting for external API calls + +## Security Guidelines + +### Data Protection +- Never log sensitive user data (calendar events, personal info) +- Use proper validation for all user inputs +- Implement CSRF protection for state-changing operations +- Follow OAuth best practices for Google integration +- Use environment variables for all sensitive configuration + +### Authentication & Authorization +- Use Supertokens for consistent session management +- Implement proper role-based access if needed +- Validate user permissions for calendar operations +- Use secure session cookies +- Implement proper logout functionality + +## Documentation & Learning Resources + +### Internal Documentation +- **Main docs**: https://docs.compasscalendar.com +- **Contributing guide**: Follow conventions at docs.compasscalendar.com/docs/contribute/convention-guide +- **Setup guide**: Available in main repository README +- **API documentation**: Generated from TypeScript types + +### External References +- **Google Calendar API**: https://developers.google.com/calendar +- **React best practices**: https://react.dev/learn +- **TypeScript handbook**: https://www.typescriptlang.org/docs/ +- **Accessibility guidelines**: https://www.w3.org/WAI/WCAG21/quickref/ + +## Common Patterns & Examples + +### Event Types and Interfaces +```typescript +// Core event interface from @core/types/event.types +interface Schema_Event { + _id?: string; + allDayOrder?: number; + description?: string | null | undefined; + endDate?: string; + isAllDay?: boolean; + isSomeday?: boolean; + gEventId?: string; + gRecurringEventId?: string; + order?: number; + origin?: Origin; + priority?: Priority; + recurrence?: { + rule?: string[]; + eventId?: string; + }; + startDate?: string; + title?: string; + updatedAt?: Date | string; + user?: string; +} + +// Grid event interface from @web/common/types/web.event.types +interface Schema_GridEvent extends Schema_Event { + hasFlipped?: boolean; + isOpen?: boolean; + row?: number; + position: { + isOverlapping: boolean; + widthMultiplier: number; + horizontalOrder: number; + dragOffset: { y: number }; + initialX: number | null; + initialY: number | null; + }; +} + +// Priority enum from @core/constants/core.constants +enum Priorities { + UNASSIGNED = "unassigned", + WORK = "work", + SELF = "self", + RELATIONS = "relationships", +} + +type Priority = Priorities.UNASSIGNED | Priorities.WORK | Priorities.SELF | Priorities.RELATIONS; +``` + +### Event Creation Pattern +```typescript +const createEvent = async (event: Omit): Promise => { + // Validate time boundaries with dayjs + const start = dayjs(event.startDate); + const end = dayjs(event.endDate); + + // Sync with Google Calendar if needed + // Store in local database + // Return created event with _id +}; +``` + +### Component Structure Pattern +```typescript +interface GridEventProps { + event: Schema_GridEvent; + isDraft: boolean; + isDragging: boolean; + isPlaceholder: boolean; + isResizing: boolean; + isRecurring: boolean; + isInPast: boolean; + measurements: Measurements_Grid; + onEventMouseDown: (event: Schema_GridEvent, e: MouseEvent) => void; + onScalerMouseDown: ( + event: Schema_GridEvent, + e: MouseEvent, + dateToChange: "startDate" | "endDate", + ) => void; + weekProps: WeekProps; +} + +export const GridEvent = memo(forwardRef( + ({ event, isDraft, isDragging, ...props }, ref) => { + const isRecurring = event.recurrence && event.recurrence?.eventId !== null; + const isInPast = dayjs().isAfter(dayjs(event.endDate)); + + return ( + + {/* Component implementation */} + + ); + } +)); +``` + +### Import Patterns +```typescript +import dayjs from "dayjs"; +import { Priorities, Origin } from "@core/constants/core.constants"; +import { Schema_Event, Schema_GridEvent } from "@core/types/event.types"; +import { Schema_GridEvent as WebGridEvent } from "@web/common/types/web.event.types"; +``` + +## Error Handling + +### Frontend Error Boundaries +- Use React Error Boundaries for component-level errors +- Provide meaningful error messages to users +- Log errors for debugging but never expose sensitive data +- Implement graceful fallbacks for failed operations + +### Backend Error Handling +- Use consistent error response format +- Log errors with appropriate context +- Handle Google API rate limits gracefully +- Provide retry mechanisms for transient failures + +Remember: The goal is to build software that genuinely improves how people manage their time, without adding unnecessary complexity to their lives or to the codebase. \ No newline at end of file