Uh oh!
There was an error while loading. Please reload this page.
fix: rename Agent Skills route to /skills and update sidebar label - #30
Merged
joaodibba merged 1 commit intoJun 12, 2026
Merged
Conversation
Uh oh!
There was an error while loading. Please reload this page.
joaodibba added a commit
that referenced
this pull request
Jun 12, 2026
… per-page meta titles/descriptions (#31) ## What changed and why SEO/indexability improvements based on Gonçalo's audit, as requested by João. Highest-value static wins with no new npm dependencies, no unrelated churn, and no conflict with #30 (already merged). --- ### Architecture findings (pre-PR) | Concern | Finding | |---|---| | Routing mode | `history: "hash"` — all docs URLs are `#/docs/…` | | Hosting fallback | `public/.htaccess` already rewrites all paths → `index.html` ✓ | | Static file serving | Vite copies `public/` verbatim to `dist/` ✓ | | Existing metadata | `index.html` had generic OG/Twitter tags but **no canonical**, **no JSON-LD**, **no robots.txt**, **no sitemap**, **no per-page titles** | | PR #30 | Merged before this PR — `docs/skills` route is live ✓ | | Hash URL + canonicals | Hash fragments are not real URLs → single canonical at root is correct; per-page canonicals add no benefit without SSR | | Clean URL migration | Deferred — server must be verified to support `try_files` / Apache rewrite for every `/docs/*` path; .htaccess is present but hosting needs confirmation | --- ### Changes | File | What | |---|---| | `public/robots.txt` | Allow all crawlers; `Sitemap:` directive pointing to sitemap | | `public/sitemap.xml` | 29 `<url>` entries for every registered route (home, all docs pages, playground) | | `public/llms.txt` | [llmstxt.org](https://llmstxt.org) convention — machine-readable site manifest for LLM indexers (GPTBot, Claude, Gemini) | | `index.html` | `<link rel="canonical">` → root URL; two JSON-LD blocks (WebSite + SoftwareApplication); improved title/description copy ("zero-HTML" framing) | | `src/utils/seo.ts` | **New** — `updatePageMeta(pathname)` with per-route `<title>` + `<meta name="description">` map (29 routes) | | `src/views/elements/Base.ts` | Call `updatePageMeta(Router.pathname)` in `BaseView` constructor — fires on every docs page navigation | --- ### What was deferred / not included | Item | Reason | |---|---| | **Clean (history-mode) URLs** | Requires confirming hosting supports path rewrites for _all_ `/docs/*` URLs before enabling `history: "browser"` in the router — wrong call without server verification; the `.htaccess` is present but needs testing | | **Per-page canonical URLs** | No benefit over root canonical with hash routing + no SSR | | **Prerendering / static HTML** | Out of scope — would require either SSR or a prerender plugin | --- ### Validation ``` npm install npm run build # ✓ built in 11.11s — zero errors, zero new warnings ``` Build confirms all 3 static files are copied to `dist/` (`robots.txt`, `sitemap.xml`, `llms.txt`), `index.html` contains canonical and JSON-LD, and `seo.ts` is tree-shaken cleanly into the bundle. **Diff:** 6 files — 430 insertions, 9 deletions (index.html copy improvements). ### Reviewer @zico15
joaodibba added a commit
that referenced
this pull request
Jun 12, 2026
…e URLs (#32) ## SEO P0 — Clean URLs via Browser History Routing Follow-up to #29, #30, #31. ### Problem Hash routing (`/#/docs/skills`) is not indexable by search engines — the fragment after `#` is never sent to the server, so Googlebot sees only `https://typecomposer.com/` for every page. Direct deep-links to `/docs/skills` also 404 without a proper SPA fallback. This means the sitemap, per-route canonicals, and per-page meta added in #31 cannot deliver their full SEO value. ### Solution Switch `Router.create` from `history: "hash"` to `history: "browser"` (HTML5 `pushState`). The server-side SPA fallback (`.htaccess`) was **already present in the repo** before this PR and contains the correct `RewriteRule ^.*$ /index.html [L,QSA]` — so direct deep-links will be served correctly on the Apache-hosted production site once this PR is merged and deployed. --- ### Files Changed (7) | File | Change | |------|--------| | `src/router/router.ts` | `history: "hash"` → `history: "browser"` | | `vite.config.js` | `base: "./"` → `base: "/"` — absolute asset paths prevent broken JS/CSS loads when a user navigates directly to a nested route like `/docs/skills` (relative `./assets/` would resolve to `/docs/assets/`) | | `src/utils/seo.ts` | `updatePageMeta()` updates `<title>` and `<meta name="description">` per route. Runtime `setCanonical()` workaround **removed** — the static root canonical in `index.html` covers the home route, and `sitemap.xml` provides authoritative clean-URL canonicals for all 29 pages without requiring JS. | | `public/sitemap.xml` | Strip `#/` from all 29 URLs (`/#/docs/skills` → `/docs/skills`, `/#/playground` → `/playground`) | | `public/llms.txt` | Same URL migration for all 29 doc links; Router key concept updated to reference `history: "browser"` | | `index.html` | JSON-LD `SearchAction.target` updated from `/#/docs/{search_term_string}` → `/docs/{search_term_string}`; canonical comment tidied | | `public/.htaccess` | Comments improved for clarity; **rewrite rule logic unchanged** — it was already correct | --- ### Build Validation (commit 2) ``` npm run build ✓ 2405 modules transformed — no errors, no type errors ``` ``` dist/.htaccess ✓ present (copied from public/) dist/sitemap.xml ✓ 0 hash URLs remaining dist/llms.txt ✓ 0 hash URLs remaining dist/index.html ✓ assets load from /assets/* (absolute paths) dist/index.html ✓ root canonical <https://typecomposer.com/> present src/utils/seo.ts ✓ setCanonical() removed src/utils/seo.ts ✓ CANONICAL_BASE constant removed ``` --- ###⚠️ Hosting Verification Required Before Release The `.htaccess` SPA fallback must be honoured by the production Apache server. Please test after deploy: ```bash # Direct deep-link must return HTTP 200, not 301/302/404 curl -I https://typecomposer.com/docs/skills # Expected: HTTP/2 200 curl -I https://typecomposer.com/docs/getting-started # Expected: HTTP/2 200 curl -I https://typecomposer.com/playground # Expected: HTTP/2 200 # Assets must still load correctly curl -I https://typecomposer.com/typecomposer.svg # Expected: HTTP/2 200 curl -I https://typecomposer.com/sitemap.xml # Expected: HTTP/2 200 ``` If the Apache server requires `AllowOverride All` in its vhost config, that must be enabled separately by the hosting admin. If `.htaccess` is not supported, a `_redirects` (Netlify) or `vercel.json` equivalent would be needed — but the existing `.htaccess` confirms Apache is the target host. --- ### /docs/skills → Agent Skills ✓ Route `docs/skills` maps to `BaseView` and `PAGE_META["docs/skills"]` is unchanged: - Title: **Agent Skills | TypeComposer** - Description: _Use TypeComposer to build AI agent skills…_ --- cc @zico15
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for freeto join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What changed and why
Follow-up requested by João: clean up the Agent Skills docs page so its URL and sidebar label are consistent and clean.
Changes
content/skills-sh.mdx→content/skills.mdx/skillsroute convention (mirrors every other content file:router.mdx→/router,getting-started.mdx→/getting-started)src/assets/data.json"Skills.sh AI Skill"→"Agent Skills"; link"docs/skills-sh"→"docs/skills"src/router/router.ts"skills-sh"→"skills"so the page is reachable at#/docs/skillsThe sidebar entry remains in the Introduction section, after Getting Started, exactly as before.
No SEO, unrelated content, or architecture changes included.
Validation
Build output confirms
content/skills.mdxis picked up correctly byimport.meta.glob("/content/**/*.mdx")insrc/utils/mdx.tsand the new route is reachable.Reviewer
@zico15