Repository navigation
Home: Person structured data for personal sites - #647
Conversation
With the new site_is_person setting on, the home page carries a schema.org Person: the site title as the name, the site URL, description and image, and sameAs listing the profiles the Social Icons plugin holds. That is how a search engine ties those profiles to the site. Off by default, so a project or organisation site is not described as a person. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
There was a problem hiding this comment.
Copilot review overview
🟢 Approval recommended
The change is small, off by default, consistent with existing JSON-LD/settings patterns, well covered by tests, and the external Social Icons links[].URL shape it depends on was verified to match.
Review effort: Balanced
Findings: None
What changed in this PR
This PR adds optional schema.org Person structured data to the home page of personal goblog sites. Previously the home page only declared a WebSite, giving search engines no signal that the site belongs to a person or that the linked social profiles are the same person. The feature is gated behind a new site_is_person checkbox setting (off by default) so project/organisation sites are unaffected. When enabled, the home <head> emits a Person block (name, url, description, image) with sameAs populated from the Social Icons plugin's links, correctly handling the plugin's absence (empty sameAs).
Changes:
- Add
site_is_personcheckbox setting (seeded via migration withFirstOrCreate, so existing sites are backfilled; surfaced in the Site settings tab with help text). - Emit a home-page-only JSON-LD
Personblock intemplates/shared/_head.html, gated onis_homeandsite_is_person == "true", readingsameAsfrom.plugins.socialicons.links[].URL. - Extend
TestHeadMetadatawith asocialiconsstand-in plugin to assert JSON validity, expected fields,sameAsentries, default-off behavior, and that only the home page carries it.
| File | Description |
|---|---|
tools/migrate.go |
Seeds the new site_is_person checkbox setting (default "false"), backfilled to existing sites. |
templates/shared/_head.html |
Adds the home-page Person JSON-LD block, gated behind the setting, with sameAs from the Social Icons plugin. |
admin/settings.go |
Adds label/help for site_is_person in the Site settings tab. |
blog/blog_test.go |
Adds a socialicons stand-in plugin and assertions covering the new structured data. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
Why
A personal site's home page only declared a
WebSite. Nothing told a search engine that the site belongs to a person, or that the LinkedIn/GitHub/etc. profiles linked in the footer are the same person, which matters when someone else with the same name outranks you.Changes
site_is_personsetting (Site tab, checkbox, default off). Seeded on existing sites by the migration.Person:name(site title),url,description,image(site image), andsameAslisting the Social Icons plugin's links (.plugins.socialicons.links). Without the plugin,sameAsis empty.Testing
TestHeadMetadatacovers: absent by default; with the setting on, the block parses as JSON with the expected name, URL, image and twosameAsentries from a stand-insocialiconsplugin; not repeated on other pages.go test ./...passes. Not checked against a live site with the real wasm plugin, or in a structured-data validator.🤖 Generated with Claude Code