Skip to content

feat: static API endpoints for extension support#92

Merged
thegdsks merged 8 commits intomainfrom
fix/cloudflare-migration
Apr 10, 2026
Merged

feat: static API endpoints for extension support#92
thegdsks merged 8 commits intomainfrom
fix/cloudflare-migration

Conversation

@thegdsks
Copy link
Copy Markdown
Member

Summary

  • Adds build-time static JSON API generation (src/scripts/generate-api.ts)
  • Generates public/api/registry.json, public/api/categories.json, and per-icon detail files at public/api/registry/<slug>.json
  • Updates build script to run generation before next build
  • Fixes .gitignore to scope /scripts/ to root only and ignore generated public/api/

Why

The Cloudflare static export removed dynamic API routes, breaking the Raycast extension (404 errors). This generates equivalent static JSON files at build time so extensions can fetch data from the deployed site.

Test plan

  • pnpm build succeeds and generates out/api/registry.json
  • curl https://thesvg.org/api/registry.json returns icon list after deploy
  • curl https://thesvg.org/api/registry/github.json returns icon detail with inline SVGs
  • curl https://thesvg.org/api/categories.json returns category list

thegdsks and others added 6 commits April 4, 2026 00:08
- Enable Next.js static export (output: export)
- Remove free API routes (paid API coming to api.thesvg.org)
- Remove API docs page and components
- Remove dynamic OG image generation, use static fallback
- Convert RSS feed to build-time generation
- Add Cloudflare Pages cache headers
- Update all navigation links and references
- Set dynamicParams=false for static export compatibility
- Fix PostHog init for static export (client-side provider)
- Disable icon link prefetch to prevent RSC 404s
- Fix variant switch flicker on icon detail page
- Remove Vercel-specific configuration

Co-Authored-By: Glinr <bot@glincker.com>
…rate PostHog to instrumentation

- Fix kbd shortcut hydration error by deferring isMac detection to useEffect
- Eliminate redundant SVG fetches in download and PNG export by reusing cached svgContent
- Move PostHog init to instrumentation-client.ts (Next.js 15.3+), remove dead provider component
- Add PostHog tracking to detail page actions (PNG export, quick commands, jsdelivr, share)

Co-Authored-By: Glinr <bot@glincker.com>
- Fix duplicate function signatures in jsdelivr-button and quick-commands from merge
- Add missing svgContent dependency in png-export useCallback
- Use useSyncExternalStore for isMac detection to avoid setState-in-effect warning
Generate static JSON files at build time (registry.json, categories.json,
per-icon detail files) so Raycast and other extensions can fetch data
from the static export without needing dynamic API routes.

Co-Authored-By: Glinr <bot@glincker.com>
Copilot AI review requested due to automatic review settings April 10, 2026 20:09
@thegdsks thegdsks self-assigned this Apr 10, 2026
@thegdsks thegdsks added enhancement New feature or request ui User interface changes labels Apr 10, 2026
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR restores extension-facing “API” functionality for the static-exported site by generating equivalent JSON endpoints at build time, while also adjusting a few client utilities to better operate on inline SVG content.

Changes:

  • Add a build-time generator to emit static JSON API files under public/api/ (registry, categories, per-icon detail).
  • Run API generation automatically during pnpm build and ignore generated output in Git.
  • Update SVG download/PNG export flows to accept inline SVG markup (and add a few new PostHog capture events), alongside replacing the PostHog provider with instrumentation-client.ts.

Reviewed changes

