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
1 change: 1 addition & 0 deletions .env-example
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
NEXT_PUBLIC_GTM_ID= # Google Tag Manager container (e.g. GTM-XXXXXXX); loads GA4, Reo, LinkedIn, X, Clarity. Set only in production so forks/previews don't pollute analytics
LLMS_BASE_URL=
GITHUB_TOKEN= # Read-only GitHub token for Agent Skills generation; required in shared build environments to avoid per-IP API limits
GITHUB_APP_ID=
GITHUB_APP_PRIVATE_KEY= # Base64 encoded GitHub App private key
GITHUB_APP_INSTALLATION_ID=
Expand Down
5 changes: 5 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,11 @@ jobs:
env:
LLMS_BASE_URL: https://docs.steel.dev

- name: Generate Agent Skills index
run: bun run generate-agent-skills
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

- name: Run link validation
run: bun run validate-links

Expand Down
9 changes: 6 additions & 3 deletions lib/markdown-negotiation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,6 @@ export const MARKDOWN_USER_AGENT_SUBSTRINGS = [
const MARKDOWN_VARY_HEADERS = ['Accept', 'User-Agent'];

const EXCLUDED_EXACT_PATHS = new Set([
'/.well-known/api-catalog',
'/.well-known/llms.txt',
'/AGENTS',
'/AGENTS.md',
'/favicon.ico',
Expand All @@ -43,11 +41,14 @@ const EXCLUDED_EXACT_PATHS = new Set([
'/sitemap.xml',
]);

const EXCLUDED_PATH_PREFIXES = ['/_next', '/api', '/llms.mdx', '/og'];
// Everything under the RFC 8615 /.well-known namespace is already
// machine-readable, so none of it should ever be content-negotiated.
const EXCLUDED_PATH_PREFIXES = ['/.well-known', '/_next', '/api', '/llms.mdx', '/og'];
const EXCLUDED_ASSET_EXTENSIONS = new Set([
'.avif',
'.css',
'.gif',
'.gz',
'.ico',
'.jpeg',
'.jpg',
Expand All @@ -58,6 +59,8 @@ const EXCLUDED_ASSET_EXTENSIONS = new Set([
'.pdf',
'.png',
'.svg',
'.tar',
'.tgz',
'.ttf',
'.txt',
'.webp',
Expand Down
26 changes: 26 additions & 0 deletions next.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,32 @@ const config = {
},
async headers() {
return [
{
// The index and its digest-pinned tarballs change together on deploy,
// so both get the same short lifetime: a client holding a stale
// index.json would otherwise fetch tarballs whose sha256 no longer
// matches and have to reject them as tampered.
source: "/.well-known/agent-skills/:name.tar.gz",
headers: [
{
key: "Content-Type",
value: "application/gzip",
},
{
key: "Cache-Control",
value: "public, max-age=300, must-revalidate",
},
],
},
{
source: "/.well-known/agent-skills/index.json",
headers: [
{
key: "Cache-Control",
value: "public, max-age=300, must-revalidate",
},
],
},
{
// RFC 9727 requires the catalog to be served as a linkset. The file has
// no extension, so static serving would otherwise guess a type for it.
Expand Down
Loading
Loading