The brochure
Floor plans for every type, the full specification, the landscape plan and the story of the warehouse, laid out by Agnes Obel Interiors. Leave your email and the PDF is yours straight away.

A brochure request for a development: heading and lead on the left over a numbered contents list of six chapters with their page counts and a total, hairlines between the rows; on the right a 4:3 photograph of the dining room at dusk opens from the top once it has loaded, with the email field, submit pill and note under it as a one-line GET form, so the two columns balance.
A brochure request for a development: heading and lead on the left over a numbered contents list of six chapters with their page counts and a total, hairlines between the rows. On the right a 4:3 photograph of the dining room at dusk opens from the top once it has loaded, with the email field, the submit pill and a note about the file under it as a one-line GET form, so the two columns carry equal weight.
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://beste.dev/r/realestate46?email=YOUR_EMAIL&license_key=YOUR_KEY"Base UI flavor
npx shadcn add "https://beste.dev/r-base/realestate46?email=YOUR_EMAIL&license_key=YOUR_KEY"This installs the block to components/beste/block/realestate46.tsx plus the badge24 rule eyebrow, the button25 quiet pill used for the submit button, and the shadcn/ui button and input primitives behind them and the email field.
The installed file exports realestate46Demo alongside the block: the exact props behind the preview above. Spread it to get a working section in one line.
import { Realestate46, realestate46Demo } from "@/components/beste/block/realestate46";
export default function Page() {
return <Realestate46 {...realestate46Demo} />;
}Then replace the demo with your own props. Written out, a trimmed setup looks like this:
import { Realestate46 } from "@/components/beste/block/realestate46";
export default function Page() {
return (
<Realestate46
eyebrow="The brochure"
heading="Sixty-four pages on the buildings, the homes and the river."
description="Floor plans for every type, the full specification and the story of the warehouse."
image={{
src: "https://oud.pics/b/realestate/alder-dining-dusk.webp",
alt: "A long oak dining table at dusk under a linen pendant",
}}
chapters={[
{ title: "The place and the river walk", pages: 8 },
{ title: "Floor plans, Type A to Type E", pages: 20 },
{ title: "Specification and finishes", pages: 12 },
]}
form={{ action: "/brochure", params: { email: "email" } }}
labels={{ contents: "What is inside", pages: "pages", email: "Email", submit: "Send me the brochure" }}
note="A 24 MB PDF. We will also send you the price list."
/>
);
}| Prop | Type | Default | Description |
|---|---|---|---|
eyebrow | string | – | Short line above the heading, drawn with a rule in front of it. |
heading | string | – | Section heading. |
description | string | – | Lead paragraph under the heading. |
image | { src: string; alt: string } | – | 4:3 photograph at the top of the right column, above the form; without it both columns span the full width. |
chapters | Chapter[] | [] | Numbered contents rows with a page count each; the total is summed for the caption. |
form | BrochureForm | – | GET target and the email parameter name; without it no form renders. |
labels | Labels | {} | Captions for the contents list, the page unit, the email field and the submit pill. |
note | string | – | Line under the form about the file and what follows. |
className | string | – | Extra classes merged onto the section. |
type Chapter = { title: string; pages: number };
type BrochureForm = { action: string; params?: { email?: string } };
type Labels = { contents?: string; pages?: string; email?: string; submit?: string };method="get" form posting to form.action with one type="email" field carrying native required; its parameter name comes from form.params.email and falls back to email.pages next to labels.pages, so the total always matches the list.load event and on the frame being in view, opens from the top over 1.6 s and drifts from -6% to 6% against the scroll; on small screens it moves below the form.prefers-reduced-motion the photograph shows at once, the parallax is zero and no text moves.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.