Skip to content

Latest commit

 

History

History
114 lines (73 loc) · 5.69 KB

File metadata and controls

114 lines (73 loc) · 5.69 KB

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

Project Overview

Palimpsest is a version-aware writing tool with a React-based frontend that visualizes text diffs between article versions. Articles are written in MDX format and stored in the articles/ directory. The frontend renders articles with inline diff highlighting (green insertions, red deletions), a sidebar with outline navigation and version history, and supports Mermaid diagrams via fenced code blocks.

Development Commands

All development commands run from the frontend/ directory:

cd frontend

# Start dev server (port 5173, uses polling for file watching)
npm run dev

# Production build (runs TypeScript check first)
npm run build

# Run all tests (Vitest with jsdom)
npm run test

# Run a single test file
npx vitest run src/hooks/__tests__/useDiff.test.ts

# Run tests in watch mode
npx vitest

# Lint
npm run lint

# Preview production build
npm run preview

All dependencies and development happen in frontend/. The repository root has no package.json — do not create one or run npm install from the root.

Architecture

Monorepo-ish Layout

  • frontend/ — React + Vite + TypeScript application (all dev commands run here)
  • articles/ — Article content directories, each containing meta.json, article.mdx, and previous.mdx
  • docs/ — Design specs and implementation plans
  • .superpowers/ — Brainstorming artifacts from the superpowers workflow

Frontend Stack

  • Build: Vite with @vitejs/plugin-react (Oxc-based) and @mdx-js/rollup for MDX support
  • Styling: Tailwind CSS v3 + custom CSS in src/styles/diff.css
  • Testing: Vitest with jsdom, @testing-library/react
  • Diff engine: diff-match-patch library with semantic cleanup
  • Diagrams: mermaid library for rendering diagrams in MDX
  • MDX runtime: @mdx-js/mdx for client-side MDX compilation, @mdx-js/react for component provider, remark-gfm for GitHub Flavored Markdown

Three Rendering Modes

The app supports three view modes, each with a different rendering strategy:

  1. compare mode: DiffRenderer shows a line-level diff with red deletions and green insertions. Each line is independently compiled to MDX via @mdx-js/mdx at runtime. Special block structures (fenced code blocks, tables, lists, blockquotes) are merged across consecutive lines before compilation so they render correctly. A global compileCache deduplicates compilation for identical lines.

  2. new mode: RuntimeMdx compiles the entire current article.mdx text into a React component at runtime. Supports full MDX features including GFM tables and Mermaid diagrams.

  3. old mode: RuntimeMdx compiles the entire previous.mdx text, same as new mode but with the previous version.

The MDXProvider (from @mdx-js/react) wraps the app in main.tsx and provides custom components. Currently only a custom <pre> component is registered, which intercepts fenced mermaid code blocks and renders them as <MermaidBlock>.

Article Data Model

Each article lives in articles/{id}/ with three files:

  • meta.json — Title, version, timestamps, version history array
  • article.mdx — Current version content
  • previous.mdx — Previous version for diff comparison

Articles are loaded at runtime via fetch() from the static file server. The publicDir in vite.config.ts is set to ../ (repo root), so articles/ is served at /articles/.

Diff Pipeline

useArticle loads meta + both MDX texts → useDiff(previousText, currentText, true) computes line-level segments via diff-match-patch with semantic cleanup → DiffRenderer renders segments with per-line MDX compilation and animation via useDiffAnimation.

Path Alias

@/ resolves to frontend/src/.

TypeScript Configuration

  • tsconfig.json is a project references root pointing to tsconfig.app.json and tsconfig.node.json
  • verbatimModuleSyntax: true — requires import type for type-only imports
  • noUnusedLocals: true and noUnusedParameters: true — unused variables cause build errors
  • erasableSyntaxOnly: true — no enum, namespace, or parameter properties

MDX Components

Custom MDX components live in src/components/. MermaidBlock renders Mermaid diagrams. Fenced mermaid code blocks in MDX are automatically converted to <MermaidBlock> by the MDX pipeline via the custom <pre> component in MdxProvider.

To add a new custom component: create it in src/components/, export from src/components/index.ts, and register in src/mdx-components/MdxProvider.tsx.

Testing Patterns

  • Unit tests for hooks use renderHook from @testing-library/react with mocked fetch
  • Component tests use render/cleanup from @testing-library/react
  • vi.useFakeTimers() is used for testing animation delays in DiffRenderer
  • Tests for DiffRenderer verify HTML output via container.innerHTML and container.textContent

Important Implementation Details

  • DiffRenderer compiles each diff line individually via @mdx-js/mdx — compilation failures fall back to rendering the raw text
  • Special block structures (fenced code blocks ```, tables |, lists -/1., blockquotes >) are merged across consecutive lines before MDX compilation
  • Diff animations only trigger in compare mode; old/new modes skip animation
  • The sidebar extracts headings from raw MDX text via regex (^(#{1,3})\s+(.+)$), not from parsed AST
  • usePolling: true in Vite server config is set for environments where native file watching doesn't work reliably
  • loadArticleText guards against the dev server returning HTML fallback pages (checks content-type header)