From c5a594df32862f0a01e972760fac1151bdd060b6 Mon Sep 17 00:00:00 2001 From: Max Yinger Date: Tue, 15 Sep 2026 22:21:18 -0600 Subject: [PATCH 1/2] style(auth): restyle the OAuth success page Rework the sign-in success page on top of the command cards: - The Clerk mark drops its purple disc and follows --cli-fg, sitting in a 48px frame with a gradient fill and layered shadow. - The three cards move into a bottom banner that pins to the viewport on tall screens, with a section headline in the first column at four-up. - The headline animates per word rather than per character, and the logo, headline and close-window line settle upward as one staggered motion. - A brand-coloured conic glow sweeps the viewport edges once on load. - Dark mode gets counterparts for every token the redesign added. Co-Authored-By: Claude Opus 5 (1M context) --- .changeset/auth-success-page.md | 5 + packages/cli-core/src/lib/auth-server.ts | 126 +++++++++++++++-------- 2 files changed, 90 insertions(+), 41 deletions(-) create mode 100644 .changeset/auth-success-page.md diff --git a/.changeset/auth-success-page.md b/.changeset/auth-success-page.md new file mode 100644 index 000000000..c3b8e76ec --- /dev/null +++ b/.changeset/auth-success-page.md @@ -0,0 +1,5 @@ +--- +"clerk": patch +--- + +Restyle the sign-in success page with a theme-aware Clerk mark, the command cards grouped into a banner along the bottom, and a staggered entrance animation. diff --git a/packages/cli-core/src/lib/auth-server.ts b/packages/cli-core/src/lib/auth-server.ts index 692a1bc60..264b5cf4b 100644 --- a/packages/cli-core/src/lib/auth-server.ts +++ b/packages/cli-core/src/lib/auth-server.ts @@ -18,15 +18,15 @@ function escapeHtml(str: string): string { .replace(/'/g, "'"); } -const CLERK_LOGO = ` - - - - - +const CLERK_LOGO = ` `; const PAGE_STYLE = ` + @property --glow-angle { syntax: ""; initial-value: 0deg; inherits: false; } * { margin: 0; padding: 0; box-sizing: border-box; } :root { color-scheme: light dark; @@ -42,6 +42,14 @@ const PAGE_STYLE = ` --cli-syntax-mid: #7c3aed; --cli-syntax-target: #2563eb; --cli-accent: #6c47ff; + --cli-logo-bg: linear-gradient(180deg, rgba(10,10,10,0) 0%, rgba(10,10,10,0.02) 100%); + --cli-logo-shadow: 0px 11px 28px -10px #00000026, 0px 4px 14px -10px #0000001a, 0px 1px 2px 0px #0000000a, 0px 0px 0px 0.5px #1313161a, inset 0px -4px 16px 0px #fff, inset 0px -4px 4px 0px #ffffff80, inset 0px 3px 5px 0px #fff, inset 0px 4px 35px -6px #0000000f; + --cli-cards-bg: rgb(246, 246, 247); + --cli-brand-purple: #6c47ff; + --cli-brand-purple-soft: #9785ff; + --cli-brand-sky: #00aee3; + --cli-brand-sky-soft: #3ad4fd; + --cli-glow-opacity: 0.7; } @media (prefers-color-scheme: dark) { :root { @@ -57,24 +65,51 @@ const PAGE_STYLE = ` --cli-syntax-mid: #c4baff; --cli-syntax-target: #70b8ff; --cli-accent: #9c87ff; + --cli-logo-bg: linear-gradient(180deg, rgba(245,245,247,0.08) 0%, rgba(245,245,247,0) 100%); + --cli-logo-shadow: 0px 11px 28px -10px #00000080, 0px 4px 14px -10px #00000059, 0px 1px 2px 0px #00000059, inset 0 0 0 1px rgba(255 255 255 / 0.04), inset 0 1px 0 0 rgba(255 255 255 / 0.04), 0 0 0 1px rgba(0 0 0 / 1); + --cli-cards-bg: #17171a; + --cli-glow-opacity: 0.22; } } - body { font-family: system-ui, -apple-system, "Segoe UI", sans-serif; display: flex; justify-content: center; align-items: center; min-height: 100vh; background: var(--cli-bg); color: var(--cli-fg); } - .auth-page { text-align: center; padding-block: 4rem; padding-inline: 1rem; } - .auth-page h1 { margin-top: 1.25rem; font-size: clamp(1.875rem, 4vw, 2.5rem); } - .auth-page > p { margin-top: 0.75rem; } - @keyframes roll-in { from { transform: rotateX(90deg); opacity: 0; } to { transform: rotateX(0deg); opacity: 1; } } + .page-glow { position: fixed; z-index: 0; inset: -1.5rem; pointer-events: none; border: solid 0; border-image: conic-gradient(from var(--glow-angle), var(--cli-brand-purple), var(--cli-brand-purple-soft), var(--cli-brand-sky-soft), var(--cli-brand-sky), var(--cli-brand-sky-soft), var(--cli-brand-purple-soft), var(--cli-brand-purple)) 1; opacity: var(--cli-glow-opacity); filter: blur(3rem); animation: glow-sweep 2.8s cubic-bezier(0.4, 0.36, 0, 1) both, glow-spin 2.8s linear both; } + @keyframes glow-sweep { 0% { border-width: 0; } 40% { border-width: 2.5rem; } 100% { border-width: 0; } } + @keyframes glow-spin { to { --glow-angle: 1turn; } } + body { font-family: system-ui, -apple-system, "Segoe UI", sans-serif; min-height: 100vh; background: var(--cli-bg); color: var(--cli-fg); } + .auth-page { position: relative; z-index: 1; min-height: 100dvh; text-align: center; padding-inline: 1rem; } + .auth-hero { min-height: 100dvh; display: grid; place-content: center; } + .auth-headline { position: relative; } + .intro { --intro-drop: 2rem; } + .intro h1 { animation: settle-up 0.7s cubic-bezier(0.4, 0.36, 0, 1) 1.87s both; } + .intro > p { color: var(--cli-fg-muted); animation: sub-in 0.7s cubic-bezier(0.4, 0.36, 0, 1) 1.94s both; } + .intro .clerk-logo-frame { animation: logo-in 0.6s cubic-bezier(0.4, 0.36, 0, 1) both, settle-up-logo 0.7s cubic-bezier(0.4, 0.36, 0, 1) 1.8s both; } + .clerk-logo-frame { position: absolute; left: 50%; bottom: 100%; translate: -50% 0; margin-bottom: 1.25rem; display: inline-flex; align-items: center; justify-content: center; width: 48px; height: 48px; border-radius: 50%; background: var(--cli-logo-bg); box-shadow: var(--cli-logo-shadow); } + .clerk-logo { color: var(--cli-fg); } + .auth-page h1 { font-size: clamp(1.875rem, 4vw, 2.5rem); } + .auth-headline > p { margin-top: 0.75rem; } + @keyframes word-in { from { opacity: 0; filter: blur(14px); transform: scale(1.12); } to { opacity: 1; filter: blur(0px); transform: scale(1); } } + .word-in { display: inline-block; animation: word-in 0.9s cubic-bezier(0.4, 0.36, 0, 1) both; } @keyframes fade-in { from { opacity: 0; filter: blur(2px); } to { opacity: 1; filter: blur(0px); } } - .cli-cards { margin-top: 2.5rem; opacity: 0; animation: fade-in 0.4s ease-out 0.85s forwards; } - .cli-cards-intro { color: var(--cli-fg-muted); } - .cli-cards-grid { margin-top: 1rem; margin-inline: auto; display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 0.75rem; width: 52rem; max-width: 100%; } - @media (max-width: 860px) { .cli-cards-grid { grid-template-columns: 1fr; width: 24rem; } } - .cli-card { display: flex; flex-direction: column; gap: 0.5rem; border: 1px solid var(--cli-border); border-radius: 12px; padding: 1rem; text-align: left; } - .cli-card-title { display: flex; align-items: center; gap: 0.45rem; font-size: 13.5px; font-weight: 600; } + @keyframes cards-in { from { opacity: 0; filter: blur(14px); transform: scale(1.05); } to { opacity: 1; filter: blur(0px); transform: scale(1); } } + @keyframes settle-up { from { transform: translateY(var(--intro-drop)); } to { transform: translateY(0); } } + @keyframes settle-up-logo { from { translate: -50% var(--intro-drop); } to { translate: -50% 0; } } + @keyframes logo-in { from { opacity: 0; scale: 1.12; } to { opacity: 1; scale: 1; } } + @keyframes sub-in { from { opacity: 0; filter: blur(6px); transform: translateY(var(--intro-drop)); } to { opacity: 1; filter: blur(0px); transform: translateY(0); } } + .cli-cards { --cli-cards-width: 68rem; margin-top: 2rem; margin-bottom: 1.5rem; opacity: 0; transform-origin: 50% -20rem; animation: cards-in 0.9s cubic-bezier(0.4, 0.36, 0, 1) 0.22s both; } + .cli-cards-intro { align-self: center; padding-left: 1.5rem; text-align: left; } + .cli-cards-intro h2 { text-wrap: balance; font-size: 1.25rem; font-weight: 600; color: var(--cli-fg); } + .cli-cards-intro p { max-width: 30ch; text-wrap: balance; margin-top: 0.5rem; font-size: 0.78125rem; line-height: 1.45; color: var(--cli-fg-muted); } + .cli-cards-grid { margin-inline: auto; display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 0.5rem; padding: 0.5rem; width: var(--cli-cards-width); max-width: 100%; background: var(--cli-cards-bg); border-radius: 24px; } + @media (max-width: 1100px) { .cli-cards { --cli-cards-width: 52rem; } .cli-cards-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } .cli-cards-intro { grid-column: 1 / -1; padding-block: 1.5rem 1rem; } } + @media (max-width: 860px) { .auth-hero { min-height: 72dvh; } .auth-page { padding-bottom: 2rem; } .cli-cards { --cli-cards-width: 100%; margin-top: 1.5rem; } .cli-cards-grid { grid-template-columns: 1fr; } .cli-cards-intro { padding-inline: 1rem; } .cli-card-desc { max-width: 36ch; } } + @media (min-width: 861px) and (min-height: 700px) { .cli-cards { position: absolute; left: 1rem; right: 1rem; bottom: 1.5rem; margin: 0; } } + @media (min-width: 861px) and (min-height: 700px) { body { overflow: clip; } } + .cli-card { display: flex; flex-direction: column; gap: 0.5rem; border: 1px solid var(--cli-border); border-radius: 1rem; padding: 1rem; text-align: left; background: var(--cli-bg); } + .cli-card-head { display: flex; align-items: center; } + .cli-card-title { margin-top: 0.25rem; font-size: 0.84375rem; font-weight: 600; } .cli-card-icon { width: 14px; height: 14px; flex: none; color: var(--cli-fg-dim); } - .cli-card-desc { flex: 1; font-size: 12.5px; line-height: 1.45; color: var(--cli-fg-muted); } - .cli-card-code { display: flex; align-items: center; gap: 0.5rem; margin-top: 0.25rem; padding: 0.45rem 0.35rem 0.45rem 0.75rem; border: 1px solid var(--cli-border); border-radius: 8px; background: var(--cli-code-bg); } - .cli-card-code code { flex: 1; min-width: 0; overflow: hidden; white-space: nowrap; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12.5px; letter-spacing: -0.02em; color: var(--cli-fg); user-select: text; } + .cli-card-desc { flex: 1; font-size: 0.78125rem; line-height: 1.45; color: var(--cli-fg-muted); } + .cli-card-code { display: flex; align-items: center; gap: 0.5rem; margin-top: 0.75rem; padding: 0.35rem 0.35rem 0.35rem 0.75rem; border: 1px solid var(--cli-border); border-radius: 8px; background: var(--cli-code-bg); } + .cli-card-code code { flex: 1; min-width: 0; overflow: hidden; white-space: nowrap; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 0.78125rem; letter-spacing: -0.02em; color: var(--cli-fg); user-select: text; } .cli-prompt { color: var(--cli-fg-faint); user-select: none; } .cli-bin { color: var(--cli-syntax-mid); } .copy-btn { background: transparent; border: 0; width: 1.75rem; height: 1.75rem; cursor: pointer; color: var(--cli-fg-dim); border-radius: 6px; display: inline-flex; align-items: center; justify-content: center; flex: none; transition: color 0.3s cubic-bezier(0.4,0.36,0,1), background 0.15s, transform 0.15s; } @@ -87,19 +122,15 @@ const PAGE_STYLE = ` `; function animatedText(text: string): string { - return ( - text - .split("") - .map((letter, i) => { - const delay = (i * 0.015).toFixed(3); - const char = letter === " " ? " " : escapeHtml(letter); - return `\ -${char}`; - }) - .join("") + - `${escapeHtml(text)}` - ); + // Split on words, not characters: the words stay real text for a screen + // reader, so the headline needs no duplicate hidden copy. + return text + .split(" ") + .map((word, i) => { + const delay = (0.15 + i * 0.14).toFixed(3); + return `${escapeHtml(word)}`; + }) + .join(" "); } const TERMINAL_ICON_SVG = ``; @@ -132,7 +163,8 @@ const COPY_SCRIPT = ` function commandCard(title: string, description: string, commandHtml: string): string { return `
-
${TERMINAL_ICON_SVG}${escapeHtml(title)}
+
${TERMINAL_ICON_SVG}
+

${escapeHtml(title)}

${escapeHtml(description)}

$ ${commandHtml} @@ -145,13 +177,21 @@ const SUCCESS_HTML = ` Clerk CLI +
- ${CLERK_LOGO} -

${animatedText("Authentication successful")}

-

You may close this window.

+
+
+ ${CLERK_LOGO} +

${animatedText("Authentication successful")}

+

You may close this window.

+
+
-

Set up, configure, and ship Clerk from your agent or terminal.

+
+

One CLI, from setup to production.

+

Install Clerk, configure it, and deploy from your agent or your terminal.

+
${commandCard( "Install", "Detects your framework and sets up API keys automatically.", @@ -179,9 +219,13 @@ const ERROR_HTML = (message: string) => ` Clerk CLI
- ${CLERK_LOGO} -

Authentication failed

-

${escapeHtml(message)}

+
+
+ ${CLERK_LOGO} +

Authentication failed

+

${escapeHtml(message)}

+
+
`; From 5d1621364e894b2b3027a8c8033cbe66cb2d5597 Mon Sep 17 00:00:00 2001 From: Max Yinger Date: Tue, 15 Sep 2026 22:30:00 -0600 Subject: [PATCH 2/2] style(auth): settle the type scale on the success page Card titles, card descriptions and the section subheadline all sit at 13px/20px, with weight and colour carrying the hierarchy instead of size. The section headline keeps 20px with a 28px line height. Co-Authored-By: Claude Opus 5 (1M context) --- packages/cli-core/src/lib/auth-server.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/cli-core/src/lib/auth-server.ts b/packages/cli-core/src/lib/auth-server.ts index 264b5cf4b..7fce064ec 100644 --- a/packages/cli-core/src/lib/auth-server.ts +++ b/packages/cli-core/src/lib/auth-server.ts @@ -96,8 +96,8 @@ const PAGE_STYLE = ` @keyframes sub-in { from { opacity: 0; filter: blur(6px); transform: translateY(var(--intro-drop)); } to { opacity: 1; filter: blur(0px); transform: translateY(0); } } .cli-cards { --cli-cards-width: 68rem; margin-top: 2rem; margin-bottom: 1.5rem; opacity: 0; transform-origin: 50% -20rem; animation: cards-in 0.9s cubic-bezier(0.4, 0.36, 0, 1) 0.22s both; } .cli-cards-intro { align-self: center; padding-left: 1.5rem; text-align: left; } - .cli-cards-intro h2 { text-wrap: balance; font-size: 1.25rem; font-weight: 600; color: var(--cli-fg); } - .cli-cards-intro p { max-width: 30ch; text-wrap: balance; margin-top: 0.5rem; font-size: 0.78125rem; line-height: 1.45; color: var(--cli-fg-muted); } + .cli-cards-intro h2 { text-wrap: balance; font-size: 1.25rem; line-height: 1.75rem; font-weight: 600; color: var(--cli-fg); } + .cli-cards-intro p { max-width: 30ch; text-wrap: balance; margin-top: 0.75rem; font-size: 0.8125rem; line-height: 1.25rem; color: var(--cli-fg-muted); } .cli-cards-grid { margin-inline: auto; display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 0.5rem; padding: 0.5rem; width: var(--cli-cards-width); max-width: 100%; background: var(--cli-cards-bg); border-radius: 24px; } @media (max-width: 1100px) { .cli-cards { --cli-cards-width: 52rem; } .cli-cards-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } .cli-cards-intro { grid-column: 1 / -1; padding-block: 1.5rem 1rem; } } @media (max-width: 860px) { .auth-hero { min-height: 72dvh; } .auth-page { padding-bottom: 2rem; } .cli-cards { --cli-cards-width: 100%; margin-top: 1.5rem; } .cli-cards-grid { grid-template-columns: 1fr; } .cli-cards-intro { padding-inline: 1rem; } .cli-card-desc { max-width: 36ch; } } @@ -105,9 +105,9 @@ const PAGE_STYLE = ` @media (min-width: 861px) and (min-height: 700px) { body { overflow: clip; } } .cli-card { display: flex; flex-direction: column; gap: 0.5rem; border: 1px solid var(--cli-border); border-radius: 1rem; padding: 1rem; text-align: left; background: var(--cli-bg); } .cli-card-head { display: flex; align-items: center; } - .cli-card-title { margin-top: 0.25rem; font-size: 0.84375rem; font-weight: 600; } + .cli-card-title { margin-top: 0.25rem; font-size: 0.8125rem; line-height: 1.25rem; font-weight: 500; } .cli-card-icon { width: 14px; height: 14px; flex: none; color: var(--cli-fg-dim); } - .cli-card-desc { flex: 1; font-size: 0.78125rem; line-height: 1.45; color: var(--cli-fg-muted); } + .cli-card-desc { flex: 1; font-size: 0.8125rem; line-height: 1.25rem; color: var(--cli-fg-muted); } .cli-card-code { display: flex; align-items: center; gap: 0.5rem; margin-top: 0.75rem; padding: 0.35rem 0.35rem 0.35rem 0.75rem; border: 1px solid var(--cli-border); border-radius: 8px; background: var(--cli-code-bg); } .cli-card-code code { flex: 1; min-width: 0; overflow: hidden; white-space: nowrap; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 0.78125rem; letter-spacing: -0.02em; color: var(--cli-fg); user-select: text; } .cli-prompt { color: var(--cli-fg-faint); user-select: none; }