Skip to content

feat: Nuxt 4 rewrite#116

Open
Decipher wants to merge 59 commits into
developfrom
feat/nuxt4
Open

feat: Nuxt 4 rewrite#116
Decipher wants to merge 59 commits into
developfrom
feat/nuxt4

Conversation

@Decipher

Copy link
Copy Markdown
Owner

Summary

Complete rewrite of the stuar.tc frontend from the Druxt/Nuxt 2 era to Nuxt 4, retaining the Drupal CMS backend.

  • Nuxt 4 with full SSG (routeRules: { '/**': { prerender: true } })
  • Live data layer — GitHub activity, repo stats, contribution graphs, npm package feeds via server routes prerendered at build time (GH_TOKEN)
  • /community page with zigzag timeline for organising roles and sorted talks
  • Open-source page with enriched project data
  • Dev console (Konami-code activated) with grid/column overlays, measure tool, colour switcher, and Nuxt payload inspector
  • @stuartclark/ui integration with Tailwind v4 scanning fix
  • Netlify deploy config with custom install script that clones Decipher/sc-ui before build (UI_REPO_TOKEN)

Netlify setup (before merging)

  1. Connect Netlify project to this repo, branch feat/nuxt4
  2. Base directory: nuxt
  3. Install command: bash scripts/netlify-install.sh
  4. Build command: pnpm generate
  5. Env vars: GH_TOKEN, UI_REPO_TOKEN (read access to Decipher/sc-ui)
  6. Merge feat/oss-componentsmain on Decipher/sc-ui so the install script picks up the latest ui

Decipher added 30 commits June 30, 2026 22:52
Replaces the legacy Nuxt 2 app (nuxt/) with the Nuxt 4 rewrite:
- Nuxt 4 app structure (app/, content/, composables/, data/)
- @nuxt/ui v3 + Tailwind v4 design system (@stuartclark/ui)
- Playwright visual regression (4 breakpoints) + design baselines
- Vitest unit/component tests
- Storybook 9 (component stories + design reference)
- Content collections via @nuxt/content v3
- Project tooling: pnpm, eslint, stylelint, knip, commitlint, mise

Preserves drupal/, .github/, and other shared project files.
Non-destructive: main and develop branches are untouched.
Adds a preview:live manual CI job that spins up the site and Storybook
behind Cloudflare Quick Tunnels (via the existing nuxt-cloudflared-tunnel
module) and posts both tunnel URLs as an MR comment that auto-cleans on
job exit.

The before_script clones + builds @stuartclark/ui as a workspace sibling
(link:../../ui pattern) using the cross-project CI job token, then
installs nuxt deps.

Scripts (adapted from realityloop/website and the ui repo):
- run-live-preview-tunnel.sh: starts Storybook (:6006) then nuxt dev,
  captures both tunnel URLs, posts/cleans MR comment, heartbeat
- post-live-preview-comment.sh / upsert-mr-note.sh / delete-mr-note.sh:
  GitLab MR note management via $GITLAB_API_TOKEN
Without workflow:rules the pipeline runs as a branch (push) pipeline,
so $CI_MERGE_REQUEST_IID is never set and the preview comment is
silently skipped.
Use bulleted list so links render on separate lines in GitLab markdown.
Use 'Site' label instead of 'Playground' for the nuxt tunnel.
Mirrors @stuartclark/ui. Stages: lint (eslint, stylelint, markdownlint,
cspell, knip, commitlint), linkcheck (lychee), test (vitest), typecheck,
build (static generate), separate visual + seo Playwright jobs,
unlighthouse audit, manual live preview and baseline regeneration.

Shared .setup template clones+builds @stuartclark/ui as a sibling so the
link:../../ui dependency resolves. Adds post-visual-failure-comment.sh to
upload actual/expected/diff PNGs to the MR on visual failures.
Establishes the mise-idiomatic git-hook standard: .githooks/ scripts
delegate to mise tasks (commit-msg -> commitlint, pre-commit -> eslint)
and a hooks:install task sets core.hooksPath. Adds unlighthouse.config.ts,
.lychee.toml, and the packageManager field.
…EADME

Adds AGENTS.md, CONTRIBUTING.md, CHANGELOG.md at the submodule root.
Replaces .markdownlint.yaml with .markdownlint.jsonc (matching
@stuartclark/ui) and extends .cspell.json. README drops the stale 'v4
prototype'/'vendored module' framing and documents CI + mise hooks.
Replaces the broken Node 14/yarn/cypress/netlify workflow with a
pnpm 10/node 22 pipeline mirroring .gitlab-ci.yml, cloning+building
@stuartclark/ui as a sibling. Bumps CodeQL to v3, scoped to
main/develop, ignoring the legacy drupal/ subtree.
Declares unlighthouse.config.ts as an entry, ignores the ImageMagick
`compare` binary used by the design-diff review script, and drops two
stale ignores (app.config.ts, storybook-static/**) that knip now flags.
Unreachable from the isolated GitLab runner (same class as the existing
linkedin/fonts excludes); not a real dead link.
app.vue set og/twitter titles but never a plain <title>, so the
generated site had an empty document title and the Playwright SEO suite
failed. Adds a global title plus a template so subpages render as
"Page · stuar.tc" while the homepage stays "Stuart Clark · stuar.tc".
Generated by the manual `visual:update` CI job (arm64 runner, matching
the `visual` job environment) so Chromium rendering is consistent.
Covers all 8 pages across the phone/tablet/desktop/wide breakpoints
(32 PNGs). 2% diff tolerance (maxDiffPixelRatio).
linkcheck: switch to --format detailed piped via tee (matching
@stuartclark/ui) and add retry/max-time to the lychee download so a flaky
api.github.com call can't hang a now-blocking job. Remove allow_failure.

lint:seo: puppeteer's bundled Chrome is x86_64 and fails via Rosetta on the
arm64 runner ("failed to open elf at /lib64/ld-linux-x86-64.so.2"). Install
the native system chromium and point unlighthouse at it via
UNLIGHTHOUSE_CHROME. Remove allow_failure.
Convert visual:update and preview:live from job-level when/allow_failure to
the rules form (matching @stuartclark/ui). This is the unambiguous way to
declare a manual job that never blocks the MR merge.
The full-page visual suite flaked (~5-7% height diffs over the 2%
threshold) because @nuxt/fonts fetches Archivo/JetBrains Mono at runtime
and whether every woff2 subset has settled before the screenshot is
non-deterministic — a single wrap-point shift at phone width cascades
into ~24-32px of full-page height variance.

Apply the proven @stuartclark/ui playground-visual technique: inject a
freeze + font-normalisation stylesheet via page.addStyleTag AFTER
hydration (unhead strips init-injected styles), overriding --font-sans
/--font-mono to deterministic DejaVu OS fonts and killing animations.
Lock the colour scheme to light in beforeEach. Baselines regenerated
from CI (arm64 runner, matching the visual job).
The font-normalisation comment in tests/visual/home.spec.ts introduces
terms cspell didn't know (unhead, networkidle, normalise/stabilise
family). Add them to .cspell.json so lint:docs passes.
Regenerated via the visual:update CI job now that the suite freezes
animations and normalises fonts to deterministic DejaVu. 18 of 32
baselines shifted (phone/tablet wrap-points); the rest are byte-identical.
Patches nuxt-cloudflared-tunnel so secondary targets (e.g. Storybook) only open
a tunnel once their port is actually listening, skipping cleanly otherwise.
Wires up via the new module-level checkPorts option and the patchedDependencies
entry in pnpm-workspace.yaml.
Moves the inline titleTemplate logic out of app.vue into
app/utils/titleTemplate.ts (applyTitleTemplate) with full unit coverage,
replacing the inline closure.
Mounts the existing AppSplash component on first paint and dismisses it once
fonts have loaded plus a 300ms minimum dwell, with a splash-fade leave
transition. App root tests cover show/hide behaviour using fake timers.
Comments out the /writing links in both header and footer nav (the section is
parked) and adjusts the layout tests accordingly, while adding coverage for
elsewhere links appearing in the mobile menu.
Adds composables that fetch live data (drupal.org REST, GitHub events, npm
registry) with static-data fallbacks, and App* wrapper components that consume
them. Refactors the home and open-source pages to compose these (stat band,
activity feed, contribution heatmap, flagship Druxt card, module list with
drupal/co-maint/npm filters, DrupalCon list).

Also excludes *.stories.ts from the coverage gate, adds the project terms the
new code introduces to the cspell dictionary, and resolves resulting
typecheck/lint nits in the composables and their specs.
Replaces em-dashes with hyphens and tidies apostrophes across
about/styleguide/talks and the article markdown for typographic consistency,
softens the 'most-installed single-author' claim to 'most widely installed',
swaps the about headshot for a Gravatar URL, and adds href links to the project
cards data.
preview:live now needs only [build], so it is no longer skipped when an
earlier non-allow_failure job (e.g. visual regression with stale baselines)
fails. The manual preview stays available as long as the static generate
succeeds.
External API calls (drupal.org, api.github.com, npm registries) and
remote images made the generated site non-deterministic, so every
composable rendered with live data and captures depended on the
network. Intercept routes to fulfil images with a transparent pixel,
abort all other external requests, hide <img> boxes, and wait for the
boot splash to leave the DOM before capture. The site itself
(localhost) is served normally and composables fall back to their
static data, so snapshots are now stable.
The apt chromium crashes on launch ("Code: null") and puppeteer's
bundled Chrome is x86_64, failing under Rosetta on the arm64 runner.
Playwright's native arm64 chromium -- already proven by the visual and
seo jobs -- launches reliably with its bundled deps. Point
chrome-launcher at it via CHROME_PATH (unlighthouse auto-adds
--no-sandbox when running as root).
The drupal.org, GitHub, and npm profile links sat as a button row at
the foot of the module list, where they read as module actions. Move
them inline beneath the open-source intro as plain text links so the
module list is purely modules and the profile handles are where the
reader first lands.
The home and open-source pages fetched GitHub and Drupal APIs straight
from the browser, which capped the data at the public REST rate limits,
left contribution history at a thin 90-day window, and let burst pushes
flood the activity feed.

Move the external calls behind two Nitro server routes so a token (when
configured) raises the limits and the GitHub GraphQL contribution
calendar supplies a full year of history: /api/activity-gh fans out the
public events across three pages, /api/contributions reads the
contribution calendar. The composables now point at those proxies.

Enrich the feed itself: collapse same-repo, same-day PushEvents into a
single "pushed N times" row, pull Drupal GitLab merge requests in as a
source, and raise the cap from 5 to 30. AppActivityFeed gains a limit
prop so the home page keeps a short view while the open-source page
scrolls the full list.

Expand the contribution heatmap from 18 weeks to a full year (52) with
horizontal scroll pinned to the latest week, and switch the static
nitro preset to routeRules prerendering so the server routes can run.
Decipher added 20 commits July 7, 2026 00:50
…client data

- Konami code unlock + leet-speak password gate (session-only)
- Color scheme switcher (magenta/electric/violet/cyan/amber/orange)
- Grid overlay (4px/8px dot grid), column guide, element outlines, opacity slider
- Measure tool with dual-element pinning, gap calculation, alignment detection
- Client data inspector: Nuxt payload JSON dump + static shell iframe overlay
- Geometry utilities extracted to app/utils/dev-measure.ts (pure functions)
- 101 tests (66 component + 35 geometry), 100% coverage
- Documented in DEV-TOOLS.md
- Export fetchNpmPackages() as standalone async function
- Coalesce search.objects ?? [] once to eliminate duplicate branch points
- Use non-null assertion on data.value!.downloads (guaranteed truthy after guard)
- Add 6 tests covering all fetch branches: search fail/success, all-scoped,
  downloads fail, nullish objects, nullish downloads
- Achieves 100% coverage on useNpmPackages.ts
- Replace direct import.meta.dev with inject('devMode', import.meta.dev)
- import.meta.dev is false in vitest, so the true branch was uncovered
- Add test providing devMode:true to cover DevGrid rendering path
- Add explicit test verifying DevGrid absent by default in test env
- Achieves 100% branch coverage on default.vue
- Expand single-line CSS declaration blocks to multi-line (5 fixes)
- Convert rgba() to modern rgb() notation, alpha to % (59 auto-fixes)
- Add empty lines between CSS rules
- Wrap markdown lines to 80 chars, add blanks around fences/lists
- Add .markdownlint.jsonc symlink so config is found in submodule
Words: unleet, hacktheplanet, devconsole, devgrid, computeds,
colour, lpignore, normalises, wrongpassword, prefs
- Add useOSSProfiles composable aggregating Drupal, GitHub, and npm stats
- Add useDevPrefs composable for DevGrid module-filter toggle
- Add format.ts utils with abbreviateNumber/shortHash helpers
- Add Nitro server routes: github-stats.get.ts, repos-gh.get.ts
- Proxy activity-gh and contributions through Nitro (remove direct client fetch)
- Enrich useModules with totalDrupalStars, useNpmPackages with GitHub stars
- Add stars field to modules data, expand co-maintained entries
- Extend vitest coverage to include server/**/*.ts
- Add nuxt/dist symlink to .gitignore
- Full test coverage for all new composables, utils, and server routes
- Add AppOSSProfiles component rendering Drupal/GitHub/npm stat cards
- Wire OSS profiles into open-source page ecosystem pane
- Add DevGrid client-data inspector: Nuxt payload viewer + static SSG shell overlay
- Add DevGrid module-list filter toggle (fades low-install modules)
- Strip DrupalCon & community section from open-source (moved to /community)
- Extend loaders.spec.ts with AppOSSProfiles and AppFlagshipDruxt coverage
…pacing

- Add useContactModal composable (SSR-safe useState) for layout-level modal
- Wire about page 'Get in touch' button to open contact modal (was LinkedIn link)
- Expose ffpSites from useStats for live File (Field) Paths install count
- Replace hardcoded '31,546' in about page bio with live data interpolation
- Standardize hero spacing across index, about, open-source, community (pt-20 pb-12 mt-7)
- Disable photos section for first launch (nav commented out, homepage teaser hidden)
- Update layout and page tests for contact modal and photos disable
- Add composables table (all 10) to README and AGENTS.md
- Update pages table: add /community, mark /writing and /photos as disabled
- Add disabled-sections section to AGENTS.md
- Document hero spacing convention (pt-20 pb-12, mt-7 gaps)
- Update structure tree and status section
- Fix CHANGELOG routes (10 routes, /community replaces /speaking)
- Add CHANGELOG entries for contact modal, ffpSites, hero spacing, disabled sections
- Add h3 to knip ignoreDependencies (transitive Nitro dep used in server routes)
- Add unstub, imageapi, textimage to cspell dictionary
Add freezeDynamicContent() to the Playwright visual suite.  Called after
hydration but before the screenshot, it replaces build-time baked live
data (drupal.org install counts, GitHub stats, npm downloads, activity
feed timestamps/content, contribution heatmap cells) with fixed
placeholders so baselines are deterministic regardless of when
`nuxt generate` ran.
Baselines regenerated from x86_64 CI (job 4905).  All 32 snapshots
(8 pages × 4 breakpoints) now show ###### placeholders for live API
data instead of build-time baked values.
@coderabbitai

coderabbitai Bot commented Jul 10, 2026

Copy link
Copy Markdown

Important

Review skipped

Too many files!

This PR contains 206 files, which is 56 over the limit of 150.

To get a review, narrow the scope:
• coderabbit review --type committed # exclude uncommitted changes
• coderabbit review --dir # limit to a subdirectory
• coderabbit review --base # compare against a closer base

Upgrade to a paid plan to raise the limit.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 2fbfbec8-fec2-412e-bc62-c54fd922a799

📥 Commits

Reviewing files that changed from the base of the PR and between f11b371 and e33986d.

⛔ Files ignored due to path filters (72)
  • nuxt/components/__snapshots__/StuartClark.test.js.snap is excluded by !**/*.snap
  • nuxt/components/dui/__snapshots__/Badge.test.js.snap is excluded by !**/*.snap
  • nuxt/components/dui/__snapshots__/Button.test.js.snap is excluded by !**/*.snap
  • nuxt/components/dui/__snapshots__/Card.test.js.snap is excluded by !**/*.snap
  • nuxt/components/dui/__snapshots__/Hero.test.js.snap is excluded by !**/*.snap
  • nuxt/components/dui/__snapshots__/Navbar.test.js.snap is excluded by !**/*.snap
  • nuxt/pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
  • nuxt/public/drupal.svg is excluded by !**/*.svg
  • nuxt/public/druxt-entity.png is excluded by !**/*.png
  • nuxt/public/druxt-logo.png is excluded by !**/*.png
  • nuxt/public/favicon.svg is excluded by !**/*.svg
  • nuxt/public/github.svg is excluded by !**/*.svg
  • nuxt/public/headshot.jpg is excluded by !**/*.jpg
  • nuxt/public/npm.svg is excluded by !**/*.svg
  • nuxt/static/favicon.ico is excluded by !**/*.ico
  • nuxt/tests/visual/design-reference/about__1280w.png is excluded by !**/*.png
  • nuxt/tests/visual/design-reference/about__1680w.png is excluded by !**/*.png
  • nuxt/tests/visual/design-reference/about__375w.png is excluded by !**/*.png
  • nuxt/tests/visual/design-reference/about__768w.png is excluded by !**/*.png
  • nuxt/tests/visual/design-reference/article__1280w.png is excluded by !**/*.png
  • nuxt/tests/visual/design-reference/article__1680w.png is excluded by !**/*.png
  • nuxt/tests/visual/design-reference/article__375w.png is excluded by !**/*.png
  • nuxt/tests/visual/design-reference/article__768w.png is excluded by !**/*.png
  • nuxt/tests/visual/design-reference/home__1280w.png is excluded by !**/*.png
  • nuxt/tests/visual/design-reference/home__1680w.png is excluded by !**/*.png
  • nuxt/tests/visual/design-reference/home__375w.png is excluded by !**/*.png
  • nuxt/tests/visual/design-reference/home__768w.png is excluded by !**/*.png
  • nuxt/tests/visual/design-reference/opensource__1280w.png is excluded by !**/*.png
  • nuxt/tests/visual/design-reference/opensource__1680w.png is excluded by !**/*.png
  • nuxt/tests/visual/design-reference/opensource__375w.png is excluded by !**/*.png
  • nuxt/tests/visual/design-reference/opensource__768w.png is excluded by !**/*.png
  • nuxt/tests/visual/design-reference/photography__1280w.png is excluded by !**/*.png
  • nuxt/tests/visual/design-reference/photography__1680w.png is excluded by !**/*.png
  • nuxt/tests/visual/design-reference/photography__375w.png is excluded by !**/*.png
  • nuxt/tests/visual/design-reference/photography__768w.png is excluded by !**/*.png
  • nuxt/tests/visual/design-reference/writing__1280w.png is excluded by !**/*.png
  • nuxt/tests/visual/design-reference/writing__1680w.png is excluded by !**/*.png
  • nuxt/tests/visual/design-reference/writing__375w.png is excluded by !**/*.png
  • nuxt/tests/visual/design-reference/writing__768w.png is excluded by !**/*.png
  • nuxt/tests/visual/home.spec.ts-snapshots/about-desktop.png is excluded by !**/*.png
  • nuxt/tests/visual/home.spec.ts-snapshots/about-phone.png is excluded by !**/*.png
  • nuxt/tests/visual/home.spec.ts-snapshots/about-tablet.png is excluded by !**/*.png
  • nuxt/tests/visual/home.spec.ts-snapshots/about-wide.png is excluded by !**/*.png
  • nuxt/tests/visual/home.spec.ts-snapshots/article-desktop.png is excluded by !**/*.png
  • nuxt/tests/visual/home.spec.ts-snapshots/article-phone.png is excluded by !**/*.png
  • nuxt/tests/visual/home.spec.ts-snapshots/article-tablet.png is excluded by !**/*.png
  • nuxt/tests/visual/home.spec.ts-snapshots/article-wide.png is excluded by !**/*.png
  • nuxt/tests/visual/home.spec.ts-snapshots/home-desktop.png is excluded by !**/*.png
  • nuxt/tests/visual/home.spec.ts-snapshots/home-phone.png is excluded by !**/*.png
  • nuxt/tests/visual/home.spec.ts-snapshots/home-tablet.png is excluded by !**/*.png
  • nuxt/tests/visual/home.spec.ts-snapshots/home-wide.png is excluded by !**/*.png
  • nuxt/tests/visual/home.spec.ts-snapshots/open-source-desktop.png is excluded by !**/*.png
  • nuxt/tests/visual/home.spec.ts-snapshots/open-source-phone.png is excluded by !**/*.png
  • nuxt/tests/visual/home.spec.ts-snapshots/open-source-tablet.png is excluded by !**/*.png
  • nuxt/tests/visual/home.spec.ts-snapshots/open-source-wide.png is excluded by !**/*.png
  • nuxt/tests/visual/home.spec.ts-snapshots/photos-desktop.png is excluded by !**/*.png
  • nuxt/tests/visual/home.spec.ts-snapshots/photos-phone.png is excluded by !**/*.png
  • nuxt/tests/visual/home.spec.ts-snapshots/photos-tablet.png is excluded by !**/*.png
  • nuxt/tests/visual/home.spec.ts-snapshots/photos-wide.png is excluded by !**/*.png
  • nuxt/tests/visual/home.spec.ts-snapshots/styleguide-desktop.png is excluded by !**/*.png
  • nuxt/tests/visual/home.spec.ts-snapshots/styleguide-phone.png is excluded by !**/*.png
  • nuxt/tests/visual/home.spec.ts-snapshots/styleguide-tablet.png is excluded by !**/*.png
  • nuxt/tests/visual/home.spec.ts-snapshots/styleguide-wide.png is excluded by !**/*.png
  • nuxt/tests/visual/home.spec.ts-snapshots/uses-desktop.png is excluded by !**/*.png
  • nuxt/tests/visual/home.spec.ts-snapshots/uses-phone.png is excluded by !**/*.png
  • nuxt/tests/visual/home.spec.ts-snapshots/uses-tablet.png is excluded by !**/*.png
  • nuxt/tests/visual/home.spec.ts-snapshots/uses-wide.png is excluded by !**/*.png
  • nuxt/tests/visual/home.spec.ts-snapshots/writing-desktop.png is excluded by !**/*.png
  • nuxt/tests/visual/home.spec.ts-snapshots/writing-phone.png is excluded by !**/*.png
  • nuxt/tests/visual/home.spec.ts-snapshots/writing-tablet.png is excluded by !**/*.png
  • nuxt/tests/visual/home.spec.ts-snapshots/writing-wide.png is excluded by !**/*.png
  • nuxt/yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (206)
  • .cspell.json
  • .githooks/commit-msg
  • .githooks/pre-commit
  • .github/workflows/ci.yml
  • .github/workflows/codeql-analysis.yml
  • .gitignore
  • .gitlab-ci.yml
  • .gitlab/scripts/delete-mr-note.sh
  • .gitlab/scripts/post-commit-comment.sh
  • .gitlab/scripts/post-discord-notification.sh
  • .gitlab/scripts/post-live-preview-comment.sh
  • .gitlab/scripts/post-preview-urls.sh
  • .gitlab/scripts/post-visual-failure-comment.sh
  • .gitlab/scripts/run-live-preview-tunnel.sh
  • .gitlab/scripts/upsert-mr-note.sh
  • .lychee.toml
  • .markdownlint.jsonc
  • .mise.toml
  • AGENTS.md
  • CHANGELOG.md
  • CONTRIBUTING.md
  • README.md
  • nuxt/.babelrc
  • nuxt/.editorconfig
  • nuxt/.eslintrc.js
  • nuxt/.gitignore
  • nuxt/.husky/commit-msg
  • nuxt/.husky/common.sh
  • nuxt/.husky/pre-commit
  • nuxt/.markdownlint.jsonc
  • nuxt/.netlify/state.json
  • nuxt/.nuxtrc
  • nuxt/.nvmrc
  • nuxt/.prettierignore
  • nuxt/.prettierrc
  • nuxt/.storybook/main.ts
  • nuxt/.storybook/preview.ts
  • nuxt/DEV-TOOLS.md
  • nuxt/README.md
  • nuxt/app/app.config.ts
  • nuxt/app/app.vue
  • nuxt/app/assets/css/main.css
  • nuxt/app/components/AppActivityFeed.vue
  • nuxt/app/components/AppContributionHeatmap.vue
  • nuxt/app/components/AppDrupalConList.vue
  • nuxt/app/components/AppFlagshipDruxt.vue
  • nuxt/app/components/AppModuleList.vue
  • nuxt/app/components/AppOSSProfiles.vue
  • nuxt/app/components/AppOrganizerRoles.vue
  • nuxt/app/components/AppSplash.stories.ts
  • nuxt/app/components/AppSplash.vue
  • nuxt/app/components/AppSplashAward.vue
  • nuxt/app/components/AppStatBand.vue
  • nuxt/app/components/AppTalksList.vue
  • nuxt/app/components/DevGrid.vue
  • nuxt/app/composables/useActivity.ts
  • nuxt/app/composables/useCoMaintainedModules.ts
  • nuxt/app/composables/useContactModal.ts
  • nuxt/app/composables/useContributions.ts
  • nuxt/app/composables/useDevPrefs.ts
  • nuxt/app/composables/useDrupalCons.ts
  • nuxt/app/composables/useModules.ts
  • nuxt/app/composables/useNpmPackages.ts
  • nuxt/app/composables/useOSSProfiles.ts
  • nuxt/app/composables/useSite.ts
  • nuxt/app/composables/useStats.ts
  • nuxt/app/data/activity.ts
  • nuxt/app/data/co-maintained.ts
  • nuxt/app/data/community.ts
  • nuxt/app/data/drupalcons.ts
  • nuxt/app/data/modules.ts
  • nuxt/app/data/projects.ts
  • nuxt/app/data/site.ts
  • nuxt/app/data/stats.ts
  • nuxt/app/data/talks.ts
  • nuxt/app/data/uses.ts
  • nuxt/app/layouts/default.vue
  • nuxt/app/layouts/minimal.stories.ts
  • nuxt/app/layouts/minimal.vue
  • nuxt/app/pages/about.vue
  • nuxt/app/pages/community.vue
  • nuxt/app/pages/drupalgive.stories.ts
  • nuxt/app/pages/drupalgive.vue
  • nuxt/app/pages/index.vue
  • nuxt/app/pages/open-source.vue
  • nuxt/app/pages/photos.vue
  • nuxt/app/pages/styleguide.stories.ts
  • nuxt/app/pages/styleguide.vue
  • nuxt/app/pages/uses.stories.ts
  • nuxt/app/pages/uses.vue
  • nuxt/app/pages/writing/[...slug].vue
  • nuxt/app/pages/writing/index.vue
  • nuxt/app/utils/dev-measure.ts
  • nuxt/app/utils/format.ts
  • nuxt/app/utils/titleTemplate.ts
  • nuxt/commitlint.config.mjs
  • nuxt/components/StuartClark.test.js
  • nuxt/components/StuartClark.vue
  • nuxt/components/druxt/entity/node/article/Card.vue
  • nuxt/components/druxt/entity/node/article/Full.vue
  • nuxt/components/druxt/entity/paragraph/code/Default.vue
  • nuxt/components/druxt/entity/paragraph/repository/Default.vue
  • nuxt/components/druxt/entity/paragraph/section/Default.vue
  • nuxt/components/druxt/entity/paragraph/text-formatted/Default.vue
  • nuxt/components/druxt/field/Image.vue
  • nuxt/components/druxt/layout-paragraph/Onecol.vue
  • nuxt/components/druxt/layout-paragraph/Twocol.vue
  • nuxt/components/dui/Badge.stories.js
  • nuxt/components/dui/Badge.test.js
  • nuxt/components/dui/Badge.vue
  • nuxt/components/dui/Button.stories.js
  • nuxt/components/dui/Button.test.js
  • nuxt/components/dui/Button.vue
  • nuxt/components/dui/Card.stories.js
  • nuxt/components/dui/Card.test.js
  • nuxt/components/dui/Card.vue
  • nuxt/components/dui/Hero.stories.js
  • nuxt/components/dui/Hero.test.js
  • nuxt/components/dui/Hero.vue
  • nuxt/components/dui/Navbar.stories.js
  • nuxt/components/dui/Navbar.test.js
  • nuxt/components/dui/Navbar.vue
  • nuxt/components/logo/Drupal.vue
  • nuxt/components/logo/Github.vue
  • nuxt/components/logo/Twitter.vue
  • nuxt/content.config.ts
  • nuxt/content/articles/decoupling-configuration-with-config-pages.md
  • nuxt/content/articles/hello-world.md
  • nuxt/content/articles/layout-paragraphs-module.md
  • nuxt/content/articles/what-no-images.md
  • nuxt/cypress.json
  • nuxt/cypress/integration/Homepage.feature
  • nuxt/cypress/integration/Homepage/index.js
  • nuxt/cypress/plugins/index.js
  • nuxt/cypress/support/commands.js
  • nuxt/cypress/support/index.js
  • nuxt/eslint.config.mjs
  • nuxt/feeds/index.js
  • nuxt/jest.config.js
  • nuxt/knip.jsonc
  • nuxt/layouts/default.stories.js
  • nuxt/layouts/default.vue
  • nuxt/mixins/config.js
  • nuxt/mixins/metatag.js
  • nuxt/netlify.toml
  • nuxt/netlify/plugins/clone-ui/index.cjs
  • nuxt/netlify/plugins/clone-ui/manifest.yml
  • nuxt/netlify/plugins/clone-ui/package.json
  • nuxt/nuxt.config.js
  • nuxt/nuxt.config.ts
  • nuxt/package.json
  • nuxt/pages/.gitkeep
  • nuxt/pages/articles/_path.stories.js
  • nuxt/pages/articles/_path.vue
  • nuxt/pages/articles/index.stories.js
  • nuxt/pages/articles/index.vue
  • nuxt/pages/index.stories.js
  • nuxt/pages/index.vue
  • nuxt/patches/nuxt-cloudflared-tunnel.patch
  • nuxt/playwright.config.ts
  • nuxt/plugins/gtag.js
  • nuxt/pnpm-workspace.yaml
  • nuxt/public/.nojekyll
  • nuxt/public/robots.txt
  • nuxt/server/api/activity-gh.get.ts
  • nuxt/server/api/contributions.get.ts
  • nuxt/server/api/github-stats.get.ts
  • nuxt/server/api/repos-gh.get.ts
  • nuxt/stylelint.config.js
  • nuxt/stylelint.config.mjs
  • nuxt/tailwind.config.js
  • nuxt/tests/app.spec.ts
  • nuxt/tests/community.spec.ts
  • nuxt/tests/components/DevGrid.spec.ts
  • nuxt/tests/components/community-components.spec.ts
  • nuxt/tests/components/layout.spec.ts
  • nuxt/tests/components/loaders.spec.ts
  • nuxt/tests/composables/useActivity.spec.ts
  • nuxt/tests/composables/useCoMaintainedModules.spec.ts
  • nuxt/tests/composables/useContributions.spec.ts
  • nuxt/tests/composables/useDevPrefs.spec.ts
  • nuxt/tests/composables/useDrupalCons.spec.ts
  • nuxt/tests/composables/useModules.spec.ts
  • nuxt/tests/composables/useNpmPackages.spec.ts
  • nuxt/tests/composables/useOSSProfiles.spec.ts
  • nuxt/tests/composables/useSite.spec.ts
  • nuxt/tests/composables/useStats.spec.ts
  • nuxt/tests/pages/article-404.spec.ts
  • nuxt/tests/pages/pages.spec.ts
  • nuxt/tests/pages/writing.spec.ts
  • nuxt/tests/seo/seo.spec.ts
  • nuxt/tests/server/activity-gh.spec.ts
  • nuxt/tests/server/contributions.spec.ts
  • nuxt/tests/server/github-stats.spec.ts
  • nuxt/tests/server/repos-gh.spec.ts
  • nuxt/tests/setup/a11y.ts
  • nuxt/tests/talks.spec.ts
  • nuxt/tests/utils/dev-measure.spec.ts
  • nuxt/tests/utils/format.spec.ts
  • nuxt/tests/utils/titleTemplate.spec.ts
  • nuxt/tests/visual/compare-design.mjs
  • nuxt/tests/visual/design-reference/manifest.json
  • nuxt/tests/visual/home.spec.ts
  • nuxt/tsconfig.json
  • nuxt/unlighthouse.config.ts
  • nuxt/vitest.config.ts

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/nuxt4

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.

@netlify

netlify Bot commented Jul 10, 2026

Copy link
Copy Markdown

Deploy Preview for stuartc ready!

Name Link
🔨 Latest commit e33986d
🔍 Latest deploy log https://app.netlify.com/projects/stuartc/deploys/6a51df34c773690008efec5f
😎 Deploy Preview https://deploy-preview-116--stuartc.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
🤖 Make changes Run an agent on this branch

To edit notification comments on pull requests, go to your Netlify project configuration.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant