feat(blog): add E-E-A-T author profiles with bios and social links - #8037
Conversation
Add author biographies and social profile links (X, LinkedIn, GitHub, Mastodon) to the blog to strengthen E-E-A-T signals. - author-bios.ts: 19 author bios + socials, keyed by slug with name aliases so frontmatter bylines (e.g. "Will Madden", "Søren Bramer Schmidt", "Josh McLeod") resolve to their canonical bio. - AuthorBio.tsx: "About the author(s)" section for posts + a shared AuthorSocialLinks piece rendering FontAwesome brand icon links. - Author page: bio + social icons in the header, plus ProfilePage/Person JSON-LD (sameAs, description, image). Meta description uses the bio. - Post page: "About the author" section, and BlogPosting author schema enriched with url, sameAs, and description. Authors without a bio render gracefully with no profile block. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
WalkthroughThis PR adds author bio data and lookup helpers, renders author bio content in blog and author pages, and upgrades both pages’ JSON-LD and metadata to include richer author details. ChangesAuthor bios feature
Estimated code review effort: 3 (Moderate) | ~25 minutes 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
Comment |
|
The latest updates on your projects. Learn more about Argos notifications ↗︎
|
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (3)
apps/blog/src/app/(blog)/[slug]/page.tsx (1)
86-97: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winReuse
getAuthorSameAsinstead of re-derivingsameAsinline.
author-bios.tsalready exportsgetAuthorSameAs(name)for exactly this purpose, but Line 93 reimplementsbio.socials.map((s) => s.url). The same pattern is duplicated again inauthor/[slug]/page.tsx'sbuildAuthorJsonLd. Worth consolidating into a single shared "Person schema from author name/slug" helper (e.g. inauthor-bios.ts) sourl/description/sameAsderivation only needs to change in one place across both pages.♻️ Proposed simplification
function buildAuthorSchema(name: string): PersonSchema { const author: PersonSchema = { "`@type`": "Person", name }; const slug = toAuthorSlug(name); const bio = getAuthorBioByName(name); if (slug) author.url = toAbsoluteUrl(withBlogBasePath(`/author/${slug}`)); if (bio) { author.description = bio.bio; - if (bio.socials.length > 0) author.sameAs = bio.socials.map((s) => s.url); + const sameAs = getAuthorSameAs(name); + if (sameAs.length > 0) author.sameAs = sameAs; } return author; }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/blog/src/app/`(blog)/[slug]/page.tsx around lines 86 - 97, The author Person schema logic is re-deriving sameAs inline instead of using the shared helper. Update buildAuthorSchema to call getAuthorSameAs(name) from author-bios.ts, and consider extracting the repeated url/description/sameAs assembly into a shared Person schema helper used by both buildAuthorSchema and buildAuthorJsonLd so the author metadata stays centralized.apps/blog/src/lib/author-bios.ts (1)
226-232: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winHeads up: this helper isn't used anywhere in this cohort.
getAuthorSameAswas clearly built for populatingsameAsin structured data, but both[slug]/page.tsxandauthor/[slug]/page.tsxreimplementbio.socials.map((s) => s.url)inline instead of calling it. See the corresponding comments in those files.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/blog/src/lib/author-bios.ts` around lines 226 - 232, The sameAs URL mapping is duplicated instead of using the shared helper. Update the structured-data code in the relevant page components to call getAuthorSameAs(name) from author-bios.ts rather than reimplementing bio.socials.map((s) => s.url) inline, and remove any now-redundant local mapping logic so the helper is actually used consistently.apps/blog/src/app/(blog)/author/[slug]/page.tsx (1)
61-85: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winSame duplicate
sameAsderivation as the blog post page.Line 76 reimplements
bio?.socials.map((s) => s.url) ?? []instead of callinggetAuthorSameAs(profile.name)fromauthor-bios.ts. This mirrors the identical inline logic in[slug]/page.tsx'sbuildAuthorSchema. Consider extracting a shared "build Person schema" helper (used by both pages) so theurl/description/sameAs/@idshape stays consistent — right now this page'sPersonincludes@idwhile the blog post page's doesn't.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/blog/src/app/`(blog)/author/[slug]/page.tsx around lines 61 - 85, The author JSON-LD builder is duplicating `sameAs` logic instead of using the shared author-bios helper, which can drift from the blog post page schema. Update `buildAuthorJsonLd` to derive `sameAs` via `getAuthorSameAs(profile.name)` (or extract a shared person-schema helper used by both `buildAuthorJsonLd` and the blog post page’s `buildAuthorSchema`) so `url`, `description`, `sameAs`, and `@id` are built consistently from one source.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@apps/blog/src/components/AuthorBio.tsx`:
- Around line 57-68: AuthorBio currently assumes authors is always an array, so
a null or non-array value will make the filter/map chain throw and break post
rendering. Update AuthorBio to defensively normalize the incoming authors prop
before using it, similar to the Array.isArray check used in [slug]/page.tsx, and
only run the existing Set-based dedupe and slug/bio mapping on a verified array.
Keep the fix centered in AuthorBio and its authors handling so the rest of the
profile-building logic remains unchanged.
---
Nitpick comments:
In `@apps/blog/src/app/`(blog)/[slug]/page.tsx:
- Around line 86-97: The author Person schema logic is re-deriving sameAs inline
instead of using the shared helper. Update buildAuthorSchema to call
getAuthorSameAs(name) from author-bios.ts, and consider extracting the repeated
url/description/sameAs assembly into a shared Person schema helper used by both
buildAuthorSchema and buildAuthorJsonLd so the author metadata stays
centralized.
In `@apps/blog/src/app/`(blog)/author/[slug]/page.tsx:
- Around line 61-85: The author JSON-LD builder is duplicating `sameAs` logic
instead of using the shared author-bios helper, which can drift from the blog
post page schema. Update `buildAuthorJsonLd` to derive `sameAs` via
`getAuthorSameAs(profile.name)` (or extract a shared person-schema helper used
by both `buildAuthorJsonLd` and the blog post page’s `buildAuthorSchema`) so
`url`, `description`, `sameAs`, and `@id` are built consistently from one
source.
In `@apps/blog/src/lib/author-bios.ts`:
- Around line 226-232: The sameAs URL mapping is duplicated instead of using the
shared helper. Update the structured-data code in the relevant page components
to call getAuthorSameAs(name) from author-bios.ts rather than reimplementing
bio.socials.map((s) => s.url) inline, and remove any now-redundant local mapping
logic so the helper is actually used consistently.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: e301f649-0d80-457b-be4e-995a18973b24
📒 Files selected for processing (4)
apps/blog/src/app/(blog)/[slug]/page.tsxapps/blog/src/app/(blog)/author/[slug]/page.tsxapps/blog/src/components/AuthorBio.tsxapps/blog/src/lib/author-bios.ts
- Surface the "About the author" card near the top of each post (right after the byline, before the body) so readers and LLM/agent crawlers encounter author credentials early; restyle it as a self-contained bordered card. - Render social links with the eclipse Action icon-button treatment used by the footer and share row, so the icons read as a consistent, tightly spaced set instead of drifting apart. - Use fa-square-linkedin (the variant shipped in the FA kit) so the LinkedIn icon renders instead of showing a blank box. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Match the defensive Array.isArray handling used in [slug]/page.tsx so a null or non-array page.data.authors cannot crash post rendering. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
What
Adds E-E-A-T author profiles to the blog — author biographies plus social profile links (X, LinkedIn, GitHub, Mastodon) rendered as icons with the link embedded. Bios are sourced from the team's Notion "E-E-A-T: Author Biographies" table (19 authors).
Why
Experience, Expertise, Authoritativeness, and Trustworthiness are signals Google (and increasingly AI) use to decide whether to trust and rank content. Surfacing who wrote a post, their background, and verifiable profiles improves those signals.
Changes
lib/author-bios.ts— 19 author bios + socials, keyed by slug. Each entry carries anames[]alias list so frontmatter bylines that differ from the canonical bio name resolve correctly (e.g.Will Madden→ William Madden,Søren Bramer Schmidt→ Søren Schmidt,Josh McLeod→ Joshua McLeod).components/AuthorBio.tsx— an "About the author(s)" section for posts, plus a sharedAuthorSocialLinkspiece rendering FontAwesome brand icons (fa-brands fa-{x-twitter,linkedin,github,mastodon}), matching the existing icon system./author/[slug]) — bio + social icons in the header;ProfilePage/PersonJSON-LD (sameAs,description,image); meta description now uses the bio./[slug]) — "About the author" section, and theBlogPostingauthor schema enriched withurl,sameAs, anddescription.Authors without a bio render gracefully with no profile block.
Verification
Ran the dev server and confirmed:
ProfilePageJSON-LD.soren-bramer-schmidtalias resolves to the correct bio withsameAspopulated.tsc --noEmitpasses with 0 errors; lint clean.Notes
author-bios.tsis the single place to update.🤖 Generated with Claude Code
Summary by CodeRabbit
New Features
Bug Fixes