Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
52 commits
Select commit Hold shift + click to select a range
1e18609
wip
khromov Dec 9, 2024
d665b86
Update +server.ts
khromov Dec 9, 2024
d6041ce
Update +server.ts
khromov Dec 9, 2024
b74efca
wip
khromov Dec 10, 2024
437464f
wip
khromov Dec 10, 2024
15ed068
Update +server.ts
khromov Dec 10, 2024
98a9f90
Update +server.ts
khromov Dec 10, 2024
16046c0
wip
khromov Dec 10, 2024
c2534f9
cleanup
khromov Dec 10, 2024
0d29584
wip
khromov Dec 10, 2024
6d05a5a
refactor
khromov Dec 10, 2024
464630f
cleanupo
khromov Dec 10, 2024
4238887
Update +server.ts
khromov Dec 10, 2024
d494334
Update content.ts
khromov Dec 10, 2024
4315f7a
wip
khromov Dec 10, 2024
7bb3ebd
Create +server.ts
khromov Dec 10, 2024
8612605
minimize llms.txt
khromov Dec 10, 2024
8b2544c
Filter llms.txt
khromov Dec 10, 2024
02dbf8d
clean up
khromov Dec 10, 2024
3470a0b
Merge branch 'main' into llms-txt
khromov Dec 11, 2024
7d89403
package
khromov Dec 11, 2024
918b627
chore: naming
khromov Dec 11, 2024
b327991
Update +server.ts
khromov Dec 11, 2024
e51cf30
Dynamic path names
khromov Dec 11, 2024
ea0c646
clean up
khromov Dec 11, 2024
08f1aea
fix
khromov Dec 11, 2024
13e1cc5
Merge branch 'main' into llms-txt
dummdidumm Dec 12, 2024
c1e57a2
under_score
dummdidumm Dec 12, 2024
190ff05
code style
dummdidumm Dec 12, 2024
72a1fd1
use real document titles, filter out empty files
dummdidumm Dec 12, 2024
aaee7c6
move llms.txt to llms-small.txt
khromov Dec 12, 2024
a7f0f8d
llms.txt index
khromov Dec 12, 2024
c5fac95
Update +server.ts
khromov Dec 12, 2024
29b4726
Update +server.ts
khromov Dec 12, 2024
9eeaca6
Fix index
khromov Dec 12, 2024
9c8469c
fix
khromov Dec 12, 2024
e9d7e70
revert VERCEL_URL usage
khromov Dec 12, 2024
855a197
Update apps/svelte.dev/src/lib/server/content.ts
khromov Dec 12, 2024
f0c91cc
move llm stuff into its own module
Rich-Harris Dec 13, 2024
086c48f
revert whitespace changes
Rich-Harris Dec 13, 2024
d7f9180
snake_case
Rich-Harris Dec 13, 2024
d541799
tweak
Rich-Harris Dec 13, 2024
8137d82
snake_case etc
Rich-Harris Dec 13, 2024
edc5d43
make ignores work
Rich-Harris Dec 13, 2024
bdf0381
simplify
Rich-Harris Dec 13, 2024
e7bd8d9
unused
Rich-Harris Dec 13, 2024
f5df782
reduce indirection
Rich-Harris Dec 13, 2024
aa3a4e6
more
Rich-Harris Dec 13, 2024
84ed768
move template into separate .md file
Rich-Harris Dec 13, 2024
b2233b8
add a section to /docs
Rich-Harris Dec 13, 2024
c717f6c
Merge branch 'main' into llms-txt
Rich-Harris Dec 13, 2024
a521cc9
advent of svelte
Rich-Harris Dec 13, 2024
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
8 changes: 6 additions & 2 deletions apps/svelte.dev/content/blog/2024-12-01-advent-of-svelte.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,9 +99,13 @@ As of today, you can also return things that _aren't_ built in to the language,
- [docs](/docs/kit/hooks#Universal-hooks-transport)
- [demo](https://stackblitz.com/edit/sveltejs-kit-template-default-b5zbxomg?file=src%2Fhooks.js)

## Day 13
## Day 13: rise of the robots

Coming soon!
For those of you using LLMs to help you write code — via Cursor or Copilot or Claude or Bolt or v0 or some other interface — we now publish the documentation in a selection of robot-friendly `llms.txt` files. This is experimental and will evolve over time, but by way of example here's a [snake game](/playground/0de3c1c1a31d47bdbb7c4aa3477a6b46) built by Sonnet 3.5 with no additional prompting.

Thanks to [Didier Catz](https://x.com/didiercatz) and [Stanislav Khromov](https://bsky.app/profile/khromov.se) for building this!

- [docs](/docs/llms)

## Day 14

Expand Down
1 change: 1 addition & 0 deletions apps/svelte.dev/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@
"lightningcss": "^1.25.1",
"magic-string": "^0.30.11",
"marked": "^14.1.2",
"minimatch": "^10.0.1",
"prettier": "^3.3.2",
"prettier-plugin-svelte": "^3.2.4",
"satori": "^0.10.13",
Expand Down
134 changes: 134 additions & 0 deletions apps/svelte.dev/src/lib/server/llms.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
import { minimatch } from 'minimatch';
import { dev } from '$app/environment';
import { index } from './content';

interface GenerateLlmContentOptions {
ignore?: string[];
minimize?: Partial<MinimizeOptions>;
sections: Section[];
}

interface MinimizeOptions {
remove_legacy: boolean;
remove_note_blocks: boolean;
remove_details_blocks: boolean;
remove_playground_links: boolean;
remove_prettier_ignore: boolean;
normalize_whitespace: boolean;
}

interface Section {
slug: string;
title: string;
}

const defaults: MinimizeOptions = {
remove_legacy: false,
remove_note_blocks: false,
remove_details_blocks: false,
remove_playground_links: false,
remove_prettier_ignore: false,
normalize_whitespace: false
};

export function generate_llm_content(options: GenerateLlmContentOptions): string {
let content = '';

for (const section of options.sections) {
if (options.sections.length > 1) {
content += `# Start of ${section.title} documentation\n\n`;
}

for (const [path, document] of Object.entries(index)) {
if (!path.startsWith(`docs/${section.slug}`)) continue;

if (options.ignore?.some((pattern) => minimatch(path, pattern))) {
if (dev) console.log(`❌ Ignored by pattern: ${path}`);
continue;
}

const doc_content = options.minimize
? minimize_content(document.body, options.minimize)
: document.body;
if (doc_content.trim() === '') continue;

content += `\n# ${document.metadata.title}\n\n`;
content += doc_content;
content += '\n';
}
}

return content;
}

export const sections: Section[] = [
{ slug: 'svelte', title: 'Svelte' },
{ slug: 'kit', title: 'SvelteKit' },
{ slug: 'cli', title: 'the Svelte CLI' }
];

export function get_documentation_title(section: Section): string {
return `This is the developer documentation for ${section.title}.`;
}

function minimize_content(content: string, options?: Partial<MinimizeOptions>): string {
// Merge with defaults, but only for properties that are defined
const settings: MinimizeOptions = { ...defaults, ...options };

let minimized = content;

if (settings.remove_legacy) {
minimized = remove_quote_blocks(minimized, 'LEGACY');
}

if (settings.remove_note_blocks) {
minimized = remove_quote_blocks(minimized, 'NOTE');
}

if (settings.remove_details_blocks) {
minimized = remove_quote_blocks(minimized, 'DETAILS');
}

if (settings.remove_playground_links) {
// Replace playground URLs with /[link] but keep the original link text
minimized = minimized.replace(/\[([^\]]+)\]\(\/playground[^)]+\)/g, '[$1](/REMOVED)');
}

if (settings.remove_prettier_ignore) {
minimized = minimized
.split('\n')
.filter((line) => line.trim() !== '<!-- prettier-ignore -->')
.join('\n');
}

if (settings.normalize_whitespace) {
minimized = minimized.replace(/\s+/g, ' ');
}

minimized = minimized.trim();

return minimized;
}

function remove_quote_blocks(content: string, blockType: string): string {
return content
.split('\n')
.reduce((acc: string[], line: string, index: number, lines: string[]) => {
// If we find a block (with or without additional text), skip it and all subsequent blockquote lines
if (line.trim().startsWith(`> [!${blockType}]`)) {
// Skip all subsequent lines that are part of the blockquote
let i = index;
while (i < lines.length && (lines[i].startsWith('>') || lines[i].trim() === '')) {
i++;
}
// Update the index to skip all these lines
index = i - 1;
return acc;
}

// Only add the line if it's not being skipped
acc.push(line);
return acc;
}, [])
.join('\n');
}
8 changes: 8 additions & 0 deletions apps/svelte.dev/src/routes/docs/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,14 @@
</p>
</a>

<a href="/docs/llms">
<h2>I'm a Large Language Model (LLM)</h2>
<p>
If you're an artificial intelligence, or trying to teach one how to use Svelte, we offer the
documentation in plaintext format. Beep boop.
</p>
</a>

<a href="/chat" class="external">
<h2>Help! I'm stuck</h2>
<p>
Expand Down
29 changes: 29 additions & 0 deletions apps/svelte.dev/src/routes/docs/[...path]/llms.txt/+server.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { error } from '@sveltejs/kit';
import { generate_llm_content, get_documentation_title, sections } from '$lib/server/llms';

export const prerender = true;

export function entries() {
return sections.map((section) => ({ path: section.slug }));
}

export function GET({ params }) {
const pkg = params.path;

const section = sections.find((s) => s.slug === pkg);

if (!section) {
error(404, 'Not Found');
}

const prefix = `<SYSTEM>${get_documentation_title(section)}</SYSTEM>`;
const content = `${prefix}\n\n${generate_llm_content({ sections: [section] })}`;

return new Response(content, {
status: 200,
headers: {
'Content-Type': 'text/plain; charset=utf-8',
'Cache-Control': 'public, max-age=3600'
}
});
}
46 changes: 46 additions & 0 deletions apps/svelte.dev/src/routes/docs/llms/+page.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<script>
import { Text } from '@sveltejs/site-kit/components';
</script>

<div class="page">
<Text>
<h1>Docs for LLMs</h1>

<p>
We support the <a href="https://llmstxt.org/">llms.txt</a> convention for making documentation
available to large language models and the applications that make use of them.
</p>

<p>Currently, we have the following root-level files...</p>

<ul>
<li><a href="/llms.txt">/llms.txt</a> — a listing of the available files</li>
<li>
<a href="/llms-full.txt">/llms-full.txt</a> — complete documentation for Svelte, SvelteKit and
the CLI
</li>
<li>
<a href="/llms-small.txt">/llms-small.txt</a> — compressed documentation for use with smaller
context windows
</li>
</ul>

<p>...and package-level documentation:</p>

<ul>
<li><a href="/docs/svelte/llms.txt">/docs/svelte/llms.txt</a></li>
<li><a href="/docs/kit/llms.txt">/docs/kit/llms.txt</a></li>
<li><a href="/docs/cli/llms.txt">/docs/cli/llms.txt</a></li>
</ul>
</Text>
</div>

<style>
.page {
padding: var(--sk-page-padding-top) var(--sk-page-padding-side);
max-width: var(--sk-page-content-width);
box-sizing: content-box;
margin: auto;
text-wrap: balance;
}
</style>
15 changes: 15 additions & 0 deletions apps/svelte.dev/src/routes/llms-full.txt/+server.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { generate_llm_content, sections } from '$lib/server/llms';

export const prerender = true;

export function GET() {
const content = `<SYSTEM>This is the full developer documentation for Svelte and SvelteKit.</SYSTEM>\n\n${generate_llm_content({ sections })}`;

return new Response(content, {
status: 200,
headers: {
'Content-Type': 'text/plain; charset=utf-8',
'Cache-Control': 'public, max-age=3600'
}
});
}
47 changes: 47 additions & 0 deletions apps/svelte.dev/src/routes/llms-small.txt/+server.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { generate_llm_content, sections } from '$lib/server/llms';

export function GET() {
const main_content = generate_llm_content({
sections,
ignore: [
// Svelte ignores
'docs/svelte/legacy/**/*',
'docs/svelte/misc/custom-elements',
'docs/svelte/misc/v4-migration-guide',
'docs/svelte/misc/v5-migration-guide',
'docs/svelte/misc/faq',
'docs/svelte/reference/compiler-errors',
'docs/svelte/reference/compiler-warnings',
'docs/svelte/reference/runtime-errors',
'docs/svelte/reference/runtime-warnings',
'docs/svelte/reference/svelte-legacy',
'**/xx-*',

// SvelteKit ignores
'docs/kit/advanced/packaging',
'docs/kit/appendix/**/*',
'docs/kit/best-practices/performance',
'docs/kit/build-and-deploy/*adapter-*',
'docs/kit/build-and-deploy/writing-adapters'
],
minimize: {
remove_legacy: true,
remove_note_blocks: true,
remove_details_blocks: true,
remove_playground_links: true,
remove_prettier_ignore: true,
normalize_whitespace: true
}
});
const content = `<SYSTEM>This is the abridged developer documentation for Svelte and SvelteKit.</SYSTEM>\n\n${main_content}`;

return new Response(content, {
status: 200,
headers: {
'Content-Type': 'text/plain; charset=utf-8',
'Cache-Control': 'public, max-age=3600'
}
});
}

export const prerender = true;
22 changes: 22 additions & 0 deletions apps/svelte.dev/src/routes/llms.txt/+server.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { get_documentation_title, sections } from '$lib/server/llms';
import template from './template.md?raw';

const DOMAIN = `https://svelte.dev`;

export const prerender = true;

export function GET() {
const package_docs = sections.map(
(section) =>
`- [${section.title} documentation](${DOMAIN}/docs/${section.slug}/llms.txt): ${get_documentation_title(section)}`
);

const content = template.replace('%PACKAGE_DOCS%', package_docs.join('\n'));

return new Response(content, {
headers: {
'Content-Type': 'text/plain; charset=utf-8',
'Cache-Control': 'public, max-age=3600'
}
});
}
19 changes: 19 additions & 0 deletions apps/svelte.dev/src/routes/llms.txt/template.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Svelte Documentation for LLMs

> Svelte is a UI framework that uses a compiler to let you write breathtakingly concise components that do minimal work in the browser, using languages you already know — HTML, CSS and JavaScript.

## Documentation Sets

- [Abridged documentation](https://svelte.dev/llms-small.txt): A minimal version of the Svelte and SvelteKit documentation, with examples and non-essential content removed
- [Complete documentation](https://svelte.dev/llms-full.txt): The complete Svelte and SvelteKit documentation including all examples and additional content

## Individual Package Documentation

%PACKAGE_DOCS%

## Notes

- The abridged documentation excludes legacy compatibility notes, detailed examples, and supplementary information
- The complete documentation includes all content from the official documentation
- Package-specific documentation files contain only the content relevant to that package
- The content is automatically generated from the same source as the official documentation
11 changes: 11 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading