Skip to content

chore(web): programmatic OG meta validation + Lighthouse CI for guides + landing#2439

Merged
andrew-bierman merged 4 commits into
developmentfrom
chore/og-meta-validation
May 17, 2026
Merged

chore(web): programmatic OG meta validation + Lighthouse CI for guides + landing#2439
andrew-bierman merged 4 commits into
developmentfrom
chore/og-meta-validation

Conversation

@andrew-bierman
Copy link
Copy Markdown
Collaborator

@andrew-bierman andrew-bierman commented May 17, 2026

Summary

Follow-up to #2437 (OG hardening + Builds workflow) and #2436
(build-order fix). Establishes a per-app standard: every PackRat web
app gets programmatic OG meta validation + Lighthouse CI surfaced in PR
checks before deploy.

Covers both apps/guides and apps/landing and wires Lighthouse CI
into the Builds workflow for both.

Guides — OG meta validation

  • Static check (test:og-meta) — runs bun run build (if out/ is
    missing) and walks every out/guide/<slug>.html plus out/index.html
    with cheerio. Asserts the required tag set
    (og:title, og:description, og:image, og:image:width,
    og:image:height, og:type, og:url, og:site_name,
    twitter:card, twitter:title, twitter:description,
    twitter:image) on a 3-post random sample, and that every post
    has an absolute https:// og:image URL pointing at
    /og/<slug>.png. The root page gets the same shape with the
    site-wide image (/og-image.png or the Next.js auto-generated
    /opengraph-image route — whichever wins). Sampling keeps the suite
    fast across 500+ posts.
  • Live check — opt-in via OG_LIVE_CHECK_URL env var. Uses
    open-graph-scraper (the same parser most social platforms
    use under the hood) to fetch the live root URL + a sample guide page
    and assert the same shape. Skipped by default; useful after a deploy
    to catch CF transforms or cache layers that a built-HTML check can
    miss.

