This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
This project uses devEngines.packageManager with "onFail": "error" in package.json, which causes pnpm info and pnpm view to fail because they delegate to npm, and npm 11 rejects the request. To check package versions, run npm from outside the project directory:
(cd /tmp && npm info <package> version)This is a pnpm workspaces monorepo. Run commands from the root or within specific workspace packages.
Run from repository root for all packages:
- Build all:
pnpm build - Lint all (includes type checking):
pnpm lint - Format all:
pnpm format(oxfmt) - Format check:
pnpm format:check - Test all:
pnpm test - E2E tests all:
pnpm e2e - Markdown lint:
pnpm lint:md/ fix:pnpm lint:md:fix - Full CI:
pnpm ci(setup, build, lint, lint:md, test, e2e) - Release:
pnpm release(build + publish with changesets) - Add changeset:
pnpm changeset-add - Dev docs site:
pnpm dev:docs
- Build:
pnpm run build(uses vite) - Test:
pnpm run test(vitest) - Test watch:
pnpm run test:watch - Run single test:
pnpm vitest <test-file-path>orpnpm vitest -t "<test-name>" - E2E tests:
pnpm run e2e(playwright) - Lint (includes type checking):
pnpm run lint - Format:
pnpm run format(oxfmt) - Format check:
pnpm run format:check - Dev/preview examples:
pnpm run ladle(launches Ladle server for browsing examples/ folder)
- Dev server:
pnpm run dev - Build:
pnpm run build - Format:
pnpm run format(oxfmt + Prettier for .astro files)
After docs changes: run pnpm lint from the app directory or root.
IMPORTANT - Documentation Locations:
DO NOT EDIT the following auto-generated directories:
apps/virtuoso.dev/src/content/docs/react-virtuoso/apps/virtuoso.dev/src/content/docs/masonry/apps/virtuoso.dev/src/content/docs/gurx/apps/virtuoso.dev/src/content/docs/message-list/
These are auto-synced from source files + TypeDoc API via the docsSync integration. Any edits will be overwritten.
To edit package documentation, modify the source files in each package:
- react-virtuoso:
packages/react-virtuoso/README.mdorpackages/react-virtuoso/docs/*.md - masonry:
packages/masonry/README.mdorpackages/masonry/docs/*.md - gurx:
packages/gurx/README.mdorpackages/gurx/docs/*.md - message-list:
packages/message-list/README.mdorpackages/message-list/docs/*.md
packages/
react-virtuoso/ - Main virtualization library
gurx/ - urx state management (fork/variant)
masonry/ - Masonry layout component
message-list/ - Chat/message list component
tooling/ - Shared build tooling
apps/
virtuoso.dev/ - Starlight/Astro documentation site
examples/ - Ladle stories for testing/development
The codebase uses urx, a custom reactive state management system built on streams/observables. Core concepts:
- Systems: Stateful data-processing machines composed of streams
- Streams: Can be stateless (signals) or stateful (depots that persist values)
- Depots: Implicit state maintained in stateful streams, transformers (combineLatest), or operators (withLatestFrom, scan)
- Input/Output: Systems receive input via input streams, process via transformers/operators, emit via output streams
Key urx files: src/urx/ directory contains:
system.ts- System creation and compositionstreams.ts- Stream primitivespipe.ts- Stream operators and transformersactions.ts- Publishing/emittingtransformers.ts- Stream transformation utilities
The virtualization logic is split into modular systems in src/:
Core Systems:
listSystem.ts- Composes all feature systems into the main list systemsizeSystem.ts- Tracks and manages item sizes (critical for variable-height items)listStateSystem.ts- Manages visible item ranges and scrolling statedomIOSystem.ts- DOM measurements and interactions
Feature Systems:
groupedListSystem.ts- Grouped lists with sticky headersscrollToIndexSystem.ts- Programmatic scroll positioningfollowOutputSystem.ts- Auto-scroll for chat/feed UIsinitialTopMostItemIndexSystem.ts- Initial scroll positionscrollSeekSystem.ts- Placeholder rendering during fast scrollingwindowScrollerSystem.ts- Window-scrolling mode- And many more in
src/*System.tsfiles
React Integration:
react-urx/- Bridges urx systems to React componentsVirtuoso.tsx- Main list componentVirtuosoGrid.tsx- Grid layout componentTableVirtuoso.tsx- Table virtualization component- Component interfaces in
component-interfaces/
Variable-sized items work automatically via sizeSystem.ts:
- Uses ResizeObserver for measurements
- Maintains size ranges and estimates
- No manual height specification needed
correctItemSize()utility inutils/handles size corrections
E2E tests in packages/react-virtuoso/e2e/:
- Test files:
*.test.ts(Playwright tests) - Example pages:
examples/*.tsx(rendered in browser for tests) - Use Ladle (
pnpm run ladle) to preview examples during development
- TypeScript with strong typing; avoid
any - oxfmt: 140 char width, single quotes, no semicolons
- Naming: camelCase for variables/functions, PascalCase for components
- Imports: React first, external libs, then internal modules
- Functional components with hooks preferred
- Use urx system patterns for state management
- Error handling: prefer early returns
When writing or editing markdown documentation:
- Headings: ATX-style (
# HeadingnotHeading\n=======) - Code blocks: Always use fenced blocks with language specifiers
const foo = 'bar'- Lists: Use
-for unordered lists, indent nested items by 2 spaces - Emphasis: Use
_single underscore_for emphasis,**double asterisk**for strong - Links: Prefer inline links
[text](url)for readability
- Start with clear, descriptive headings (H1 for title, H2 for major sections)
- Use code blocks for all code examples, terminal commands, and file paths
- Include language identifiers in fenced code blocks (
typescript,bash,json) - Break long paragraphs into shorter ones (3-5 sentences max)
- Use tables for structured data comparison
- Add blank lines before and after headings, lists, code blocks, and tables
- Inline HTML allowed for badges, complex layouts, or special formatting
- Bare URLs allowed in reference sections and changelogs
- Line length not enforced (practical for existing docs)
- Multiple H1 headings allowed (document sections)
- Run
pnpm lint:mdto check markdown files - Run
pnpm lint:md:fixto auto-fix issues - Pre-commit hooks automatically lint staged .md files
- Configuration:
.markdownlint.jsonand.markdownlintignore - If necessary, use
markdownlintCLI directly, but prefer pnpm scripts
After making code changes, run these commands to verify quality:
pnpm lint- Lint and type check (oxlint --type-aware --type-check)pnpm format- Format code with oxfmtpnpm test- Run unit tests (vitest)
pnpm lint:md- If editing markdown filespnpm lint:md:fix- Auto-fix markdown issuespnpm run e2e- For UI/behavior changes (Playwright tests)pnpm run ladle- To visually inspect component changes
pnpm ci- Run complete CI pipeline (setup, build, lint, lint:md, test, e2e)pnpm format:check- Check if files are formatted without modifying them
Format issues are auto-fixed by pnpm format. oxlint issues must be fixed manually. Configure your editor to:
- Format on save using oxfmt (140 char width, single quotes, no semicolons)
- Show oxlint warnings/errors
Pre-commit hooks will block commits if lint (which includes type checking) fails.
- Make changes in
packages/react-virtuoso/src/ - Run
pnpm format && pnpm lint && pnpm test - Check examples with
pnpm run ladleif UI changes - Run
pnpm e2efor end-to-end validation if needed - Add changeset with
pnpm changeset-addfor versioned changes
This project uses lefthook for git hooks.
On every commit, the following checks run automatically on staged files:
- Code formatting: Formats
.ts/.tsx/.js/.jsxfiles with oxfmt and.astrofiles with prettier; changes are auto-staged viastage_fixed - Markdown linting: Validates .md files with markdownlint
- Code linting: Validates code files with oxlint
If you need to skip hooks (e.g., WIP commits):
LEFTHOOK=0 git commit -m "WIP: work in progress"
# Or use git commit --no-verify (not recommended)- Configuration:
lefthook.json - Install hooks:
pnpm exec lefthook install - Uninstall hooks:
pnpm exec lefthook uninstall - Run manually:
pnpm exec lefthook run pre-commit