RFC 002 phase A: headless core + Blade starter kit - #45
Merged
Conversation
The package is now headless by default, Fortify-style. Page views are
no longer auto-loaded; the UI ships as a starter kit that is ejected
into the app once and becomes app-owned code.
- New 'ui' config (NEEV_UI: 'blade' | null). null (default) registers
no Blade page routes — API, OAuth/SSO, and email flows are fully
functional standalone. 'blade' registers the page routes, rendered
from the app-owned views
- Page templates moved to stubs/blade/views/; new neev:ui {kit}
[--force] command ejects them to resources/views/vendor/neev (the
existing publish path, so already-published consumers keep working).
It never overwrites app files without --force
- Email templates are ejected by the installer regardless of kit —
app-owned and editable from day one — while the package keeps
fallback copies so headless installs send mail with zero setup. The
per-template variable contract (RFC 002 §5.5) is documented and
treated as API
- neev:install gains the kit prompt (blade/none, default blade) as a
third argument and delegates ejection to neev:ui
- Machine-facing web routes (OAuth redirect/callback) stay always-on:
they are IdP contracts, not kit UI
- Headless email links target the app frontend instead of the now
unregistered Blade routes: verification links carry the signed query
for the API 'mail.verify' endpoint ({app.url}/verify-email?...),
new-user team invitations link to {app.url}/register?invitation_id=…
- Publish tags: neev-views replaced by neev-blade-kit + neev-mail
- Blade component/layout paths register only when the kit is ejected
Tests: suite exercises the Blade flows against the stubs (simulating
an ejected app); new HeadlessModeTest (routes absent, API works,
frontend email links) and InstallUiCommandTest (ejection, --force
semantics, unknown kit). 1004 green; Pint and PHPStan clean. RFC 002
§8 questions resolved: single Blade kit incl. app-shell views;
ejection via the dedicated neev:ui command.
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
Codecov ReportCaution This repository is currently using the Sentry GitHub App to receive Codecov PR comments. This integration will be deprecated on July 8, 2026. Please install the Codecov GitHub App to continue receiving coverage reports on your pull requests. 📢 Thoughts on this report? Let us know! |
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.
What
Implements phase A of RFC 002: neev becomes headless by default (the Fortify role), and the UI ships as a starter kit that is ejected into the app once and becomes app-owned code (the Jetstream/Breeze role) — per the maintainer-agreed design.
Changes
uiconfig (NEEV_UI:'blade'|null). Defaultnull= headless: no Blade page routes; API, OAuth/SSO, and email flows fully functional standalone.'blade'registers the page routes, rendered from app-owned views.stubs/blade/views/. Newneev:ui {kit} [--force]command ejects them toresources/views/vendor/neev— the existing publish path, so consumers who already published keep working unchanged. Never overwrites app files without--force.neev:installgains the kit prompt (blade/none, defaultblade) as a third argument and delegates toneev:ui— keeping its fresh-install guard intact (§8 Q3 resolution).{app.url}/verify-email?{signed query for 'mail.verify'}; new-user team invitations →{app.url}/register?invitation_id=…&hash=…(matching the existing frontend-link conventions of the API flows).neev-viewsreplaced byneev-blade-kit+neev-mail; Blade component/layout paths register only when the kit exists in the app.BREAKING (major release, per RFC)
'ui' => 'blade'. UPGRADING.md covers all three consumer situations (Blade users: runneev:ui blade; published-views users: just set the config; headless users: nothing).Testing
tests/TestCaseboots withui=blade+ stub view paths)HeadlessModeTest: page routes 404 / names unregistered, machine-facing routes present, API login works, verification and invitation emails link to the frontend with valid signed queriesInstallUiCommandTest: blade/none ejection matrices,--forcesemantics (app files never clobbered silently), unknown kit failsNext (per RFC)
Phase B: React starter kit (future, extracted from the TAILLOG SPA work). Phase C: docs polish / marketing framing.