mirror of
https://github.com/pbakaus/impeccable.git
synced 2026-09-12 06:06:37 +03:00
Migrate from Vercel to Cloudflare Pages, fix distill command symbol
Replace Vercel serverless functions with Cloudflare Pages static rewrites and lightweight download functions. Pre-generate all API JSON data at build time for zero-invocation static serving. Also fix stale simplify→distill rename in framework-viz periodic table. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.6
parent
98d16686dc
commit
7d2d42da96
@@ -1,4 +0,0 @@
|
||||
tests/
|
||||
server/index.js
|
||||
*.test.js
|
||||
|
||||
@@ -16,10 +16,17 @@ The CSS architecture:
|
||||
## Development Server
|
||||
|
||||
```bash
|
||||
bun run dev
|
||||
bun run dev # Bun dev server at http://localhost:3000
|
||||
bun run preview # Build + Cloudflare Pages local preview
|
||||
```
|
||||
|
||||
Runs at http://localhost:3000
|
||||
## Deployment
|
||||
|
||||
Hosted on Cloudflare Pages. Static assets served from `build/`, API routes handled via `_redirects` rewrites (JSON) and Pages Functions (downloads).
|
||||
|
||||
```bash
|
||||
bun run deploy # Build + deploy to Cloudflare Pages
|
||||
```
|
||||
|
||||
## Build System
|
||||
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
import { readFileSync, existsSync } from "fs";
|
||||
import { join, dirname } from "path";
|
||||
import { fileURLToPath } from "url";
|
||||
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = dirname(__filename);
|
||||
const PROJECT_ROOT = join(__dirname, "../..");
|
||||
|
||||
const VALID_ID = /^[a-zA-Z0-9_-]+$/;
|
||||
|
||||
export default function handler(req, res) {
|
||||
try {
|
||||
const { id } = req.query;
|
||||
|
||||
if (!id || !VALID_ID.test(id)) {
|
||||
return res.status(400).json({ error: "Invalid command ID" });
|
||||
}
|
||||
|
||||
const commandPath = join(PROJECT_ROOT, "source", "skills", id, "SKILL.md");
|
||||
|
||||
if (!existsSync(commandPath)) {
|
||||
return res.status(404).json({ error: "Command not found" });
|
||||
}
|
||||
|
||||
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);
|
||||
res.status(500).json({ error: "Internal server error" });
|
||||
}
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
import { readdirSync, readFileSync, statSync, existsSync } from "fs";
|
||||
import { join, dirname } from "path";
|
||||
import { fileURLToPath } from "url";
|
||||
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = dirname(__filename);
|
||||
const PROJECT_ROOT = join(__dirname, "..");
|
||||
|
||||
export default function handler(req, res) {
|
||||
try {
|
||||
const skillsDir = join(PROJECT_ROOT, "source", "skills");
|
||||
|
||||
const entries = readdirSync(skillsDir);
|
||||
const commands = [];
|
||||
|
||||
for (const entry of entries) {
|
||||
const entryPath = join(skillsDir, entry);
|
||||
if (!statSync(entryPath).isDirectory()) continue;
|
||||
|
||||
const skillMd = join(entryPath, "SKILL.md");
|
||||
if (!existsSync(skillMd)) continue;
|
||||
|
||||
const content = readFileSync(skillMd, "utf-8");
|
||||
const frontmatterMatch = content.match(/^---\n([\s\S]+?)\n---/);
|
||||
|
||||
if (frontmatterMatch) {
|
||||
const frontmatter = frontmatterMatch[1];
|
||||
const userInvokable = /user-invokable:\s*true/.test(frontmatter);
|
||||
if (!userInvokable) continue;
|
||||
|
||||
const nameMatch = frontmatter.match(/name:\s*(.+)/);
|
||||
const descMatch = frontmatter.match(/description:\s*(.+)/);
|
||||
|
||||
commands.push({
|
||||
id: entry,
|
||||
name: nameMatch?.[1]?.trim() || entry,
|
||||
description: descMatch?.[1]?.trim() || "No description available",
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
res.status(500).json({ error: "Internal server error" });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,74 +0,0 @@
|
||||
import { readFileSync, existsSync } from "fs";
|
||||
import { join, dirname, basename } from "path";
|
||||
import { fileURLToPath } from "url";
|
||||
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = dirname(__filename);
|
||||
const PROJECT_ROOT = join(__dirname, "../../../..");
|
||||
|
||||
const PROVIDER_CONFIG_DIRS = {
|
||||
'cursor': '.cursor',
|
||||
'claude-code': '.claude',
|
||||
'gemini': '.gemini',
|
||||
'codex': '.codex',
|
||||
'agents': '.agents',
|
||||
'kiro': '.kiro',
|
||||
};
|
||||
|
||||
function getFilePath(type, provider, id) {
|
||||
const distDir = join(PROJECT_ROOT, "dist");
|
||||
|
||||
const configDir = PROVIDER_CONFIG_DIRS[provider];
|
||||
if (!configDir) return null;
|
||||
|
||||
if (type === "skill" || type === "command") {
|
||||
return join(distDir, provider, configDir, "skills", id, "SKILL.md");
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
const VALID_ID = /^[a-zA-Z0-9_-]+$/;
|
||||
const ALLOWED_PROVIDERS = [
|
||||
'cursor', 'claude-code', 'gemini', 'codex', 'agents', 'kiro',
|
||||
'universal', 'universal-prefixed',
|
||||
];
|
||||
|
||||
export default function handler(req, res) {
|
||||
try {
|
||||
const { type, provider, id } = req.query;
|
||||
|
||||
if (type !== "skill" && type !== "command") {
|
||||
return res.status(400).json({ error: "Invalid type" });
|
||||
}
|
||||
|
||||
if (!provider || !ALLOWED_PROVIDERS.includes(provider)) {
|
||||
return res.status(400).json({ error: "Invalid provider" });
|
||||
}
|
||||
|
||||
if (!id || !VALID_ID.test(id)) {
|
||||
return res.status(400).json({ error: "Invalid file ID" });
|
||||
}
|
||||
|
||||
const filePath = getFilePath(type, provider, id);
|
||||
|
||||
if (!filePath) {
|
||||
return res.status(400).json({ error: "Invalid provider" });
|
||||
}
|
||||
|
||||
if (!existsSync(filePath)) {
|
||||
return res.status(404).json({ error: "File not found" });
|
||||
}
|
||||
|
||||
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);
|
||||
} catch (error) {
|
||||
console.error("Error downloading file:", error);
|
||||
res.status(500).json({ error: "Internal server error" });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,39 +0,0 @@
|
||||
import { readFileSync, existsSync } from "fs";
|
||||
import { join, dirname } from "path";
|
||||
import { fileURLToPath } from "url";
|
||||
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = dirname(__filename);
|
||||
const PROJECT_ROOT = join(__dirname, "../../..");
|
||||
|
||||
const ALLOWED_PROVIDERS = [
|
||||
'universal', 'universal-prefixed',
|
||||
];
|
||||
|
||||
export default function handler(req, res) {
|
||||
try {
|
||||
const { provider } = req.query;
|
||||
|
||||
if (!provider || !ALLOWED_PROVIDERS.includes(provider)) {
|
||||
return res.status(400).json({ error: "Invalid provider" });
|
||||
}
|
||||
|
||||
const distDir = join(PROJECT_ROOT, "dist");
|
||||
const zipPath = join(distDir, `${provider}.zip`);
|
||||
|
||||
if (!existsSync(zipPath)) {
|
||||
return res.status(404).json({ error: "Bundle not found" });
|
||||
}
|
||||
|
||||
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"`);
|
||||
res.send(content);
|
||||
} catch (error) {
|
||||
console.error("Error downloading bundle:", error);
|
||||
res.status(500).json({ error: "Internal server error" });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
import { join, dirname } from "path";
|
||||
import { fileURLToPath } from "url";
|
||||
import { readPatterns } from "../scripts/lib/utils.js";
|
||||
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = dirname(__filename);
|
||||
const PROJECT_ROOT = join(__dirname, "..");
|
||||
|
||||
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);
|
||||
res.status(500).json({ error: "Internal server error" });
|
||||
}
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
import { readdirSync, readFileSync, statSync, existsSync } from "fs";
|
||||
import { join, dirname } from "path";
|
||||
import { fileURLToPath } from "url";
|
||||
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = dirname(__filename);
|
||||
const PROJECT_ROOT = join(__dirname, "..");
|
||||
|
||||
export default function handler(req, res) {
|
||||
try {
|
||||
const skillsDir = join(PROJECT_ROOT, "source", "skills");
|
||||
|
||||
const entries = readdirSync(skillsDir);
|
||||
const skills = [];
|
||||
|
||||
for (const entry of entries) {
|
||||
const entryPath = join(skillsDir, entry);
|
||||
if (!statSync(entryPath).isDirectory()) continue;
|
||||
|
||||
const skillMd = join(entryPath, "SKILL.md");
|
||||
if (!existsSync(skillMd)) continue;
|
||||
|
||||
const content = readFileSync(skillMd, "utf-8");
|
||||
const frontmatterMatch = content.match(/^---\n([\s\S]+?)\n---/);
|
||||
|
||||
if (frontmatterMatch) {
|
||||
const frontmatter = frontmatterMatch[1];
|
||||
const nameMatch = frontmatter.match(/name:\s*(.+)/);
|
||||
const descMatch = frontmatter.match(/description:\s*(.+)/);
|
||||
|
||||
skills.push({
|
||||
id: entry,
|
||||
name: nameMatch?.[1]?.trim() || entry,
|
||||
description: descMatch?.[1]?.trim() || "No description available",
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
res.status(500).json({ error: "Internal server error" });
|
||||
}
|
||||
}
|
||||
@@ -8,23 +8,200 @@
|
||||
"motion": "^12.23.26",
|
||||
"playwright": "^1.57.0",
|
||||
},
|
||||
"devDependencies": {
|
||||
"wrangler": "^4.71.0",
|
||||
},
|
||||
},
|
||||
},
|
||||
"packages": {
|
||||
"@cloudflare/kv-asset-handler": ["@cloudflare/kv-asset-handler@0.4.2", "", {}, "sha512-SIOD2DxrRRwQ+jgzlXCqoEFiKOFqaPjhnNTGKXSRLvp1HiOvapLaFG2kEr9dYQTYe8rKrd9uvDUzmAITeNyaHQ=="],
|
||||
|
||||
"@cloudflare/unenv-preset": ["@cloudflare/unenv-preset@2.15.0", "", { "peerDependencies": { "unenv": "2.0.0-rc.24", "workerd": "1.20260301.1 || ~1.20260302.1 || ~1.20260303.1 || ~1.20260304.1 || >1.20260305.0 <2.0.0-0" }, "optionalPeers": ["workerd"] }, "sha512-EGYmJaGZKWl+X8tXxcnx4v2bOZSjQeNI5dWFeXivgX9+YCT69AkzHHwlNbVpqtEUTbew8eQurpyOpeN8fg00nw=="],
|
||||
|
||||
"@cloudflare/workerd-darwin-64": ["@cloudflare/workerd-darwin-64@1.20260301.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-+kJvwociLrvy1JV9BAvoSVsMEIYD982CpFmo/yMEvBwxDIjltYsLTE8DLi0mCkGsQ8Ygidv2fD9wavzXeiY7OQ=="],
|
||||
|
||||
"@cloudflare/workerd-darwin-arm64": ["@cloudflare/workerd-darwin-arm64@1.20260301.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-PPIetY3e67YBr9O4UhILK8nbm5TqUDl14qx4rwFNrRSBOvlzuczzbd4BqgpAtbGVFxKp1PWpjAnBvGU/OI/tLQ=="],
|
||||
|
||||
"@cloudflare/workerd-linux-64": ["@cloudflare/workerd-linux-64@1.20260301.1", "", { "os": "linux", "cpu": "x64" }, "sha512-Gu5vaVTZuYl3cHa+u5CDzSVDBvSkfNyuAHi6Mdfut7TTUdcb3V5CIcR/mXRSyMXzEy9YxEWIfdKMxOMBjupvYQ=="],
|
||||
|
||||
"@cloudflare/workerd-linux-arm64": ["@cloudflare/workerd-linux-arm64@1.20260301.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-igL1pkyCXW6GiGpjdOAvqMi87UW0LMc/+yIQe/CSzuZJm5GzXoAMrwVTkCFnikk6JVGELrM5x0tGYlxa0sk5Iw=="],
|
||||
|
||||
"@cloudflare/workerd-windows-64": ["@cloudflare/workerd-windows-64@1.20260301.1", "", { "os": "win32", "cpu": "x64" }, "sha512-Q0wMJ4kcujXILwQKQFc1jaYamVsNvjuECzvRrTI8OxGFMx2yq9aOsswViE4X1gaS2YQQ5u0JGwuGi5WdT1Lt7A=="],
|
||||
|
||||
"@cspotcode/source-map-support": ["@cspotcode/source-map-support@0.8.1", "", { "dependencies": { "@jridgewell/trace-mapping": "0.3.9" } }, "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw=="],
|
||||
|
||||
"@emnapi/runtime": ["@emnapi/runtime@1.8.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-mehfKSMWjjNol8659Z8KxEMrdSJDDot5SXMq00dM8BN4o+CLNXQ0xH2V7EchNHV4RmbZLmmPdEaXZc5H2FXmDg=="],
|
||||
|
||||
"@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.27.3", "", { "os": "aix", "cpu": "ppc64" }, "sha512-9fJMTNFTWZMh5qwrBItuziu834eOCUcEqymSH7pY+zoMVEZg3gcPuBNxH1EvfVYe9h0x/Ptw8KBzv7qxb7l8dg=="],
|
||||
|
||||
"@esbuild/android-arm": ["@esbuild/android-arm@0.27.3", "", { "os": "android", "cpu": "arm" }, "sha512-i5D1hPY7GIQmXlXhs2w8AWHhenb00+GxjxRncS2ZM7YNVGNfaMxgzSGuO8o8SJzRc/oZwU2bcScvVERk03QhzA=="],
|
||||
|
||||
"@esbuild/android-arm64": ["@esbuild/android-arm64@0.27.3", "", { "os": "android", "cpu": "arm64" }, "sha512-YdghPYUmj/FX2SYKJ0OZxf+iaKgMsKHVPF1MAq/P8WirnSpCStzKJFjOjzsW0QQ7oIAiccHdcqjbHmJxRb/dmg=="],
|
||||
|
||||
"@esbuild/android-x64": ["@esbuild/android-x64@0.27.3", "", { "os": "android", "cpu": "x64" }, "sha512-IN/0BNTkHtk8lkOM8JWAYFg4ORxBkZQf9zXiEOfERX/CzxW3Vg1ewAhU7QSWQpVIzTW+b8Xy+lGzdYXV6UZObQ=="],
|
||||
|
||||
"@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.27.3", "", { "os": "darwin", "cpu": "arm64" }, "sha512-Re491k7ByTVRy0t3EKWajdLIr0gz2kKKfzafkth4Q8A5n1xTHrkqZgLLjFEHVD+AXdUGgQMq+Godfq45mGpCKg=="],
|
||||
|
||||
"@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.27.3", "", { "os": "darwin", "cpu": "x64" }, "sha512-vHk/hA7/1AckjGzRqi6wbo+jaShzRowYip6rt6q7VYEDX4LEy1pZfDpdxCBnGtl+A5zq8iXDcyuxwtv3hNtHFg=="],
|
||||
|
||||
"@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.27.3", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-ipTYM2fjt3kQAYOvo6vcxJx3nBYAzPjgTCk7QEgZG8AUO3ydUhvelmhrbOheMnGOlaSFUoHXB6un+A7q4ygY9w=="],
|
||||
|
||||
"@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.27.3", "", { "os": "freebsd", "cpu": "x64" }, "sha512-dDk0X87T7mI6U3K9VjWtHOXqwAMJBNN2r7bejDsc+j03SEjtD9HrOl8gVFByeM0aJksoUuUVU9TBaZa2rgj0oA=="],
|
||||
|
||||
"@esbuild/linux-arm": ["@esbuild/linux-arm@0.27.3", "", { "os": "linux", "cpu": "arm" }, "sha512-s6nPv2QkSupJwLYyfS+gwdirm0ukyTFNl3KTgZEAiJDd+iHZcbTPPcWCcRYH+WlNbwChgH2QkE9NSlNrMT8Gfw=="],
|
||||
|
||||
"@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.27.3", "", { "os": "linux", "cpu": "arm64" }, "sha512-sZOuFz/xWnZ4KH3YfFrKCf1WyPZHakVzTiqji3WDc0BCl2kBwiJLCXpzLzUBLgmp4veFZdvN5ChW4Eq/8Fc2Fg=="],
|
||||
|
||||
"@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.27.3", "", { "os": "linux", "cpu": "ia32" }, "sha512-yGlQYjdxtLdh0a3jHjuwOrxQjOZYD/C9PfdbgJJF3TIZWnm/tMd/RcNiLngiu4iwcBAOezdnSLAwQDPqTmtTYg=="],
|
||||
|
||||
"@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.27.3", "", { "os": "linux", "cpu": "none" }, "sha512-WO60Sn8ly3gtzhyjATDgieJNet/KqsDlX5nRC5Y3oTFcS1l0KWba+SEa9Ja1GfDqSF1z6hif/SkpQJbL63cgOA=="],
|
||||
|
||||
"@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.27.3", "", { "os": "linux", "cpu": "none" }, "sha512-APsymYA6sGcZ4pD6k+UxbDjOFSvPWyZhjaiPyl/f79xKxwTnrn5QUnXR5prvetuaSMsb4jgeHewIDCIWljrSxw=="],
|
||||
|
||||
"@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.27.3", "", { "os": "linux", "cpu": "ppc64" }, "sha512-eizBnTeBefojtDb9nSh4vvVQ3V9Qf9Df01PfawPcRzJH4gFSgrObw+LveUyDoKU3kxi5+9RJTCWlj4FjYXVPEA=="],
|
||||
|
||||
"@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.27.3", "", { "os": "linux", "cpu": "none" }, "sha512-3Emwh0r5wmfm3ssTWRQSyVhbOHvqegUDRd0WhmXKX2mkHJe1SFCMJhagUleMq+Uci34wLSipf8Lagt4LlpRFWQ=="],
|
||||
|
||||
"@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.27.3", "", { "os": "linux", "cpu": "s390x" }, "sha512-pBHUx9LzXWBc7MFIEEL0yD/ZVtNgLytvx60gES28GcWMqil8ElCYR4kvbV2BDqsHOvVDRrOxGySBM9Fcv744hw=="],
|
||||
|
||||
"@esbuild/linux-x64": ["@esbuild/linux-x64@0.27.3", "", { "os": "linux", "cpu": "x64" }, "sha512-Czi8yzXUWIQYAtL/2y6vogER8pvcsOsk5cpwL4Gk5nJqH5UZiVByIY8Eorm5R13gq+DQKYg0+JyQoytLQas4dA=="],
|
||||
|
||||
"@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.27.3", "", { "os": "none", "cpu": "arm64" }, "sha512-sDpk0RgmTCR/5HguIZa9n9u+HVKf40fbEUt+iTzSnCaGvY9kFP0YKBWZtJaraonFnqef5SlJ8/TiPAxzyS+UoA=="],
|
||||
|
||||
"@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.27.3", "", { "os": "none", "cpu": "x64" }, "sha512-P14lFKJl/DdaE00LItAukUdZO5iqNH7+PjoBm+fLQjtxfcfFE20Xf5CrLsmZdq5LFFZzb5JMZ9grUwvtVYzjiA=="],
|
||||
|
||||
"@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.27.3", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-AIcMP77AvirGbRl/UZFTq5hjXK+2wC7qFRGoHSDrZ5v5b8DK/GYpXW3CPRL53NkvDqb9D+alBiC/dV0Fb7eJcw=="],
|
||||
|
||||
"@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.27.3", "", { "os": "openbsd", "cpu": "x64" }, "sha512-DnW2sRrBzA+YnE70LKqnM3P+z8vehfJWHXECbwBmH/CU51z6FiqTQTHFenPlHmo3a8UgpLyH3PT+87OViOh1AQ=="],
|
||||
|
||||
"@esbuild/openharmony-arm64": ["@esbuild/openharmony-arm64@0.27.3", "", { "os": "none", "cpu": "arm64" }, "sha512-NinAEgr/etERPTsZJ7aEZQvvg/A6IsZG/LgZy+81wON2huV7SrK3e63dU0XhyZP4RKGyTm7aOgmQk0bGp0fy2g=="],
|
||||
|
||||
"@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.27.3", "", { "os": "sunos", "cpu": "x64" }, "sha512-PanZ+nEz+eWoBJ8/f8HKxTTD172SKwdXebZ0ndd953gt1HRBbhMsaNqjTyYLGLPdoWHy4zLU7bDVJztF5f3BHA=="],
|
||||
|
||||
"@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.27.3", "", { "os": "win32", "cpu": "arm64" }, "sha512-B2t59lWWYrbRDw/tjiWOuzSsFh1Y/E95ofKz7rIVYSQkUYBjfSgf6oeYPNWHToFRr2zx52JKApIcAS/D5TUBnA=="],
|
||||
|
||||
"@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.27.3", "", { "os": "win32", "cpu": "ia32" }, "sha512-QLKSFeXNS8+tHW7tZpMtjlNb7HKau0QDpwm49u0vUp9y1WOF+PEzkU84y9GqYaAVW8aH8f3GcBck26jh54cX4Q=="],
|
||||
|
||||
"@esbuild/win32-x64": ["@esbuild/win32-x64@0.27.3", "", { "os": "win32", "cpu": "x64" }, "sha512-4uJGhsxuptu3OcpVAzli+/gWusVGwZZHTlS63hh++ehExkVT8SgiEf7/uC/PclrPPkLhZqGgCTjd0VWLo6xMqA=="],
|
||||
|
||||
"@img/colour": ["@img/colour@1.1.0", "", {}, "sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ=="],
|
||||
|
||||
"@img/sharp-darwin-arm64": ["@img/sharp-darwin-arm64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-darwin-arm64": "1.2.4" }, "os": "darwin", "cpu": "arm64" }, "sha512-imtQ3WMJXbMY4fxb/Ndp6HBTNVtWCUI0WdobyheGf5+ad6xX8VIDO8u2xE4qc/fr08CKG/7dDseFtn6M6g/r3w=="],
|
||||
|
||||
"@img/sharp-darwin-x64": ["@img/sharp-darwin-x64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-darwin-x64": "1.2.4" }, "os": "darwin", "cpu": "x64" }, "sha512-YNEFAF/4KQ/PeW0N+r+aVVsoIY0/qxxikF2SWdp+NRkmMB7y9LBZAVqQ4yhGCm/H3H270OSykqmQMKLBhBJDEw=="],
|
||||
|
||||
"@img/sharp-libvips-darwin-arm64": ["@img/sharp-libvips-darwin-arm64@1.2.4", "", { "os": "darwin", "cpu": "arm64" }, "sha512-zqjjo7RatFfFoP0MkQ51jfuFZBnVE2pRiaydKJ1G/rHZvnsrHAOcQALIi9sA5co5xenQdTugCvtb1cuf78Vf4g=="],
|
||||
|
||||
"@img/sharp-libvips-darwin-x64": ["@img/sharp-libvips-darwin-x64@1.2.4", "", { "os": "darwin", "cpu": "x64" }, "sha512-1IOd5xfVhlGwX+zXv2N93k0yMONvUlANylbJw1eTah8K/Jtpi15KC+WSiaX/nBmbm2HxRM1gZ0nSdjSsrZbGKg=="],
|
||||
|
||||
"@img/sharp-libvips-linux-arm": ["@img/sharp-libvips-linux-arm@1.2.4", "", { "os": "linux", "cpu": "arm" }, "sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A=="],
|
||||
|
||||
"@img/sharp-libvips-linux-arm64": ["@img/sharp-libvips-linux-arm64@1.2.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw=="],
|
||||
|
||||
"@img/sharp-libvips-linux-ppc64": ["@img/sharp-libvips-linux-ppc64@1.2.4", "", { "os": "linux", "cpu": "ppc64" }, "sha512-FMuvGijLDYG6lW+b/UvyilUWu5Ayu+3r2d1S8notiGCIyYU/76eig1UfMmkZ7vwgOrzKzlQbFSuQfgm7GYUPpA=="],
|
||||
|
||||
"@img/sharp-libvips-linux-riscv64": ["@img/sharp-libvips-linux-riscv64@1.2.4", "", { "os": "linux", "cpu": "none" }, "sha512-oVDbcR4zUC0ce82teubSm+x6ETixtKZBh/qbREIOcI3cULzDyb18Sr/Wcyx7NRQeQzOiHTNbZFF1UwPS2scyGA=="],
|
||||
|
||||
"@img/sharp-libvips-linux-s390x": ["@img/sharp-libvips-linux-s390x@1.2.4", "", { "os": "linux", "cpu": "s390x" }, "sha512-qmp9VrzgPgMoGZyPvrQHqk02uyjA0/QrTO26Tqk6l4ZV0MPWIW6LTkqOIov+J1yEu7MbFQaDpwdwJKhbJvuRxQ=="],
|
||||
|
||||
"@img/sharp-libvips-linux-x64": ["@img/sharp-libvips-linux-x64@1.2.4", "", { "os": "linux", "cpu": "x64" }, "sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw=="],
|
||||
|
||||
"@img/sharp-libvips-linuxmusl-arm64": ["@img/sharp-libvips-linuxmusl-arm64@1.2.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw=="],
|
||||
|
||||
"@img/sharp-libvips-linuxmusl-x64": ["@img/sharp-libvips-linuxmusl-x64@1.2.4", "", { "os": "linux", "cpu": "x64" }, "sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg=="],
|
||||
|
||||
"@img/sharp-linux-arm": ["@img/sharp-linux-arm@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-arm": "1.2.4" }, "os": "linux", "cpu": "arm" }, "sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw=="],
|
||||
|
||||
"@img/sharp-linux-arm64": ["@img/sharp-linux-arm64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-arm64": "1.2.4" }, "os": "linux", "cpu": "arm64" }, "sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg=="],
|
||||
|
||||
"@img/sharp-linux-ppc64": ["@img/sharp-linux-ppc64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-ppc64": "1.2.4" }, "os": "linux", "cpu": "ppc64" }, "sha512-7zznwNaqW6YtsfrGGDA6BRkISKAAE1Jo0QdpNYXNMHu2+0dTrPflTLNkpc8l7MUP5M16ZJcUvysVWWrMefZquA=="],
|
||||
|
||||
"@img/sharp-linux-riscv64": ["@img/sharp-linux-riscv64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-riscv64": "1.2.4" }, "os": "linux", "cpu": "none" }, "sha512-51gJuLPTKa7piYPaVs8GmByo7/U7/7TZOq+cnXJIHZKavIRHAP77e3N2HEl3dgiqdD/w0yUfiJnII77PuDDFdw=="],
|
||||
|
||||
"@img/sharp-linux-s390x": ["@img/sharp-linux-s390x@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-s390x": "1.2.4" }, "os": "linux", "cpu": "s390x" }, "sha512-nQtCk0PdKfho3eC5MrbQoigJ2gd1CgddUMkabUj+rBevs8tZ2cULOx46E7oyX+04WGfABgIwmMC0VqieTiR4jg=="],
|
||||
|
||||
"@img/sharp-linux-x64": ["@img/sharp-linux-x64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-x64": "1.2.4" }, "os": "linux", "cpu": "x64" }, "sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ=="],
|
||||
|
||||
"@img/sharp-linuxmusl-arm64": ["@img/sharp-linuxmusl-arm64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-linuxmusl-arm64": "1.2.4" }, "os": "linux", "cpu": "arm64" }, "sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg=="],
|
||||
|
||||
"@img/sharp-linuxmusl-x64": ["@img/sharp-linuxmusl-x64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-linuxmusl-x64": "1.2.4" }, "os": "linux", "cpu": "x64" }, "sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q=="],
|
||||
|
||||
"@img/sharp-wasm32": ["@img/sharp-wasm32@0.34.5", "", { "dependencies": { "@emnapi/runtime": "^1.7.0" }, "cpu": "none" }, "sha512-OdWTEiVkY2PHwqkbBI8frFxQQFekHaSSkUIJkwzclWZe64O1X4UlUjqqqLaPbUpMOQk6FBu/HtlGXNblIs0huw=="],
|
||||
|
||||
"@img/sharp-win32-arm64": ["@img/sharp-win32-arm64@0.34.5", "", { "os": "win32", "cpu": "arm64" }, "sha512-WQ3AgWCWYSb2yt+IG8mnC6Jdk9Whs7O0gxphblsLvdhSpSTtmu69ZG1Gkb6NuvxsNACwiPV6cNSZNzt0KPsw7g=="],
|
||||
|
||||
"@img/sharp-win32-ia32": ["@img/sharp-win32-ia32@0.34.5", "", { "os": "win32", "cpu": "ia32" }, "sha512-FV9m/7NmeCmSHDD5j4+4pNI8Cp3aW+JvLoXcTUo0IqyjSfAZJ8dIUmijx1qaJsIiU+Hosw6xM5KijAWRJCSgNg=="],
|
||||
|
||||
"@img/sharp-win32-x64": ["@img/sharp-win32-x64@0.34.5", "", { "os": "win32", "cpu": "x64" }, "sha512-+29YMsqY2/9eFEiW93eqWnuLcWcufowXewwSNIT6UwZdUUCrM3oFjMWH/Z6/TMmb4hlFenmfAVbpWeup2jryCw=="],
|
||||
|
||||
"@jridgewell/resolve-uri": ["@jridgewell/resolve-uri@3.1.2", "", {}, "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw=="],
|
||||
|
||||
"@jridgewell/sourcemap-codec": ["@jridgewell/sourcemap-codec@1.5.5", "", {}, "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og=="],
|
||||
|
||||
"@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.9", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.0.3", "@jridgewell/sourcemap-codec": "^1.4.10" } }, "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ=="],
|
||||
|
||||
"@poppinss/colors": ["@poppinss/colors@4.1.6", "", { "dependencies": { "kleur": "^4.1.5" } }, "sha512-H9xkIdFswbS8n1d6vmRd8+c10t2Qe+rZITbbDHHkQixH5+2x1FDGmi/0K+WgWiqQFKPSlIYB7jlH6Kpfn6Fleg=="],
|
||||
|
||||
"@poppinss/dumper": ["@poppinss/dumper@0.6.5", "", { "dependencies": { "@poppinss/colors": "^4.1.5", "@sindresorhus/is": "^7.0.2", "supports-color": "^10.0.0" } }, "sha512-NBdYIb90J7LfOI32dOewKI1r7wnkiH6m920puQ3qHUeZkxNkQiFnXVWoE6YtFSv6QOiPPf7ys6i+HWWecDz7sw=="],
|
||||
|
||||
"@poppinss/exception": ["@poppinss/exception@1.2.3", "", {}, "sha512-dCED+QRChTVatE9ibtoaxc+WkdzOSjYTKi/+uacHWIsfodVfpsueo3+DKpgU5Px8qXjgmXkSvhXvSCz3fnP9lw=="],
|
||||
|
||||
"@sindresorhus/is": ["@sindresorhus/is@7.2.0", "", {}, "sha512-P1Cz1dWaFfR4IR+U13mqqiGsLFf1KbayybWwdd2vfctdV6hDpUkgCY0nKOLLTMSoRd/jJNjtbqzf13K8DCCXQw=="],
|
||||
|
||||
"@speed-highlight/core": ["@speed-highlight/core@1.2.14", "", {}, "sha512-G4ewlBNhUtlLvrJTb88d2mdy2KRijzs4UhnlrOSRT4bmjh/IqNElZa3zkrZ+TC47TwtlDWzVLFADljF1Ijp5hA=="],
|
||||
|
||||
"blake3-wasm": ["blake3-wasm@2.1.5", "", {}, "sha512-F1+K8EbfOZE49dtoPtmxUQrpXaBIl3ICvasLh+nJta0xkz+9kF/7uet9fLnwKqhDrmj6g+6K3Tw9yQPUg2ka5g=="],
|
||||
|
||||
"cookie": ["cookie@1.1.1", "", {}, "sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ=="],
|
||||
|
||||
"detect-libc": ["detect-libc@2.1.2", "", {}, "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ=="],
|
||||
|
||||
"error-stack-parser-es": ["error-stack-parser-es@1.0.5", "", {}, "sha512-5qucVt2XcuGMcEGgWI7i+yZpmpByQ8J1lHhcL7PwqCwu9FPP3VUXzT4ltHe5i2z9dePwEHcDVOAfSnHsOlCXRA=="],
|
||||
|
||||
"esbuild": ["esbuild@0.27.3", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.27.3", "@esbuild/android-arm": "0.27.3", "@esbuild/android-arm64": "0.27.3", "@esbuild/android-x64": "0.27.3", "@esbuild/darwin-arm64": "0.27.3", "@esbuild/darwin-x64": "0.27.3", "@esbuild/freebsd-arm64": "0.27.3", "@esbuild/freebsd-x64": "0.27.3", "@esbuild/linux-arm": "0.27.3", "@esbuild/linux-arm64": "0.27.3", "@esbuild/linux-ia32": "0.27.3", "@esbuild/linux-loong64": "0.27.3", "@esbuild/linux-mips64el": "0.27.3", "@esbuild/linux-ppc64": "0.27.3", "@esbuild/linux-riscv64": "0.27.3", "@esbuild/linux-s390x": "0.27.3", "@esbuild/linux-x64": "0.27.3", "@esbuild/netbsd-arm64": "0.27.3", "@esbuild/netbsd-x64": "0.27.3", "@esbuild/openbsd-arm64": "0.27.3", "@esbuild/openbsd-x64": "0.27.3", "@esbuild/openharmony-arm64": "0.27.3", "@esbuild/sunos-x64": "0.27.3", "@esbuild/win32-arm64": "0.27.3", "@esbuild/win32-ia32": "0.27.3", "@esbuild/win32-x64": "0.27.3" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-8VwMnyGCONIs6cWue2IdpHxHnAjzxnw2Zr7MkVxB2vjmQ2ivqGFb4LEG3SMnv0Gb2F/G/2yA8zUaiL1gywDCCg=="],
|
||||
|
||||
"framer-motion": ["framer-motion@12.23.26", "", { "dependencies": { "motion-dom": "^12.23.23", "motion-utils": "^12.23.6", "tslib": "^2.4.0" }, "peerDependencies": { "@emotion/is-prop-valid": "*", "react": "^18.0.0 || ^19.0.0", "react-dom": "^18.0.0 || ^19.0.0" }, "optionalPeers": ["@emotion/is-prop-valid", "react", "react-dom"] }, "sha512-cPcIhgR42xBn1Uj+PzOyheMtZ73H927+uWPDVhUMqxy8UHt6Okavb6xIz9J/phFUHUj0OncR6UvMfJTXoc/LKA=="],
|
||||
|
||||
"fsevents": ["fsevents@2.3.2", "", { "os": "darwin" }, "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA=="],
|
||||
|
||||
"kleur": ["kleur@4.1.5", "", {}, "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ=="],
|
||||
|
||||
"miniflare": ["miniflare@4.20260301.1", "", { "dependencies": { "@cspotcode/source-map-support": "0.8.1", "sharp": "^0.34.5", "undici": "7.18.2", "workerd": "1.20260301.1", "ws": "8.18.0", "youch": "4.1.0-beta.10" }, "bin": { "miniflare": "bootstrap.js" } }, "sha512-fqkHx0QMKswRH9uqQQQOU/RoaS3Wjckxy3CUX3YGJr0ZIMu7ObvI+NovdYi6RIsSPthNtq+3TPmRNxjeRiasog=="],
|
||||
|
||||
"motion": ["motion@12.23.26", "", { "dependencies": { "framer-motion": "^12.23.26", "tslib": "^2.4.0" }, "peerDependencies": { "@emotion/is-prop-valid": "*", "react": "^18.0.0 || ^19.0.0", "react-dom": "^18.0.0 || ^19.0.0" }, "optionalPeers": ["@emotion/is-prop-valid", "react", "react-dom"] }, "sha512-Ll8XhVxY8LXMVYTCfme27WH2GjBrCIzY4+ndr5QKxsK+YwCtOi2B/oBi5jcIbik5doXuWT/4KKDOVAZJkeY5VQ=="],
|
||||
|
||||
"motion-dom": ["motion-dom@12.23.23", "", { "dependencies": { "motion-utils": "^12.23.6" } }, "sha512-n5yolOs0TQQBRUFImrRfs/+6X4p3Q4n1dUEqt/H58Vx7OW6RF+foWEgmTVDhIWJIMXOuNNL0apKH2S16en9eiA=="],
|
||||
|
||||
"motion-utils": ["motion-utils@12.23.6", "", {}, "sha512-eAWoPgr4eFEOFfg2WjIsMoqJTW6Z8MTUCgn/GZ3VRpClWBdnbjryiA3ZSNLyxCTmCQx4RmYX6jX1iWHbenUPNQ=="],
|
||||
|
||||
"path-to-regexp": ["path-to-regexp@6.3.0", "", {}, "sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ=="],
|
||||
|
||||
"pathe": ["pathe@2.0.3", "", {}, "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w=="],
|
||||
|
||||
"playwright": ["playwright@1.57.0", "", { "dependencies": { "playwright-core": "1.57.0" }, "optionalDependencies": { "fsevents": "2.3.2" }, "bin": { "playwright": "cli.js" } }, "sha512-ilYQj1s8sr2ppEJ2YVadYBN0Mb3mdo9J0wQ+UuDhzYqURwSoW4n1Xs5vs7ORwgDGmyEh33tRMeS8KhdkMoLXQw=="],
|
||||
|
||||
"playwright-core": ["playwright-core@1.57.0", "", { "bin": { "playwright-core": "cli.js" } }, "sha512-agTcKlMw/mjBWOnD6kFZttAAGHgi/Nw0CZ2o6JqWSbMlI219lAFLZZCyqByTsvVAJq5XA5H8cA6PrvBRpBWEuQ=="],
|
||||
|
||||
"semver": ["semver@7.7.4", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA=="],
|
||||
|
||||
"sharp": ["sharp@0.34.5", "", { "dependencies": { "@img/colour": "^1.0.0", "detect-libc": "^2.1.2", "semver": "^7.7.3" }, "optionalDependencies": { "@img/sharp-darwin-arm64": "0.34.5", "@img/sharp-darwin-x64": "0.34.5", "@img/sharp-libvips-darwin-arm64": "1.2.4", "@img/sharp-libvips-darwin-x64": "1.2.4", "@img/sharp-libvips-linux-arm": "1.2.4", "@img/sharp-libvips-linux-arm64": "1.2.4", "@img/sharp-libvips-linux-ppc64": "1.2.4", "@img/sharp-libvips-linux-riscv64": "1.2.4", "@img/sharp-libvips-linux-s390x": "1.2.4", "@img/sharp-libvips-linux-x64": "1.2.4", "@img/sharp-libvips-linuxmusl-arm64": "1.2.4", "@img/sharp-libvips-linuxmusl-x64": "1.2.4", "@img/sharp-linux-arm": "0.34.5", "@img/sharp-linux-arm64": "0.34.5", "@img/sharp-linux-ppc64": "0.34.5", "@img/sharp-linux-riscv64": "0.34.5", "@img/sharp-linux-s390x": "0.34.5", "@img/sharp-linux-x64": "0.34.5", "@img/sharp-linuxmusl-arm64": "0.34.5", "@img/sharp-linuxmusl-x64": "0.34.5", "@img/sharp-wasm32": "0.34.5", "@img/sharp-win32-arm64": "0.34.5", "@img/sharp-win32-ia32": "0.34.5", "@img/sharp-win32-x64": "0.34.5" } }, "sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg=="],
|
||||
|
||||
"supports-color": ["supports-color@10.2.2", "", {}, "sha512-SS+jx45GF1QjgEXQx4NJZV9ImqmO2NPz5FNsIHrsDjh2YsHnawpan7SNQ1o8NuhrbHZy9AZhIoCUiCeaW/C80g=="],
|
||||
|
||||
"tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
|
||||
|
||||
"undici": ["undici@7.18.2", "", {}, "sha512-y+8YjDFzWdQlSE9N5nzKMT3g4a5UBX1HKowfdXh0uvAnTaqqwqB92Jt4UXBAeKekDs5IaDKyJFR4X1gYVCgXcw=="],
|
||||
|
||||
"unenv": ["unenv@2.0.0-rc.24", "", { "dependencies": { "pathe": "^2.0.3" } }, "sha512-i7qRCmY42zmCwnYlh9H2SvLEypEFGye5iRmEMKjcGi7zk9UquigRjFtTLz0TYqr0ZGLZhaMHl/foy1bZR+Cwlw=="],
|
||||
|
||||
"workerd": ["workerd@1.20260301.1", "", { "optionalDependencies": { "@cloudflare/workerd-darwin-64": "1.20260301.1", "@cloudflare/workerd-darwin-arm64": "1.20260301.1", "@cloudflare/workerd-linux-64": "1.20260301.1", "@cloudflare/workerd-linux-arm64": "1.20260301.1", "@cloudflare/workerd-windows-64": "1.20260301.1" }, "bin": { "workerd": "bin/workerd" } }, "sha512-oterQ1IFd3h7PjCfT4znSFOkJCvNQ6YMOyZ40YsnO3nrSpgB4TbJVYWFOnyJAw71/RQuupfVqZZWKvsy8GO3fw=="],
|
||||
|
||||
"wrangler": ["wrangler@4.71.0", "", { "dependencies": { "@cloudflare/kv-asset-handler": "0.4.2", "@cloudflare/unenv-preset": "2.15.0", "blake3-wasm": "2.1.5", "esbuild": "0.27.3", "miniflare": "4.20260301.1", "path-to-regexp": "6.3.0", "unenv": "2.0.0-rc.24", "workerd": "1.20260301.1" }, "optionalDependencies": { "fsevents": "~2.3.2" }, "peerDependencies": { "@cloudflare/workers-types": "^4.20260226.1" }, "optionalPeers": ["@cloudflare/workers-types"], "bin": { "wrangler": "bin/wrangler.js", "wrangler2": "bin/wrangler.js" } }, "sha512-j6pSGAncOLNQDRzqtp0EqzYj52CldDP7uz/C9cxVrIgqa5p+cc0b4pIwnapZZAGv9E1Loa3tmPD0aXonH7KTkw=="],
|
||||
|
||||
"ws": ["ws@8.18.0", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw=="],
|
||||
|
||||
"youch": ["youch@4.1.0-beta.10", "", { "dependencies": { "@poppinss/colors": "^4.1.5", "@poppinss/dumper": "^0.6.4", "@speed-highlight/core": "^1.2.7", "cookie": "^1.0.2", "youch-core": "^0.3.3" } }, "sha512-rLfVLB4FgQneDr0dv1oddCVZmKjcJ6yX6mS4pU82Mq/Dt9a3cLZQ62pDBL4AUO+uVrCvtWz3ZFUL2HFAFJ/BXQ=="],
|
||||
|
||||
"youch-core": ["youch-core@0.3.3", "", { "dependencies": { "@poppinss/exception": "^1.2.2", "error-stack-parser-es": "^1.0.5" } }, "sha512-ho7XuGjLaJ2hWHoK8yFnsUGy2Y5uDpqSTq1FkHLK4/oqKtyUU1AFbOOxY4IpC9f0fTLjwYbslUz0Po5BpD1wrA=="],
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
const VALID_ID = /^[a-zA-Z0-9_-]+$/;
|
||||
|
||||
const ALLOWED_PROVIDERS = [
|
||||
'cursor', 'claude-code', 'gemini', 'codex', 'agents', 'kiro',
|
||||
'universal', 'universal-prefixed',
|
||||
];
|
||||
|
||||
const PROVIDER_CONFIG_DIRS = {
|
||||
'cursor': '.cursor',
|
||||
'claude-code': '.claude',
|
||||
'gemini': '.gemini',
|
||||
'codex': '.codex',
|
||||
'agents': '.agents',
|
||||
'kiro': '.kiro',
|
||||
};
|
||||
|
||||
export async function onRequestGet(context) {
|
||||
const { type, provider, id } = context.params;
|
||||
|
||||
if (type !== 'skill' && type !== 'command') {
|
||||
return Response.json({ error: "Invalid type" }, { status: 400 });
|
||||
}
|
||||
|
||||
if (!provider || !ALLOWED_PROVIDERS.includes(provider)) {
|
||||
return Response.json({ error: "Invalid provider" }, { status: 400 });
|
||||
}
|
||||
|
||||
if (!id || !VALID_ID.test(id)) {
|
||||
return Response.json({ error: "Invalid file ID" }, { status: 400 });
|
||||
}
|
||||
|
||||
const configDir = PROVIDER_CONFIG_DIRS[provider];
|
||||
if (!configDir) {
|
||||
return Response.json({ error: "Invalid provider" }, { status: 400 });
|
||||
}
|
||||
|
||||
const url = new URL(context.request.url);
|
||||
url.pathname = `/_data/dist/${provider}/${configDir}/skills/${id}/SKILL.md`;
|
||||
|
||||
const response = await context.env.ASSETS.fetch(url);
|
||||
|
||||
if (!response.ok) {
|
||||
return Response.json({ error: "File not found" }, { status: 404 });
|
||||
}
|
||||
|
||||
const content = await response.arrayBuffer();
|
||||
|
||||
return new Response(content, {
|
||||
headers: {
|
||||
'Content-Type': 'application/octet-stream',
|
||||
'Content-Disposition': 'attachment; filename="SKILL.md"',
|
||||
'Cache-Control': 'public, s-maxage=86400, stale-while-revalidate=3600',
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
const ALLOWED_PROVIDERS = ['universal', 'universal-prefixed'];
|
||||
|
||||
export async function onRequestGet(context) {
|
||||
const { provider } = context.params;
|
||||
|
||||
if (!provider || !ALLOWED_PROVIDERS.includes(provider)) {
|
||||
return Response.json({ error: "Invalid provider" }, { status: 400 });
|
||||
}
|
||||
|
||||
const url = new URL(context.request.url);
|
||||
url.pathname = `/_data/dist/${provider}.zip`;
|
||||
|
||||
const response = await context.env.ASSETS.fetch(url);
|
||||
|
||||
if (!response.ok) {
|
||||
return Response.json({ error: "Bundle not found" }, { status: 404 });
|
||||
}
|
||||
|
||||
const content = await response.arrayBuffer();
|
||||
const safeProvider = provider.replace(/[^a-zA-Z0-9._-]/g, '');
|
||||
|
||||
return new Response(content, {
|
||||
headers: {
|
||||
'Content-Type': 'application/zip',
|
||||
'Content-Disposition': `attachment; filename="impeccable-style-${safeProvider}.zip"`,
|
||||
'Cache-Control': 'public, s-maxage=86400, stale-while-revalidate=3600',
|
||||
}
|
||||
});
|
||||
}
|
||||
+7
-3
@@ -19,13 +19,17 @@
|
||||
"license": "SEE LICENSE FILE",
|
||||
"scripts": {
|
||||
"build": "bun run scripts/build.js",
|
||||
"clean": "rm -rf dist",
|
||||
"clean": "rm -rf dist build",
|
||||
"rebuild": "bun run clean && bun run build",
|
||||
"dev": "bun run server/index.js",
|
||||
"start": "bun --production run server/index.js",
|
||||
"preview": "bun run build && wrangler pages dev",
|
||||
"deploy": "bun run build && wrangler pages deploy build/",
|
||||
"test": "bun test",
|
||||
"screenshot": "bun run scripts/screenshot-antipatterns.js",
|
||||
"og-image": "bun run scripts/generate-og-image.js"
|
||||
},
|
||||
"type": "module"
|
||||
"type": "module",
|
||||
"devDependencies": {
|
||||
"wrangler": "^4.71.0"
|
||||
}
|
||||
}
|
||||
|
||||
+1
-3920
File diff suppressed because one or more lines are too long
@@ -34,7 +34,7 @@ const commandSymbols = {
|
||||
optimize: 'Op',
|
||||
harden: 'Ha',
|
||||
clarify: 'Cl',
|
||||
simplify: 'Si',
|
||||
distill: 'Di',
|
||||
adapt: 'Ad',
|
||||
extract: 'Ex',
|
||||
animate: 'An',
|
||||
@@ -55,7 +55,7 @@ const commandNumbers = {
|
||||
optimize: 5,
|
||||
harden: 6,
|
||||
clarify: 7,
|
||||
simplify: 8,
|
||||
distill: 8,
|
||||
adapt: 9,
|
||||
extract: 10,
|
||||
animate: 11,
|
||||
|
||||
@@ -180,6 +180,84 @@ These are hidden folders (dotfiles) — press Cmd+Shift+. in Finder to see them.
|
||||
console.log(`✓ Assembled universal${label} directory (${providerMappings.length} providers)`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate static API data for Cloudflare Pages deployment.
|
||||
* Pre-builds all API responses as JSON files so they can be served
|
||||
* as static assets via _redirects rewrites (no function invocations needed).
|
||||
*/
|
||||
function generateApiData(buildDir, skills, patterns) {
|
||||
const apiDir = path.join(buildDir, '_data', 'api');
|
||||
fs.mkdirSync(apiDir, { recursive: true });
|
||||
|
||||
// skills.json
|
||||
const skillsData = skills.map(s => ({
|
||||
id: path.basename(path.dirname(s.filePath)),
|
||||
name: s.name,
|
||||
description: s.description,
|
||||
userInvokable: s.userInvokable,
|
||||
}));
|
||||
fs.writeFileSync(path.join(apiDir, 'skills.json'), JSON.stringify(skillsData));
|
||||
|
||||
// commands.json (user-invokable skills only)
|
||||
const commandsData = skillsData.filter(s => s.userInvokable);
|
||||
fs.writeFileSync(path.join(apiDir, 'commands.json'), JSON.stringify(commandsData));
|
||||
|
||||
// patterns.json
|
||||
fs.writeFileSync(path.join(apiDir, 'patterns.json'), JSON.stringify(patterns));
|
||||
|
||||
// command-source/{id}.json (one per skill)
|
||||
const cmdSourceDir = path.join(apiDir, 'command-source');
|
||||
fs.mkdirSync(cmdSourceDir, { recursive: true });
|
||||
for (const skill of skills) {
|
||||
const id = path.basename(path.dirname(skill.filePath));
|
||||
const content = fs.readFileSync(skill.filePath, 'utf-8');
|
||||
fs.writeFileSync(
|
||||
path.join(cmdSourceDir, `${id}.json`),
|
||||
JSON.stringify({ content })
|
||||
);
|
||||
}
|
||||
|
||||
console.log(`✓ Generated static API data (${skillsData.length} skills, ${commandsData.length} commands)`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy dist files to build output for Cloudflare Pages Functions access.
|
||||
* Download functions use env.ASSETS.fetch() to read these files.
|
||||
*/
|
||||
function copyDistToBuild(distDir, buildDir) {
|
||||
const destDir = path.join(buildDir, '_data', 'dist');
|
||||
copyDirSync(distDir, destDir);
|
||||
console.log('✓ Copied dist files to build output');
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate Cloudflare Pages config files (_headers, _redirects)
|
||||
*/
|
||||
function generateCFConfig(buildDir) {
|
||||
// _headers: security + cache headers
|
||||
const headers = `/*
|
||||
X-Content-Type-Options: nosniff
|
||||
X-Frame-Options: DENY
|
||||
|
||||
/api/*
|
||||
Cache-Control: public, s-maxage=86400, stale-while-revalidate=3600
|
||||
|
||||
/_data/api/*
|
||||
Cache-Control: public, s-maxage=86400, stale-while-revalidate=3600
|
||||
`;
|
||||
fs.writeFileSync(path.join(buildDir, '_headers'), headers);
|
||||
|
||||
// _redirects: rewrite JSON API routes to static files (200 = rewrite, not redirect)
|
||||
const redirects = `/api/skills /_data/api/skills.json 200
|
||||
/api/commands /_data/api/commands.json 200
|
||||
/api/patterns /_data/api/patterns.json 200
|
||||
/api/command-source/:id /_data/api/command-source/:id.json 200
|
||||
`;
|
||||
fs.writeFileSync(path.join(buildDir, '_redirects'), redirects);
|
||||
|
||||
console.log('✓ Generated Cloudflare Pages config (_headers, _redirects)');
|
||||
}
|
||||
|
||||
/**
|
||||
* Main build process
|
||||
*/
|
||||
@@ -232,6 +310,11 @@ async function build() {
|
||||
// Create ZIP bundles (individual + universal)
|
||||
await createAllZips(DIST_DIR);
|
||||
|
||||
// Generate static API data and Cloudflare Pages config
|
||||
generateApiData(buildDir, skills, patterns);
|
||||
copyDistToBuild(DIST_DIR, buildDir);
|
||||
generateCFConfig(buildDir);
|
||||
|
||||
// Copy Claude Code output to project's .claude directory for local development
|
||||
const claudeCodeSrc = path.join(DIST_DIR, 'claude-code', '.claude');
|
||||
const claudeCodeDest = path.join(ROOT_DIR, '.claude');
|
||||
|
||||
-14
@@ -1,14 +0,0 @@
|
||||
{
|
||||
"$schema": "https://openapi.vercel.sh/vercel.json",
|
||||
"buildCommand": "bun run build",
|
||||
"outputDirectory": "build",
|
||||
"functions": {
|
||||
"api/**/*.js": {
|
||||
"includeFiles": "source/**,dist/**,scripts/**"
|
||||
}
|
||||
},
|
||||
"rewrites": [
|
||||
{ "source": "/cheatsheet", "destination": "/cheatsheet.html" }
|
||||
]
|
||||
}
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
name = "impeccable-style"
|
||||
compatibility_date = "2024-12-01"
|
||||
pages_build_output_dir = "./build"
|
||||
Reference in New Issue
Block a user