Skip to content

SEO generator: derive market list from on-chain registry (replaces dead Supabase)#92

Open
krandder wants to merge 1 commit into
mainfrom
seo-registry-fed
Open

SEO generator: derive market list from on-chain registry (replaces dead Supabase)#92
krandder wants to merge 1 commit into
mainfrom
seo-registry-fed

Conversation

@krandder

@krandder krandder commented Jul 5, 2026

Copy link
Copy Markdown
Contributor

What

Rewrites scripts/generate-seo.mjs so the static-page market list comes from the on-chain registry (the Checkpoint indexer at https://api.futarchy.fi/registry/graphql, aggregator 0xC5eB43D53e2FE5FddE5faf400CC4167e5b5d4Fc1) instead of the deleted Supabase project (nvhqdqtlsdboctqjcelq.supabase.co). No Supabase, no OpenAI, no new dependencies — plain fetch with the same three flat GraphQL queries the runtime already uses in src/hooks/useAggregatorProposals.js.

Why

generate-seo.mjs was the only thing that could update src/config/markets.js, which drives getStaticPaths (fallback: false, static export) in src/pages/markets/[address].js. With Supabase gone the script could not run at all, so the market list was frozen at 29 entries and new markets never got a canonical /markets/<address> static page or OG/Twitter meta. Now any market in the registry is picked up automatically at the next generate-seo + build, with no manual list edit.

Data-source swap

Before After
Market list Supabase market_event table (deleted) Registry indexer: aggregatororganizationsproposalentities
Titles/descriptions Supabase metadata + OpenAI blurbs (ai_prompts prompt template) displayNameQuestion/displayNameEvent, proposal description, proposal/org metadata JSON
Images Supabase metadata + mapped-seo.json mapped-seo.json override → proposal metadata.seo.image → org coverImage/logo → generic fallback

Registry today: 7 organizations, 22 proposal entities, 20 unique market addresses (duplicate metadata entities for one proposalAddress are deduped deterministically: non-archived > has-SEO > smallest entity id). Archived and visibility: hidden entries are skipped for new pages, matching the frontend list behaviour — they get pages automatically once made public.

Legacy content

The AI blurbs had no registry equivalent, so the 29 existing entries' generated content (titles, descriptions, images, keywords) is snapshotted verbatim into a new checked-in file, src/config/legacy-seo.json. The generator merges it first:

  • URLs and meta content of all 29 legacy markets are unchanged (same checksummed path keys, same tags).
  • Where a legacy market is still in the registry (4 of 29), its isActive/resolution status is refreshed from registry metadata.
  • Legacy markets absent from the registry (25) keep their pages but are marked isActive: false (they're not shown in the registry-fed frontend list anyway).
  • New markets (9 today) get deterministic template SEO. New page keys use the address exactly as the registry returns it (lowercase) — the same value the frontend uses to build /markets/<address> links.

Fail-loud policy

The generator exits non-zero (aborting build-with-seo) on: unreachable endpoint, HTTP/GraphQL errors, missing aggregator, zero organizations, zero proposals, or an output smaller than the legacy snapshot. A silent empty market list can never ship. Output is deterministic (no AI, no timestamps; two consecutive runs are byte-identical).

Verified

  • node scripts/generate-seo.mjs → 38 markets written (29 legacy + 9 new), byte-identical on re-run; bogus endpoint → exit 1.
  • npm run build → static export succeeds, 38 /markets/<address>.html pages with correct OG meta (spot-checked GIP-151).
  • npm run auto-qa:test:unit → 692/692 pass, including the @supabase/supabase-js import ratchet at 0. Also deleted scripts/test-market-events.js, the last file anywhere importing @supabase/supabase-js (dead since PR Remove remaining Supabase clients and drop @supabase/supabase-js #90 dropped the dependency).

Build wiring recommendation (not done in this PR)

generate-seo still only runs via the optional build-with-seo script; plain build uses whatever markets.js is checked in. Recommendation: make build-with-seo the default build in CI/Netlify — the generator is now dependency-free, fast (3 GraphQL queries), deterministic, and fail-loud, so the historical reasons to keep it out of the default path (Supabase creds, OpenAI cost/nondeterminism) are gone. Left unwired here to avoid unilaterally changing deploy behaviour; it's a one-line change ("build": "npm run generate-seo && next build") once ops signs off. Until then, committing the regenerated markets.js (as this PR does) keeps plain builds correct.

🤖 Generated with Claude Code

The build-time SEO generator (scripts/generate-seo.mjs) read the
market list from the Supabase market_event table and AI blurbs from
ai_prompts via OpenAI. The Supabase project is deleted, so the script
could not run at all and src/config/markets.js was frozen at 29
hardcoded entries — new markets never got a canonical
/markets/<address> static page (getStaticPaths uses fallback: false
with static export).

The generator now fetches the same Checkpoint registry indexer the
frontend runtime uses (https://api.futarchy.fi/registry/graphql,
aggregator 0xC5eB...4Fc1) with the same three flat queries as
useAggregatorProposals.js, using plain fetch — no new dependencies,
no Supabase, no OpenAI.

- src/config/legacy-seo.json: checked-in snapshot of the 29
  Supabase/OpenAI-era entries. Their URLs and meta content are
  preserved verbatim; lifecycle status (isActive, resolution) is
  refreshed from the registry when the market is still listed there.
- New registry markets get template SEO built from
  displayNameQuestion/Event, proposal description, org metadata
  (logo/coverImage) and mapped-seo.json image overrides. Archived and
  hidden (staging/test) entries are skipped, matching frontend list
  behaviour; duplicate metadata entities for one proposalAddress are
  deduped deterministically.
- Fail-loud policy: unreachable endpoint, GraphQL errors, missing
  aggregator, zero orgs/proposals, or an output smaller than the
  legacy snapshot all exit non-zero, so a build can never silently
  ship with an empty market list.
- Regenerated markets.js: 38 markets (29 legacy + 9 new from the
  registry).
- Removed scripts/test-market-events.js (dead Supabase debug script;
  its dependency was dropped in PR #90).

🤖 Generated with [Claude Code](https://claude.com/claude-code)
@netlify

netlify Bot commented Jul 5, 2026

Copy link
Copy Markdown

Deploy Preview for futarchy ready!

Name Link
🔨 Latest commit 22221a5
🔍 Latest deploy log https://app.netlify.com/projects/futarchy/deploys/6a4ad42989ccc000085d5bf4
😎 Deploy Preview https://deploy-preview-92--futarchy.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
🤖 Make changes Run an agent on this branch

To edit notification comments on pull requests, go to your Netlify project configuration.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant