Skip to content
Draft
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
305 changes: 305 additions & 0 deletions .github/copilot-instructions.md
Original file line number Diff line number Diff line change
@@ -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<Schema_Event, '_id'>): Promise<Schema_Event> => {
// 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<HTMLDivElement, GridEventProps>(
({ event, isDraft, isDragging, ...props }, ref) => {
const isRecurring = event.recurrence && event.recurrence?.eventId !== null;
const isInPast = dayjs().isAfter(dayjs(event.endDate));

return (
<StyledEvent
ref={ref}
priority={event.priority || Priorities.UNASSIGNED}
isRecurring={isRecurring}
isDragging={isDragging}
// ... other props
>
{/* Component implementation */}
</StyledEvent>
);
}
));
```

### 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.