Not software, not trends. Two days on taking a brief apart, arguing in front of a client, and pricing the answer without flinching. Sixteen seats, run by the four people who do it here every week.
Both days run 09:30 to 17:00 with a real lunch. You bring one live brief of your own, and by the second afternoon it has been taken apart in front of everyone at least once.
Nobody defends anything yet. We take the first brief apart in ten minutes to show what that looks like, then work through the four questions that break most of them.
Typical duration09:30 to 13:00
Both days, lunch on both, the printed workbook, and a follow-up call six weeks later when you have tried it on something real.
A second seat from the same studio
Two people from one team get more out of it than one, so this is priced to encourage it.
A half-day on your brief, after
Three weeks later, one of us spends an afternoon on the thing you brought. Remote or in Lisbon.
Bring the workshop in-house
The same two days for one team, at your office, up to twenty people.
We ask everyone six weeks later, once the shine has worn off and they have tried it on a real client.
I have raised my prices twice since March and lost nothing. That is the whole two days, honestly.
Lena Vasquez
Founder, independent studio
The staged client meeting was worse than any real one I have had. Which turned out to be the point.
Caleb Ross
Design lead, in-house team
I came for the pricing session and got more out of the first morning, where they took my brief apart in ten minutes.
Imani Brooks
Freelance art director
Sixteen people is small enough that you cannot hide, which is uncomfortable and the reason it works.
Yusuf Adeyemi
Studio partner
I went back and rewrote a proposal on the train home. It was the first one I had sent without apologising for the price.
Marta Nowak
Founder, two-person studio
Half of it was things I already knew and had never said out loud to a client. Saying them out loud in that room was the difference.
Theo Lambert
Creative director, in-house
Anything else, write to the address in the footer. A person answers, not a form.
People who present their own work to clients: founders of small studios, freelancers, and in-house leads who have to defend a decision. If somebody else does your talking, this is the wrong two days.
A single-page campaign for a two-day workshop: a tab bar navbar whose tabs are the sections below it, a cinematic hero with the date, a four-tab agenda with a photograph per half day, one ticket price with three add-ons, four accounts from past attendees, a booking FAQ and a newsletter footer carrying the same anchors.
Composed from 7 blocks. Installing this page installs all of them, plus the pieces and primitives they use.
Built in the Polaris collection.
A single-page campaign for a two-day workshop: a tab bar navbar whose tabs are the sections below it, a cinematic hero with the date, a four-tab agenda with a photograph per half day, one ticket price with three add-ons, six accounts from past attendees, a booking FAQ, and a newsletter footer carrying the same anchors. Seven blocks, one install, one page.
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.
npx shadcn add "https://ui.beste.co/page/r/landing3?email=YOUR_EMAIL&license_key=YOUR_KEY"This installs the page to components/beste/page/landing3.tsx and everything behind it: the seven blocks it composes (navbar51, hero115, workflow28, pricing64, testimonial26, faq71, footer104), the button1 and badge6 components they use, and the shadcn/ui tabs and button primitives. Ten files, no follow-up installs.
The installed file exports landing3Demo alongside the page: the exact props behind the preview above. Spread it to get a working page in one line.
import { Landing3, landing3Demo } from "@/components/beste/page/landing3";
export default function Page() {
return <Landing3 {...landing3Demo} />;
}Each section is a separate prop, so the usual next step is to keep the demo and replace one section at a time. Keep the navbar's href values pointing at the anchors, or the page stops navigating itself.
import { Landing3, landing3Demo } from "@/components/beste/page/landing3";
export default function Page() {
return (
<Landing3
{...landing3Demo}
tickets={{
label: "Tickets",
heading: "One price, and three things you can add.",
plan: { name: "Two days", price: "€680", description: "Both days, lunch, and the notes afterwards." },
addons: [
{ name: "Portfolio review", price: "€120" },
{ name: "Dinner on the first night", price: "€45" },
{ name: "Recording", price: "€90" },
],
}}
/>
);
}Every prop is the full prop object of the block that renders that section, so anything the block accepts is accepted here.
| Prop | Type | Default | Description |
|---|---|---|---|
navbar | ComponentProps<typeof Navbar51> | – | Tab bar navbar; its tabs are the anchors below |
hero | ComponentProps<typeof Hero115> | – | Cinematic hero carrying the date |
agenda | ComponentProps<typeof Workflow28> | – | Four half days, a photograph each |
tickets | ComponentProps<typeof Pricing64> | – | One price and three add-ons |
testimonial | ComponentProps<typeof Testimonial26> | – | Accounts from past attendees |
faq | ComponentProps<typeof Faq71> | – | Booking questions |
footer | ComponentProps<typeof Footer104> | – | Newsletter footer, repeating the anchors |
className | string | – | Extra classes for the page's outer wrapper |
| Section | Anchor | Block | Notes |
|---|---|---|---|
| Agenda | #agenda | workflow28 | Visual: a photograph per half day, not a bullet list |
| Tickets | #tickets | pricing64 | Given bg-muted/50; one plan, three add-ons |
| Attendees | #attendees | testimonial26 | Six accounts, which is what fills the grid |
| Questions | #questions | faq71 | Also given bg-muted/50 |
agenda removes that section entirely rather than rendering an empty one. On a one-page site that also removes the target of a navbar tab, so drop the matching tab too.sticky top-0 z-50 by the page and stays for the whole document, which is the point of a tab bar: on a one-page site it is the only navigation there is, so it has to be reachable from the bottom of the page as well as the top.div carrying the id and a scroll-mt offset, so no block is modified to be linkable.style element that targets html, with a prefers-reduced-motion guard. Element selectors only, so class obfuscation cannot detach it.dark band and no closing CTA block on this page: the tickets section is the call to action, and putting a second one after the FAQ would ask twice.navbar51
Two-row navbar with brand, availability status and seal CTA on top, and an underlined active-tab link row that scrolls horizontally on mobile.