Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
148 changes: 148 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -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.
13 changes: 5 additions & 8 deletions ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
149 changes: 1 addition & 148 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -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
22 changes: 14 additions & 8 deletions IMPLEMENTATION_PLAN.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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<typeof document_schema>`, 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 `<script lang="ts">`. Node components use the typed-node pattern; internal components get explicit prop types.
6. Convert tests to `.ts`, update the vitest include glob and `vite.config` filename, then verify `pnpm check`, `pnpm test`, `pnpm build`, and `pnpm lint` all pass.
Expand Down Expand Up @@ -1126,7 +1132,7 @@ Current `site_settings` table:

### 2. `get_document(document_id)` and `save_document(combined_doc)` are already page-id driven

In `src/lib/api.remote.js`, `get_document` already accepts a `document_id`.
In `src/app/api.remote.ts`, `get_document` already accepts a `document_id`.
This is a strong foundation for `/:page_id`.

Current limitations:
Expand Down Expand Up @@ -1485,7 +1491,7 @@ This produces a deterministic, editor-friendly page browser:

### 1.1 Add helper functions in server/data layer

Introduce helpers in `src/lib/api.remote.js` or extracted server modules for:
Introduce helpers in `src/app/api.remote.ts` or extracted server modules for:

- `get_home_page_id()`
- `list_page_documents()`
Expand Down Expand Up @@ -1516,7 +1522,7 @@ Behavior:

Create a page factory for `/new`, likely in:

- `src/lib/new_page.js`
- `src/app/new_page.js`
or nearby route helper

It should expose a `create_empty_doc()` helper (or equivalent) that:
Expand Down Expand Up @@ -1591,7 +1597,7 @@ Current behavior:
Implemented:

- `src/routes/new/+page.svelte`
- `src/lib/new_page.js`
- `src/app/new_page.js`

Current behavior:

Expand Down Expand Up @@ -1777,17 +1783,17 @@ These constraints must be respected during implementation:
- `src/routes/[page_id]/+page.svelte`
- `src/routes/new/+page.svelte`
- `src/app/components/PageEditor.svelte`
- maybe `src/lib/new_page.js`
- maybe `src/app/new_page.js`
- maybe `src/lib/server/page_browser.js`
- maybe `src/lib/server/page_summary.js`

### Updated files

- `src/routes/+page.svelte`
- `src/lib/api.remote.js`
- `src/app/api.remote.ts`
- `src/app/components/PagesDrawer.svelte`
- `src/app/components/Overlays.svelte`
- possibly `src/lib/server/migrations.js` if additional seed/settings support is needed
- `src/app/migrations.ts` as the application migration entry point, if additional seed/settings support is needed

## Recommended implementation order

Expand Down
Loading