

Also from Kynth Studios


Also from Kynth Studios


Also from Kynth Studios
1# CLAUDE.md23This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.45## Project Overview67Boards is an open-source creative toolkit for AI-generated content (images, video, audio, text) built as a monorepo with both Python and TypeScript/JavaScript components.89## Architecture1011**Monorepo Structure:**1213- `/packages/` - Shared libraries (Python backend, React frontend)14- `/apps/` - Applications (Next.js example app, Docusaurus docs)15- `/design/` - Architecture and design documents1617**Tech Stack:**1819- **Backend**: Python 3.12 with SQLAlchemy + Supabase (storage and optional auth)20- **Frontend**: React + Next.js with TypeScript21- **Job System**: Framework-agnostic queue (RQ or Dramatiq) with workers22- **API**: GraphQL (Strawberry) with urql client; SSE for job progress23- **Infrastructure**: PostgreSQL, Redis (via Docker Compose)24- **Package Management**: pnpm (Node) and uv (Python)25- **Build System**: Turborepo for orchestrating builds2627## Essential Commands2829```bash30# Initial setup31make install # Install all dependencies (Python and Node)32make docker-up # Start PostgreSQL and Redis3334# Development35make dev # Start all development servers (backend + frontend)36make dev-backend # Start backend development server only37make dev-worker # Start background worker (development)38make dev-worker-watch # Start background worker with auto-reload (requires entr)39make dev-frontend # Start frontend development servers only40pnpm turbo dev # Alternative: start dev servers via Turbo4142# Documentation43make docs # Start documentation development server44make dev-docs # Start documentation development server (same as above)45make build-docs # Build documentation for production46make serve-docs # Serve built documentation4748# Testing49make test # Run all tests (Python pytest + Node tests)50make test-backend # Run backend (Python) tests only51make test-frontend # Run frontend (Node) tests only52pnpm turbo test # Run Node tests only via Turbo53uv run pytest tests/ # Run Python tests in a specific package5455# Code Quality56make lint # Run all linters (ruff, pyright for Python; ESLint for JS)57make lint-backend # Lint backend (Python) only58make lint-frontend # Lint frontend (Node) only59make typecheck # Run all type checking (Python and TypeScript)60make typecheck-backend # Typecheck backend (Python) only61make typecheck-frontend # Typecheck frontend (TypeScript) only62pnpm turbo lint # Run Node linters only via Turbo63pnpm turbo typecheck # Run TypeScript checking only via Turbo6465# Building66make build # Build all packages (Python and Node)67make build-backend # Build backend (Python) only68make build-frontend # Build frontend (Node) only69pnpm turbo build # Build Node packages only via Turbo7071# Docker Services72make docker-up # Start PostgreSQL and Redis73make docker-down # Stop services74make docker-logs # View service logs7576# Cleanup77make clean # Remove all build artifacts and dependencies78make clean-backend # Clean backend (Python) artifacts only79make clean-frontend # Clean frontend (Node) artifacts only8081# Other82make help # Show all available Makefile commands83```8485## Development Workflow86871. **Python packages**: Located in `/packages/*/` with `pyproject.toml` or `setup.py`. Installed in editable mode during setup using uv.882. **Node packages**: Managed via pnpm workspaces. Internal packages referenced as `workspace:*`.893. **Turbo pipeline**: Configured in `turbo.json` with build dependencies and caching.9091## Key Design Principles9293- **Hooks-first frontend design**: The toolkit ships React hooks, not mandatory UI components94- **Pluggable auth**: Support for multiple auth providers via adapters (Supabase, Clerk, Auth0, custom JWT/OIDC)95- **Observability**: Structured logs, job metrics, audit trail on credit transactions96- **GraphQL abstraction**: Example applications MUST NOT directly import from `urql` or GraphQL operations (e.g., `@weirdfingers/boards/graphql/operations`). All GraphQL usage must be abstracted behind hooks from `@weirdfingers/boards` (e.g., `useBoards`, `useBoard`, `useGenerators`). When adding new GraphQL functionality, create a hook in `/packages/frontend/src/hooks/` first, then use that hook in example applications.9798## Code Placement Guidelines99100**CRITICAL**: Boards is a toolkit of reusable packages, not just an application. Most code should go into published packages (`packages/`), not the application (`apps/baseboards`).101102### Published Packages103104The following packages are published to public registries:105106- **`packages/backend`** → PyPI (Python package for backends)107- **`packages/frontend`** → npm as `@weirdfingers/boards` (React hooks)108- **`packages/cli-launcher`** → npm (CLI tool for scaffolding/deployment)109- **Auth packages** → npm as `@weirdfingers/boards-auth-*` (separate packages per provider)110111### Package Decision Tree112113**When adding new code, ask:**1141151. **Is this specific to the Baseboards application UI/UX?**116117 - YES → `apps/baseboards`118 - NO → Continue to question 21191202. **Is this reusable toolkit functionality?**121122 - NO → Reconsider the design123 - YES → Continue to question 31241253. **Is this backend/server-side logic?**126127 - YES → `packages/backend`128 - NO → Continue to question 41291304. **Is this React/frontend logic?**131 - YES → `packages/frontend`132 - NO → Determine appropriate package (CLI, auth, etc.)133134### packages/backend (Python - Published to PyPI)135136**SHOULD contain:**137138- GraphQL schema definitions (Strawberry types and resolvers)139- SQLAlchemy models and database logic140- Business logic and service layer141- FastAPI/Starlette routes and middleware142- Auth plugins/adapters (backend auth logic)143- Job queue integration (RQ/Dramatiq workers)144- Database migrations145- Reusable utilities for backend development146147**SHOULD NOT contain:**148149- Application-specific business rules150- Hardcoded configuration for specific deployments151- Frontend-specific logic152153**Example:**154155```python156# ✅ Good - Generic board creation logic157@strawberry.mutation158def create_board(self, info: Info, input: CreateBoardInput) -> Board:159 """Create a new board - reusable across any Boards deployment"""160 board = Boards()161 board.title = input.title162 board.description = input.description163 # ... generic board creation logic164 return board165166# ❌ Bad - Application-specific business rule167@strawberry.mutation168def create_board(self, info: Info, input: CreateBoardInput) -> Board:169 """Create board with hardcoded Baseboards-specific limits"""170 if user.boards_count > 10: # Hardcoded limit specific to Baseboards app171 raise Exception("Maximum 10 boards")172 # ...173```174175### packages/frontend (React/TypeScript - Published to npm)176177**SHOULD contain:**178179- React hooks for all Boards functionality180- GraphQL operations and fragments181- urql client configuration and exchanges182- TypeScript type definitions for GraphQL responses183- Generic, unstyled React components (sparingly - favor hooks)184- Frontend auth adapters (Supabase, Clerk integration)185- SSE/WebSocket utilities186- Reusable state management utilities187188**MUST be framework-agnostic:**189190- React only (no Next.js-specific code)191- Should work with Remix, Vite, Create React App, etc.192- No `next/router`, `next/navigation`, `next/image`, etc.193194**Components policy:**195196- Favor hooks over components197- If shipping components, they MUST support:198 - Arbitrary theming (no hardcoded styles)199 - Accessibility (a11y)200 - Internationalization (i18n)201- When in doubt, ship a hook and let apps build their own UI202203**SHOULD NOT contain:**204205- Next.js-specific code206- Styled/opinionated components207- Application business logic208- Direct imports that bypass hooks (apps importing from `/graphql/operations` directly)209210**Example:**211212```typescript213// ✅ Good - Generic hook for any React app214export function useBoards() {215 const [result] = useQuery({ query: BoardsQuery });216 return {217 boards: result.data?.boards ?? [],218 loading: result.fetching,219 error: result.error,220 };221}222223// ✅ Good - Unstyled, accessible component224export function BoardCard({ board, className, onSelect }: BoardCardProps) {225 return (226 <article227 className={className}228 role="button"229 aria-label={board.title}230 onClick={() => onSelect?.(board)}231 >232 {/* Minimal, unstyled structure */}233 </article>234 );235}236237// ❌ Bad - Next.js-specific code238import { useRouter } from "next/navigation";239export function useBoards() {240 const router = useRouter(); // Not framework-agnostic!241 // ...242}243244// ❌ Bad - Styled, opinionated component245export function BoardCard({ board }: BoardCardProps) {246 return (247 <div className="bg-blue-500 rounded-lg p-4 shadow-xl">248 {/* Hardcoded Tailwind styles - should be in app */}249 </div>250 );251}252```253254### apps/baseboards (Next.js - Published via Docker)255256**Purpose:** Baseboards serves dual roles:2572581. **Reference implementation** - demonstrates best practices for using the packages2592. **Standalone application** - production-ready Boards instance deployable via Docker260261**SHOULD contain:**262263- Next.js pages, layouts, and routing264- UI components with styling (Tailwind, Radix UI, etc.)265- Application-specific configuration (environment variables, themes)266- Sensible defaults that users can deploy as-is267- Example flows demonstrating package usage268- Generic application logic (not overly opinionated)269270**SHOULD import:**271272- Hooks from `@weirdfingers/boards`273- Types from `@weirdfingers/boards`274275**SHOULD NOT import:**276277- Direct urql client usage (use hooks instead)278- GraphQL operations from `@weirdfingers/boards/graphql/operations`279- Anything that bypasses the hooks abstraction280281**SHOULD NOT contain:**282283- Reusable business logic (move to `packages/frontend` or `packages/backend`)284- Hardcoded business rules that make it too opinionated285- Backend logic (keep in `packages/backend`)286287**Philosophy:** Baseboards should be both:288289- Generic enough to deploy unchanged for most use cases290- Well-structured enough to serve as a customization starting point291292**Example:**293294```typescript295// ✅ Good - Uses hooks from the package296import { useBoards, useCreateBoard } from "@weirdfingers/boards";297298export function BoardsPage() {299 const { boards, loading } = useBoards();300 const createBoard = useCreateBoard();301302 return (303 <div className="container mx-auto">304 {/* Baseboards-specific styled UI */}305 {boards.map((board) => (306 <StyledBoardCard key={board.id} board={board} />307 ))}308 </div>309 );310}311312// ❌ Bad - Bypasses hooks, imports GraphQL directly313import { useQuery } from "urql";314import { BoardsQuery } from "@weirdfingers/boards/graphql/operations";315316export function BoardsPage() {317 const [result] = useQuery({ query: BoardsQuery }); // Should use useBoards() hook318 // ...319}320321// ❌ Bad - Reusable logic that should be in packages/frontend322export function useBoardValidation() {323 // This is generic logic that other apps would need - move to packages/frontend!324 return { validateTitle, validateDescription };325}326```327328### packages/cli-launcher (Node.js - Published to npm)329330**SHOULD contain:**331332- CLI commands for project scaffolding333- Docker deployment utilities334- Development environment setup335336**SHOULD NOT contain:**337338- Application business logic339- Backend/frontend code (import from published packages instead)340341### Auth Packages (Published to npm)342343**Available packages:**344345- `@weirdfingers/boards-auth-supabase` - Supabase authentication provider346- `@weirdfingers/boards-auth-clerk` - Clerk authentication provider347- `@weirdfingers/boards-auth-jwt` - JWT authentication provider348- `@weirdfingers/boards-auth-auth0` (placeholder) - Auth0 authentication provider349350Each contains frontend auth adapter implementations for their respective providers.351352## Database Configuration353354Local development uses Docker Compose with:355356- PostgreSQL 15 on port 5433 (user: boards, password: boards_dev, database: boards_dev)357- Redis 7 on port 6380358359## Code Quality Rules360361### Type Checking and Testing362363- To typecheck the backend and frontend, run `make typecheck` at the root of the project364- To run tests for the backend and frontend, run `make test` at the root of the project365366### Logging367368- For backend logging, always use `@packages/backend/src/boards/logging.py` which is based on `structlog`369- Use keyword arguments for log data, avoid f-strings370- Never use `exc_info=True` in log statements371372### SQLAlchemy Object Creation373374**IMPORTANT**: When creating SQLAlchemy model instances, DO NOT pass properties as kwargs to the constructor. Instead, set properties explicitly after instantiation. This allows the type checker (pyright) to catch incorrect property names.375376**Bad** (kwargs bypass type checking):377378```python379new_board = Boards(380 tenant_id=tenant_uuid,381 owner_id=auth_context.user_id,382 title=input.title,383 descritpion=input.description, # Typo won't be caught!384)385```386387**Good** (explicit assignment catches typos):388389```python390new_board = Boards()391new_board.tenant_id = tenant_uuid392new_board.owner_id = auth_context.user_id393new_board.title = input.title394new_board.descritpion = input.description # Type checker will error!395```396397### Database Migrations: `updated_at` Triggers398399All tables with an `updated_at` column have a `BEFORE UPDATE` trigger that automatically sets `updated_at = CURRENT_TIMESTAMP`. When adding a new table with an `updated_at` column, you **must** also add a trigger for it in a migration:400401```python402op.execute("""403 CREATE TRIGGER trg_<table_name>_updated_at404 BEFORE UPDATE ON boards.<table_name>405 FOR EACH ROW406 EXECUTE FUNCTION boards.update_updated_at_column();407""")408```409410The shared trigger function `boards.update_updated_at_column()` already exists. Do **not** manually set `updated_at` in application code -- the trigger handles it.411412### GraphQL Schema Changes413414**CRITICAL**: When modifying GraphQL types in the backend, you MUST update the frontend in the same commit:4154161. **Backend changes** in `/packages/backend/src/boards/graphql/types/`:417418 - Update the Strawberry GraphQL type definition419 - If removing/renaming fields, grep the frontend codebase first4204212. **Frontend changes** that MUST be synchronized:422423 - Update GraphQL fragments in `/packages/frontend/src/graphql/operations.ts`424 - Update TypeScript interfaces in `/packages/frontend/src/hooks/`425 - Search for any component usage in example applications4264273. **Validation**: GraphQL queries that reference non-existent fields will fail at schema validation (before resolver execution), returning errors like "Cannot query field 'fieldName' on type 'TypeName'". This prevents resolvers from being called.428429**Example workflow when removing a field**:430431```bash432# 1. Remove from backend GraphQL type433# 2. Search frontend for references434grep -r "fieldName" packages/frontend apps/435# 3. Update all found references436# 4. Run typecheck to catch any missed TypeScript references437make typecheck438```439440### Git Commit Policy441442**IMPORTANT**: Claude Code must NEVER commit changes to git without being explicitly instructed to do so by the user.443444Claude Code should:445446- Make code changes as requested447- Run tests and verify changes448- Show git status and explain what files have been modified449- Suggest commit messages if helpful450451But Claude Code must NOT:452453- Run `git add` commands454- Run `git commit` commands455- Run `git push` commands456457Unless the user explicitly asks for commits to be made.458459**CRITICAL**: Claude Code must NEVER push to remote repositories unless explicitly instructed to commit changes, always ask the user to push manually. This prevents accidental pushes to production or shared branches.460461## Task Management462This project uses a CLI ticket system for task management. Run `tk help` when you need to use it.463
One repository carrying more than one format is the comparison this product exists for: does anyone actually write different content in each file, or is one a copy of the other?
| Repository | Format | Stack | Covers | Score | Changed |
|---|---|---|---|---|---|
| weirdfingers/boards.cursor/rules/backend-logging.mdc · 4 | Cursor rules | styledo-not | 41/100 | 14 days ago | |
| weirdfingers/boards.cursor/rules/no-graphql-in-examples.mdc · 4 | Cursor rules | api | 24/100 | 14 days ago | |
| weirdfingers/boards.cursor/rules/node-pnpm.mdc · 4 | Cursor rules | setupstyledependenciesmonorepo | 50/100 | 14 days ago | |
| weirdfingers/boards.cursor/rules/python-tooling.mdc · 4 | Cursor rules | setupteststyle | 67/100 | 14 days ago | |
| weirdfingers/boards.cursor/rules/test.mdc · 4 | Cursor rules | test | 34/100 | 14 days ago | |
| weirdfingers/boards.cursor/rules/typecheck.mdc · 4 | Cursor rules | no sections | 30/100 | 14 days ago |
Same format, overlapping stack, ranked by quality.
| Repository | Format | Stack | Covers | Score | Changed |
|---|---|---|---|---|---|
| bagisto/bagistoCLAUDE.md · 28k | CLAUDE.md | setupbuildteststyle+5 | 100/100 | 7 days ago | |
| Adit-Jain-srm/NightmareNetCLAUDE.md · 46 | CLAUDE.md | buildtestlint-formatstyle+6 | 100/100 | 14 days ago | |
| microsoft/playwrightCLAUDE.md · 95k | CLAUDE.md | buildtestlint-formatstyle+7 | 100/100 | 7 days ago | |
| nimbalyst/nimbalystpackages/android/CLAUDE.md · 1.5k | CLAUDE.md | setupbuildstylearch+2 | 100/100 | 14 days ago | |
| dotCMS/corecore-web/CLAUDE.md · 949 | CLAUDE.md | teststylearchtesting-strategy+3 | 100/100 | 14 days ago | |
| tphakala/birdnet-goCLAUDE.md · 1.6k | CLAUDE.md | buildtestlint-formatstyle+8 | 100/100 | today | |
| tyrchen/geektime-bootcamp-aiw7/genslides/backend/CLAUDE.md · 230 | CLAUDE.md | testlint-formatstylearch+6 | 100/100 | 9 days ago | |
| dotCMS/coreCLAUDE.md · 949 | CLAUDE.md | setupbuildteststyle+7 | 99/100 | today |
A badge carrying the measured quality of the strongest agent config file in this repository, out of 100. It reads from this index every time somebody loads your page, so it changes when the measurement changes and there is nothing to keep up to date. Free, no account, and the value is not something you or we can set by hand.
[](https://rulestack.kynth.studio/configs/weirdfingers-boards-claude)Would rather not hotlink us? Every badge is also served in shields.io’s endpoint schema, so shields renders the image and your readers never talk to our domain:
Published by Toolproof, the masthead over this index and eight others. The method behind the number is at toolproof.kynth.studio/methodology, and the whole thing is readable as JSON with no key at /api.
(0.60)