Skip to content
shadcn.io

shadcn.io is not affiliated with official shadcn/ui

Magic Link Login Block for Svelte

A full-height passwordless sign-in for a newsletter tool: one email field, then a Check your inbox state with a drawn envelope, a Resend button that really waits 30 seconds, and a way to change the address.

Framework
UI library

Preview

Preview width

Installation

Part of Pro
Pro unlocks the code and one-line install of every Pro button and text effect, plus the MCP for your AI editor.
Have Pro already? Sign in to open it.Opens here as soon as you're Pro.

Overview

Sign people in without a password, with this magic link login block for Svelte with Ark UI. It's the sign-in page of Pigeonry, a newsletter tool: the page's side rails run the full height of the screen and one band crosses it between two rules, holding a centred column with the product's mark, a heading and one sentence. A Field holds the email address, checked when the form is sent, and the Shine Button reads "Email me a link", the only colored control. A good press waits a moment and swaps the form, in the same space, for "Check your inbox": a drawn envelope with a tick, the address, an outline "Open mail app" button and a Countdown Button "Resend link" whose label counts 30 seconds down while a fill drains behind it, with "Use a different email" to go back. Nothing is sent, and the page says so. It's built from Field, Input, Button, Countdown Button, Shine Button and Guides, with a CSS entrance only. For newsletters, communities and any product where nobody wants another password.

FAQ

What stays in the page, and how do I send real links?

Everything: the form checks the address, waits 700 ms and shows the inbox state, and a polite status message says "This demo sent nothing". Nothing is emailed and no token exists. In a product, post the address to your auth endpoint where the code says so. The server creates a single-use token that expires soon (15 minutes is common), stores only its hash, and emails a link that carries it. The page that link opens exchanges the token for a session and discards it.

Is the 30-second wait real?

Yes. Pressing Resend link starts the count: the button reads Resend in 30s, ticks down once a second, and a fill drains behind the label, run by a CSS animation whose end is the end of the wait. Pressing it while it counts does nothing, and focus stays on it. The first send starts the same count, so the button is already waiting when the inbox state appears. A real server should enforce its own limit too, since a page's timer can be skipped.

Does the page tell strangers whether an address has an account?

No, and yours shouldn't. The inbox state reads the same for every well-formed address, whether or not an account exists; your server decides quietly whether to send a sign-in link, a sign-up link or nothing. Only a malformed address gets a problem message.

What does Open mail app do?

In the demo it only says that a real link would open your mail app. The web has no way to open the visitor's mail app directly; products usually link to the webmail they can guess from the address's domain, or to a mailto: or app link on a phone. Pick what fits your audience and keep the button a link, not a script.

Why is the button never disabled?

A disabled button can't explain itself and keyboard users can't reach it. Pressing it with an empty or malformed address marks the field invalid, writes one sentence under it and moves focus there. Typing clears the problem, and the field keeps a line for its problem even when there is none, so nothing moves.

Why doesn't the page jump when the state changes?

The form and the inbox share one grid cell, and an unseen copy of the inbox holds its height, so the centred page keeps the heading where it is. The form turns invisible and inert while the inbox shows, so nothing hidden takes focus. Under reduced motion the swap is instant.