Repository navigation
feat(frontend): M1 frontend foundation (Vue 3 + Inertia 3 + TypeScript, Node 24) - #10
Merged
Merged
Conversation
- .nvmrc pins Node 24; package.json engines ^24.15.0 and .npmrc engine-strict=true make npm ci reject other Node majors. - inertiajs/inertia-laravel ^3.0 (resolved v3.7.0). - vue ^3.5, @inertiajs/vue3 ^3.0; dev: @vitejs/plugin-vue, typescript ~6.0.3, vue-tsc, @vue/tsconfig, @types/node 24, vitest 5, @vue/test-utils 2, jsdom 29. - package-lock.json generated with Node 24.22.2 / npm 11.19.1.
create-vue layout without composite: tsconfig.json holds only references; tsconfig.app.json (DOM, resources/js) and tsconfig.node.json (Vite/Vitest config) extend @vue/tsconfig with strict, noUncheckedIndexedAccess, exactOptionalPropertyTypes, noImplicitOverride and verbatimModuleSyntax. '@/*' maps to resources/js without baseUrl. vite.config.js becomes vite.config.ts (content unchanged) so the node project has an input. Adds typecheck (vue-tsc --build --force) and test (vitest run) scripts.
- HandleInertiaRequests (root view 'app') shares only locale and direction; direction is rtl for Arabic, ltr otherwise. Appended to the web group. - app.blade.php sets <html lang dir> from the shared props and loads resources/js/app.ts through @Vite; welcome.blade.php is removed. - app.ts boots createInertiaApp, resolving pages from import.meta.glob('./pages/**/*.vue'); no Inertia Vite plugin. - Storefront/Home.vue is a neutral placeholder; M2 styles it. - types/shared.ts types the shared props via InertiaConfig, temporary until ADR-0018. - vite.config.ts adds the vue() plugin and the app.ts entry. config/inertia.php is not published: v3.7.0 already defaults pages.paths to resources/js/pages and testing.ensure_pages_exist to true, so assertInertia()->component() verifies the page file exists. Tests: Inertia component and props, <html lang dir> for en/ltr, and the ar/rtl derivation with the locale set directly until M3 adds routing.
- vitest.config.ts is separate from the Vite config: vue() plugin and jsdom, without the Laravel plugin. - Home.test.ts mounts Storefront/Home (Inertia <Head> mocked) and asserts the heading renders. - The PHP 8.5 / Laravel 13 job (required check, name unchanged) sets up Node from .nvmrc and runs npm ci + npm run build before Pest, the only frontend build in CI. - A new, independent Node 24 / Vue 3 job runs npm ci (engine-strict) -> typecheck -> test -> npm audit --omit=dev, with the audit last so an advisory cannot hide the other results.
- security.md: npm audit --omit=dev is blocking in CI; dev-only advisories (GHSA-3g3m-2fjr-6pw4, GHSA-g3hv-75wg-m249 via @vue/test-utils -> js-beautify) are recorded with chain, rationale and reassessment date, plus when to reassess. - definition-of-done.md: local gate order npm ci -> npm run build -> composer check -> typecheck -> test -> npm audit --omit=dev.
This was referenced Nov 8, 2026
Merged
Merged
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 free
to 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.
M1 frontend foundation: Vue 3 + Inertia 3 + strict TypeScript on Node 24.
/is now served through Inertia, with a separate frontend CI job. No product UI yet; M2 styles the page.Summary
Five logical commits on
main(0934dbe):build(frontend): Node 24 / Vue 3 / Inertia 3 toolchain, lockfile generated on Node 24.22.2 / npm 11.19.1build(frontend): strict TypeScript projects (app + node)feat(storefront): Inertia shell servingStorefront/Home(tests first)ci(frontend): Vitest smoke test and theNode 24 / Vue 3jobdocs(engineering): frontend local check and npm auditingRelated Issues
N/A
Requirement
M1 (frontend foundation), per the Phase 1/2 specification and ADR-0020.
Type of Change
What Changed
.nvmrc=24;engines.node=^24.15.0;.npmrcaddsengine-strict=true.inertiajs/inertia-laravel^3.0 (v3.7.0).vue^3.5,@inertiajs/vue3^3.0. Dev:@vitejs/plugin-vue,typescript~6.0.3,vue-tsc,@vue/tsconfig,@types/node24,vitest5,@vue/test-utils2,jsdom29.tsconfig.jsonholds only references, totsconfig.app.json(DOM) andtsconfig.node.json(Vite/Vitest config). Nocomposite.strict,noUncheckedIndexedAccess,exactOptionalPropertyTypes,noImplicitOverride,verbatimModuleSyntax.@/*is mapped withoutbaseUrl.HandleInertiaRequestsmiddleware shares onlylocaleanddirection(rtlforar).app.blade.phpsets<html lang dir>from those props.app.tsresolves pages viaimport.meta.glob, without the Inertia Vite plugin.Storefront/Home.vueas a placeholder.types/shared.tsis temporary, until ADR-0018.welcome.blade.php.PHP 8.5 / Laravel 13job (required, name unchanged) now sets up Node from.nvmrcand runsnpm ci+npm run buildbefore Pest. That is the only frontend build in CI.Node 24 / Vue 3job runsnpm ci→ typecheck → test →npm audit --omit=dev, with the audit last.security.md: npm audit policy, plus the dev-only advisories recorded.definition-of-done.md: the local check order.Design / Architecture
config/inertia.phpis not published (T3). v3.7.0 already defaultspages.pathstoresources/js/pagesandtesting.ensure_pages_existtotrue, soassertInertia()->component()fails if the page file is missing. A published copy would drift from later releases.@tsconfig/node24/@types/jsdompackages.vue-tsc --build --forcecompiles cleanly.ssr.ensure_bundle_existsat its defaulttrue, the gateway skips SSR, so tests and CI never contact an SSR server.exactOptionalPropertyTypes(T4): no library conflicts were hit. The flag stays on.Testing
Test Evidence
Local, Node 24.22.2 / npm 11.19.1, PHP 8.5, with
APP_CONFIG_CACHEpointed at a path that doesn't exist, from a cleannode_modules/public/build:npm cinpm run buildcomposer checkcomposer.jsonvalid · 0 advisories · Pint passed · PHPStan 0 errors · Pest 8 passed (31 assertions)npm run typechecknpm testnpm audit --omit=devassertInertia: componentStorefront/Home,locale=en,direction=ltr<html lang="en" dir="ltr">; with localear:direction=rtl,<html lang="ar" dir="rtl">(locale set directly until M3 adds routing)/uptest, arch tests, Pint and PHPStan (level 6, unchanged) passconst n: number = 'x'failsvue-tscwithTS2322, exit 2; clean again after removalStorefront/Homemounts and renders its headingnode --versionin theNode 24 / Vue 3job (Node from.nvmrc)npm ciagainst this lockfile on Node 22.22.0 / npm 10.9.4:EBADENGINE,Required: {"node":"^24.15.0"}, exit 1, nothing installednpm audit --omit=dev: 0, blocking in CI. Dev-only advisories recorded insecurity.mdphp artisan testapp-*.js: 184.80 kB, 62.31 kB gzip;Home-*.js: 0.30 kB gzip; CSS 10.03 kB gzipapp/Modules,spatie/laravel-data, migrations, Boost,@inertiajs/vite, ESLint.laravel/boostappears incomposer.lockonly as inertia-laravel'sconflict: <2.5.0constraint; it is not installedSecurity / Data Isolation
localeanddirectiononly)Dev-only npm advisories (moderate, test-time only, never shipped), recorded in
security.mdwith a 2026-11-05 reassessment date:@vue/test-utils→js-beautify→globeditorconfig/glob→minimatchDatabase / Migration
Screenshots / Recording
N/A. The page is a neutral placeholder; M2 styles it.
Documentation
docs/engineering/security.md,docs/engineering/definition-of-done.md)Reviewer Notes
.github/workflows/ci.yml: build-once in the required job; the frontend job has noneeds:.HandleInertiaRequests::share().fontainewarning from the existing bunny-fontsoptimizedFallbackssetting. It predates M1 and is left unchanged.CLAUDE.mdasks agents to install Laravel Boost. That was deliberately not done (F-5).Node 24 / Vue 3to themainruleset's required checks after this merges (it must have run once onmain). Until then, never merge with it red.eslint-plugin-vue+typescript-eslint.types/shared.tswith generated types once ADR-0018 is decided.Definition of Done
composer checkpasses locally (validate, audit, Pint, PHPStan, Pest)