Skip to content

feat: website overhaul — content, SEO/AEO, AI-discoverability, i18n - #211

Merged
Umang01-hash merged 28 commits into
mainfrom
feature/website-overhaul
May 4, 2026
Merged

Umang01-hash merged 28 commits into
mainfrom
feature/website-overhaul

Conversation

@aryanmehrotra

@aryanmehrotra aryanmehrotra commented May 1, 2026 •

Copy link
Copy Markdown
Member

Summary

A substantial revamp of gofr.dev focused on three things:

  1. Content first. Tell visitors what GoFr does before showing who uses it. New SEO pages (/why-gofr, /comparison/*, /migrate/*, /learn, /faq), a richer team page, a roadmap, and home-page reordering so substance leads.
  2. Make the site machine-readable. AI search engines (Perplexity, ChatGPT, Claude, Gemini) and AI coding assistants (Claude Code, Cursor, Codex, Aider) get first-class entry points: /AGENTS.md, /llms.txt, FAQ/HowTo JSON-LD, dynamic sitemap.
  3. Replace static copy with build-time data. Releases, roadmap, team, and contributors come from GitHub via build-time scripts with offline-tolerant snapshot fallbacks. The site now stays current without hand-edits.

138 files changed, ~20k insertions / ~500 deletions across the two commits on this branch.

What landed

Content

  • New SEO pages, all rendered through existing Markdoc chrome (no new design tokens):
    • /why-gofr — narrative pitch grounded in the framework's own positioning.
    • /comparison + /comparison/gofr-vs-{gin,fiber,echo,chi} — feature matrix and per-framework deep dives. Each acknowledges the competing framework's strengths so the tone stays honest, not adversarial.
    • /migrate + /migrate/from-{gin,fiber,express,flask,spring-boot} — concrete code translations.
    • /learn — three tracks (switchers / Go devs new to GoFr / production builders).
    • /faq — long-tail Q&A grouped by topic, audited for accuracy (CockroachDB / ClickHouse mis-categorisation fixed, Go version mismatch removed, unverifiable production-readiness claims pulled).
    • /team — auto-generated; 6 maintainers + 128 community contributors fed live from GitHub.
    • /roadmap — milestones pulled from GitHub at build time.
  • Home page restructured for substance-first reading: Hero → feature grid → datasource marquee → company logos → ecosystem recognition → testimonials. Pitch first, then prove.
  • EcosystemRecognition strip surfaces ThoughtWorks Tech Radar, CNCF Landscape, JetBrains Open Source — neutral credibility signals to complement the existing customer logos.
  • Hero copy refined: tighter subhead, latest-release badge from changelog data, AI-coding-assistant tertiary line pointing at /AGENTS.md.
  • Removed: ZopSmart references throughout (footer, showcase, CompanyTrustedList, FAQ, GFGTracks); the standalone Calendly CTA in the hero; the duplicate AGENTS.md callout banner; the copyright/license footer line; the standalone A note on benchmarks section in /comparison; the /benchmarks page (kept for a future revisit when there are real numbers to publish).

SEO / AEO infrastructure

  • Per-page Markdoc frontmatter (nextjs.metadata.title / description) on every doc + SEO page so Google + AI Overviews see unique titles.
  • New Markdoc tags for AI-search optimisation:
    • {% answer %} — direct-answer block at the top of a doc, the kind LLMs quote.
    • {% faq %} + {% faq-item %} — collapsible Q/A; emits FAQPage JSON-LD.
    • {% howto %} — numbered steps; emits HowTo JSON-LD.
  • Dynamic /sitemap.xml via fast-glob walk of src/app/**/page.{md,jsx}; replaces the static file.
  • Twitter / OpenGraph metadata blocks on every layout that owns a route group.
  • robots.txt + .well-known/security.txt + humans.txt added.

For AI coding assistants and search engines

  • /AGENTS.md — curated context file. 10 core rules, a minimal app, a tight Migrations section (rules + pointer rather than inlined examples to save tokens), and a categorised where to look link index. Linked inline from the hero.
  • /llms.txt — Markdown-shaped curated link index per the llmstxt.org spec. Sectioned so AI engines can partial-fetch.
  • Footer: replaced the duplicate For AI assistants entry with LLM index → /llms.txt. Top-of-page + bottom-of-page placement matches audience: AGENTS.md is for the developer wiring up an assistant (hero), llms.txt is for the AI crawler (footer).

Build-time data fetchers

  • utils/fetch-releases.mjs → src/app/changelog/releases.json
  • utils/fetch-roadmap.mjs → src/data/roadmap.json
  • utils/fetch-team.mjs → src/data/team-enriched.json
  • utils/generate-changelog-rss.mjs → public/changelog.xml (RSS)

Each fetcher has an offline-tolerant snapshot fallback so a rate-limited or offline build keeps the previously-fetched JSON rather than silently emptying it.

Build hooks adjusted: the GitHub fetchers no longer run on every build (they hit GitHub rate limits and slowed local dev). They now run only via npm run refresh-data. Only the local-only RSS generator runs on prebuild. JSON snapshots are committed; refresh on demand or on release.

i18n

  • Spanish (/es/*) and Simplified Chinese (/zh/*) variants of the hero, with LocaleAutoRedirect picking the user's preferred language on first visit (and storing a manual override so the user's later choice sticks).
  • Footer language switcher.
  • hreflang annotations on the root layout.

New components

  • MarketingPage — chrome wrapper for SEO pages (no left sidebar, right-rail TOC kept).
  • LatestReleaseBadge — small inline version chip in the hero fed from releases.json.
  • LocaleAutoRedirect — browser-language sniffing on /.
  • EcosystemRecognition — TW Radar / CNCF / JetBrains row with per-source metadata.
  • Faq + FaqSearchProvider — client-side search across FAQ items.
  • Answer / HowTo — Markdoc tag renderers.

Changelog / RSS

  • Changelog page: full release history (108 releases) with deep-link anchors per version (/changelog#v1.56.0 auto-expands).
  • RSS feed at /changelog.xml regenerated from releases.json.

CSS

  • prism.css: removed the global code { background-color } rule that was painting per-line pill backgrounds on every <code> inside <pre>. Scoped to :not(pre) > code.

Test plan

  • next dev runs cleanly; home page returns 200.
  • All new routes render: /why-gofr, /comparison/*, /migrate/*, /learn, /faq, /team, /roadmap, /showcase, /examples, /changelog, /community, /events.
  • /AGENTS.md and /llms.txt serve as static plaintext.
  • /sitemap.xml dynamically lists every page.{md,jsx} route.
  • Team page renders all 6 maintainers with avatars + 128-strong contributor grid.
  • FAQ collapsible blocks open/close; client-side search filters.
  • Hero latest-release badge reads v1.56.4 from releases.json.
  • Manual: Lighthouse on home + 3 representative doc pages (target SEO ≥ 95, A11y ≥ 90).
  • Manual: Google Rich Results Test on a doc with {% faq %} and a doc with {% howto %}.
  • Manual: Verify Spanish / Chinese hero variants render correctly.

Commits

  1. feat: website overhaul — content, SEO/AEO, AI-discoverability, i18n — main body of work
  2. team: add Srijan Rastogi and Vipul Rawat as maintainers — maintainer additions

🤖 Generated with Claude Code

aryanmehrotra and others added 11 commits April 8, 2026 13:55
- /changelog: Timeline of releases with markdown rendering, fetched from GitHub API during build
- /showcase: Company logos, industry tags, testimonials from engineers
- /community: Discord, GitHub, Reddit, Twitter, LinkedIn cards with contributing section
- /examples: 17 examples with tag filtering, featured section
- Header nav: Docs, Changelog, Examples, Community
- Footer: Added links to all new pages
- Mobile nav: Site-wide links added
- Search: Improved ranking with word-boundary matching, keyboard hints
- CLI page: Replaced "Coming Soon" with install instructions and links
- Releases: Redirects to /changelog
- Pkg pages: Show redirect to relevant docs instead of blank
- SEO: robots.txt, comprehensive sitemap
- New components: SectionCards, Tabs, PkgRedirect
- Markdoc: Registered tabs and section-cards tags

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Substantial revamp of gofr.dev focused on three things: (1) telling
visitors what GoFr does before showing who uses it, (2) making the
site machine-readable for AI search engines and coding assistants,
and (3) replacing static copy with build-time data pulled from the
framework repo so the site stays current without hand-edits.

Content
-------
- New SEO pages, all rendered through existing Markdoc chrome:
    /why-gofr           — narrative pitch grounded in the framework's
                          own positioning ("opinionated microservice
                          framework, Kubernetes-first, observability
                          built in").
    /comparison         — pillar with feature matrix; per-framework
                          deep dives at /comparison/gofr-vs-{gin,
                          fiber,echo,chi}. Each acknowledges the
                          competing framework's strengths so the
                          tone stays honest, not adversarial.
    /migrate            — index + concrete code translations for
                          /migrate/from-{gin,fiber,express,flask,
                          spring-boot}.
    /learn              — three tracks (switchers / Go devs new to
                          GoFr / production builders), each just an
                          ordered list of links into existing docs.
    /faq                — long-tail Q&A grouped by topic (pricing,
                          features, datasources, observability,
                          comparison, deployment, testing). Audited
                          for accuracy: removed unverifiable production-
                          readiness claims, fixed CockroachDB / ClickHouse
                          mis-categorisation, removed Go version mismatch.
    /team               — auto-generated from src/data/team.json and
                          enriched live from GitHub (avatars, location,
                          contributor count). 4 maintainers + 130
                          contributors at time of writing.
    /roadmap            — milestones pulled from GitHub at build time.
    /showcase, /examples, /community, /events, /changelog — refreshed
                          existing pages with metadata, RSS, dynamic
                          content where applicable.
- Home page restructured for substance-first reading:
    Hero → feature grid → datasource marquee → company logos →
    ecosystem recognition → testimonials. Pitch first, then prove.
- New EcosystemRecognition strip surfaces ThoughtWorks Tech Radar
  (Languages & Frameworks), CNCF Landscape (App Definition &
  Development), and JetBrains Open Source program — neutral
  credibility signals to complement the existing customer logos.
- Hero copy refined: tighter subhead, latest-release badge from
  changelog data, AI-coding-assistant tertiary line pointing at
  /AGENTS.md (real, shipped) for visitors building with Claude Code,
  Cursor, Codex, or Aider.
- Removed: ZopSmart references throughout (footer, showcase,
  CompanyTrustedList, FAQ, GFGTracks); the standalone Calendly
  CTA in the hero; the "block our calendar" tertiary; the AGENTS.md
  callout banner that duplicated the hero's inline link; the
  copyright/license footer line; the standalone "A note on
  benchmarks" section in /comparison; the /benchmarks page (kept
  for a future revisit when there are real numbers to publish).

SEO / AEO infrastructure
------------------------
- Per-page Markdoc frontmatter (nextjs.metadata.title / description)
  on every doc + SEO page so Google + AI Overviews see unique,
  intent-matched titles instead of inheriting from layout.
- New Markdoc tags for AI-search optimisation:
    {% answer %}    — direct-answer block at the top of a doc, the
                      kind LLMs quote.
    {% faq %} +
    {% faq-item %}  — collapsible Q/A block; emits FAQPage JSON-LD.
    {% howto %}     — numbered steps; emits HowTo JSON-LD.
- Dynamic sitemap at /sitemap.xml — walks src/app/**/page.{md,jsx}
  via fast-glob at build time; replaces the previous static file
  (deleted) so newly added pages appear automatically.
- Twitter / OpenGraph metadata blocks on every layout that owns a
  route group (faq, comparison, migrate, learn, examples, etc.).
- robots.txt + .well-known/security.txt + humans.txt added.

For AI coding assistants and search engines
-------------------------------------------
- /AGENTS.md — curated context file at the well-known root path.
  10 core rules an assistant must respect, a minimal app, a tight
  Migrations section (rules + pointer rather than inlined examples
  to save tokens), and a categorised "where to look" link index.
  Linked inline from the hero for visitors using Claude Code /
  Cursor / Aider / Codex / Continue.
- /llms.txt — Markdown-shaped curated link index per the emerging
  llmstxt.org spec. Sectioned (Quick Start / Advanced Guide /
  Datasources / References / Comparison and migration / Examples
  and showcase / Project / For AI assistants) so AI engines can
  partial-fetch.
- Footer: replaced the duplicate "For AI assistants" entry with
  "LLM index" → /llms.txt. Top-of-page + bottom-of-page placement
  matches the audience split: AGENTS.md is for the developer
  wiring up an assistant (hero), llms.txt is for the AI crawler
  (footer).

Build-time data fetchers
------------------------
- utils/fetch-releases.mjs       — GitHub releases → src/app/changelog/releases.json
- utils/fetch-roadmap.mjs        — GitHub milestones → src/data/roadmap.json
- utils/fetch-team.mjs           — Team + contributors → src/data/team-enriched.json
- utils/generate-changelog-rss.mjs — public/changelog.xml (RSS)
Each fetcher has an offline-tolerant snapshot fallback so a
rate-limited or offline build keeps the previously-fetched JSON
rather than silently emptying it.

Build hooks adjusted: the GitHub fetchers no longer run on every
build (they hit GitHub rate limits and slowed local dev). They now
run only via `npm run refresh-data`; only the (local-only) RSS
generator runs on `prebuild`. JSON snapshots are committed and
update on demand or on release.

i18n / localisation
-------------------
- Spanish (/es/*) and Simplified Chinese (/zh/*) variants of the
  hero, with LocaleAutoRedirect picking the user's preferred
  language on first visit (and storing a manual override so the
  user's later choice sticks).
- Footer language switcher.
- hreflang annotations on the root layout.

Components added
----------------
- MarketingPage         — chrome wrapper for SEO pages (no left
                          sidebar, right rail TOC kept).
- LatestReleaseBadge    — small inline version chip in the hero
                          fed from releases.json.
- LocaleAutoRedirect    — browser-language sniffing on /.
- EcosystemRecognition  — TW Radar / CNCF / JetBrains row with
                          per-source metadata.
- Faq + FaqSearchProvider — client-side search across FAQ items.
- Answer / HowTo        — Markdoc tag renderers.

Changelog / RSS
---------------
- changelog page: full release history (108 releases) with deep-
  link anchors per version (/changelog#v1.56.0 auto-expands).
- RSS feed at /changelog.xml regenerated from releases.json.

CSS fixes
---------
- prism.css: removed the global `code { background-color }` rule
  that was painting per-line "pill" backgrounds on every `<code>`
  inside `<pre>`. Scoped to `:not(pre) > code`.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Both have been active contributors to gofr-dev/gofr (verified via
the framework's commit history). LinkedIn URLs supplied directly;
GitHub handles confirmed via the noreply.github.com address pattern
in their commits.

team-enriched.json regenerated against the live GitHub API: 6 core
members + 128 community contributors (total 134; the two new
maintainers move out of the community contributor list, keeping
the total stable).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
team page
- Card stripped to identity essentials: avatar, name, role, location,
  GitHub + LinkedIn. Removed bio, company, blog, and the stats row
  (commits/repos/followers) — every card now has identical structure
  so the grid reads as one set of people, not six different layouts.
- Spacer (`flex-1` + `h-full`) removed; cards size to content rather
  than forcing a tall uniform height with dead air above the footer.
- Sort: Creator pinned first, then Maintainers ordered by commit count
  to gofr-dev/gofr (highest first). Source order in team.json is left
  alone so this is purely a render-time sort.
- New section between maintainer cards and the contributor wall:
  Top contributors (top 5 community devs by commit count). Visual
  hierarchy steps maintainers (72px avatar) → top contributors (64px,
  with login + commit count) → contributor wall (40px avatar dots).

team-enriched / fetch-team
- Cross-reference contributors API to stash each core member's commit
  count under github_data.gofr_contributions. Field is harmless when
  not rendered; powers the sort and the future-proofing in case we
  ever want to surface it again.

changelog
- Client-side pagination, 20 releases per page. Initial render emits
  all release data into the DOM (so deep-link anchors keep working)
  but only the first chunk is visible. "Show 20 older" advances the
  window in PAGE_SIZE chunks; "Showing X of Y" status line.
- Right rail now powered by `allGroups` (from full release list)
  instead of the visible window — every month is one click away.
  Click handler auto-extends `shown` to include the target month
  before scrolling, so an older month from the rail just works.
- Deep-link auto-expand fixed: a hash like /changelog#v1.30.0 that
  points past the current pagination window now extends `shown` to
  include the target before scrolling.
- ReleaseCard hydration mismatch fixed: `hashMatch` was being
  computed at render time from `window.location.hash`, which differs
  server vs client. Moved to a useEffect that runs after hydration.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
changelog
- Body now groups by minor-version line (v1.56, v1.55, …) instead of
  by month. Section headers use mono / no .x suffix per feedback. Each
  release card keeps its date inline as metadata, so chronology is
  visible without being the sort axis.
- Right rail is a flat list of every exact release ("v1.56.4 · Apr 29
  '24"). Year shown as compact apostrophe form so the rail row stays
  narrow but spans-multiple-years isn't ambiguous.
- Click → jumps to that release; auto-extends pagination if it sits
  past the visible window. Active row is set by a release-tag scroll-
  spy so the rail tracks position as you scroll.
- Removed the by-month / by-version tab toggle — version-only navi-
  gation reads cleaner.

SEO / AI discoverability
- src/app/layout.jsx: <link rel="alternate"> tags for /llms.txt
  (text/plain) and /AGENTS.md (text/markdown), plus the emerging
  rel="llm" and rel="ai-context" hints. Crawlers that follow rel-
  alternate pick up both files automatically.
- public/robots.txt: explicit comment annotations referencing both
  AI files, so a human auditing the site's crawler policy sees them
  without having to crawl every link.
- src/app/sitemap.js: /llms.txt and /AGENTS.md added as STATIC_ROUTES
  with priority 0.9 so they appear in /sitemap.xml as first-class
  indexable URLs.

showcase
- CTA reframed: "Add your company to the showcase" → "Share a
  testimonial". The issue prefill template now asks for Name / Role
  / Happy to be quoted publicly instead of Company name / Industry.
  Better fit for the audience that actually adopts GoFr (individual
  developers) versus pushing contributors to get corporate sign-off.

home page
- Fixed silent click-trap: the decorative blur-orb <Image> in the
  feature grid was absolute + opacity-25 + mt-80 with no pointer-
  events setting, so it floated above the DBlist / ecosystem cards /
  testimonials below and swallowed their clicks. Added
  pointer-events-none.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Six research agents spanning llms.txt adoption, AGENTS.md
convention, AI engine citation patterns, traditional Google SEO,
community/social traffic for OSS frameworks, and crawler/bot
directives converged on a small set of evidence-backed wins.
Hyped surfaces (heavy schema stacking, llms.txt as a crawler
signal, OG cards as direct AI signal) were dropped.

sitemap.js
- Drop <changefreq> and <priority>: Google explicitly ignores both.
- Compute per-route <lastmod> from `git log -1 --format=%cI` of the
  source page file (fs mtime fallback when git is unavailable).
  Honest "last actually edited" beats build-time on every URL —
  Google trains on the signal and discounts sitemaps that bump
  every URL on every build.
- Add /llms.txt, /AGENTS.md, /robots.txt as static-file entries so
  they're discoverable from the sitemap too.

src/app/layout.jsx
- Site-wide <meta name="robots"> with max-snippet:-1,
  max-image-preview:large, max-video-preview:-1 — required to be
  quoted in full by AI Overviews and to surface large image
  previews in SERP cards. Restrictive-wins-on-conflict makes this
  the safe default.

public/robots.txt
- Explicit allow-list per canonical 2025-26 AI/answer bot user-
  agent (OpenAI: GPTBot/OAI-SearchBot/ChatGPT-User; Anthropic:
  ClaudeBot/Claude-SearchBot/Claude-User; Google: Googlebot/
  Google-Extended; Bing, Perplexity, Apple, Meta, Cohere, You,
  DuckAssist, Amazon). User-agent: * already permits everything;
  per-bot stanzas make the policy unambiguous to crawler operators.
- Comment annotations pointing humans at /AGENTS.md and /llms.txt.

src/components/DocStructuredData.jsx (new)
- Per-doc TechArticle + BreadcrumbList JSON-LD. Client component so
  Next 14 static export pre-renders the <script type="application/
  ld+json"> tags into the HTML payload that crawlers read; usePathname()
  resolves at build time, not runtime, for static routes.

src/components/LastUpdatedByline.jsx + utils/generate-doc-mtimes.mjs
  + src/data/doc-mtimes.json (new)
- Small visible "Last updated <date>" line under each doc title.
  Date comes from a per-route map regenerated at prebuild from
  git log of the source file. Reasoning: Dec 2025 Google core
  update rewarded freshness — winners averaged 393 days since last
  update vs. losers' 500 days (Amsive analysis). Visible byline
  + accurate sitemap lastmod = real freshness signal both surfaces.
- Hooked into npm prebuild and refresh-data scripts.

DocsLayout.jsx
- Wires DocStructuredData (in head) + LastUpdatedByline (under title)
  on every doc page. No change to other layouts.

What was deliberately not added (research said no):
- llms.txt as anything beyond a manual-paste DX surface (~0.1% of
  AI-bot requests touch it; Google's John Mueller: "no AI system
  currently uses llms.txt"; SE Ranking 300k-domain study: no
  correlation with citations).
- FAQPage / HowTo / SpeakableSpecification / multiple Article-style
  schemas — controlled studies show no ranking lift; one schema
  *worsened* a citation-prediction model in BrightEdge's analysis.
- ai.txt, noai/noimageai meta tags — academic only, the site
  *wants* AI ingestion.
- AGENTS.md repo move (gofr-dev/gofr) — separate framework PR.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The framework Dockerfile (gofr-dev/gofr/docs/Dockerfile) does
COPY-then-build inside `ghcr.io/gofr-dev/website:latest`. There is
no .git directory in that builder stage, so generate-doc-mtimes.mjs
falls back to fs.statSync — which gives every doc the same Docker
COPY timestamp, defeating the freshness signal entirely.

Move it from `prebuild` to `refresh-data` (manual maintainer step):
- Local dev: maintainer runs `npm run refresh-data`, real git
  mtimes get baked into src/data/doc-mtimes.json, JSON committed.
- Docker build: prebuild only does the local-safe RSS regen; the
  committed mtime snapshot is served as-is.

The deployed site shows real "Last updated" dates from the website
repo's git history of when each doc was last touched. Far better
than build-time-for-everything.

Verified by `npm run build`: static export at out/ ships all 100+
routes; sitemap.xml uses the new shape (loc + lastmod only); doc
pages render TechArticle + BreadcrumbList JSON-LD and the visible
Last updated byline; robots.txt lists the AI/answer-bot allow-list.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Adds a `Refresh data from GitHub` step to the release_package job
that runs `yarn refresh-data` before the Docker build, with the
built-in `GITHUB_TOKEN` for auth (1000 req/hr — well above our
~150-request budget per refresh and far above the 60/hr unauth
cliff that has bitten previous local refreshes).

Why deploy-time fetch + committed snapshots, both:
  - Fresh data on every release: releases.json, roadmap.json,
    team-enriched.json, doc-mtimes.json all reflect the state at
    the moment of deploy, not whenever a maintainer last ran
    `npm run refresh-data` on their laptop.
  - But never an empty site: each fetch script already has a
    per-source snapshot fallback (e.g. fetch-team.mjs uses
    snapshotByGithub when a profile fetch fails), and the workflow
    step has `continue-on-error: true` so even a fully rate-limited
    GitHub doesn't block deploy. The committed JSONs are the
    last-known-good state.

Other workflow tweaks:
  - `fetch-depth: 0` on checkout so generate-doc-mtimes.mjs has
    the full git log to compute per-doc "Last updated" timestamps.
    A shallow clone would give every doc the same boot timestamp.
  - Add `setup-node` + `yarn install` to the release_package job
    (previously missing — the original workflow only had Node in
    the `build` job).

No PAT required: GITHUB_TOKEN suffices because all data we read
is public on github.com, and 1000 req/hr is plenty.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The website's Dockerfile builds a "source bundle" image that the
framework's docs/Dockerfile then layers `npm install && npm run
build` on top of. The old version copied src/, utils/, and config
files but missed `public/` entirely — meaning every static asset
(robots.txt, AGENTS.md, llms.txt, opengraph-image.png, security.txt,
the favicon, blur orbs, …) was absent from the deployed site even
though they're committed in the repo.

Verified end-to-end locally by rebuilding both images and curling
the resulting container:

  before:  /robots.txt  /AGENTS.md  /llms.txt  →  404
  after:   /robots.txt  /AGENTS.md  /llms.txt  →  200

robots.txt now serves with all 21 explicit User-agent stanzas;
llms.txt and AGENTS.md serve with their full bodies; the doc-page
JSON-LD (TechArticle + BreadcrumbList) and the visible "Last
updated" byline all render correctly through the deploy chain.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Old logic sorted contributors by raw commit count from the
/contributors API. That misses reviewers, triagers, and discussion
participants entirely — somebody who reviews 150 PRs but commits
sparingly was outranked by a one-time bulk-commit author.

New logic computes a composite score per contributor at fetch
time:

    score = 1·commits
          + 5·prs_merged           # gated, finished work
          + 2·reviews_authored     # quality gating + mentorship
          + 0.5·comments_authored  # triage + support + design

Signals come from three GitHub Search API queries per candidate:
- is:pr is:merged author:U repo:R       → PRs merged by user
- is:pr reviewed-by:U repo:R            → PRs they formally reviewed
- commenter:U repo:R                    → unique threads commented on

API budget: top 15 candidates by raw commit count × 3 calls = 45.
Throttled at 7 sec/user to stay safely under the Search API's
30/min authenticated limit (~1:54 wall time per refresh). Sized so
that anyone realistically in the running for "top 5 by composite"
is in the candidate pool — picking 15 over 5 covers the case where
a heavy reviewer's commit count puts them outside the top 5 commit-
sorted but inside the top 5 by composite.

Snapshot fallback: if a search call fails for any user, the
previous JSON value is preserved instead of dropping the signal to
zero. Existing per-source fallback for commits/contributors stays
untouched.

Result for gofr-dev/gofr today:

  rank | login              | score | commits | PRs | reviews | comments
  -----|--------------------|-------|---------|-----|---------|---------
  1    | ccoVeille          |  597  |   48    | 27  |  155    |  208
  2    | akshat-kumar-singhal|  136  |   44    | 10  |   14    |   28
  3    | mfreeman451        |  134  |  124    |  0  |    3    |    8
  4    | gizmo-rt           |  115  |   58    |  6  |    8    |   23
  5    | illenko            |   86  |   31    |  6  |    8    |   19

ccoVeille jumps from #4 (commits only) to #1 — exactly the kind of
contributor the old logic missed.

Page treatment: heading caveat reads "Ranked by GitHub-visible
contributions … commits, merged PRs, reviews, and comments combined"
so visitors know what's measured. Each card still leads with raw
commit count (most legible single number) and shows a soft
secondary line listing PRs and reviews when non-zero. Hover title
exposes the full breakdown including comments.

Caveats explicit in code comments:
- Discussions are GraphQL-only and punted to a phase 2.
- Recency weighting is punted (Search returns lifetime totals).
- Review-quality and PR-size are not captured — every formal
  review and every merged PR weight equally.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Pulling out the partial-i18n surface entirely:

- Footer language strip (English · Español · 简体中文) removed.
- LocaleAutoRedirect (browser-language sniffing on first visit, with
  localStorage opt-out) removed and its mount in Layout.jsx unwired.
- /es and /zh route directories deleted — they only mirrored the
  hero, leaving the rest of the site English. Half-translated
  surfaces are worse than honest English-only.
- Footer imports trimmed: usePathname, clsx, React no longer needed
  after the language-switcher block was deleted.

The rel="alternate" tags pointing at /llms.txt and /AGENTS.md stay
— those are AI-discoverability hints, not language alternates.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
aryanmehrotra and others added 3 commits May 1, 2026 17:52
Two complementary publish jobs replace the single tag-only flow,
so the framework's stage deploy can track gofr-dev/website's main
branch via :stage while prod stays anchored to tagged releases.

publish_stage (new):
  - Fires on push to main, on a daily cron at 04:00 UTC, and via
    workflow_dispatch.
  - Runs `yarn refresh-data` so :stage bakes in fresh releases /
    roadmap / team / doc-mtimes on every publish.
  - Tags ghcr.io/gofr-dev/website:stage.
  - Cron exists so :stage picks up new GoFr releases / maintainer
    activity even between merges. workflow_dispatch is the manual
    button for ad-hoc refreshes.

release_package (existing behavior, body unchanged):
  - Fires on tag v* push.
  - Publishes ghcr.io/gofr-dev/website:<tag> + :latest with fresh
    data. Prod tracks tags.

The framework-side companion (gofr-dev/gofr#3370) parameterizes
docs/Dockerfile to accept WEBSITE_TAG, points website-stage.yml at
:stage, and adds inline refresh + local source-bundle build to
website-prod.yml so prod always ships with current data on every
GoFr `v*.*.*` tag.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Removed publish_stage job and the cron / push-to-main triggers.
Stage and prod in the framework repo now both check out this
website source, run yarn refresh-data, and build their source-bundle
in-runner — so neither needs a pre-published :stage on ghcr.

What this trims:
  - ~120 unnecessary CI runs/month (the daily cron)
  - Surprise 05:00 UTC stage rollouts
  - The two-layer cron/staleness coordination headache

Workflow now only fires on:
  - push tag v*  → release_package publishes :latest + :vX.Y.Z
                   (kept as the public artifact + rollback target)
  - PR to main/development → build job only (no publish)

Companion change in gofr-dev/gofr#3370 ports the inline-refresh
pattern from website-prod.yml to website-stage.yml.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…deploys

Restores the publish_stage job removed in the previous commit. The
framework's stage workflow pulls :stage rather than rebuilding the
website source from scratch on every push to development, so :stage
needs to exist as a published image keyed to website main.

Triggers:
  - push to main         → publish :stage with fresh data
  - workflow_dispatch    → manual refresh of :stage on demand
                           (e.g. right after a GoFr release lands)

What this is NOT:
  - Not a public artifact (that's :latest, published on tag).
  - Not on a schedule. Data freshness is tied to actual main merges
    and the explicit workflow_dispatch button — no surprise overnight
    rollouts.

Prod deploys (gofr-dev/gofr's website-prod.yml) still inline-rebuild
the source-bundle locally on every framework v*.*.* tag, so prod
freshness is independent of when :stage was last refreshed.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
aryanmehrotra added a commit to gofr-dev/gofr that referenced this pull request May 1, 2026
Moves framework-specific content out of gofr-dev/website and into
this repo, mirroring how docs/quick-start/, docs/advanced-guide/,
docs/datasources/, docs/references/, docs/events.json, and
docs/testimonials.json already work — content lives where the
framework lives, design lives in the website repo.

Marketing pages (14 .md files):
  docs/why-gofr/page.md
  docs/comparison/page.md + 4 sub-pages (gofr-vs-{gin,fiber,echo,chi})
  docs/migrate/page.md + 5 sub-pages (from-{gin,fiber,express,flask,spring-boot})
  docs/learn/page.md
  docs/faq/page.md

Framework-content data files (4):
  docs/team.json                     — maintainers list
  docs/showcase/companies.json       — companies using GoFr
  docs/examples/examples.json        — runnable examples index
  docs/AGENTS.md                     — curated rules for AI assistants

What this means for editing:
  - Update a comparison page or fix a typo in /faq → PR here, in this
    repo, alongside any related framework change. No cross-repo PR.
  - Add a maintainer or roll a contributor → edit team.json here.
  - Refine an AGENTS.md rule → edit here. /AGENTS.md served from
    this content via the website's overlay.

What stays in the website repo (gofr-dev/website):
  - All layouts and JSX components (the rendering chrome).
  - Build pipeline, fetcher scripts, design tokens.
  - Build-time-generated JSON (releases, roadmap, team-enriched,
    doc-mtimes) — output of CI fetchers, not source content.
  - Site-discovery metadata: public/llms.txt, robots.txt, humans.txt,
    .well-known/security.txt — about the site as a whole, not
    framework specifics.

docs/Dockerfile updated with 9 new COPY directives, all pointing at
the same destinations the website previously held the files at:

  COPY docs/why-gofr     /app/src/app/why-gofr
  COPY docs/comparison   /app/src/app/comparison
  COPY docs/migrate      /app/src/app/migrate
  COPY docs/learn        /app/src/app/learn
  COPY docs/faq          /app/src/app/faq
  COPY docs/team.json    /app/src/data/team.json
  COPY docs/showcase/companies.json  /app/src/app/showcase/companies.json
  COPY docs/examples/examples.json   /app/src/app/examples/examples.json
  COPY docs/AGENTS.md    /app/public/AGENTS.md

Companion change in gofr-dev/website#211 removes these 18 files
from that repo so there's exactly one source of truth.

Sequencing: this PR can land first — stage/prod keep working off
the website's current copies until the website removes them.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
These 18 files are framework-specific content — positioning, comparisons,
migration guides, the maintainer list, the AI-assistant rule sheet —
and they should evolve in lockstep with the framework. They now live
in gofr-dev/gofr/docs/ and overlay this tree at deploy time, exactly
how docs/quick-start, docs/advanced-guide, events.json, testimonials.json,
and navigation.js already work.

Companion: gofr-dev/gofr#3370 adds these files there + the 9 new
COPY directives in docs/Dockerfile.

Removed from this repo:
  src/app/why-gofr/page.md
  src/app/comparison/page.md + 4 sub-pages
  src/app/migrate/page.md + 5 sub-pages
  src/app/learn/page.md
  src/app/faq/page.md
  src/data/team.json
  src/app/showcase/companies.json
  src/app/examples/examples.json
  public/AGENTS.md

What stays in this repo (per the design/infrastructure principle):
  - All layouts and JSX components (rendering chrome) — the layout.jsx
    in why-gofr/, comparison/*, migrate/*, learn/, faq/, showcase/,
    examples/ remain so Next.js routing keeps working when the .md
    or .json gets dropped in by the framework's Dockerfile.
  - Build pipeline (utils/*.mjs, package.json, next.config.mjs,
    tailwind.config.js).
  - Build-time-generated JSON (releases, roadmap, team-enriched,
    doc-mtimes) — outputs of CI fetchers.
  - Site-discovery metadata: public/llms.txt, robots.txt, humans.txt,
    .well-known/security.txt — about the site as a whole.

Local dev caveat: routes that depend on the overlaid files will 404
locally until either (a) the framework's Dockerfile is exercised or
(b) someone clones gofr-dev/gofr and symlinks the content tree.
Same caveat already applies to /docs/* — handled identically.

Sequencing: gofr-dev/gofr#3370 must merge first so the framework
docs/ has the content; then this commit removes the local copies.
The deploy pipeline (gofr-dev/gofr's website-stage.yml and
website-prod.yml) checks out gofr-dev/website, builds source-bundle
locally, and overlays framework docs/ — so the deploy chain reads
content from gofr-dev/gofr regardless of whether this repo's local
copies exist.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
aryanmehrotra added a commit to gofr-dev/gofr that referenced this pull request May 1, 2026
Moves framework-specific content out of gofr-dev/website and into
this repo, mirroring how docs/quick-start/, docs/advanced-guide/,
docs/datasources/, docs/references/, docs/events.json, and
docs/testimonials.json already work — content lives where the
framework lives, design lives in the website repo.

Marketing pages (14 .md files):
  docs/why-gofr/page.md
  docs/comparison/page.md + 4 sub-pages (gofr-vs-{gin,fiber,echo,chi})
  docs/migrate/page.md + 5 sub-pages (from-{gin,fiber,express,flask,spring-boot})
  docs/learn/page.md
  docs/faq/page.md

Framework-content data files (4):
  docs/team.json                     — maintainers list
  docs/showcase/companies.json       — companies using GoFr
  docs/examples/examples.json        — runnable examples index
  docs/AGENTS.md                     — curated rules for AI assistants

What this means for editing:
  - Update a comparison page or fix a typo in /faq → PR here, in this
    repo, alongside any related framework change. No cross-repo PR.
  - Add a maintainer or roll a contributor → edit team.json here.
  - Refine an AGENTS.md rule → edit here. /AGENTS.md served from
    this content via the website's overlay.

What stays in the website repo (gofr-dev/website):
  - All layouts and JSX components (the rendering chrome).
  - Build pipeline, fetcher scripts, design tokens.
  - Build-time-generated JSON (releases, roadmap, team-enriched,
    doc-mtimes) — output of CI fetchers, not source content.
  - Site-discovery metadata: public/llms.txt, robots.txt, humans.txt,
    .well-known/security.txt — about the site as a whole, not
    framework specifics.

docs/Dockerfile updated with 9 new COPY directives, all pointing at
the same destinations the website previously held the files at:

  COPY docs/why-gofr     /app/src/app/why-gofr
  COPY docs/comparison   /app/src/app/comparison
  COPY docs/migrate      /app/src/app/migrate
  COPY docs/learn        /app/src/app/learn
  COPY docs/faq          /app/src/app/faq
  COPY docs/team.json    /app/src/data/team.json
  COPY docs/showcase/companies.json  /app/src/app/showcase/companies.json
  COPY docs/examples/examples.json   /app/src/app/examples/examples.json
  COPY docs/AGENTS.md    /app/public/AGENTS.md

Companion change in gofr-dev/website#211 removes these 18 files
from that repo so there's exactly one source of truth.

Sequencing: this PR can land first — stage/prod keep working off
the website's current copies until the website removes them.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
aryanmehrotra and others added 4 commits May 1, 2026 18:49
Removed 56 src/app/docs/**/page.md files, three docs screenshot
PNGs, and three top-level marketing pages that were accidentally
checked in by an early `git add -A`. All of these are overlaid by
gofr-dev/gofr's docs/Dockerfile at deploy time, so they don't
belong in this repo's source.

What got removed (now framework-only):
  src/app/docs/advanced-guide/    (20 page.md)
  src/app/docs/datasources/       (15 page.md, incl. nested migrations)
  src/app/docs/quick-start/       (7  page.md)
  src/app/docs/references/        (4  page.md)
  src/app/docs/page.md            (1)
  public/jaeger-traces.png
  public/quick-start-logs.png
  public/quick-start-trace.png

What's restored as snapshots (imported by JSX or scripts at build
time, so the local build needs them — framework's overlay still
wins at deploy):
  src/data/team.json
  src/app/showcase/companies.json
  src/app/examples/examples.json
  public/AGENTS.md

What stays as snapshots (already-committed pattern, not changed
this round):
  src/app/events/events.json
  src/lib/navigation.js
  utils/testimonials.json

Net effect on PR diff: -12,165 lines, +170 lines, 64 files
touched in this commit alone — most of the previous PR weight was
the duplicated docs content.

Verified: `npm run build` succeeds, all routes still emit, the
framework Dockerfile's COPY directives unchanged so deploy still
works (it just no longer overwrites pre-existing copies).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Five external audit reports converged on a small set of high-leverage
fixes. Landing them all at once.

Critical:
- Soft-404 on /docs fixed at the framework side (next commit on
  gofr-dev/gofr#3370): nextjs.metadata frontmatter added to
  docs/page.md so the route renders a real <title>.
- Broken hreflang alternates (/es, /zh — both routes 404) removed
  from src/app/page.jsx. Google flagged these in Search Console as
  page-level errors on every site URL.
- /pkg/** redirect stubs (23 routes, no SEO content, just
  PkgRedirect → /docs) now ship with `robots: noindex,nofollow` via
  src/app/pkg/layout.jsx and are excluded from sitemap.xml. Same
  for /cli/** and /releases. These were 27 of the orphan URLs the
  audit flagged.
- FAQPage JSON-LD now auto-emits on /faq. Previously FaqList only
  generated the schema when an explicit `items={[...]}` prop was
  passed; the Markdoc {% faq %}{% faq-item %} pattern doesn't pass
  one. Refactored FaqList to walk its React children, extract
  question + answer text, and emit FAQPage schema regardless of
  whether items was supplied. Single highest-leverage AEO fix —
  unlocks Google AI Overview citation eligibility for Q/A queries.
- <main id="main"> landmark + skip-to-main link added to
  src/components/Layout.jsx. WCAG 2.4.1 (Bypass Blocks) was failing
  on every page.
- DocStructuredData now reads doc-mtimes.json directly to populate
  schema.org dateModified instead of relying on the caller to pass
  lastUpdated. The caller (DocsLayout) wasn't passing it, so every
  TechArticle in the wild was missing dateModified — invisible
  freshness signal.

High:
- alt="Transistor" (from a stale tutorial template) repeated on 11
  marquee logos (DBlistComponent.jsx) and 9 trusted-companies logos
  (CompanyTrustedList.jsx) — both now use real names ("Redis",
  "Kafka", "American Express", etc.) sourced from the data array.
- prefers-reduced-motion: reduce honored in src/styles/prism.css —
  the 30s scrolling marquee freezes and lays items out statically
  for users who've requested reduced motion at OS level. WCAG 2.3.3.
- generate-doc-mtimes.mjs now walks /why-gofr, /comparison,
  /migrate, /learn, /faq in addition to /docs — so every overlay-
  content page gets a real "Last updated" byline + dateModified
  instead of only the docs tree.

What stays as snapshots (no change needed):
- src/data/doc-mtimes.json regenerates on next refresh-data run.
- Sitemap auto-rebuilds at next build.

What's NOT in this commit (followups):
- /docs/quick-start/introduction lead-with-Prerequisite issue —
  framework PR concern.
- Per-route OG/Twitter card overrides — bigger change, separate commit.
- Accordion <div onClick> → <button> — separate commit, isolated.
- /llms-full.txt generator — separate commit.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Three more audit findings landed in one go:

a11y — Accordion now native <button>
- src/components/Accordion.jsx wrapped its content in <div onClick>
  with no role/tabIndex/keyboard handler. Replaced with <button
  type="button" aria-expanded={isOpen}>. Now activatable by Enter
  and Space, reachable via keyboard, exposes role=button to AT.
- Inner decorative <button>+arrow image collapsed to a plain
  aria-hidden=true Image (parent <button> already handles
  activation; nested interactive elements were redundant + wrong).

aeo — /llms-full.txt now actually exists
- AGENTS.md advertises https://gofr.dev/llms-full.txt as the
  "everything-in-one-file" variant for Anthropic Files API / OpenAI
  Assistants File Search / ChatGPT custom GPT knowledge bases. The
  URL was 404. utils/generate-llms-full.mjs walks every Markdoc
  page, strips frontmatter, concatenates with route-prefixed H2s
  per page, emits public/llms-full.txt. Wired into prebuild and
  refresh-data.
- robots.txt comment annotation, sitemap.xml, and the layout's
  <link rel="alternate" type="text/plain"> all now reference it.

quick-start intro page (framework PR companion change)
- gofr-dev/gofr/docs/quick-start/introduction/page.md previously
  led with "# Prerequisite" — failed Princeton GEO's "first 200
  words contains the answer" rule. Replaced with "# Hello, GoFr"
  + a 1-sentence definition + a 1-sentence promise of what the
  page delivers, before any prerequisites. AI Overview / Perplexity
  citation eligibility for "what is GoFr" / "go framework with
  observability" queries.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
team
- Removed Srijan Rastogi from src/data/team.json. Re-ran
  fetch-team.mjs to regenerate team-enriched.json — now 5 core
  members, 129 community contributors (Srijan moves into the
  community grid since he's still an active gofr-dev/gofr
  contributor).

fetch-team.mjs
- Added a framework-fallback path: when src/data/team.json is
  missing locally (which is the long-term direction — team.json
  lives in gofr-dev/gofr/docs/ and overlays at deploy), the script
  now falls back to ../gofr/docs/team.json if the sibling clone is
  available. Lets a maintainer run `yarn refresh-data` from the
  website repo without first hand-copying team.json over.

The companion deletion of Srijan from gofr-dev/gofr/docs/team.json
landed in PR #3370 (next push).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
aryanmehrotra added a commit to gofr-dev/gofr that referenced this pull request May 1, 2026
Per maintainer team decision. Srijan Rastogi remains in the
gofr-dev/gofr contributor history and will continue to appear in
the community contributor grid on /team (sourced live from the
GitHub contributors API at deploy time), just not in the core
maintainer cards row above it.

Companion change in gofr-dev/website#211 regenerates the website's
team-enriched.json snapshot to reflect the new 5-maintainer roster.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
aryanmehrotra and others added 7 commits May 1, 2026 21:21
… & preconnect

- next.config.mjs: extend Markdoc loader to derive openGraph/twitter title+description
  from each page's frontmatter so /comparison, /faq, /why-gofr, /migrate/*, /learn,
  and /docs/** stop inheriting the home page's social card. Authors can still override
  via nextjs.metadata.openGraph in frontmatter.
- src/app/layout.jsx: hoist hardcoded <meta og:*> JSX into the metadata export so
  Next's metadata-merge actually runs; drop root-level alternates.canonical='/' that
  was branding every subpage as a duplicate of home.
- src/components/Hero.jsx: bump subtitle/tertiary text from slate-400/500 to
  slate-300/400 for WCAG AA contrast on slate-900; lazy-load decorative blur orbs
  and mark them aria-hidden.
- src/components/Search.jsx: add aria-label to the search input (no visible label).
- src/app/team/layout.jsx: preconnect + dns-prefetch to avatars.githubusercontent.com
  to cut DNS+TLS RTT on first paint of the contributor wall.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The previous commit emitted openGraph: { type: 'article' } unconditionally
on every Markdoc page. Next's metadata merge replaces openGraph as a whole
key (it does not deep-merge), so doc pages without nextjs.metadata frontmatter
ended up with og:title and og:description stripped instead of inheriting the
root layout's defaults.

Fix: only emit page-level openGraph / twitter when the page actually
contributes a title, description, or explicit override block. Otherwise omit
the keys so parent layout values pass through unchanged.

Verified against /docs/quick-start/configuration (no frontmatter → inherits
home og:title) and /comparison/gofr-vs-gin (frontmatter → unique og:title).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Roadmap data currently has milestones=[] and every item carries
milestone=null, so the only group rendering was the catch-all
"Without a milestone" bucket. The label looked like a placeholder /
debug string in production. Drop the heading text when the group has
no milestone — items still render in a flat grid below the page
header. When milestones come back, the section heading reappears
automatically.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
P0:
- Hero.jsx: fix `x:px-12` typo → `xs:px-12`; the real `xs:` 10px
  breakpoint defined in tailwind.config.js was never applied because
  of the missing `s`. Grid padding now activates on phones.
- Hero.jsx: code editor wrapper text-sm → `text-xs sm:text-[13px]` so
  long code lines stay readable instead of forcing zoom on phones.
- Reviews.jsx: `mx-10` → `mx-4 sm:mx-10` (16px margin on phones);
  `md:columns-3` → `sm:columns-2 md:columns-3` (2-col tablet step).

P1:
- MobileNavigation.jsx: drawer `max-w-xs` → `max-w-[85vw] sm:max-w-xs`
  so it leaves a 15vw safe-zone on tiny phones.
- team/page.jsx: wrap social-icon links with `min-h/w-[36px] p-2 -m-2`
  so the touch target reaches WCAG 2.5.5 minimums; visual icon size
  unchanged at desktop.
- roadmap/page.jsx: bump label/metadata `text-[10px]`/`text-[11px]` to
  responsive `text-[11px] sm:text-[10px]` etc — readable at 320px.

P2:
- Reviews.jsx: add `min-w-0`/`truncate` so long author names don't push
  the avatar off-screen.
- Fence.jsx: code blocks `text-[13px]` → `text-xs sm:text-[13px]`.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Page weight + critical-path:
- HomePage.jsx: blur orbs drop `unoptimized` and `priority`, switch to
  `loading="lazy"` + proper `width`/`height` so Next can serve WebP/AVIF
  responsives. Add `pointer-events-none`, `select-none`, `aria-hidden`
  + `hidden sm:block` so the decorative 200+ KB PNGs don't load on
  phones at all.
- VerticalTimeline.jsx: same blur-orb treatment.

Bugsnag (Layout.jsx):
- Replace eager `import { ErrorBoundary } from './BugsnagWrapper'` with
  in-file LazyBugsnagBoundary that dynamic-imports `@bugsnag/js` +
  `@bugsnag/plugin-react` via requestIdleCallback. Until ready, a tiny
  componentDidCatch fallback keeps the UX intact (errors silently
  no-op pre-init, acceptable given 99% of users never trigger them).

GitHub stars (Layout.jsx + new util):
- Replace render-blocking `useEffect` GitHub fetch with build-time
  snapshot at `src/data/github-stars.json`. New utils/fetch-github-stars.mjs
  mirrors the fetch-team.mjs pattern (snapshot fallback on API failure,
  optional GITHUB_TOKEN). Wired into `npm run refresh-data`. Optional
  once-per-session client refresh keeps long-lived browsers fresh,
  gated by sessionStorage so it doesn't fire on every navigation.

`'use client'` audit (removed where the directive was load-bearing only
out of habit — these components have no state/effects/handlers/browser
APIs and can render server-side):
- Footer.jsx, LatestReleaseBadge.jsx, SectionCards.jsx
- src/app/{comparison,docs,faq,learn,migrate,why-gofr}/layout.jsx (each
  was a one-liner wrapping a server component)

Footer hierarchy fix (addresses the "Documentation/Quick Start look the
same" complaint — they're footer column links sitting under a column
heading that wasn't visually differentiated enough):
- Column heading restyled `text-sm font-semibold text-white` →
  `text-xs uppercase tracking-wider text-slate-400`. Standard footer
  label treatment — the heading now reads as a small all-caps label
  clearly above the sentence-case links instead of merging into them.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The previous version gated the runtime fetch behind a sessionStorage
flag — meaning after the first navigation, the header stayed pinned
to whatever number was in src/data/github-stars.json (the build-time
snapshot). Users with stale browser caches saw the seed value (1.9K)
even after we'd rebuilt with the real count.

Restore the original "real-time" behaviour: the build-time snapshot
gives an instantly-correct first paint, then a background fetch on
every mount silently replaces it with the truly current number. Use
`stargazers_count` (the canonical field) and fall back to the legacy
`watchers` alias for safety.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Fence.jsx — when a markdown fence is written without a language tag
(```​ instead of ```go), prism-react-renderer's Highlight crashes the
entire page prerender on `language.toLowerCase()`. Fall back to 'text'
so a missing tag becomes a soft degrade (plain code block, no syntax
colors) instead of a hard build failure. Same crash pattern that
broke v1.56.2 and was patched in v1.56.3 (per releases.json).

Hero.jsx — revert the xs:px-12 mobile "fix". The original `x:px-12`
was a typo that never matched any breakpoint, so the visual was
designed around `px-4` (16px) being the only horizontal padding. The
typo correction silently activated a real `xs:` breakpoint (defined
as 10px in tailwind.config.js, i.e. always-on) which jumped the
hero's horizontal padding to 48px on every screen — narrowing the
content and exposing the feature cards that used to sit below the
fold. Drop the class entirely; the layout returns to its original
proportions.

package.json — wire `node utils/fetch-github-stars.mjs` into the
prebuild step so every Docker container build refreshes the baked-in
star count instead of serving the seed snapshot. Combined with the
earlier dynamic-stars patch in Layout.jsx, the header now (a) gets
the truly current count at build time, and (b) live-refreshes on
every page mount.

src/data/github-stars.json — refreshed snapshot.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
aryanmehrotra and others added 2 commits May 2, 2026 15:43
Setting `images: { unoptimized: true }` in next.config.mjs is the
official fix for static-export sites. Without it, Next's <Image>
component emits `/_next/image?url=...` srcs that 404 at runtime
under output: 'export' (the optimisation API is server-only) — the
browser falls back to its broken-image placeholder.

This regressed when the perf batch dropped per-component
`unoptimized` props in HomePage.jsx and VerticalTimeline.jsx
(visible as the broken-image artefact on /events between event
cards in user-reported screenshots). The config-level switch covers
every <Image> usage at once so we don't have to remember the prop
on each new image.

Also keep belt-and-suspenders `unoptimized` on the two decorative
blur-orb <Image>s (HomePage + VerticalTimeline) so the intent is
explicit even if someone flips the global later.

Verified every previously-broken URL on /events now returns 200:
- /_next/static/media/blur-cyan.d28a5585.png
- /events/hackathon.jpg
- /events/OpenSourceIndia.jpeg
- /events/gopherconAfrica.jpeg
- /events/WorkShop.jpeg

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Visual / interaction:
- Hero: revert dead-code `xs:px-12` → no class (preserves prod proportions);
  bump code-editor body to text-sm on desktop to match prod scale;
  remove the LatestReleaseBadge + AI/llms tertiary, restore prod's
  "Want to evaluate and adopt GoFr at your org? block our calendar."
  CTA pointing at the existing Calendly URL; remove `unoptimized`
  bypass per the static-export image fix; gentle gopher drift via
  motion-safe:animate-gentle-drift; line-by-line stagger reveal on
  the code lines via motion-safe:animate-line-in.
- HomePage: density-matched section padding (Vercel/Stripe pattern) —
  thin marquee strip py-8, logo wall py-12, ecosystem/testimonials
  py-20, feature-card grid py-20. Replaces uniform py-24 which was
  producing visible dead air on thin sections.
- Footer: "Documentation" → "Production Guides" (links the new
  /docs/guides/* tree); column heading becomes uppercase tracking-
  wider so the heading-to-link hierarchy is unmistakable.
- New: FadeInOnScroll, StaggerChildren, CountUp helpers (no new
  deps; pure IntersectionObserver). FadeInOnScroll wraps every
  trailing section so they fade up/down on scroll. StaggerChildren
  ripples the 6 feature cards in left→right. CountUp animates 0 →
  21,500 on the trusted-by line when it scrolls into view.
- Cards: 1 px hover lift on QuickLinks + Ecosystem cards.
- Color seams removed: bg-gray-900 stripped from DBlistComponent +
  CompanyTrustedList, bg-[#101827] stripped from Reviews. Page now
  reads as one continuous bg-slate-900 from hero to footer.
- prefers-reduced-motion now PAUSES the marquee animation in place
  rather than disabling it (the `position: static` fallback was
  collapsing all items to the same coordinate and hiding the row).

Static-export image fix:
- next.config.mjs `images: { unoptimized: true }` so /_next/image
  is no longer emitted under output: 'export'. Without this, every
  <Image> rendered a /_next/image?url=... src that 404'd in
  production and showed as a browser broken-image icon (visible
  on /events/ and on the homepage's blur orb).

SEO / AEO:
- Markdoc loader (next.config.mjs) now derives a per-page
  `alternates.canonical` from the source-tree path, in addition to
  the openGraph/twitter title+description it already auto-fills.
  Result: every Markdoc page emits a unique <link rel="canonical">.
- Layout / page metadata: home description padded from 70 chars
  → 150 chars; cli/gofr/page.jsx and 23 /pkg/**/page.jsx redirect
  stubs each now export a sensible local metadata.title (parent
  noindex preserved).
- DocsHeader: removed the manual <title> + <meta description> tags
  it was injecting from inside the React tree. They duplicated the
  canonical pair Next's metadata API already emits — Google was
  being shown two titles and free to pick the wrong one.
  Single root cause for ~25 doc pages losing their SEO title.
- robots.txt: added explicit allow stanzas for CCBot and Bytespider
  (Common Crawl + Bytedance) alongside the existing GPTBot /
  ClaudeBot / PerplexityBot / Google-Extended / Applebot-Extended /
  Meta-ExternalAgent set.
- llms.txt: added the 8 newer migration pages (Echo, chi, NestJS,
  FastAPI, Django REST, ASP.NET Core, Laravel, Rails).
- utils/generate-llms-full.mjs walker: added a "Production guides"
  section so the dockerizing / helm-chart / k8s-deploy guides flow
  into the dump on the next refresh.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@aryanmehrotra
aryanmehrotra requested a review from Umang01-hash May 3, 2026 18:12
@aryanmehrotra
aryanmehrotra marked this pull request as ready for review May 3, 2026 18:12
Copilot AI review requested due to automatic review settings May 3, 2026 18:12

Copilot AI left a comment

Copy link
Copy Markdown

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 is a large website overhaul for gofr.dev focused on SEO/AEO, AI-discoverability, fresher build-time data, and broader marketing/documentation surface area. It adds new public entry points and metadata infrastructure while also reshaping key user-facing pages like home, changelog, examples, showcase, roadmap, and team.

Changes:

  • Added SEO/AEO infrastructure: route metadata, structured data, AI-facing resources (AGENTS.md, llms.txt, llms-full.txt), dynamic sitemap, robots/security/humans files, and docs freshness data.
  • Added or reworked major site surfaces: homepage, examples, showcase, roadmap, changelog, events, team, FAQ/docs helpers, and multiple new shared UI components.
  • Replaced several runtime fetches/manual copy paths with build-time GitHub-driven snapshots and updated CI/build scripts to refresh/publish generated assets.

Reviewed changes

Copilot reviewed 109 out of 118 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
utils/generate-llms-full.mjs Generates concatenated AI-facing docs dump.
utils/generate-doc-mtimes.mjs Builds route-to-last-modified JSON from git history.
utils/generate-changelog-rss.mjs Generates RSS feed from changelog snapshot.
utils/fetch-roadmap.mjs Fetches milestones/issues into roadmap snapshot.
utils/fetch-releases.mjs Fetches GitHub releases into changelog data.
utils/fetch-github-stars.mjs Fetches GitHub star count snapshot.
tailwind.config.js Adds homepage animation keyframes/utilities.
src/styles/prism.css Refines inline code styling and reduced-motion handling.
src/markdoc/tags.js Registers new Markdoc tags/components.
src/markdoc/search.mjs Improves search title parsing and scoring.
src/data/team.json Adds maintainer/team source data.
src/data/github-stars.json Commits star-count snapshot.
src/data/doc-mtimes.json Commits generated last-modified snapshot.
src/components/goforgofr/GFGTracks.jsx Removes old company reference.
src/components/VerticalTimeline.jsx Fixes decorative image behavior/loading.
src/components/Tabs.jsx Adds client-side tab UI component.
src/components/StaggerChildren.jsx Adds staggered reveal container.
src/components/SectionCards.jsx Adds navigation card grid component.
src/components/Reviews.jsx Tweaks testimonial layout responsiveness.
src/components/QuickLinks.jsx Adds hover motion to quick links.
src/components/Prose.jsx Updates prose typography/tables/code styling.
src/components/PkgRedirect.jsx Adds redirect UI for package vanity routes.
src/components/Navigation.jsx Converts docs nav to collapsible client nav.
src/components/MobileNavigation.jsx Expands mobile nav with top-level site links.
src/components/MarketingPage.jsx Adds wrapper for SEO landing pages.
src/components/Layout.jsx Reworks global layout/header/error boundary/stars handling.
src/components/LatestReleaseBadge.jsx Adds release badge from changelog data.
src/components/LastUpdatedByline.jsx Adds visible last-updated byline from snapshot data.
src/components/HowTo.jsx Adds HowTo renderer + JSON-LD.
src/components/HomePage.jsx Reorders homepage sections and adds motion wrappers.
src/components/Hero.jsx Refines hero copy, CTAs, visuals, and code animation.
src/components/Footer.jsx Rebuilds footer information architecture.
src/components/Fence.jsx Redesigns fenced code blocks and copy UI.
src/components/Faq.jsx Adds FAQ accordion + FAQPage JSON-LD support.
src/components/FadeInOnScroll.jsx Adds section fade-on-scroll wrapper.
src/components/EcosystemRecognition.jsx Adds ecosystem recognition credibility strip.
src/components/DocsLayout.jsx Adds structured data and last-updated support to docs layout.
src/components/DocsHeader.jsx Removes duplicate head metadata from visible docs header.
src/components/DocStructuredData.jsx Adds doc JSON-LD output.
src/components/DBlistComponent.jsx Improves datasource marquee accessibility/content.
src/components/CountUp.jsx Adds animated counter component.
src/components/CompanyTrustedList.jsx Reworks company/social proof block.
src/components/Answer.jsx Adds answer callout component.
src/components/Accordion.jsx Improves accordion accessibility semantics.
src/app/why-gofr/layout.jsx Applies marketing-page wrapper.
src/app/team/layout.jsx Adds metadata and avatar CDN preconnect intent.
src/app/sitemap.xml Removes old static sitemap.
src/app/sitemap.js Adds dynamic sitemap generation.
src/app/showcase/page.jsx Adds showcase page with companies/testimonials.
src/app/showcase/layout.jsx Adds showcase route metadata.
src/app/showcase/companies.json Adds showcase company list.
src/app/roadmap/page.jsx Adds roadmap page driven by snapshot data.
src/app/roadmap/layout.jsx Adds roadmap route metadata.
src/app/releases/layout.jsx Replaces old releases layout with client redirect.
src/app/pkg/layout.jsx Adds noindex layout for package vanity routes.
src/app/pkg/gofr/datasource/surrealdb/page.jsx Converts vanity route to redirect page.
src/app/pkg/gofr/datasource/solr/page.jsx Converts vanity route to redirect page.
src/app/pkg/gofr/datasource/scylladb/page.jsx Converts vanity route to redirect page.
src/app/pkg/gofr/datasource/pubsub/sqs/page.jsx Converts vanity route to redirect page.
src/app/pkg/gofr/datasource/pubsub/nats/page.jsx Converts vanity route to redirect page.
src/app/pkg/gofr/datasource/pubsub/eventhub/page.jsx Converts vanity route to redirect page.
src/app/pkg/gofr/datasource/oracle/page.jsx Converts vanity route to redirect page.
src/app/pkg/gofr/datasource/opentsdb/page.jsx Converts vanity route to redirect page.
src/app/pkg/gofr/datasource/mongo/page.jsx Converts vanity route to redirect page.
src/app/pkg/gofr/datasource/kv-store/nats/page.jsx Converts vanity route to redirect page.
src/app/pkg/gofr/datasource/kv-store/badger/page.jsx Converts vanity route to redirect page.
src/app/pkg/gofr/datasource/file/sftp/page.jsx Converts vanity route to redirect page.
src/app/pkg/gofr/datasource/file/s3/page.jsx Converts vanity route to redirect page.
src/app/pkg/gofr/datasource/file/gcs/page.jsx Converts vanity route to redirect page.
src/app/pkg/gofr/datasource/file/ftp/page.jsx Converts vanity route to redirect page.
src/app/pkg/gofr/datasource/file/azure/page.jsx Converts vanity route to redirect page.
src/app/pkg/gofr/datasource/elasticsearch/page.jsx Converts vanity route to redirect page.
src/app/pkg/gofr/datasource/dgraph/page.jsx Converts vanity route to redirect page.
src/app/pkg/gofr/datasource/dbresolver/page.jsx Converts vanity route to redirect page.
src/app/pkg/gofr/datasource/couchbase/page.jsx Converts vanity route to redirect page.
src/app/pkg/gofr/datasource/clickhouse/page.jsx Converts vanity route to redirect page.
src/app/pkg/gofr/datasource/cassandra/page.jsx Converts vanity route to redirect page.
src/app/pkg/gofr/datasource/arangodb/page.jsx Converts vanity route to redirect page.
src/app/page.jsx Expands homepage metadata and adds JSON-LD.
src/app/not-found.jsx Rebuilds 404 page with search/helpful links.
src/app/migrate/layout.jsx Applies marketing-page wrapper.
src/app/learn/layout.jsx Applies marketing-page wrapper.
src/app/layout.jsx Moves global metadata into Next metadata API and adds AI discovery links.
src/app/faq/layout.jsx Applies marketing-page wrapper.
src/app/examples/page.jsx Adds examples/recipes landing page.
src/app/examples/layout.jsx Adds examples route metadata.
src/app/examples/examples.json Adds example catalog data.
src/app/events/layout.jsx Adds events route metadata.
src/app/events/events.json Refreshes event content/image sources.
src/app/docs/layout.jsx Removes unnecessary client directive.
src/app/comparison/layout.jsx Applies marketing-page wrapper.
src/app/cli/gofr/page.jsx Replaces placeholder CLI page with actual landing content.
src/app/changelog/layout.jsx Adds changelog route metadata.
public/robots.txt Adds crawler/AI bot policy and sitemap reference.
public/quick-start-trace.png Adds public asset for docs/site content.
public/quick-start-logs.png Adds public asset for docs/site content.
public/llms.txt Adds curated LLM link index.
public/llms-full.txt Commits generated full-content LLM dump.
public/jaeger-traces.png Adds public asset for docs/site content.
public/humans.txt Adds humans.txt metadata file.
public/AGENTS.md Adds AI assistant guidance document.
public/.well-known/security.txt Adds RFC 9116 security contact file.
package.json Adds prebuild and refresh-data scripts.
next.config.mjs Enables export-safe images and richer Markdoc metadata generation.
Dockerfile Copies public assets into image build context.
.github/workflows/package.yml Expands CI/publishing workflow for stage/latest images and data refresh.

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

Comment thread public/llms.txt
Comment on lines +78 to +90
- [Migrating from Gin](https://gofr.dev/migrate/from-gin)
- [Migrating from Fiber](https://gofr.dev/migrate/from-fiber)
- [Migrating from Echo](https://gofr.dev/migrate/from-echo)
- [Migrating from chi](https://gofr.dev/migrate/from-chi)
- [Migrating from Express (Node.js)](https://gofr.dev/migrate/from-express)
- [Migrating from NestJS (TypeScript)](https://gofr.dev/migrate/from-nestjs)
- [Migrating from Flask (Python)](https://gofr.dev/migrate/from-flask)
- [Migrating from FastAPI (Python)](https://gofr.dev/migrate/from-fastapi)
- [Migrating from Django REST (Python)](https://gofr.dev/migrate/from-django-rest)
- [Migrating from Spring Boot (Java)](https://gofr.dev/migrate/from-spring-boot)
- [Migrating from ASP.NET Core (C#)](https://gofr.dev/migrate/from-aspnet-core)
- [Migrating from Laravel (PHP)](https://gofr.dev/migrate/from-laravel)
- [Migrating from Rails (Ruby)](https://gofr.dev/migrate/from-rails)
Comment thread public/AGENTS.md
- From Chi: see <https://gofr.dev/comparison/gofr-vs-chi>
- From Express (Node.js): <https://gofr.dev/migrate/from-express>
- From Flask (Python): <https://gofr.dev/migrate/from-flask>
- From Spring Boot (Java): <https://gofr.dev/migrate/from-spring-boot>
Comment on lines +27 to +37
const SECTIONS = [
{ dir: 'src/app/docs/quick-start', label: 'Quick Start' },
{ dir: 'src/app/docs/advanced-guide', label: 'Advanced Guide' },
{ dir: 'src/app/docs/datasources', label: 'Datasources' },
{ dir: 'src/app/docs/references', label: 'References' },
{ dir: 'src/app/why-gofr', label: 'Why GoFr' },
{ dir: 'src/app/comparison', label: 'Comparison' },
{ dir: 'src/app/migrate', label: 'Migration guides' },
{ dir: 'src/app/learn', label: 'Learn' },
{ dir: 'src/app/faq', label: 'FAQ' },
]
Comment thread src/components/Layout.jsx
Comment on lines +133 to +144
// Live refresh on every page load. The build-time snapshot in
// src/data/github-stars.json gives an instantly-correct first paint;
// this fetch then replaces it with the truly current number so the
// header stays real-time. Failures are silent — we keep the
// pre-paint number.
fetch('https://api.github.com/repos/gofr-dev/gofr')
.then((r) => (r.ok ? r.json() : null))
.then((data) => {
const live = data?.stargazers_count ?? data?.watchers
if (typeof live === 'number') setGithubStars(live)
})
.catch(() => {})
Comment on lines +31 to +34
<CountUp
value={21500}
durationMs={1500}
format={(n) => `${n.toLocaleString()}+`}
Comment on lines +9 to +17
useEffect(() => {
router.replace('/changelog')
}, [router])

return (
<div className="flex min-h-[70vh] items-center justify-center">
<p className="text-slate-500">
Redirecting to changelog...
</p>
@Umang01-hash
Umang01-hash merged commit c7661de into main May 4, 2026
8 checks passed
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.

3 participants