Landing — OG meta validation (new in this PR's second commit)

  • apps/landing/__tests__/og-meta.test.ts mirrors the guides pattern:
    walks every top-level out/*.html plus nested out/<slug>/index.html
    (skipping 404.html / 500.html), asserts the same 12-tag set on
    every page, requires an absolute https og:image pointing at the
    site-wide image (/og-image.png or /opengraph-image), and ships
    the same OG_LIVE_CHECK_URL-gated open-graph-scraper block (now
    sampling root + /pricing).
  • cheerio + open-graph-scraper added to apps/landing devDeps
    (test-only — explicitly not runtime).
  • test:og-meta script added.

Lighthouse CI in the Builds workflow

The repo already has .lighthouserc.{js,mobile.js} (perf ≥ 0.8;
a11y / best-practices / SEO ≥ 0.9; LCP < 2500 ms / 4000 ms;
CLS < 0.1) and a standalone lighthouse.yml that rebuilds. This PR
wires LHCI into the Builds workflow so scores ship next to the build
artifact in the same PR check, reusing the already-built out/:

  • New lighthouse:ci script in both apps/guides and apps/landing
    (lhci autorun — no rebuild, since the build step already ran).
  • New Lighthouse CI step in both Builds jobs, after the OG meta
    validation. Marked continue-on-error: true so perf regressions
    surface as a yellow check rather than blocking the PR.
  • New Summarize Lighthouse scores step emits the LHCI output tail
    to $GITHUB_STEP_SUMMARY so reviewers see scores directly in the
    PR Checks UI without clicking into job logs.
  • Budgets unchanged — this PR is enforcement, not threshold tuning.

CI integration

  • Builds (guides): build → validate OG meta → Lighthouse CI → summary
  • Builds (landing): build → validate OG meta → Lighthouse CI → summary

A meta-tag regression fails the PR check. A Lighthouse score regression
yellow-checks it and surfaces the numbers.

Docs

  • New apps/landing/README.md — build pipeline, OG validation layers,
    Lighthouse CI integration, manual debugger URLs.
  • apps/guides/README.md updated with a cross-reference to the shared
    pattern and a new Lighthouse CI section.

Why

After #2437 we had OG images generated and the Builds workflow surfacing
post / image counts in the Step Summary, but nothing was asserting that
the meta tags themselves actually make it into the built HTML — and
Lighthouse only ran in a separate workflow that wasn't part of the
main build's check signal. A silent regression — e.g. a Next.js upgrade
dropping metadataBase resolution, an image moving to a relative path,
or a perf regression from a new font — would only be caught when a
user noticed a broken Slack preview or a slow page. This closes both
gaps with fast, deterministic checks on every PR, for both web apps.

Scope notes

  • apps/trails: declares minimal OG metadata (no images, no
    twitter:card, no metadataBase). Adding the 12-tag validation
    would require also fleshing out the metadata — out of scope for an
    enforcement PR. To be picked up separately when the trails app
    hardens its OG story.
  • apps/admin / apps/web: internal tools, not public-facing
    marketing. Excluded by the user's mandate scope.

Test plan

  • bun install succeeds with the new landing devDeps
  • bun check-types — 0 errors
  • bun check (biome) — clean
  • bun run --cwd apps/guides build — produces out/ with all 504 guide HTML files
  • bun run --cwd apps/guides test:og-meta — 5 static tests pass, 2 live tests skipped
  • bun run --cwd apps/landing build — produces out/ with 9 top-level routes
  • bun run --cwd apps/landing test:og-meta — 4 static tests pass, 2 live tests skipped
  • bun run --cwd apps/landing lighthouse:ci — starts LHCI cleanly (full local run not required; CI will exercise it)
  • On merge, both Builds (guides) and Builds (landing) runs include the new OG + Lighthouse steps with the LHCI Step Summary visible in the PR Checks UI
  • (optional, manual) OG_LIVE_CHECK_URL=https://guides.packratai.com bun run --cwd apps/guides test:og-meta passes after deploy
  • (optional, manual) OG_LIVE_CHECK_URL=https://packratai.com bun run --cwd apps/landing test:og-meta passes after deploy

🤖 Generated with Claude Code

Adds a follow-up to #2437 that asserts the OG / Twitter meta tags
expected by social previewers actually land in the built HTML, and
optionally re-checks them over the wire against a deployed URL.

- New `apps/guides/__tests__/og-meta.test.ts` runs `bun run build`
  (if `out/` is missing) and walks every `out/guide/<slug>.html` plus
  `out/index.html`, parsing with cheerio. It asserts the full meta set
  (og:title, og:description, og:image, og:image:width, og:image:height,
  og:type, og:url, og:site_name, twitter:card, twitter:title,
  twitter:description, twitter:image) on a 3-post random sample, that
  every post has an absolute `https://` og:image pointing at
  `/og/<slug>.png`, and that the root page uses the site-wide image
  (not a per-post one). Sampling keeps the suite fast across 500+ posts.
- Optional live pass via `open-graph-scraper` is gated on
  `OG_LIVE_CHECK_URL`. Same shape, fetched over the wire — useful after
  a deploy to catch CF transforms / cache layers that a built-HTML check
  can miss.
- New `test:og-meta` script and wired into the `Builds` workflow after
  the guides build, before the artifact upload — a meta-tag regression
  fails the workflow check on the PR.
- `cheerio` and `open-graph-scraper` added as devDependencies of
  `apps/guides` (test-only, not runtime deps).
- README documents both passes and lists the manual debugger URLs
  (opengraph.xyz, microlink, FB Sharing Debugger, LinkedIn Post
  Inspector) for post-deploy verification.

Antecedents: #2436 (build-order fix) and #2437 (OG hardening + Builds
workflow).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings May 17, 2026 07:00
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 17, 2026

Warning

Rate limit exceeded

@andrew-bierman has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 1 minute and 16 seconds before requesting another review.

You’ve run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: c85a9259-a4ed-4dd0-8a86-1366f6af8a3a

📥 Commits

Reviewing files that changed from the base of the PR and between 64637fc and c10521f.

⛔ Files ignored due to path filters (1)
  • bun.lock is excluded by !**/*.lock, !bun.lock
📒 Files selected for processing (13)
  • .github/workflows/builds.yml
  • .gitignore
  • apps/guides/.lighthouserc.js
  • apps/guides/.lighthouserc.mobile.js
  • apps/guides/README.md
  • apps/guides/__tests__/og-meta.test.ts
  • apps/guides/package.json
  • apps/landing/.lighthouserc.js
  • apps/landing/.lighthouserc.mobile.js
  • apps/landing/README.md
  • apps/landing/__tests__/og-meta.test.ts
  • apps/landing/package.json
  • packages/env/scripts/no-raw-process-env.ts
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch chore/og-meta-validation

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 17, 2026

Coverage Report for Expo Unit Tests Coverage (./apps/expo)

Status Category Percentage Covered / Total
🔵 Lines 82.76% 485 / 586
🔵 Statements 82.76% (🎯 75%) 485 / 586
🔵 Functions 92.59% 50 / 54
🔵 Branches 90.9% 170 / 187
File CoverageNo changed files found.
Generated in workflow #1331 for commit c10521f by the Vitest Coverage Report Action

@github-actions github-actions Bot added documentation Improvements or additions to documentation dependencies Pull requests that update a dependency file ci/cd web labels May 17, 2026
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 17, 2026

Coverage Report for API Unit Tests Coverage (./packages/api)

Status Category Percentage Covered / Total
🔵 Lines 66.4% 504 / 759
🔵 Statements 66.4% (🎯 65%) 504 / 759
🔵 Functions 90.47% 38 / 42
🔵 Branches 88.32% 227 / 257
File CoverageNo changed files found.
Generated in workflow #1331 for commit c10521f by the Vitest Coverage Report Action

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds automated Open Graph/Twitter metadata validation for the guides static export, including CI integration and documentation for static and optional live checks.

Changes:

  • Adds test:og-meta Vitest coverage using Cheerio and optional open-graph-scraper live validation.
  • Runs OG meta validation in the guides build workflow.
  • Documents the validation workflow and adds related dev dependencies.

Reviewed changes

Copilot reviewed 4 out of 5 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
apps/guides/__tests__/og-meta.test.ts Adds static and optional live OG/Twitter metadata validation tests.
apps/guides/package.json Adds the test:og-meta script and dev dependencies.
.github/workflows/builds.yml Runs OG meta validation after the guides build.
apps/guides/README.md Documents OG metadata validation and manual validators.
bun.lock Locks newly added metadata validation dependencies.

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

Comment on lines +216 to +218
describe.skipIf(!process.env.OG_LIVE_CHECK_URL)('live OG check', () => {
const liveUrl = (process.env.OG_LIVE_CHECK_URL ?? '').replace(/\/$/, '');

Comment on lines +180 to +181
expect(ogImage, `${slug}: og:image should point at /og/${slug}.png`).toMatch(
new RegExp(`/og/${escapeRegex(slug)}\\.png$`),
…flow

Extends the guides OG meta validation pattern to the landing marketing
site, and wires Lighthouse CI into the Builds workflow for both apps.

Per the team mandate: every web app gets programmatic OG and Lighthouse
evaluation, surfaced in PR checks before deploy.

Landing-side OG meta:
- apps/landing/__tests__/og-meta.test.ts walks built HTML in out/
  (top-level *.html + nested <slug>/index.html, skipping 404/500),
  asserts the same 12-tag OG/Twitter set as guides, requires absolute
  https og:image pointing at the site-wide image, and includes the
  same OG_LIVE_CHECK_URL-gated open-graph-scraper block.
- Adds cheerio + open-graph-scraper as devDependencies (matching guides).
- Adds test:og-meta script.

Lighthouse CI in Builds workflow:
- Adds lighthouse:ci script (lhci autorun, no rebuild) to both apps.
- Builds workflow gains a Lighthouse CI step after OG validation in
  each job, with continue-on-error so perf regressions yellow-check
  rather than block, and a Step Summary block so reviewers see the
  output without clicking into job logs.
- Uses existing .lighthouserc.{js,mobile.js} budgets unchanged.

Docs:
- New apps/landing/README.md documents the build pipeline + OG +
  Lighthouse validation layers + manual debugger links.
- Updates apps/guides/README.md to cross-reference the shared pattern
  and document the new Lighthouse CI integration.

.gitignore: adds .lighthouseci/ output dir.

packages/env/scripts/no-raw-process-env.ts auto-updated by postinstall
env script to allow OG_LIVE_CHECK_URL reads in the two new test files.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@cloudflare-workers-and-pages
Copy link
Copy Markdown
Contributor

cloudflare-workers-and-pages Bot commented May 17, 2026

Deploying packrat-guides with  Cloudflare Pages  Cloudflare Pages

Latest commit: c10521f
Status:⚡️  Build in progress...

View logs

@andrew-bierman andrew-bierman changed the title chore(guides): programmatic OG meta validation chore(web): programmatic OG meta validation + Lighthouse CI for guides + landing May 17, 2026
@cloudflare-workers-and-pages
Copy link
Copy Markdown
Contributor

cloudflare-workers-and-pages Bot commented May 17, 2026

Deploying packrat-landing with  Cloudflare Pages  Cloudflare Pages

Latest commit: c10521f
Status: ✅  Deploy successful!
Preview URL: https://1e480d45.packrat-landing.pages.dev
Branch Preview URL: https://chore-og-meta-validation.packrat-landing.pages.dev

View logs

andrew-bierman and others added 2 commits May 17, 2026 01:20
…ove continue-on-error

Three real issues from the latest #2439 CI run:
- 404.html and 500.html were dragging Lighthouse runs down — they inherently lack <title>/<html lang>/meta description by design. Used assertMatrix with a regex pattern to exclude them; full assertion set still runs against every other HTML.
- continue-on-error: true on the Lighthouse step meant failures didn't fail CI. Removed both (guides + landing). Lighthouse is now a real gate.
- LHCI reports were going to temporary-public-storage URLs only. Added actions/upload-artifact steps for apps/<name>/.lighthouseci with 14-day retention so reviewers can click through after the PR run.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@cloudflare-workers-and-pages
Copy link
Copy Markdown
Contributor

cloudflare-workers-and-pages Bot commented May 17, 2026

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Preview URL Updated (UTC)
✅ Deployment successful!
View logs
packrat-admin c10521f Commit Preview URL

Branch Preview URL
May 17 2026, 07:24 AM

@andrew-bierman andrew-bierman merged commit dd81e3f into development May 17, 2026
15 of 16 checks passed
@andrew-bierman andrew-bierman deleted the chore/og-meta-validation branch May 17, 2026 07:26
andrew-bierman added a commit that referenced this pull request May 20, 2026
Substantial rebase covering 225 dev commits — #2414 type unification,
#2422 single-param refactor, #2433 MCP+CLI Eden Treaty rewrite, #2439 OG
meta validation, #2441/#2442 OG URL fix, plus many smaller.

Conflicts resolved:
- apps/expo/features/packs/utils/uploadImage.ts: kept HEAD's userId
  cache, used dev's object-arg getPresignedUrl call (matches function
  signature).
- apps/expo/features/trips/hooks/useDeleteTrip.ts: kept HEAD's async +
  optimistic-delete comment, used dev's object-arg obs() call (matches
  current obs signature in apps/expo/lib/store.ts).

Post-merge cleanup of dev-introduced single-param violations:
- apps/expo/lib/utils/__tests__/getRelativeTime.test.ts: rewrote 3 test
  call sites to object args matching the refactored getRelativeTime.
- packages/api/src/utils/__tests__/embeddingHelper.test.ts: rewrote 7
  test call sites to object args matching the refactored
  getEmbeddingText; updated Parameters<> type indexes.
- packages/overpass/src/client.test.ts: converted makeResponse to
  single object param and updated all 11 call sites.
- scripts/lint/no-owned-max-params.ts: added
  apps/trails/scripts/generate-og-images.ts to EXCLUDED_FILES (same
  globalThis.fetch shim pattern as the existing landing/guides
  entries).

Verification: bun install ok; bun check-types 0 errors; biome check
0 errors (2 unrelated warnings); no-owned-max-params 0 violations.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ci/cd dependencies Pull requests that update a dependency file documentation Improvements or additions to documentation web

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants