From 98d16686dc4f3993a9d7fa49544af0fa894c6eb0 Mon Sep 17 00:00:00 2001 From: Paul Bakaus Date: Sun, 8 Mar 2026 17:10:04 -0700 Subject: [PATCH] Add edge cache headers to all API routes to reduce Vercel function invocations All API routes serve static content that only changes at deploy time, but had 0% cache hit rate. Adding s-maxage=86400 lets Vercel's CDN cache responses at the edge, which should take the ~28K daily API requests from 0% to ~99% cache. Co-Authored-By: Claude Opus 4.6 --- api/command-source/[id].js | 1 + api/commands.js | 1 + api/download/[type]/[provider]/[id].js | 1 + api/download/bundle/[provider].js | 1 + api/patterns.js | 1 + api/skills.js | 1 + 6 files changed, 6 insertions(+) diff --git a/api/command-source/[id].js b/api/command-source/[id].js index 848afa85d..f6a7a3c73 100644 --- a/api/command-source/[id].js +++ b/api/command-source/[id].js @@ -23,6 +23,7 @@ export default function handler(req, res) { } const content = readFileSync(commandPath, "utf-8"); + res.setHeader("Cache-Control", "public, s-maxage=86400, stale-while-revalidate=3600"); res.status(200).json({ content }); } catch (error) { console.error("Error in /api/command-source:", error); diff --git a/api/commands.js b/api/commands.js index 5c2107be3..e34b38acf 100644 --- a/api/commands.js +++ b/api/commands.js @@ -39,6 +39,7 @@ export default function handler(req, res) { } } + res.setHeader("Cache-Control", "public, s-maxage=86400, stale-while-revalidate=3600"); res.status(200).json(commands); } catch (error) { console.error("Error in /api/commands:", error); diff --git a/api/download/[type]/[provider]/[id].js b/api/download/[type]/[provider]/[id].js index 307ffd047..20869e18a 100644 --- a/api/download/[type]/[provider]/[id].js +++ b/api/download/[type]/[provider]/[id].js @@ -62,6 +62,7 @@ export default function handler(req, res) { const content = readFileSync(filePath); const fileName = basename(filePath).replace(/[^a-zA-Z0-9._-]/g, ''); + res.setHeader("Cache-Control", "public, s-maxage=86400, stale-while-revalidate=3600"); res.setHeader("Content-Type", "application/octet-stream"); res.setHeader("Content-Disposition", `attachment; filename="${fileName}"`); res.send(content); diff --git a/api/download/bundle/[provider].js b/api/download/bundle/[provider].js index e10dc739a..39a9c3ba2 100644 --- a/api/download/bundle/[provider].js +++ b/api/download/bundle/[provider].js @@ -26,6 +26,7 @@ export default function handler(req, res) { } const content = readFileSync(zipPath); + res.setHeader("Cache-Control", "public, s-maxage=86400, stale-while-revalidate=3600"); res.setHeader("Content-Type", "application/zip"); const safeProvider = provider.replace(/[^a-zA-Z0-9._-]/g, ''); res.setHeader("Content-Disposition", `attachment; filename="impeccable-style-${safeProvider}.zip"`); diff --git a/api/patterns.js b/api/patterns.js index 52eb0956e..aa7b65075 100644 --- a/api/patterns.js +++ b/api/patterns.js @@ -10,6 +10,7 @@ export default function handler(req, res) { try { // Extract patterns from SKILL.md using the shared utility const { patterns, antipatterns } = readPatterns(PROJECT_ROOT); + res.setHeader("Cache-Control", "public, s-maxage=86400, stale-while-revalidate=3600"); res.status(200).json({ patterns, antipatterns }); } catch (error) { console.error("Error in /api/patterns:", error); diff --git a/api/skills.js b/api/skills.js index e91ed2541..4e0bca44d 100644 --- a/api/skills.js +++ b/api/skills.js @@ -36,6 +36,7 @@ export default function handler(req, res) { } } + res.setHeader("Cache-Control", "public, s-maxage=86400, stale-while-revalidate=3600"); res.status(200).json(skills); } catch (error) { console.error("Error in /api/skills:", error);