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
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
test-results
node_modules

# Output
Expand Down Expand Up @@ -26,3 +27,8 @@ vite.config.ts.timestamp-*
*.db

.vscode/settings.json

*storybook.log
storybook-static

coverage/
8 changes: 8 additions & 0 deletions .mcp.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"mcpServers": {
"svelte": {
"type": "http",
"url": "https://mcp.svelte.dev/mcp"
}
}
}
2 changes: 1 addition & 1 deletion .prettierrc
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,5 @@
}
}
],
"tailwindStylesheet": "src/routes/layout.css"
"tailwindStylesheet": "./src/routes/layout.css"
}
14 changes: 14 additions & 0 deletions .storybook/main.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import type { StorybookConfig } from "@storybook/sveltekit";

const config: StorybookConfig = {
stories: ["../src/**/*.mdx", "../src/**/*.stories.@(js|ts|svelte)"],
addons: [
"@storybook/addon-svelte-csf",
"@chromatic-com/storybook",
"@storybook/addon-vitest",
"@storybook/addon-a11y",
"@storybook/addon-docs",
],
framework: "@storybook/sveltekit",
};
export default config;
16 changes: 16 additions & 0 deletions .storybook/preview.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import type { Preview } from "@storybook/sveltekit";

export default {
parameters: {
controls: {
matchers: {
color: /(background|color)$/i,
date: /Date$/i,
},
},

a11y: {
test: "error",
},
},
} satisfies Preview;
7 changes: 7 additions & 0 deletions .storybook/vitest.setup.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import * as a11yAddonAnnotations from "@storybook/addon-a11y/preview";
import { setProjectAnnotations } from "@storybook/sveltekit";
import * as projectAnnotations from "./preview";

// This is an important step to apply the right configuration when testing your stories.
// More info at: https://storybook.js.org/docs/api/portable-stories/portable-stories-vitest#setprojectannotations
setProjectAnnotations([a11yAddonAnnotations, projectAnnotations]);
52 changes: 1 addition & 51 deletions .vscode/mcp.json
Original file line number Diff line number Diff line change
@@ -1,57 +1,7 @@
{
"servers": {
"svelte": {
"type": "http",
"url": "https://mcp.svelte.dev/mcp"
},
"ESLint": {
"type": "stdio",
"command": "pnpm",
"args": [
"dlx",
"--package=jiti",
"--package=@eslint/mcp@latest",
"-s",
"mcp"
]
},
"io.github.upstash/context7": {
"type": "stdio",
"command": "pnpm",
"args": [
"dlx",
"-s",
"@upstash/context7-mcp@latest",
"--api-key",
"${input:CONTEXT7_API_KEY}"
]
},
"io.github.ChromeDevTools/chrome-devtools-mcp": {
"type": "stdio",
"command": "pnpm",
"args": ["dlx", "-s", "chrome-devtools-mcp@0.12.0"]
},
"socket-mcp": {
"type": "stdio",
"command": "pnpm",
"args": ["dlx", "-s", "@socketsecurity/mcp@latest"],
"env": {
"SOCKET_API_KEY": "${input:socket_api_key}"
}
}
},
"inputs": [
{
"id": "CONTEXT7_API_KEY",
"type": "promptString",
"description": "API key for authentication",
"password": true
},
{
"type": "promptString",
"id": "socket_api_key",
"description": "Socket API Key",
"password": true
}
]
}
}
2 changes: 1 addition & 1 deletion .vscode/settings.example.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"files.associations": {
"*.css": "tailwindcss"
},
"svelte.enable-ts-plugin": true,
"svelte.enable-ts-plugin": false,
"svelte.ask-to-enable-ts-plugin": false,
"svelte.language-server.runtime": "node",
"eslint.validate": ["javascript", "typescript", "svelte"],
Expand Down
219 changes: 15 additions & 204 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -1,214 +1,25 @@
# Agent Guidelines
# Dear Agent,

## Planning & Workflow
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:

> [!IMPORTANT]
> **ALWAYS plan before implementing.**
>
> 1. Break down tasks into small steps.
> 2. Use `manage_todo_list`.
> 3. Identify files and dependencies.
## Available MCP Tools:

### Do's
### 1. list-sections

- **Read code first** (`read_file`).
- **Make small, incremental changes**.
- **Test your changes**.
- **Use Svelte MCP** (`svelte-autofixer` is mandatory).
- **Follow DaisyUI** (semantic classes like `btn-primary`).
- **Validate with ESLint**.
- **Check DB schema** (`src/lib/server/db/schema.ts`).
- **Use Drizzle ORM syntax** (always prefer `db.select()` over `db.query` or raw `sql` templates).
- **Mark todos complete** immediately.
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.

### Don'ts
### 2. get-documentation

- **No raw Tailwind colors**.
- **No large sweeping changes**.
- **Don't skip `svelte-autofixer`**.
- **Don't ignore TS/ESLint errors**.
- **No emojis**.
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.

### Definition of Done
### 3. svelte-autofixer

- Code implemented & tested.
- Diff is small and focused.
- `svelte-autofixer` passed.
- ESLint passed.
- Types correct.
- DaisyUI conventions followed.
- Todos completed.
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.

## Git Hygiene
### 4. playground-link

- **Never Commit**: Generated code, dependencies, secrets, IDE settings, OS files, logs.
- **Safe to Commit**: Source, config, docs, tests, migrations.
- **Workflow**: Review diff -> Stage specific files -> Commit with conventional commit message.

## MCP Servers

### 1. Svelte (`mcp_svelte_*`)

- `list-sections`: **First step** to find docs.
- `get-documentation`: Fetch relevant sections.
- `svelte-autofixer`: **Mandatory** before finalizing components.
- `playground-link`: Offer only after user confirmation.

