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
10 changes: 10 additions & 0 deletions pkgs/agent-skills/pgflow-docs/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
name: pgflow-docs
description: Access pgflow documentation on-demand. Use when working with pgflow workflows, Supabase integration, or understanding flow concepts.
---

# pgflow Documentation

```bash
curl -s https://www.pgflow.dev/toc.md
```
2 changes: 2 additions & 0 deletions pkgs/website/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
"astro": "^5.7.14",
"astro-d2": "^0.8.0",
"astro-robots-txt": "^1.0.0",
"micromatch": "^4.0.8",
"react": "^19.1.1",
"react-dom": "^19.1.1",
"sharp": "^0.33.5",
Expand All @@ -35,6 +36,7 @@
"typescript": "^5.8.3"
},
"devDependencies": {
"@types/micromatch": "^4.0.10",
"prettier-plugin-astro": "^0.14.1",
"wrangler": "^4.20.3"
}
Expand Down
133 changes: 133 additions & 0 deletions pkgs/website/src/pages/toc.md.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
import type { APIRoute } from 'astro';
import { getCollection } from 'astro:content';
import micromatch from 'micromatch';

const BASE_URL = 'https://www.pgflow.dev';

const TOPIC_ORDER = [
'get-started',
'build',
'deploy',
'concepts',
'reference',
'tutorials',
'comparisons',
];

const TOPIC_LABELS: Record<string, string> = {
'get-started': 'Get Started',
build: 'Build',
deploy: 'Deploy',
concepts: 'Concepts',
reference: 'Reference',
tutorials: 'Tutorials',
comparisons: 'Comparisons',
};

const DEPRIORITIZED_PATTERNS = [
'reference/manual-installation',
'deploy/connection-string',
'deploy/prune-records',
'deploy/troubleshooting-connections',
'reference/queue-worker/*',
'comparisons/*',
];

function isDeprioritized(slug: string, patterns: string[]): boolean {
return micromatch.isMatch(slug, patterns);
}

function getTopicFromSlug(slug: string): string {
const parts = slug.split('/');
return parts[0] || '';
}

function getDocPath(slug: string): string {
return `${BASE_URL}/${slug}/index.md`;
}

export const GET: APIRoute = async () => {
const docs = await getCollection('docs');

const prioritizedDocs = docs.filter(
(doc) => !isDeprioritized(doc.id, DEPRIORITIZED_PATTERNS)
);
const deprioritizedDocs = docs.filter((doc) =>
isDeprioritized(doc.id, DEPRIORITIZED_PATTERNS)
);

const groupedByTopic: Record<string, typeof docs> = {};
for (const doc of prioritizedDocs) {
const topic = getTopicFromSlug(doc.id);
if (!groupedByTopic[topic]) {
groupedByTopic[topic] = [];
}
groupedByTopic[topic].push(doc);
}

const lines: string[] = [
'# pgflow Documentation',
'',
'All links below are raw markdown files:',
'',
'```bash',
'curl -s https://www.pgflow.dev/get-started/installation/index.md',
'```',
'',
];

for (const topicId of TOPIC_ORDER) {
const topicDocs = groupedByTopic[topicId];
if (!topicDocs || topicDocs.length === 0) continue;

const topicLabel = TOPIC_LABELS[topicId] || topicId;
lines.push(`## ${topicLabel}`);
lines.push('');

const sortedDocs = [...topicDocs].sort((a, b) => {
const aOrder = a.data.sidebar?.order ?? 999;
const bOrder = b.data.sidebar?.order ?? 999;
return aOrder - bOrder;
});

for (const doc of sortedDocs) {
const title = doc.data.title;
const description = doc.data.description || '';
const path = getDocPath(doc.id);
const line = description
? `- [${title}](${path}) - ${description}`
: `- [${title}](${path})`;
lines.push(line);
}
lines.push('');
}

if (deprioritizedDocs.length > 0) {
lines.push('---');
lines.push('');
lines.push('## Niche / Advanced');
lines.push('');
lines.push(
'> Only use these if you know what you are doing or have specific needs.'
);
lines.push('');

const sortedDeprioritized = [...deprioritizedDocs].sort((a, b) => {
const aOrder = a.data.sidebar?.order ?? 999;
const bOrder = b.data.sidebar?.order ?? 999;
return aOrder - bOrder;
});

for (const doc of sortedDeprioritized) {
const title = doc.data.title;
const path = getDocPath(doc.id);
lines.push(`- [${title}](${path})`);
}
}

return new Response(lines.join('\n'), {
headers: {
'Content-Type': 'text/markdown; charset=utf-8',
},
});
};
Loading
Loading