feat: align login flow with latest Figma designs - #286
Merged
Conversation
- Inject branding font_url at document level so branded/heading fonts render - Login CTA "Continue" -> "Sign in"; add missing identifier.field.password label - Drop the sign-up subheadline and the post-registration passkey upsell step - Rename passkey registration action to "Continue with a passkey" - Remove the duplicate "Forgot password?" button (link only) Updates the default flow definition, api-mock flow machine, locales (en/de/it), and the affected component/api-mock/e2e specs accordingly. Co-authored-by: Cursor <cursoragent@cursor.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
The standalone mock auth server only served GET /sessions/me, so the demo sign-out (DELETE /__nextgen/sessions/me via the SDK proxy) 404'd and left the session cookie stuck. Add the spec's revokeMySession handler: 204 + cookie clear on success, 401 without a cookie, 404 for an unknown session, 409 for an already-expired one. Covered by spec-conformance tests. Co-authored-by: Cursor <cursoragent@cursor.com>
Contributor
There was a problem hiding this comment.
Pull request overview
Aligns the <zitadel-login> orchestrator’s UI copy and flow behavior with the latest external Figma designs, including branded font loading, updated CTA/title wording, and removing the post-registration passkey upsell from the default flow. It also updates the api-mock and related test suites to match the new “register → done” behavior.
Changes:
- Load
branding.font_urlvia a document-level<link rel="stylesheet">(instead of inside the Shadow DOM) and adjust the default Liquid template to omit empty subtitles and de-duplicate forgot-password rendering. - Update
en/de/itlocales for “Sign in” CTAs, add the missingidentifier.field.passwordlabel, remove the sign-up subtitle, and rename the passkey registration action to “Continue with a passkey”. - Remove the post-registration
passkey-upsellstep from the default flow definition and route api-mock flows directly todone, updating unit/e2e specs and dev playground docs accordingly (plus adding api-mock logout coverage).
Reviewed changes
Copilot reviewed 20 out of 20 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| packages/components/src/orchestrator/zitadel-login.spec.ts | Updates component spec helper/expectations for the no-upsell flow completion. |
| packages/components/src/orchestrator/templates/default.liquid | Omits empty subtitles and renders forgot-password only once using the recover action metadata. |
| packages/components/src/orchestrator/locales/en.ts | Updates sign-in wording, adds password label key, empties register subtitle, renames passkey CTA. |
| packages/components/src/orchestrator/locales/de.ts | Mirrors the en locale changes for German. |
| packages/components/src/orchestrator/locales/it.ts | Mirrors the en locale changes for Italian. |
| packages/components/src/orchestrator/font-loader.ts | Moves font stylesheet injection to document.head and cleans up legacy shadow-root insertion. |
| packages/components/dev/pages/login.ts | Updates dev playground guidance/examples to reflect “sign-in → done” (no upsell). |
| packages/api-mock/src/spec-conformance.spec.ts | Adds conformance coverage for DELETE /sessions/me behavior (revoke + cookie clear). |
| packages/api-mock/src/server.ts | Adds DELETE /sessions/me logout endpoint and documents it in the custom routes list. |
| packages/api-mock/src/index.spec.ts | Updates MSW handler tests for the no-upsell register/login paths and adjusts passkey login scenario setup. |
| packages/api-mock/src/index.browser.spec.ts | Updates browser MSW test to go straight from submit to done. |
| packages/api-mock/src/flow-machine.ts | Changes default transitions to route login/register submits directly to done while keeping legacy upsell states reachable via injection. |
| packages/api-mock/AGENTS.md | Updates documented happy path and clarifies legacy upsell fixtures are now injection-only. |
| internal/api/integration_test/project_test.go | Updates integration test to assert the default flow no longer contains the passkey-upsell step. |
| apps/demo-nuxt-e2e/src/auth.spec.ts | Removes passkey-upsell interaction from Nuxt e2e sign-in and tightens URL wait timeout. |
| apps/demo-next/src/app/login/widget.tsx | Removes the “Howdy!” locale override so the widget uses the default “Sign in” title/copy. |
| apps/demo-next-e2e/src/auth.spec.ts | Removes passkey-upsell interaction from Next e2e sign-in and tightens URL wait timeout. |
| apps/cli-journey-e2e/src/user-journey.spec.ts | Updates CLI journey registration helper to reflect registration completing directly (no upsell). |
| api/openapi/endpoints/flow_definitions/examples/default-login-flow-definition.json | Removes passkey-upsell from the default flow example by targeting done after register-password submit. |
| .changeset/login-figma-polish.md | Adds a patch changeset for @zitadel/components describing the user-visible login-flow adjustments. |
Address PR review: applyFontUrl cast getElementById() to HTMLLinkElement and removed it, which could clobber an unrelated host-page element sharing the "zl-font-link" id. Only treat a matching stylesheet <link> we own as existing. Adds font-loader unit coverage for inject/idempotent/replace/remove and the no-clobber guard. Co-authored-by: Cursor <cursoragent@cursor.com>
Drop the defensive instanceof/getElementById guard in favour of a tag-scoped `link#zl-font-link` lookup, which by construction only matches our own <link> (no risk of clobbering an unrelated host node). Reuse the existing link across re-renders and only update href when it changes, avoiding a needless font re-fetch on every render. Trim the tests to the inject / reuse / remove behaviours. Co-authored-by: Cursor <cursoragent@cursor.com>
bastionstack
enabled auto-merge (squash)
June 15, 2026 08:54
vitorbari
added a commit
that referenced
this pull request
Jun 15, 2026
Resolves conflicts with #286 (login Figma polish): - default-login example JSON: dropped passkey-upsell step (removed on main) - packages/components default.liquid: kept new array iteration; threaded main's actions_by_name.recover forgot-link guard and the `recover` exclusion in the secondary-action loop - project_test.go: switched the FindStep("passkey-upsell") assertion to the main-side `assert.False(t, ok)` form Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
fforootd
pushed a commit
that referenced
this pull request
Jun 15, 2026
This PR was opened by the [Changesets release](https://github.com/changesets/action) GitHub action. When you're ready to do a release, you can merge this and the packages will be published to npm automatically. If you're not ready to do a release yet, that's fine, whenever you add more changesets to main, this PR will be updated.⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ `main` is currently in **pre mode** so this branch has prereleases rather than normal releases. If you want to exit prereleases, run `changeset pre exit` on `main`.⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ # Releases ## @zitadel/cli@0.1.0-alpha.5 ### Minor Changes - [#257](#257) [`6f8dd2d`](6f8dd2d) Thanks [@mridang](https://github.com/mridang)! - Add `setup --framework react|vue|angular|nuxt` support to the CLI. Each framework scaffolds its auth entry/pages and wires `/__nextgen/*` calls to the backend with a `sk_<project_id>` bearer attached: React and Vue get a dev proxy magicast-merged into the Vite config (`vite.config.*`) that reads the project id from `ZITADEL_PROJECT_ID`; Angular gets a `proxy.conf.cjs` wired into `angular.json` that reads it from `zitadel.json`; and Nuxt registers the `@zitadel/sdk-nuxt` module in the Nuxt config (`nuxt.config.*`), which adds the proxy via server middleware. A `--dev-port` flag sets the scaffolded dev-server port. - [#299](#299) [`f77ca44`](f77ca44) Thanks [@fforootd](https://github.com/fforootd)! - Make the generated Next.js auth app easier for agents and developers to prove end-to-end registration, logout, and login in a visible browser. ### Patch Changes - [#295](#295) [`f02718f`](f02718f) Thanks [@fforootd](https://github.com/fforootd)! - Allow fresh app scaffolding after `zitadel start` creates local runtime ignore files, and load Nuxt runtime config through the Nuxt virtual imports module. - Updated dependencies []: - @zitadel/api@0.1.0-alpha.5 ## @zitadel/components@0.1.0-alpha.5 ### Patch Changes - [#299](#299) [`f77ca44`](f77ca44) Thanks [@fforootd](https://github.com/fforootd)! - Make the generated Next.js auth app easier for agents and developers to prove end-to-end registration, logout, and login in a visible browser. - [#286](#286) [`3795b67`](3795b67) Thanks [@bastionstack](https://github.com/bastionstack)! - Align the login flow with the latest Figma designs: load `branding.font_url` at document level so branded fonts (including the heading face) actually render, change the sign-in CTA from "Continue" to "Sign in", add the missing `identifier.field.password` label, drop the sign-up subheadline, and rename the passkey registration action to "Continue with a passkey". The default login flow no longer shows the post-registration passkey upsell screen — passkey registration is offered up front instead. ## @zitadel/sdk-angular@0.1.0-alpha.5 ### Patch Changes - Updated dependencies [[`f77ca44`](f77ca44), [`3795b67`](3795b67)]: - @zitadel/components@0.1.0-alpha.5 - @zitadel/api@0.1.0-alpha.5 ## @zitadel/sdk-next@0.1.0-alpha.5 ### Patch Changes - Updated dependencies [[`f77ca44`](f77ca44), [`3795b67`](3795b67)]: - @zitadel/components@0.1.0-alpha.5 - @zitadel/api@0.1.0-alpha.5 - @zitadel/sdk-core@0.1.0-alpha.5 ## @zitadel/sdk-nuxt@0.1.0-alpha.5 ### Patch Changes - [#295](#295) [`f02718f`](f02718f) Thanks [@fforootd](https://github.com/fforootd)! - Allow fresh app scaffolding after `zitadel start` creates local runtime ignore files, and load Nuxt runtime config through the Nuxt virtual imports module. - Updated dependencies [[`f77ca44`](f77ca44), [`3795b67`](3795b67)]: - @zitadel/components@0.1.0-alpha.5 - @zitadel/api@0.1.0-alpha.5 - @zitadel/sdk-core@0.1.0-alpha.5 ## @zitadel/sdk-react@0.1.0-alpha.5 ### Patch Changes - Updated dependencies [[`f77ca44`](f77ca44), [`3795b67`](3795b67)]: - @zitadel/components@0.1.0-alpha.5 - @zitadel/api@0.1.0-alpha.5 - @zitadel/sdk-core@0.1.0-alpha.5 ## @zitadel/sdk-vue@0.1.0-alpha.5 ### Patch Changes - Updated dependencies [[`f77ca44`](f77ca44), [`3795b67`](3795b67)]: - @zitadel/components@0.1.0-alpha.5 - @zitadel/api@0.1.0-alpha.5 - @zitadel/sdk-core@0.1.0-alpha.5 ## @zitadel/api@0.1.0-alpha.5 ## @zitadel/sdk-core@0.1.0-alpha.5 Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
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.
Summary
Implements five login-flow UI changes from the external UI design Figma:
font-loaderinjected the branding<link rel="stylesheet">into the component's shadow root, where browsers ignore@font-face/webfont stylesheets. It now injects intodocument.head, so the branded heading font actually loads.identifier.field.passwordlabel (was rendering the raw key).register.descriptionis now empty by design; the template omits an empty subtitle).done.Locale changes are mirrored across
en/de/it. The "Forgot password?" control is rendered once (link only) — the duplicate secondary button was removed.Also in this PR: api-mock logout endpoint
While verifying the flow in the demo, sign-out failed because the standalone mock auth server only served
GET /sessions/me, so the SDK proxy'sDELETE /__nextgen/sessions/me404'd and left the session cookie stuck. This PR adds the spec'srevokeMySessionhandler (DELETE /sessions/me): 204 + cookie clear on success, 401 without a cookie, 404 for an unknown session, 409 for an already-expired one. Covered by api-mock spec-conformance tests. (@zitadel/api-mockis not a published package, so no changeset.)Changes
font-loader.ts— inject font<link>at document level; guard the lookup so an unrelated host-page element sharing thezl-font-linkid is never clobbered (+ unit tests)locales/{en,de,it}.ts— CTA/title wording,identifier.field.password, emptyregister.description, passkey renametemplates/default.liquid— omit empty subtitle; de-dupe forgot-password linkdefault-login-flow-definition.json+project_test.go— register-password →done, nopasskey-upsellstepapi-mock/flow-machine.ts+ specs/AGENTS — flow goes straight todoneapi-mock/server.ts— addDELETE /sessions/me(revokeMySession) + spec-conformance testsTest plan
nx run-many -t test -p @zitadel/components,@zitadel/api-mock(components 158, api-mock 26)nx run-many -t test:browser -p @zitadel/components,@zitadel/api-mocknx run-many -t lint,typecheck -p @zitadel/components,@zitadel/api-mockTestCreateProjectProvisionsDefaultLoginFlow(postgres_integration)