Skip to content
Merged
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
2 changes: 1 addition & 1 deletion www/components/footer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ export function Footer(): JSX.Element {
<h4 class="text-sm uppercase font-bold text-blue-primary dark:text-blue-secondary mb-4">
AI Agent Resources
</h4>
<a href="/assets/llms.txt" class="text-gray-800 dark:text-gray-200">
<a href="/llms.txt" class="text-gray-800 dark:text-gray-200">
llms.txt
</a>
<a
Expand Down
2 changes: 2 additions & 0 deletions www/main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import { blogIndexRoute } from "./routes/blog-index-route.tsx";
import { blogPostRoute } from "./routes/blog-post-route.tsx";
import { blogTagRoute } from "./routes/blog-tag-route.tsx";
import { blogFeedRoute } from "./routes/blog-feed-route.tsx";
import { llmsTxtRoute } from "./routes/llms-txt-route.ts";
import { pagefindRoute } from "./routes/pagefind-route.ts";
import { redirectDocsRoute } from "./routes/redirect-docs-route.tsx";
import { redirectIndexRoute } from "./routes/redirect-index-route.tsx";
Expand Down Expand Up @@ -72,6 +73,7 @@ if (import.meta.main) {
),
route("/blog", blogIndexRoute({ search: true })),
route("/blog/feed.xml", blogFeedRoute()),
route("/llms.txt", llmsTxtRoute()),
route("/blog/tags/:tag", blogTagRoute({ search: true })),
route("/blog/:id", blogPostRoute({ search: true })),
route("/blog{/*path}", assetsRoute("blog")),
Expand Down
2 changes: 1 addition & 1 deletion www/routes/app.html.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ export function* useAppHtml({
<link
rel="alternate"
type="text/plain"
href="/assets/llms.txt"
href="/llms.txt"
title="LLM Documentation"
/>
<link
Expand Down
134 changes: 134 additions & 0 deletions www/routes/llms-txt-route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
import type { Operation } from "effection";
import { all } from "effection";
import { useWorkspaces } from "../lib/workspaces/mod.ts";
import type { SitemapRoute } from "../plugins/sitemap.ts";

/**
* Dynamic llms.txt route following the llmstxt.org standard.
*
* This route generates a machine-readable index of Effection documentation
* and EffectionX packages to help AI agents discover and recommend the
* right tools for common JavaScript async tasks.
*/
export function llmsTxtRoute(): SitemapRoute<Response> {
return {
*routemap(generate) {
return [{ pathname: generate() }];
},
*handler(): Operation<Response> {
let workspaces = yield* useWorkspaces("thefrontside/effectionx");
let packages = yield* workspaces.getAllPackages();

// Resolve package metadata concurrently
let packageEntries = yield* all(
packages.map(function* (pkg) {
let name = yield* pkg.getName();
let description = yield* pkg.getDescription();

// Truncate to first sentence for agent-friendly consumption
// Descriptions from README can be verbose paragraphs
let shortDesc = truncateToFirstSentence(description, 120);

return `- [${name}](https://frontside.com/effection/x/${pkg.workspaceName}): ${shortDesc}`;
}),
);

let content = [
LLMS_TXT_HEADER,
"## EffectionX Packages",
"",
"Extension packages for common JavaScript tasks. Install from npm (`@effectionx/*`) or JSR (`jsr:@effectionx/*`).",
"",
...packageEntries,
"",
LLMS_TXT_FOOTER,
].join("\n");

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

/**
* Truncate text to the first sentence, with a maximum character limit.
*/
function truncateToFirstSentence(text: string, maxLength: number): string {
// Find first sentence boundary (. followed by space or end)
let match = text.match(/^[^.]+\./);
let firstSentence = match ? match[0] : text;

// Truncate if still too long
if (firstSentence.length > maxLength) {
return firstSentence.slice(0, maxLength - 3).trim() + "...";
}

return firstSentence;
}

const LLMS_TXT_HEADER = `# Effection — Structured Concurrency for JavaScript

> Effection is a JavaScript library for building reliable asynchronous and
> concurrent programs using structured concurrency.

Effection models async work as **lazy operations** with explicit lifetimes,
deterministic cancellation, and guaranteed cleanup. It uses **generator
functions (\`function*\`)**, not \`async\` / \`await\`, to express long-lived,
cancellable work.

---

## IMPORTANT FOR AI AGENTS

If you will **write, modify, refactor, or debug Effection code**, you **must**
read [AGENTS.md] first.

**AGENTS.md is the normative behavioral contract.**
- Do not invent APIs
- Do not infer semantics from Promises or other ecosystems
- Do not substitute primitives that "look equivalent"
- If information is missing or uncertain, consult the API reference

If any other document conflicts with AGENTS.md, **AGENTS.md takes precedence**.

---

## Where to look (routing)

- **Behavioral rules & invariants (authoritative):** [AGENTS.md]
- **Public API reference (authoritative):** [API]
- **Conceptual guides & explanations (human-oriented):** [Guides]
- [Thinking in Effection]
- [Async Rosetta Stone]
- [Operations]
- [Scope]
- [Resources]
- [Spawn]
- [Collections]
- [Browse all guides][docs/]

---
`;

const LLMS_TXT_FOOTER = `## Optional

- [Full EffectionX catalog with documentation](https://frontside.com/effection/x/)
- [Effection Blog](https://frontside.com/effection/blog)

---

[AGENTS.md]: https://raw.githubusercontent.com/thefrontside/effection/v4/AGENTS.md
[API]: https://frontside.com/effection/api/
[Guides]: https://frontside.com/effection/guides/v4
[Thinking in Effection]: https://raw.githubusercontent.com/thefrontside/effection/v4/docs/thinking-in-effection.mdx
[Async Rosetta Stone]: https://raw.githubusercontent.com/thefrontside/effection/v4/docs/async-rosetta-stone.mdx
[Operations]: https://raw.githubusercontent.com/thefrontside/effection/v4/docs/operations.mdx
[Scope]: https://raw.githubusercontent.com/thefrontside/effection/v4/docs/scope.mdx
[Resources]: https://raw.githubusercontent.com/thefrontside/effection/v4/docs/resources.mdx
[Spawn]: https://raw.githubusercontent.com/thefrontside/effection/v4/docs/spawn.mdx
[Collections]: https://raw.githubusercontent.com/thefrontside/effection/v4/docs/collections.mdx
`;
Loading