Two files, one repository
skillrecordings/egghead-next ships 3 formats across 33 indexed files. The question worth asking is whether the second one says anything the first does not.
| Dimension | Shared | Only in A | Only in B | Overlap |
|---|---|---|---|---|
| Sections | 0 | 2 | 24 | 0% |
| Commands | 0 | 0 | 11 | 0% |
| Section tags | 1 | 0 | 11 | 8% |
What each file covers
Sections
0 shared · 2 only in A · 24 only in B- − Agent Notes
- − Logging
- + CLAUDE.md
- + Project Overview
- + Essential Commands
- + Install dependencies (MUST use pnpm)
- + Development
- + Testing
- + Code Quality
- + Sanity CMS
- + Architecture Overview
- + Tech Stack
- + Directory Structure
- + Key Patterns
- + Preferred Code Organization Structure
- + Development Setup
- + Testing Approach
- + Pre-commit Checks
- + Common Tasks
- + Adding a New Page
- + Creating Components
- + Working with tRPC
- + Important Notes
- + Working with Course Builder Database
- + Database Connection
- + Important Patterns
Commands
0 shared · 0 only in A · 11 only in B- + pnpm install
- + pnpm dev
- + pnpm dev:concurrent
- + pnpm test
- + pnpm test:ci
- + pnpm lint
- + pnpm format
- + pnpm build
- + pnpm sanity
- + pnpm test -- path/to/test
- + pnpm
Section tags
1 shared · 0 only in A · 11 only in B- + setup
- + build
- + test
- + lint-format
- + code-style
- + architecture
- + types
- + testing-strategy
- + git-pr
- + dependencies
- + database
- agent-behaviour
Line diff
skillrecordings/egghead-next · AGENTS.md
@@ −1 @@
1# Agent Notes
2
3## Logging
4
5- Do not add direct `console.*` logging in application code. Use the shared structured logger from `src/utils/structured-log.ts`.
6- Runtime skip, fallback, and handled-error paths should emit structured `logEvent(...)` entries with stable event names and object payloads.
7- Logging must respect `LOG_LEVEL=off` and `--no-log`; when disabled, suppress log output.
8
skillrecordings/egghead-next · CLAUDE.md
@@ +1 @@
1# CLAUDE.md
2
3This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4
5## Project Overview
6
7This is the Next.js frontend for egghead.io, an online learning platform. It requires the `egghead-rails` backend to be running for full functionality.
8
9## Essential Commands
10
11```bash
12# Install dependencies (MUST use pnpm)
13pnpm install
14
15# Development
16pnpm dev # Start Next.js dev server on port 3000
17pnpm dev:concurrent # Run dev server + Inngest dev server
18
19# Testing
20pnpm test # Run tests in watch mode
21pnpm test:ci # Run tests once (for CI)
22
23# Code Quality
24pnpm lint # Run ESLint with auto-fix
25pnpm format # Run Prettier on all files
26pnpm build # Production build (also runs type checking)
27
28# Sanity CMS
29pnpm sanity # Start Sanity Studio
30```
31
32## Architecture Overview
33
34### Tech Stack
35
36- **Framework**: Next.js 14.2.4 with React 18.3.1
37- **Language**: TypeScript with strict mode
38- **Styling**: Tailwind CSS + CSS Modules
39- **State Management**: XState (state machines), React hooks, tRPC (server state)
40- **Database**: Postgres
41- **CMS**: Sanity
42- **Video**: Mux
43- **Payments**: Stripe
44- **Authentication**: Custom auth via app.egghead.io
45- **Search**: Typesense
46
47### Directory Structure
48
49```
50src/
51├── app/ # Next.js 13+ app directory (new routing)
52├── pages/ # Legacy pages directory (being migrated)
53├── components/ # React components (feature-based organization)
54├── lib/ # Core utilities and API clients
55├── server/ # tRPC routers and server-side logic
56├── hooks/ # Custom React hooks
57├── inngest/ # Event-driven background jobs
58├── machines/ # XState state machines
59└── utils/ # Pure utility functions
60```
61
62### Key Patterns
63
641. **Component Organization**: Feature-based folders (e.g., `components/posts/`, `components/workshop/claude-code/`)
652. **Path Aliases**: Use `@/` for imports from `src/` directory
663. **Data Fetching**: Use tRPC for type-safe API calls
674. **Styling**: Prefer Tailwind utilities, use CSS modules for complex styles
685. **State Machines**: Use XState for complex UI states
696. **Testing**: Co-locate tests in `__tests__` folders or `*.test.ts` files
707. **Code Organization**: Follow separation of concerns - extract schemas, database logic, and UI components into separate modules
71
72### Preferred Code Organization Structure
73
74When working with large files or creating new features, follow this separation of concerns pattern:
75
76#### 1. Schemas and Types (`src/schemas/`)
77
78- Extract all Zod schemas and TypeScript types into dedicated schema files
79- Example: `src/schemas/post.ts` for post-related types
80- Export both schemas and inferred types: `export type Post = z.infer<typeof PostSchema>`
81
82#### 2. Database Operations (`src/lib/[feature]/` or `src/lib/[feature]-query.ts`)
83
84- Extract database queries and data fetching logic
85- Use `'use server'` directive for server-side operations
86- Create utility functions for common operations
87- Structure:
88 ```
89 src/lib/posts/
90 ├── get-post.ts # Main data fetching
91 ├── get-tags.ts # Related data fetching
92 ├── get-course.ts # Associated data
93 └── utils.ts # Utility functions
94 src/lib/posts-query.ts # Main export file
95 ```
96
97#### 3. UI Components (`src/components/[feature]/`)
98
99- Extract reusable UI components into feature folders
100- Keep components focused on single responsibilities
101- Include prop interfaces and proper TypeScript types
102- Structure:
103 ```
104 src/components/posts/
105 ├── post-player.tsx # Main interactive components
106 ├── instructor-profile.tsx # Data display components
107 ├── tag-list.tsx # List components
108 ├── powered-by-mux.tsx # Utility components
109 └── icons/
110 └── github-icon.tsx # Icon components
111 ```
112
113#### 4. Main Page/Route Files
114
115- Keep page files focused on orchestration and layout
116- Import from extracted modules rather than inline definitions
117- Target: Reduce page files to ~200-300 lines maximum
118- Handle only: data fetching orchestration, layout, and SEO
119
120**When to apply this structure:**
121
122- Files exceeding 500+ lines
123- Multiple responsibilities in a single file (data fetching + UI + types)
124- Difficulty finding specific functionality
125- Need to reuse components elsewhere
126- Components that could benefit from isolated testing
127
128**Benefits of this approach:**
129
130- **Maintainability**: Each piece has a single responsibility
131- **Testability**: Components and functions can be tested in isolation
132- **Reusability**: Components can be used elsewhere in the app
133- **Performance**: Better code splitting and bundle optimization
134- **Developer Experience**: Easier to find and modify specific functionality
135
136**Real-world example:** The `src/pages/[post].tsx` was refactored from 967 lines to 262 lines following this pattern.
137
138## Development Setup
139
1401. Ensure Node.js 18.17.1 is installed (check `.nvmrc`)
1412. Install dependencies: `pnpm install`
1423. Pull environment variables: `vercel env pull .env.local`
1434. Start the Rails backend: `cd ../egghead-rails && foreman start`
1445. Configure Stripe webhooks if working with payments
1456. Start development: `pnpm dev`
146
147## Testing Approach
148
149- Jest with React Testing Library
150- Tests live alongside source files
151- Run single test: `pnpm test -- path/to/test`
152- Mock external dependencies (Stripe, Mux, etc.)
153- Use XState testing utilities for state machines
154
155## Pre-commit Checks
156
157Husky automatically runs:
158
1591. Prettier formatting on all files
1602. ESLint with auto-fix on TypeScript files
161
162## Common Tasks
163
164### Adding a New Page
165
166- Use app directory: `src/app/your-page/page.tsx`
167- Follow existing patterns for data fetching and layouts
168
169### Creating Components
170
171- Check existing components first for patterns (see `src/components/posts/` for reference)
172- Use TypeScript interfaces for props
173- Follow accessibility best practices
174- Extract components into feature-based folders (e.g., `src/components/[feature]/`)
175- Keep components focused on single responsibilities
176- For large page files, extract UI components following the preferred code organization structure
177
178### Working with tRPC
179
180- Routers in `src/server/routers/`
181- Use `trpc.useQuery()` for data fetching
182- Type safety is automatic
183
184### Sanity CMS
185
186- Studio runs at `/studio`
187- Schema files in `studio/schemas/`
188- Use GROQ queries for data fetching
189
190## Important Notes
191
192- Always use `pnpm` (not npm or yarn)
193- The project uses both app/ and pages/ directories (migration in progress)
194- Environment variables come from Vercel
195- Backend must be running for most features
196- Check `src/lib/` for existing utilities before creating new ones
197
198## Working with Course Builder Database
199
200The project integrates with a separate Course Builder database for new course content. Key patterns:
201
202### Database Connection
203
204- Uses `mysql2/promise` with connection pooling
205- Connection string from `COURSE_BUILDER_DATABASE_URL` env var
206- Always use the existing `getConnectionPool()` function in `src/lib/get-course-builder-metadata.ts`
207
208### Important Patterns
209
2101. **Server-Side Only**: MySQL connections must run server-side only
211
212 - Create wrapper functions that check `typeof window === 'undefined'`
213 - Use dynamic imports inside the wrapper: `await import('./get-course-builder-metadata')`
214 - Never import mysql2 directly in files that could be bundled for client
215 - See `load-course-builder-metadata-wrapper.ts` for the pattern
216
2172. **Query Patterns**:
218
219 - Content is stored in `egghead_ContentResource` table
220 - Use flexible slug matching: `id = ? OR JSON_UNQUOTE(JSON_EXTRACT(fields, '$.slug')) = ?`
221 - Fields are JSON, parse with: `typeof row.fields === 'string' ? JSON.parse(row.fields) : row.fields`
222
2233. **Content Types**:
224
225 - Posts with `type = 'post'` and `fields.postType = 'course'` are courses
226 - Video resources have `type = 'videoResource'`
227 - Relationships via `egghead_ContentResourceResource` join table
228
2294. **Error Handling**:
230 - Always release connections in finally block: `conn.release()`
231 - Return `null` for missing data, not errors
232 - Log helpful debug messages for troubleshooting
233
@@ −1 +1 @@
1−# Agent Notes
1+# CLAUDE.md
22
3−## Logging
3+This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
44
5−- Do not add direct `console.*` logging in application code. Use the shared structured logger from `src/utils/structured-log.ts`.
6−- Runtime skip, fallback, and handled-error paths should emit structured `logEvent(...)` entries with stable event names and object payloads.
7−- Logging must respect `LOG_LEVEL=off` and `--no-log`; when disabled, suppress log output.
5+## Project Overview
6+
7+This is the Next.js frontend for egghead.io, an online learning platform. It requires the `egghead-rails` backend to be running for full functionality.
8+
9+## Essential Commands
10+
11+```bash
12+# Install dependencies (MUST use pnpm)
13+pnpm install
14+
15+# Development
16+pnpm dev # Start Next.js dev server on port 3000
17+pnpm dev:concurrent # Run dev server + Inngest dev server
18+
19+# Testing
20+pnpm test # Run tests in watch mode
21+pnpm test:ci # Run tests once (for CI)
22+
23+# Code Quality
24+pnpm lint # Run ESLint with auto-fix
25+pnpm format # Run Prettier on all files
26+pnpm build # Production build (also runs type checking)
27+
28+# Sanity CMS
29+pnpm sanity # Start Sanity Studio
30+```
31+
32+## Architecture Overview
33+
34+### Tech Stack
35+
36+- **Framework**: Next.js 14.2.4 with React 18.3.1
37+- **Language**: TypeScript with strict mode
38+- **Styling**: Tailwind CSS + CSS Modules
39+- **State Management**: XState (state machines), React hooks, tRPC (server state)
40+- **Database**: Postgres
41+- **CMS**: Sanity
42+- **Video**: Mux
43+- **Payments**: Stripe
44+- **Authentication**: Custom auth via app.egghead.io
45+- **Search**: Typesense
46+
47+### Directory Structure
48+
49+```
50+src/
51+├── app/ # Next.js 13+ app directory (new routing)
52+├── pages/ # Legacy pages directory (being migrated)
53+├── components/ # React components (feature-based organization)
54+├── lib/ # Core utilities and API clients
55+├── server/ # tRPC routers and server-side logic
56+├── hooks/ # Custom React hooks
57+├── inngest/ # Event-driven background jobs
58+├── machines/ # XState state machines
59+└── utils/ # Pure utility functions
60+```
61+
62+### Key Patterns
63+
64+1. **Component Organization**: Feature-based folders (e.g., `components/posts/`, `components/workshop/claude-code/`)
65+2. **Path Aliases**: Use `@/` for imports from `src/` directory
66+3. **Data Fetching**: Use tRPC for type-safe API calls
67+4. **Styling**: Prefer Tailwind utilities, use CSS modules for complex styles
68+5. **State Machines**: Use XState for complex UI states
69+6. **Testing**: Co-locate tests in `__tests__` folders or `*.test.ts` files
70+7. **Code Organization**: Follow separation of concerns - extract schemas, database logic, and UI components into separate modules
71+
72+### Preferred Code Organization Structure
73+
74+When working with large files or creating new features, follow this separation of concerns pattern:
75+
76+#### 1. Schemas and Types (`src/schemas/`)
77+
78+- Extract all Zod schemas and TypeScript types into dedicated schema files
79+- Example: `src/schemas/post.ts` for post-related types
80+- Export both schemas and inferred types: `export type Post = z.infer<typeof PostSchema>`
81+
82+#### 2. Database Operations (`src/lib/[feature]/` or `src/lib/[feature]-query.ts`)
83+
84+- Extract database queries and data fetching logic
85+- Use `'use server'` directive for server-side operations
86+- Create utility functions for common operations
87+- Structure:
88+ ```
89+ src/lib/posts/
90+ ├── get-post.ts # Main data fetching
91+ ├── get-tags.ts # Related data fetching
92+ ├── get-course.ts # Associated data
93+ └── utils.ts # Utility functions
94+ src/lib/posts-query.ts # Main export file
95+ ```
96+
97+#### 3. UI Components (`src/components/[feature]/`)
98+
99+- Extract reusable UI components into feature folders
100+- Keep components focused on single responsibilities
101+- Include prop interfaces and proper TypeScript types
102+- Structure:
103+ ```
104+ src/components/posts/
105+ ├── post-player.tsx # Main interactive components
106+ ├── instructor-profile.tsx # Data display components
107+ ├── tag-list.tsx # List components
108+ ├── powered-by-mux.tsx # Utility components
109+ └── icons/
110+ └── github-icon.tsx # Icon components
111+ ```
112+
113+#### 4. Main Page/Route Files
114+
115+- Keep page files focused on orchestration and layout
116+- Import from extracted modules rather than inline definitions
117+- Target: Reduce page files to ~200-300 lines maximum
118+- Handle only: data fetching orchestration, layout, and SEO
119+
120+**When to apply this structure:**
121+
122+- Files exceeding 500+ lines
123+- Multiple responsibilities in a single file (data fetching + UI + types)
124+- Difficulty finding specific functionality
125+- Need to reuse components elsewhere
126+- Components that could benefit from isolated testing
127+
128+**Benefits of this approach:**
129+
130+- **Maintainability**: Each piece has a single responsibility
131+- **Testability**: Components and functions can be tested in isolation
132+- **Reusability**: Components can be used elsewhere in the app
133+- **Performance**: Better code splitting and bundle optimization
134+- **Developer Experience**: Easier to find and modify specific functionality
135+
136+**Real-world example:** The `src/pages/[post].tsx` was refactored from 967 lines to 262 lines following this pattern.
137+
138+## Development Setup
139+
140+1. Ensure Node.js 18.17.1 is installed (check `.nvmrc`)
141+2. Install dependencies: `pnpm install`
142+3. Pull environment variables: `vercel env pull .env.local`
143+4. Start the Rails backend: `cd ../egghead-rails && foreman start`
144+5. Configure Stripe webhooks if working with payments
145+6. Start development: `pnpm dev`
146+
147+## Testing Approach
148+
149+- Jest with React Testing Library
150+- Tests live alongside source files
151+- Run single test: `pnpm test -- path/to/test`
152+- Mock external dependencies (Stripe, Mux, etc.)
153+- Use XState testing utilities for state machines
154+
155+## Pre-commit Checks
156+
157+Husky automatically runs:
158+
159+1. Prettier formatting on all files
160+2. ESLint with auto-fix on TypeScript files
161+
162+## Common Tasks
163+
164+### Adding a New Page
165+
166+- Use app directory: `src/app/your-page/page.tsx`
167+- Follow existing patterns for data fetching and layouts
168+
169+### Creating Components
170+
171+- Check existing components first for patterns (see `src/components/posts/` for reference)
172+- Use TypeScript interfaces for props
173+- Follow accessibility best practices
174+- Extract components into feature-based folders (e.g., `src/components/[feature]/`)
175+- Keep components focused on single responsibilities
176+- For large page files, extract UI components following the preferred code organization structure
177+
178+### Working with tRPC
179+
180+- Routers in `src/server/routers/`
181+- Use `trpc.useQuery()` for data fetching
182+- Type safety is automatic
183+
184+### Sanity CMS
185+
186+- Studio runs at `/studio`
187+- Schema files in `studio/schemas/`
188+- Use GROQ queries for data fetching
189+
190+## Important Notes
191+
192+- Always use `pnpm` (not npm or yarn)
193+- The project uses both app/ and pages/ directories (migration in progress)
194+- Environment variables come from Vercel
195+- Backend must be running for most features
196+- Check `src/lib/` for existing utilities before creating new ones
197+
198+## Working with Course Builder Database
199+
200+The project integrates with a separate Course Builder database for new course content. Key patterns:
201+
202+### Database Connection
203+
204+- Uses `mysql2/promise` with connection pooling
205+- Connection string from `COURSE_BUILDER_DATABASE_URL` env var
206+- Always use the existing `getConnectionPool()` function in `src/lib/get-course-builder-metadata.ts`
207+
208+### Important Patterns
209+
210+1. **Server-Side Only**: MySQL connections must run server-side only
211+
212+ - Create wrapper functions that check `typeof window === 'undefined'`
213+ - Use dynamic imports inside the wrapper: `await import('./get-course-builder-metadata')`
214+ - Never import mysql2 directly in files that could be bundled for client
215+ - See `load-course-builder-metadata-wrapper.ts` for the pattern
216+
217+2. **Query Patterns**:
218+
219+ - Content is stored in `egghead_ContentResource` table
220+ - Use flexible slug matching: `id = ? OR JSON_UNQUOTE(JSON_EXTRACT(fields, '$.slug')) = ?`
221+ - Fields are JSON, parse with: `typeof row.fields === 'string' ? JSON.parse(row.fields) : row.fields`
222+
223+3. **Content Types**:
224+
225+ - Posts with `type = 'post'` and `fields.postType = 'course'` are courses
226+ - Video resources have `type = 'videoResource'`
227+ - Relationships via `egghead_ContentResourceResource` join table
228+
229+4. **Error Handling**:
230+ - Always release connections in finally block: `conn.release()`
231+ - Return `null` for missing data, not errors
232+ - Log helpful debug messages for troubleshooting
8233
