A second address
Two rooms above a bookshop on Rua das Flores, the same three practitioners on rotation, and the same rule: nobody is rushed.
A full-height coming-soon page on a photograph that drifts slower than the page under a scrim and film grain: a serif headline settling in word by word, an intro, a live serif countdown to the opening date, and a rounded email field with a light sliding-marker pill.
A full-screen opening announcement over a photograph that drifts behind film grain: the headline settles in word by word, a live countdown ticks under the description, and a rounded email capture sits opposite it.
Upgrade to Pro
Pro blocks install through the shadcn CLI with your license key and ship their full source. Docs and live previews stay open to everyone, so you can read every block's details first.
Swap YOUR_EMAIL and YOUR_KEY for the email and license key on your account. Find your license key on your account page.
Radix flavor
npx shadcn add "https://ui.beste.co/r/comingsoon80?email=YOUR_EMAIL&license_key=YOUR_KEY"Base UI flavor
npx shadcn add "https://ui.beste.co/r-base/comingsoon80?email=YOUR_EMAIL&license_key=YOUR_KEY"This installs the block to components/beste/block/comingsoon80.tsx, the shadcn input primitive the capture is built on, and the button22 sliding-marker pill and the text1 word stagger it uses.
The installed file exports comingsoon80Demo alongside the block: the exact props behind the preview above. Spread it to get a working countdown page in one line.
import { Comingsoon80, comingsoon80Demo } from "@/components/beste/block/comingsoon80";
export default function Page() {
return <Comingsoon80 {...comingsoon80Demo} />;
}Then replace the demo with your own props. Written out, a trimmed setup looks like this:
import { Comingsoon80 } from "@/components/beste/block/comingsoon80";
export default function Page() {
return (
<Comingsoon80
eyebrow="A second address"
heading="Porto opens in the new year."
description="Two rooms above a bookshop, the same three practitioners on rotation."
opensAt="2027-01-12T09:00:00Z"
image={{ src: "/photos/lake.jpg", alt: "A calm lake reflecting mountains at first light" }}
form={{
placeholder: "Your email",
button: "Tell me when",
note: "One email when the doors open. Nothing before, nothing after.",
}}
labels={{ days: "Days", hours: "Hours", minutes: "Minutes", seconds: "Seconds" }}
/>
);
}| Prop | Type | Default | Description |
|---|---|---|---|
eyebrow | string | – | Small-caps line above the headline |
heading | string | – | Headline, rendered as the page h1 through Text1 |
description | string | – | Paragraph above the countdown |
opensAt | string | – | ISO date the countdown runs toward; the countdown is skipped when unset |
image | { src: string; alt: string } | – | Full-bleed background photograph |
form | { placeholder: string; button: string; note: string } | – | Email capture; the whole form is skipped when unset |
labels | Comingsoon80Labels | {} | Names of the four countdown units |
className | string | – | Extra classes for the outer <section> |
type Comingsoon80Labels = {
days?: string;
hours?: string;
minutes?: string;
seconds?: string;
};Date.now() on every tick rather than decremented, so a tab that was backgrounded for an hour shows the correct time the moment it wakes rather than an interval's worth of drift.00 across all four units instead of counting up into negatives.useState initialiser, which means the first paint already carries real numbers rather than four zeroes that snap a second later.tabular-nums, so the row does not change width as the seconds roll over.trigger="mount": a full-screen page is above the fold, so waiting for a scroll into view would leave it invisible.feTurbulence filter takes its id from useId, so two grain surfaces on one page do not collide on a global SVG id.Input is restyled for a dark surface (a translucent fill, a background/30 border, and the focus ring traded for a solid border), because the shadcn default is drawn for a light one.preventDefault(); no address is captured or sent until you wire it up.Wiring the form up
This block ships the form markup only; state, validation, and submit are yours to add. Our guide wires the shadcn Field primitives to React Hook Form, TanStack Form, and Formisch on one field system.
comingsoon81
A light full-height waitlist page: the wordmark in the corner, a centred eyebrow, a serif headline that settles in word by word, an intro, a rounded email field with a sliding-marker pill, a reassurance line and an avatar count of the names so far.
comingsoon77
A pre-launch section on a full-bleed photograph under a dark gradient, with a light display heading, four oversized countdown figures between hairline rules, and a working email capture card.
comingsoon49
A two-column coming-soon section with a vertical monospace edge label, an oversized wordmark, a tagline and a working email notify form, beside a framed portrait image tile.
comingsoon56
A hospitality coming-soon section with an interior image beside a venue name, a square eyebrow, a heading, an opening details grid with icons, and a working email list form with a success state.