Copilot reviewed 13 out of 14 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
src/scripts/generate-api.ts New script that generates public/api/* JSON files from src/data/icons.json.
package.json Runs the generator before next build.
.gitignore Ignores generated public/api/ and scopes /scripts/ ignore to repo root only.
src/lib/svg-to-png.ts Allows PNG conversion from either raw SVG markup or a URL.
src/components/icons/icon-detail-page.tsx Reuses fetched SVG content for SVG download and passes inline SVG to PNG export.
src/components/icons/detail/png-export.tsx Uses inline SVG when available and captures a PostHog event on export.
src/components/icons/detail/quick-commands.tsx Captures PostHog event on copy.
src/components/icons/detail/jsdelivr-button.tsx Captures PostHog event on copy.
src/components/blog/share-buttons.tsx Captures PostHog events for copy/share clicks.
src/components/search/search-bar.tsx Updates Mac detection to avoid SSR hydration mismatch.
src/components/header.tsx Same Mac detection update as search bar.
src/app/layout.tsx Removes PostHogProvider usage.
instrumentation-client.ts New PostHog initialization entrypoint.
src/components/posthog-provider.tsx Removes the old PostHog provider component.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +36 to +43
function readSvgFile(relativePath: string): string {
const fullPath = join(ROOT, "public", relativePath);
if (!existsSync(fullPath)) return "";
try {
return readFileSync(fullPath, "utf-8").trim();
} catch {
return "";
}
Copy link

Copilot AI Apr 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

readSvgFile() uses join(ROOT, "public", relativePath), but icons.json variant paths start with a leading / (e.g. /icons/...). In Node, path.join() discards prior segments when a later segment is absolute, so this will resolve to /icons/... and the SVG files won’t be found, causing svg fields to be empty in the generated per-icon JSON. Strip the leading slash (or otherwise normalize to a relative path) before joining so the script reads from <repo>/public/icons/....

Copilot uses AI. Check for mistakes.
Comment thread src/scripts/generate-api.ts
Comment thread src/scripts/generate-api.ts
Comment thread src/components/search/search-bar.tsx Outdated
Comment thread instrumentation-client.ts Outdated
@greptile-apps
Copy link
Copy Markdown

greptile-apps bot commented Apr 10, 2026

Greptile Summary

This PR adds a build-time static JSON API generator (src/scripts/generate-api.ts) that produces public/api/registry.json, public/api/categories.json, and per-icon detail files at public/api/registry/<slug>.json. It also updates the build script to run the generator before next build and fixes .gitignore scoping. The approach is well-suited for the Cloudflare static export constraint and correctly leverages tsx to execute the script at build time.

Confidence Score: 5/5

Safe to merge — all findings are minor P2 style suggestions with no correctness or reliability impact.

The implementation is correct: the script reads icons.json, writes well-structured JSON to public/api/, and the build pipeline wires it correctly before next build. Path resolution via __dirname is fine with tsx in CJS mode (no "type": "module" in package.json). All three findings are P2 — a stale doc comment, a missing aliases field that's a nice-to-have, and redundant pagination-like fields. None block the intended use case.

src/scripts/generate-api.ts — minor: wrong doc comment path, omitted aliases in detail output, and misleading limit/count fields in registry.json

Important Files Changed

Filename Overview
src/scripts/generate-api.ts New build-time script that generates static JSON API files; minor issues with doc comment path and omitted aliases field in per-icon detail output
package.json Build script updated to run tsx src/scripts/generate-api.ts before next build; correct and straightforward
.gitignore Adds public/api/ ignore for generated files and correctly scopes /scripts/ to root-only; both changes are appropriate

Sequence Diagram

sequenceDiagram
    participant Dev as Developer
    participant Build as pnpm build
    participant Script as generate-api.ts
    participant FS as Filesystem
    participant CF as Cloudflare Pages
    participant Ext as Raycast Extension

    Dev->>Build: pnpm build
    Build->>Script: tsx src/scripts/generate-api.ts
    Script->>FS: Read src/data/icons.json
    FS-->>Script: Icon entries
    Script->>FS: Write public/api/registry.json
    Script->>FS: Write public/api/categories.json
    Script->>FS: Write public/api/registry/slug.json (per icon)
    Script-->>Build: exit 0
    Build->>CF: next build → out/ (includes public/api/)
    CF-->>Ext: GET /api/registry.json → 200 JSON
    CF-->>Ext: GET /api/registry/github.json → 200 JSON
    CF-->>Ext: GET /api/categories.json → 200 JSON
Loading

Reviews (1): Last reviewed commit: "feat: add static API generation for exte..." | Re-trigger Greptile

Comment thread src/scripts/generate-api.ts
Comment thread src/scripts/generate-api.ts
Comment thread src/scripts/generate-api.ts
thegdsks and others added 2 commits April 10, 2026 15:20
- Strip leading slash in readSvgFile for safe path.join
- Clean public/api/ before regeneration to remove stale files
- Add aliases to per-icon detail output
- Remove redundant count/limit from registry.json
- Fix doc comment path to match actual file location
- Guard PostHog init with runtime key check, add fallback host
- Remove unused useState import in search-bar

Co-Authored-By: Glinr <bot@glincker.com>
Keep runtime PostHog guard and unused useState removal from branch.

Co-Authored-By: Glinr <bot@glincker.com>
@thegdsks thegdsks merged commit 5f2be97 into main Apr 10, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request ui User interface changes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants