This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
pnpm dev- Start development server with preheat scriptpnpm build- Build production application (runs svelte build + file copying)pnpm check- Run TypeScript type checkingpnpm lint- Run prettier + eslint + stylelintpnpm test- Run Playwright testspnpm test:unit- Run Vitest unit tests
pnpm db:studio- Open Prisma Studio GUIpnpm db:generate- Generate Prisma clientpnpm db:push- Push schema changes to databasepnpm db:seed- Seed database with test datapnpm i-changed-the-schema- Shortcut for push + generate after schema changes
pnpm test:ui- Run Playwright tests with UIpnpm check:watch- Run TypeScript check in watch mode
- Frontend: SvelteKit with Svelte 5, TypeScript
- Backend: Node.js with SvelteKit server-side rendering
- Database: MySQL with Prisma ORM (PlanetScale)
- Caching: Redis (Upstash)
- Deployment: Vercel with Node.js 22.x runtime
- Monitoring: Sentry for error tracking
src/
├── routes/
│ ├── (site)/ # Main website layout
│ ├── (blank)/ # Clean layout for embeds
│ └── api/ # API endpoints
├── lib/ # Reusable components
├── server/ # Server-side logic and utilities
├── state/ # Svelte stores for client state
├── styles/ # CSS architecture with themes
├── actions/ # Svelte actions
└── utilities/ # Shared utilities
The application manages podcast content with these key models:
- Show: Episodes with metadata, transcripts, AI-generated content
- User: GitHub OAuth authentication with role-based access
- Guest: Guest profiles with social links and appearances
- Transcript: Full transcription with utterances and speaker identification
- Video: YouTube integration with playlists
- UserSubmission: User-generated content submissions
- Show notes are stored as markdown files in the
/shows/directory - AI-generated content (summaries, tweets, show notes) using OpenAI/Anthropic
- Automated transcription via Deepgram
- Multi-layer caching with Redis for performance
- Components: PascalCase for
.sveltefiles (e.g.,ShowCard.svelte) - Variables/Functions: snake_case for variables, functions, and props
- Constants: UPPER_CASE for true constants only
- Types: PascalCase for TypeScript interfaces
- Use
$statefor reactive state declarations - Use
$derivedfor computed values - Use
$effectfor side effects and lifecycle - Use
$propsfor component props with destructuring - Use
$bindablefor two-way bindable props - Use classes for complex state management (state machines)
- CSS variables defined in
src/styles/variables.css - Use
bgandfgconvention for background/foreground colors - Custom media queries for responsive design:
@custom-media --below-med (width < 700px); @custom-media --above-med (width > 700px);
- Components: Group related components in
/src/lib/ - Routes: Use SvelteKit's file-based routing with layout groups
- State: Svelte stores in
/src/state/for global state - Server: All server-side logic in
/src/server/
- Advanced web audio player with offline support
- Media Session API integration
- Position saving and resume functionality
- Service worker for offline playback
- Client-side search using FlexSearch
- Web workers for non-blocking search
- Fuzzy search across shows, guests, and transcripts
- Role-based access control
- Content management for shows and guests
- AI content generation tools
- Transcript management
- Redis caching for database queries
- IndexedDB for offline data storage
- Aggressive caching strategies
- Service worker for offline functionality
- Create components in
/src/lib/for reusable UI - Add routes in
/src/routes/following the layout structure - Use Prisma for database operations via
/src/server/prisma-client.ts - Implement caching for database queries using the cache utilities
- Add proper TypeScript types and error handling
- Modify
/prisma/schema.prisma - Run
pnpm i-changed-the-schemato apply changes - Update seed data if needed in
/prisma/seed.ts
- Use Playwright for integration tests
- Use Vitest for unit tests
- Run linting before commits
- Test across different screen sizes and devices
- Application deploys to Vercel automatically
- Environment variables managed through Vercel dashboard
- Database hosted on PlanetScale
- Redis cache on Upstash
// For complex state, use classes
class PlayerState {
currentShow = $state<Show | null>(null);
isPlaying = $state(false);
play() {
this.isPlaying = true;
}
}
export const playerState = new PlayerState();// Use the cached prisma client
import { prisma } from '$server/prisma-client';
// Cache database queries
const shows = await prisma.show.findMany({
where: { show_type: 'TASTY' },
orderBy: { number: 'desc' }
});<script lang="ts">
import { playerState } from '$state/player.svelte';
let { show } = $props<{ show: Show }>();
let isPlaying = $derived(playerState.currentShow?.id === show.id);
</script>
<div class="show-card">
<h3>{show.title}</h3>
<button onclick={() => playerState.play(show)}>
{isPlaying ? 'Pause' : 'Play'}
</button>
</div>Remember to follow the existing code conventions and patterns when adding new features or modifying existing code.