diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 00000000..b8168fb1 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,148 @@ +# AGENTS.md + +This file provides guidance to coding agents when working with code in this repository. + +## Commands + +**Development:** + +- `pnpm dev` - Start development server +- `pnpm build` - Build for production +- `pnpm preview` - Preview production build + +**Implementation Guidelines:** + +- Before implementing any feature, read `ARCHITECTURE.md` for design decisions and `IMPLEMENTATION_PLAN.md` for the step-by-step implementation spec +- Design decisions go in `ARCHITECTURE.md`, implementation steps go in `IMPLEMENTATION_PLAN.md` +- New features must be specified before implementation begins — the spec should be concise but sufficient to derive the implementation from +- If a gap in either doc is discovered during implementation, update it with a minimal but concise change before proceeding with the code +- Do exactly what the user asks for — one step at a time +- Do NOT think 4 steps ahead or add extra features/improvements +- Only implement the specific change requested +- You can suggest what the next step could be, but don't implement it +- For anything that runs from the home route (`/`) in no-backend / Vercel mode, do NOT add top-level imports of backend-only modules like `#app/api.remote.js` or anything that pulls in `#lib/server/db.js` +- In home-route server files, import backend-only code lazily inside the `has_backend` guard so static/Vercel deployments do not evaluate database code at module load time + +**Refactoring Guidelines:** + +- During refactors, make ONLY the minimal changes needed (e.g., renaming APIs) +- Do NOT "improve" or restructure logic while refactoring +- If you see something that could be improved, note it separately for a future task +- Refactoring and improving are two separate activities - never combine them + +**Code Style:** + +- Use snake_case for all variable names, function names, and identifiers +- This applies to JavaScript/TypeScript code, test files, and any new code written + +**Styling:** + +- Use Tailwind CSS classes whenever possible +- Minimize custom CSS - only use it for things Tailwind can't handle (e.g., CSS custom properties like `var(--editing)`) +- Use Tailwind's arbitrary value syntax for custom properties: `text-(--editing)`, `border-(--editing)` +- Do not use rounded corners (keep elements rectangular) + +**What to NOT change (keep camelCase):** + +- `window.getSelection()` - native API +- `document.activeElement` - native API +- `navigator.clipboard` - native API +- `addEventListener` - native API +- `preventDefault()` - native API +- `stopPropagation()` - native API +- `getRangeAt()` - native API +- Svelte event handlers: `onclick`, `onmousedown`, etc. +- DOM properties: `innerHTML`, `textContent`, `nodeType`, etc. + +**Pattern**: If it's a web platform API or Svelte API, keep camelCase. If it's our custom variable/function name, use snake_case. + +**File Extensions:** + +- Files using Svelte runes (`$state`, `$derived`, `$effect`, etc.) must use `.svelte.js` or `.svelte.ts` extension + +**Documentation Style:** + +- Use sentence case for all headings in documentation (README.md, etc.) +- Use sentence case for code comments +- Sentence case means: capitalize only the first word and proper nouns +- **Exception**: "Svedit" is always capitalized as it's a proper noun (the product name) +- Examples: + - ✓ "Getting started" (not "Getting Started") + - ✓ "Why Svedit?" (not "Why svedit?") - Svedit is a proper noun + - ✓ "Developing Svedit" (not "Developing svedit") - Svedit is a proper noun + - ✓ "Document-scoped commands" (not "Document-Scoped Commands") + - ✓ "Create a new user" (not "Create a New User") + - ✓ "API reference" (not "API Reference") +- This applies to: markdown headings, JSDoc comments, inline comments, commit messages + +## Architecture + +Svedit is a rich content editor template built with Svelte 5 that uses a graph-based data model. + +### Core Components + +**Document Model:** + +- `Document` - Central document class with state management, transactions, and history +- `Tras` - Handles atomic operations on the document +- Documents are represented as graphs of nodes with properties and references + +**Selection:** + +- Supports text, node, and property selections +- Maps between internal selection model and DOM selection +- Handles complex selection scenarios like backwards selections and multi-node selections + +**Key Components:** + +- `Svedit.svelte` - Main editor component with event handling and selection management +- `NodeArrayProperty.svelte` - Renders containers that hold sequences of nodes +- `AnnotatedTextProperty.svelte` - Handles annotated text rendering and editing +- Node components (`Story`, `List`, etc.) - Render specific content types + +### Schema + +Content is defined through schemas that specify: + +- Node types and their properties +- Property types: `string`, `integer`, `boolean`, `string_array`, `annotated_text`, `node`, `node_array` +- Reference relationships between nodes +- Default types for node arrays + +### Data Flow + +1. Raw document data is loaded into a Svedit `Session` +2. Changes are made through transactions for undo/redo support +3. Selection state is synchronized between internal model and DOM +4. Components render content based on document state and schema definitions + +## Schema and Inserter + +When adding new properties to a node type: + +1. Add to schema in `src/app/document_schema.ts` (`document_schema`) +2. Add to inserter in `src/app/session.ts` (`inserters`) + +## Available MCP Tools + +You are able to use the Svelte MCP server, where you have access to comprehensive Svelte 5 and SvelteKit documentation. Here's how to use the available tools effectively: + +### 1. list-sections + +Use this FIRST to discover all available documentation sections. Returns a structured list with titles, use_cases, and paths. +When asked about Svelte or SvelteKit topics, ALWAYS use this tool at the start of the chat to find relevant sections. + +### 2. get-documentation + +Retrieves full documentation content for specific sections. Accepts single or multiple sections. +After calling the list-sections tool, you MUST analyze the returned documentation sections (especially the use_cases field) and then use the get-documentation tool to fetch ALL documentation sections that are relevant for the user's task. + +### 3. svelte-autofixer + +Analyzes Svelte code and returns issues and suggestions. +You MUST use this tool whenever writing Svelte code before sending it to the user. Keep calling it until no issues or suggestions are returned. + +### 4. playground-link + +Generates a Svelte Playground link with the provided code. +After completing the code, ask the user if they want a playground link. Only call this tool after user confirmation and NEVER if code was written to files in their project. diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md index e9751315..a2ab2e13 100644 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md @@ -110,16 +110,13 @@ Requests whose host addresses the server itself (`localhost`, `127.0.0.1`, `::1` **Remote functions** (`$app/server`) allow server-side functions to be called directly from components via `query()` and `action()`. This replaces traditional REST endpoints for document loading and saving: -- **`src/lib/api.remote.ts`** — server-side functions for document and asset operations, called directly from components. Uses `query()` for reads and `action()` for writes. Access to `locals` (e.g. for auth checks) via `getRequestEvent()`. +- **`src/app/api.remote.ts`** — application-specific server-side functions for document and asset operations, called directly from components. Uses `query()` for reads and `action()` for writes. Access to `locals` (e.g. for auth checks) via `getRequestEvent()`. -**Server initialization** — `src/hooks.server.ts` exports an `init()` function (SvelteKit's `ServerInit` hook) that runs once on server startup. This is where database migration runs: +**Server initialization** — `src/hooks.server.ts` exports an `init()` function (SvelteKit's `ServerInit` hook) that runs once on server startup. In full runtime mode it lazily imports the app migration entry point, which combines framework migrations with the project's migrations: -```js -import migrate from '#lib/server/migrate.js'; - -export async function init() { - migrate(); -} +```ts +const { run_migrations } = await import('#app/migrations.js'); +run_migrations(); ``` The `handle` hook runs on every request and is where session validation and `event.locals` assignment happens. diff --git a/CLAUDE.md b/CLAUDE.md index 55c04d15..5c11c218 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1,148 +1 @@ -# CLAUDE.md - -This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. - -## Commands - -**Development:** - -- `pnpm dev` - Start development server -- `pnpm build` - Build for production -- `pnpm preview` - Preview production build - -**Implementation Guidelines:** - -- Before implementing any feature, read `ARCHITECTURE.md` for design decisions and `IMPLEMENTATION_PLAN.md` for the step-by-step implementation spec -- Design decisions go in `ARCHITECTURE.md`, implementation steps go in `IMPLEMENTATION_PLAN.md` -- New features must be specified before implementation begins — the spec should be concise but sufficient to derive the implementation from -- If a gap in either doc is discovered during implementation, update it with a minimal but concise change before proceeding with the code -- Do exactly what the user asks for — one step at a time -- Do NOT think 4 steps ahead or add extra features/improvements -- Only implement the specific change requested -- You can suggest what the next step could be, but don't implement it -- For anything that runs from the home route (`/`) in no-backend / Vercel mode, do NOT add top-level imports of backend-only modules like `#lib/api.remote.js` or anything that pulls in `#lib/server/db.js` -- In home-route server files, import backend-only code lazily inside the `has_backend` guard so static/Vercel deployments do not evaluate database code at module load time - -**Refactoring Guidelines:** - -- During refactors, make ONLY the minimal changes needed (e.g., renaming APIs) -- Do NOT "improve" or restructure logic while refactoring -- If you see something that could be improved, note it separately for a future task -- Refactoring and improving are two separate activities - never combine them - -**Code Style:** - -- Use snake_case for all variable names, function names, and identifiers -- This applies to JavaScript/TypeScript code, test files, and any new code written - -**Styling:** - -- Use Tailwind CSS classes whenever possible -- Minimize custom CSS - only use it for things Tailwind can't handle (e.g., CSS custom properties like `var(--editing)`) -- Use Tailwind's arbitrary value syntax for custom properties: `text-(--editing)`, `border-(--editing)` -- Do not use rounded corners (keep elements rectangular) - -**What to NOT change (keep camelCase):** - -- `window.getSelection()` - native API -- `document.activeElement` - native API -- `navigator.clipboard` - native API -- `addEventListener` - native API -- `preventDefault()` - native API -- `stopPropagation()` - native API -- `getRangeAt()` - native API -- Svelte event handlers: `onclick`, `onmousedown`, etc. -- DOM properties: `innerHTML`, `textContent`, `nodeType`, etc. - -**Pattern**: If it's a web platform API or Svelte API, keep camelCase. If it's our custom variable/function name, use snake_case. - -**File Extensions:** - -- Files using Svelte runes (`$state`, `$derived`, `$effect`, etc.) must use `.svelte.js` or `.svelte.ts` extension - -**Documentation Style:** - -- Use sentence case for all headings in documentation (README.md, etc.) -- Use sentence case for code comments -- Sentence case means: capitalize only the first word and proper nouns -- **Exception**: "Svedit" is always capitalized as it's a proper noun (the product name) -- Examples: - - ✓ "Getting started" (not "Getting Started") - - ✓ "Why Svedit?" (not "Why svedit?") - Svedit is a proper noun - - ✓ "Developing Svedit" (not "Developing svedit") - Svedit is a proper noun - - ✓ "Document-scoped commands" (not "Document-Scoped Commands") - - ✓ "Create a new user" (not "Create a New User") - - ✓ "API reference" (not "API Reference") -- This applies to: markdown headings, JSDoc comments, inline comments, commit messages - -## Architecture - -Svedit is a rich content editor template built with Svelte 5 that uses a graph-based data model. - -### Core Components - -**Document Model:** - -- `Document` - Central document class with state management, transactions, and history -- `Tras` - Handles atomic operations on the document -- Documents are represented as graphs of nodes with properties and references - -**Selection:** - -- Supports text, node, and property selections -- Maps between internal selection model and DOM selection -- Handles complex selection scenarios like backwards selections and multi-node selections - -**Key Components:** - -- `Svedit.svelte` - Main editor component with event handling and selection management -- `NodeArrayProperty.svelte` - Renders containers that hold sequences of nodes -- `AnnotatedTextProperty.svelte` - Handles annotated text rendering and editing -- Node components (`Story`, `List`, etc.) - Render specific content types - -### Schema - -Content is defined through schemas that specify: - -- Node types and their properties -- Property types: `string`, `integer`, `boolean`, `string_array`, `annotated_text`, `node`, `node_array` -- Reference relationships between nodes -- Default types for node arrays - -### Data Flow - -1. Raw document data is loaded into a Svedit `Session` -2. Changes are made through transactions for undo/redo support -3. Selection state is synchronized between internal model and DOM -4. Components render content based on document state and schema definitions - -## Schema and Inserter - -When adding new properties to a node type: - -1. Add to schema in `src/app/document_schema.ts` (`document_schema`) -2. Add to inserter in `src/app/session.ts` (`inserters`) - -## Available MCP Tools - -You are able to use the Svelte MCP server, where you have access to comprehensive Svelte 5 and SvelteKit documentation. Here's how to use the available tools effectively: - -### 1. list-sections - -Use this FIRST to discover all available documentation sections. Returns a structured list with titles, use_cases, and paths. -When asked about Svelte or SvelteKit topics, ALWAYS use this tool at the start of the chat to find relevant sections. - -### 2. get-documentation - -Retrieves full documentation content for specific sections. Accepts single or multiple sections. -After calling the list-sections tool, you MUST analyze the returned documentation sections (especially the use_cases field) and then use the get-documentation tool to fetch ALL documentation sections that are relevant for the user's task. - -### 3. svelte-autofixer - -Analyzes Svelte code and returns issues and suggestions. -You MUST use this tool whenever writing Svelte code before sending it to the user. Keep calling it until no issues or suggestions are returned. - -### 4. playground-link - -Generates a Svelte Playground link with the provided code. -After completing the code, ask the user if they want a playground link. Only call this tool after user confirmation and NEVER if code was written to files in their project. +See AGENTS.md diff --git a/IMPLEMENTATION_PLAN.md b/IMPLEMENTATION_PLAN.md index 7a401616..5e3b1831 100644 --- a/IMPLEMENTATION_PLAN.md +++ b/IMPLEMENTATION_PLAN.md @@ -22,6 +22,12 @@ - End with one clear prompt to install Editable through the existing `/manual` quickstart. - Keep this text-first page in code until the same content is represented in the page builder. +## App/lib boundary refactor + +- Move `api.remote.ts` into `src/app` because it contains Editable-specific remote functions and is part of the application customization surface. +- Keep generic document-graph operations in `src/lib/document_graph.ts` and pass the document schema from callers instead of importing the app schema there. +- Preserve existing behavior and keep the refactor limited to imports and schema parameter plumbing. + ## Retina video resolution - Cap processed video at a 1440px short side, producing up to 2560×1440 for 16:9 landscape video. @@ -77,7 +83,7 @@ Convert the whole codebase from JS+JSDoc to TypeScript per the "Language: TypeSc 1. Replace `jsconfig.json` with `tsconfig.json` (same options, `allowJs`/`checkJs` kept during transition) and point the `check` script at it. 2. Convert the document schema to `src/app/document_schema.ts`, export `type Nodes = NodeMap`, and add a typed `get_svedit_context()` in `src/app/svedit_context.ts` (mirrors the svedit demo app). -3. Convert `src/lib` modules (root, `client/`, `server/`, `server/markdown/`, `server/migrations/`), translating existing JSDoc annotations to TS syntax. +3. Convert `src/lib` modules (root, `client/`, `server/`, `server/markdown/`, and framework migrations), translating existing JSDoc annotations to TS syntax. 4. Convert `src/routes` modules (`hooks.server`, load functions, API endpoints, `app_utils`, `commands.svelte`, `create_session`, helpers). 5. Convert all Svelte components to `