feat(docs): redesign homepage — interactive sections, rich footer, OG, sitemap#89
feat(docs): redesign homepage — interactive sections, rich footer, OG, sitemap#89
Conversation
- UseCaseTabs: pill-based tab selector with macOS terminal block, copy-to-clipboard, headline + description per use case - ComparisonTable: styled card with intro text and icon-based ✓/✗ rows - ProductionCta: CTA banner with animated SVG building icon cycling brand colours - Register all three components globally in theme/index.ts - Replace prose sections and markdown table in index.md with component tags
- 3-step guided install: curl command, token export, first search - macOS-style terminal blocks with copy-to-clipboard on steps 1 and 3 - Connector line between steps with brand gradient - Token hint with direct link to GitHub token generation page - Full installation guide link at the bottom
- 3 card-based steps: Search across the org, Triage interactively, Export & replay - Each card has a branded icon box, step badge, title and description - Arrow connectors between steps - Hover elevation matching feature card style - Inserted between InstallSection and UseCaseTabs in index.md
|
Coverage after merging feat/homepage-sections into main will be
Coverage Report
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Pull request overview
This PR modernizes the VitePress docs homepage into a component-driven landing page, adds Open Graph/Twitter metadata with an auto-generated social preview image, and enables sitemap generation for improved sharing/SEO.
Changes:
- Replaces the static
docs/index.mdhomepage content with interactive Vue theme sections (install flow, use cases, comparison table, CTA, testimonials) plus a homepage-only rich footer. - Adds VitePress config enhancements: OG/Twitter
<head>tags,vite.definefor latest version/blog slug, a build-time OG PNG generator plugin, and sitemap config. - Introduces a standalone
scripts/generate-og.tshelper + wiring inpackage.json, lockfile, and Knip ignores.
Reviewed changes
Copilot reviewed 17 out of 19 changed files in this pull request and generated 8 comments.
Show a summary per file
| File | Description |
|---|---|
| scripts/generate-og.ts | Standalone script to render social-preview.svg to PNG. |
| package.json | Adds docs:build:og script and @resvg/resvg-js dev dependency. |
| knip.json | Ignores scripts/** and @resvg/resvg-js for docs-only tooling. |
| docs/index.md | Swaps static markdown sections for homepage Vue components. |
| docs/.vitepress/config.mts | Adds OG/Twitter meta, build-time OG PNG generation, vite.define version vars, and sitemap config. |
| docs/.vitepress/theme/index.ts | Registers new homepage components and conditionally swaps rich vs minimal footer. |
| docs/.vitepress/theme/custom.css | Hides default VitePress footer to rely on custom footers. |
| docs/.vitepress/theme/*.vue | Adds homepage sections (install/how-it-works/use-cases/comparison/cta/testimonials) + rich/minimal footers + version badge. |
| bun.lock | Locks @resvg/resvg-js and its platform packages. |
| .github/instructions/release.instructions.md | Notes that the hero version badge auto-updates from package.json. |
| <li><a href="/github-code-search/getting-started/">Getting started</a></li> | ||
| <li><a href="/github-code-search/getting-started/installation">Installation</a></li> | ||
| <li><a href="/github-code-search/usage/">Usage</a></li> | ||
| <li><a href="/github-code-search/reference/cli-options">CLI reference</a></li> | ||
| <li><a href="/github-code-search/reference/keyboard-shortcuts">Keyboard shortcuts</a></li> |
There was a problem hiding this comment.
These links are hard-coded to /github-code-search/..., which will break when the docs are built with a different base (the config explicitly supports version snapshots via VITEPRESS_BASE). Prefer withBase('/getting-started/...') or VitePress useRouter() navigation so the footer works for versioned docs too.
| </div> | ||
|
|
||
| <div class="ts-grid"> | ||
| <blockquote class="ts-card" v-for="t in testimonials" :key="t.handle"> |
There was a problem hiding this comment.
:key="t.handle" uses a property that doesn't exist on the testimonials objects, so every item gets an undefined key (Vue will warn and may reuse DOM nodes incorrectly). Add a stable unique field (e.g. handle), or key by a guaranteed-unique value such as name (or name + role), or as a last resort use the v-for index.
| <blockquote class="ts-card" v-for="t in testimonials" :key="t.handle"> | |
| <blockquote class="ts-card" v-for="t in testimonials" :key="t.name + ' - ' + t.role"> |
| <div class="uc-pills" role="tablist"> | ||
| <button | ||
| v-for="(uc, i) in USE_CASES" | ||
| :key="uc.id" | ||
| class="uc-pill" | ||
| :class="{ active: active === i }" | ||
| role="tab" | ||
| :aria-selected="active === i" | ||
| @click="active = i" |
There was a problem hiding this comment.
The markup declares role="tablist"/role="tab"/role="tabpanel", but it doesn't implement the required ARIA tab semantics (ids, aria-controls/aria-labelledby, roving tabindex, and keyboard navigation via arrow keys). Either implement full ARIA tabs behavior or remove the tab roles and treat these as a regular button group to avoid misrepresenting accessibility semantics.
| <pre | ||
| class="is-code" | ||
| ><code><span class="is-prompt">$</span> github-code-search query <span class="is-str">"TODO"</span> --org my-org</code></pre> |
There was a problem hiding this comment.
The displayed Step 3 command is duplicated in the template instead of reusing SEARCH_CMD (which is what gets copied). This can drift over time (copy button could copy something different than what the user sees). Consider rendering SEARCH_CMD in the terminal block and/or deriving both display + copy from the same constant.
| <pre | |
| class="is-code" | |
| ><code><span class="is-prompt">$</span> github-code-search query <span class="is-str">"TODO"</span> --org my-org</code></pre> | |
| <pre class="is-code"> | |
| <code><span class="is-prompt">$</span> {{ SEARCH_CMD }}</code> | |
| </pre> |
| <div class="rf-col"> | ||
| <p class="rf-col-title">Project</p> | ||
| <ul class="rf-links"> | ||
| <li><a href="/github-code-search/blog/">Blog</a></li> |
There was a problem hiding this comment.
This internal link is hard-coded to /github-code-search/blog/, which will break for versioned docs builds where base is /github-code-search/vX/. Use withBase('/blog/') (or similar base-aware navigation) for internal links.
| <li><a href="/github-code-search/blog/">Blog</a></li> | |
| <li><a :href="withBase('/blog/')">Blog</a></li> |
| /** | ||
| * Converts docs/public/social-preview.svg → docs/public/social-preview.png (1200 px wide). | ||
| * Run standalone: bun scripts/generate-og.ts | ||
| * Also called automatically by the VitePress vite plugin in config.mts during docs:build. |
There was a problem hiding this comment.
In this file header, the comment says the script is "called automatically by the VitePress vite plugin" during docs:build, but the plugin currently re-implements the logic inline instead of invoking this script. Please update the comment to reflect reality (or refactor the VitePress plugin to call this script) to avoid misleading future maintainers.
| * Also called automatically by the VitePress vite plugin in config.mts during docs:build. | |
| * The VitePress vite plugin in config.mts currently re-implements this logic inline during docs:build | |
| * instead of invoking this script directly. |
|
|
||
| const CURL_CMD = | ||
| "curl -fsSL https://raw.githubusercontent.com/fulll/github-code-search/main/install.sh | bash"; | ||
| const VERIFY_CMD = "github-code-search --version"; |
There was a problem hiding this comment.
VERIFY_CMD is declared but never used. Either remove it, or use it for a dedicated "verify" step/button (and rename copiedVerify/target accordingly) so the state variables match the UI intent.
| const VERIFY_CMD = "github-code-search --version"; |
| <div class="is-footer"> | ||
| <a href="/github-code-search/getting-started/installation" class="is-link-full"> | ||
| Full installation guide → | ||
| </a> |
There was a problem hiding this comment.
This internal link is hard-coded to /github-code-search/..., but the docs base is configurable via VITEPRESS_BASE for versioned snapshots (e.g. /github-code-search/vX/). Use withBase() (or derive from useData().site.value.base) for internal doc links so they work under both the canonical base and versioned bases.
Motivation
La homepage était du prose statique. Ce PR la transforme en une landing page moderne comparable à Bun.sh / Vite, tout en restant sobre et en phase avec la charte fulll.
Ce qui change
Nouveaux composants Vue
VersionBadge.vuevite.define+package.jsonà chaquedocs:build, sans action manuelleInstallSection.vueHowItWorks.vueUseCaseTabs.vueComparisonTable.vueProductionCta.vueTestimonialsSection.vueRichFooter.vueMinimalFooter.vue--vp-c-*natif) — toutes les autres pagesConfig VitePress
<head>, PNG 1200 px généré automatiquement au build depuisdocs/public/social-preview.svgvia un plugin Vite +@resvg/resvg-jssitemap: { hostname }→✓ generating sitemap...au buildvite.define:__LATEST_VERSION__+__LATEST_BLOG_SLUG__injectés depuispackage.jsonScripts & tooling
scripts/generate-og.ts: script standalonebun run docs:build:ogpour régénérer le PNG OG indépendammentknip.json:scripts/**et@resvg/resvg-jsignorés (docs-only)Instructions release
.github/instructions/release.instructions.md— note ajoutée dans le post-release checklist : le badge version se met à jour automatiquement, aucune action manuelle requise.Comment tester
Vérifier :
/getting-started/docs/.vitepress/dist/sitemap.xmlprésentdocs/public/social-preview.pngrégénéré (101 KB)