### 2. Context7 (`mcp_context7_*`)

- `resolve-library-id` -> `get-library-docs`: For external library docs.
- Use proactively for new dependencies.

### 3. ESLint (`mcp_eslint_*`)

- `lint-files`: Validate changes.

### 4. Socket (`mcp__extension_so_depscore`)

- `depscore`: Check new dependencies.

## Project Structure

**Stack**: SvelteKit (Svelte 5), SQLite + Drizzle, Lucia Auth, DaisyUI, CodeMirror 6, Loro CRDT.

### Key Directories

```text
src/
├── lib/
│ ├── assets/ # Static assets
│ ├── components/ # Svelte components
│ ├── editor/ # Editor utilities
│ ├── remote/ # Remote data fetching
│ ├── server/ # Server-only code (Auth, DB, Real-time)
│ ├── types/ # TypeScript types
│ ├── utils/ # Shared utilities
│ ├── crypto.ts # Crypto utils
│ ├── loro.ts # Loro CRDT
│ ├── schema.ts # Shared Effect Schema
│ └── unawaited.ts # Unawaited promise handler
├── routes/
│ ├── (auth)/ # Login/Signup
│ ├── api/ # API endpoints
│ ├── notes/ # Note pages
│ ├── +layout.svelte # Root layout
│ ├── +page.svelte # Home page
│ └── layout.css # Global styles
└── hooks.server.ts # Server hooks
```

### Important Files

- `src/lib/server/db/schema.ts`: DB Schema (Users, Sessions, Notes).
- `src/lib/server/auth.ts`: Lucia-inspired Auth config.
- `src/lib/server/real-time.ts`: Loro CRDT sync.
- `src/lib/components/codemirror/`: Editor components.

## Commands

- **Type Check**: `pnpm check`
- **Format**: `pnpm prettier --write path/to/file.ts`
- **Migrations**: `pnpm drizzle-kit generate` -> `pnpm drizzle-kit migrate`
- **Lint**: Use ESLint MCP.

## DaisyUI Styling

Use semantic classes. Avoid raw Tailwind colors.

### Correct

```svelte
<button class="btn btn-primary">Save</button>
<div class="card bg-base-200">...</div>
<span class="badge badge-error">Error</span>
```

### Incorrect

```svelte
<button class="bg-blue-500 text-white">Save</button>
<div class="bg-gray-800">...</div>
```

## Svelte 5 Patterns

### Script Order

1. Imports
2. Props (`$props()`)
3. Functions/Promises
4. Effects/State (`$effect`, `$state`)
5. Derived Async (`$derived(await query)`)

### Context

Use `createContext` from `svelte`.

```typescript
import { createContext } from "svelte";
export const [getLinkContext, setLinkContext] = createContext<LinkContext>();
```

### Remote Functions

Wrap in `$derived` for reactivity.

```svelte
<script lang="ts">
import { getNote } from "$lib/remote/notes.remote";
let { noteId } = $props();
let noteQuery = $derived(getNote(noteId));
let note = $derived(await noteQuery);
</script>
```

#### Optimistic Updates

Use `.updates()` with `.withOverride()`.

```typescript
import { getPosts, createPost } from "$lib/remote/posts.remote";

async function handleSubmit() {
const newPost = { id: "temp", title: "New Post" };
await createPost(newPost).updates(
getPosts().withOverride((posts) => [newPost, ...posts]),
);
}
```

### Shared State & SSR

> [!WARNING]
> **NEVER** use global shared stores (exported `writable` or `$state` in module scope).

In SSR, module state is shared across requests.
**Instead:**

- Use `createContext` for component-scoped state.
- Pass data via `props`.

### Optimistic UI

Use `$derived` overrides or `$state.eager`.

```svelte
<script lang="ts">
let { post, like } = $props();
let likes = $derived(post.likes);
async function onclick() {
likes += 1; // Optimistic update
try {
await like();
} catch {
likes -= 1;
}
}
</script>
```

### Legacy Patterns (Avoid)

- **No `load` functions**: Use Remote Functions.
- **No `{#await}`**: Use top-level `await` or `<svelte:boundary>`s in `<script>`.
- **No Stores**: Avoid `writable`, `readable`, `derived` stores. Use Runes (`$state`, `$derived`) instead.
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.
1 change: 1 addition & 0 deletions CLAUDE.md
12 changes: 6 additions & 6 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ Before you can begin contributing, you'll first need to set up the repository.

In order to contribute, you'll need the following software installed and on your `PATH`.

- Node.js: [Download Node.js](https://nodejs.org/en/download/current) with the version specified in our [`nvmrc`](./.nvmrc)
- Corepack: [How to Install](https://github.com/nodejs/corepack#manual-installs) (tl;dr: `npm i -g corepack && corepack enable`)
- Git: [Install](https://git-scm.com/install/)
- Node.js: [Download Node.js](https://nodejs.org/en/download/current) with the version specified in our [`nvmrc`](./.nvmrc).
- Corepack: [How to Install](https://github.com/nodejs/corepack#manual-installs) (TL;DR: `npm i -g corepack && corepack enable`).
- Git: [Install](https://git-scm.com/install/).

### Steps

Expand All @@ -30,6 +30,6 @@ To actually set up the repository, follow these instructions:

## Helpful Commands

- Run development server: `pnpm dev`
- Update the database: `pnpm db:push`
- Inspect the database: `pnpm db:studio`
- Run development server: `pnpm dev`.
- Update the database: `pnpm db:push`.
- Inspect the database: `pnpm db:studio`.
Loading
Loading