Landing Page
betaA whole landing page, built from our website components: a floating navbar, a split hero, a logo row, bento grids, a comparison, a testimonial wall, pricing, a FAQ, and a footer.
Preview
The app your team is missing.
One app the whole team is in. Leads and members each get their own dashboard: who's coming, the plan, the calendar, and how each goal is going.
Used by teams at
Start with your team's people, then organize the week.
Set the team up
Leads plan events and check who is coming. Everyone answers for themselves.
Everyone answers
Every meeting and event has an answer-by date, so nobody chases replies in a chat.
Watch the count
The number going sits on the event, and the list fills in as people answer.
Who's coming, what's planned, and how goals are going. In one place.
Reminder emails
Pick the event, and the email takes people straight back to it.
A calendar that updates itself
When an event changes, calendar apps pick up the new time.
Goals
Track goals by team and quarter. Everyone finds their own progress.
The rest of the team runs from the same app.
Team operations
Availability, reminders, calendar feeds, and roles sit together around the week.
Team conversations
Talk about the work and keep in touch in the channels you belong to.
Saved agendas
Attach a saved agenda to another event, or copy it for the next one.
Answer for someone
The person who texts their lead still gets counted. The lead sets the answer.
Check-in notes
Review someone's past check-ins before deciding what to discuss next.
Calendar feed
Add the team calendar to any calendar app once, and it stays up to date.
Download your data
Any member can download what we hold about them, without asking first.
Delete an account
Members can ask for their account to be deleted, across every record.
Always in sync
When an event changes, every phone shows the new time on its next refresh.
What a team gets with a workspace, and what it has without one.
| Team task | Workspace | Shared table | Group chat |
|---|---|---|---|
| Who's coming, with an answer-by date | Included | Manual work | Manual work |
| Reminder email to whoever hasn't answered | Included | Not included | Not included |
| A calendar on everyone's phone | Included | Not included | Not included |
| Team and admin roles | Included | Manual work | Manual work |
Team leads noticed first, then everyone else did.
Monday mornings used to start with forty messages. Now everyone answers in one place, and I know who is coming before I book the room.
Priya RamanDesign lead at a studio Setup took an afternoon.
Tomás OkaforOffice manager at a clinic People stopped asking me what time the all-hands is. That alone was worth it.
Elin SatoTeam lead at a library We had three spreadsheets, a group chat, and a whiteboard in the office. Now we have one list that everyone trusts.
Marcus BellHead of operations at a bakery I can see who is out before the shift starts, so I plan the queue around them.
Ana LindqvistSupport lead at an agency The reminders go out on their own. I have not chased a late reply all quarter.
Hana NovakEngineering manager at a lab
I run a team too. Request access and I will set yours up with you.
The whole team
- Who's coming, with answer-by dates
- Reminder emails
- A calendar feed for every phone
Ask us anything
Tell me how the week runs, and we'll set it up together.
- Your team's name and size
- What you use today
Questions teams ask.
Install
1. Add the registry to
components.json, once per app. Without it, the shadcn CLI looks up@txbrendanin a public list that txbrendan/ui does not control.npx shadcn@latest registry add "@txbrendan=https://txbrendan.dev/r/{name}.json"2. Add the theme, once per app. It replaces your color tokens with ones checked for contrast.
npx shadcn@latest add @txbrendan/theme3. Add the template. It also adds every component it uses. Its own files go in your
componentsfolder, and they are yours to edit.npx shadcn@latest add @txbrendan/landing-page
Use it for
- The home page of a product site. Render it as the whole page, from your app's page file.
- Write every word in the props: one object for the navbar, the hero, each section, and the footer.
- Order the sections the way a visitor decides: what it is, who uses it, what it does, how it compares, what people say, what it costs, then questions.
- Give a testimonials section its words in the section's `headline`, not the wall's own `title`, so every section heading matches.
- Put a logos section first, right under the hero, with six to twelve customer logos. Leave the hero's own `logos` out then, so the logos show once.
- Give each section an `id`, like "pricing", and point the navbar's links at it, like "#pricing".
- Pass your router's link once in `renderLink`. The navbar, the bento cards, and the footer all use it.
- Set `embedded` when you show the page inside another page, like a gallery, so it has no second main.
Avoid it for
- A section type the template does not have. Install the part and add it to your copy, which is your own code once installed.
- More than one pricing section, or more than three plans in it.
- Words you can't stand behind, like a customer logo you have no right to show.
Props
- navbar
The Navbar's props. It floats as a pill once the page scrolls, and folds into a menu below 42rem.
NavbarProps
- hero
The Hero's props: the claim, the lead, the call to action, logos, and the preview.
HeroProps
- sections
The sections under the hero, top to bottom. Each has an optional `id` and `headline`, and a `type` that says which part draws it.
LandingSection[] · default []
- footer
The Footer's props: the brand, a line about you, link columns, and the legal line.
FooterProps
- renderLink
Draws every link in the navbar, the bento cards, and the footer, unless a part sets its own.
(props: NavbarLinkProps) => ReactNode · default a plain <a>
- embedded
Renders the content in a div, not a main, for a preview inside another page.
boolean · default false
- className
Extra classes on the root, which holds the container query.
string
- LandingSection
Type. One section. Bento draws a BentoGrid of cards, comparison a Comparison, faq a FAQ, logos a Logo Marquee, testimonials a Testimonial Wall, and pricing a row of PricingCards, with an optional monthly or yearly switch.
{ id?: string; headline?: HeadlineProps } & ({ type: "bento"; cards: BentoCardProps[] } | { type: "comparison"; comparison: ComparisonProps } | { type: "faq"; faq: FaqProps } | { type: "logos"; logos: LogoMarqueeProps } | { type: "pricing"; plans: PricingCardProps[]; billing?: PricingBilling } | { type: "testimonials"; testimonials: TestimonialWallProps })
| Prop | Type | Default | What it does |
|---|---|---|---|
| navbar | NavbarProps | - | The Navbar's props. It floats as a pill once the page scrolls, and folds into a menu below 42rem. |
| hero | HeroProps | - | The Hero's props: the claim, the lead, the call to action, logos, and the preview. |
| sections | LandingSection[] | [] | The sections under the hero, top to bottom. Each has an optional `id` and `headline`, and a `type` that says which part draws it. |
| footer | FooterProps | - | The Footer's props: the brand, a line about you, link columns, and the legal line. |
| renderLink | (props: NavbarLinkProps) => ReactNode | a plain <a> | Draws every link in the navbar, the bento cards, and the footer, unless a part sets its own. |
| embedded | boolean | false | Renders the content in a div, not a main, for a preview inside another page. |
| className | string | - | Extra classes on the root, which holds the container query. |
| LandingSection | { id?: string; headline?: HeadlineProps } & ({ type: "bento"; cards: BentoCardProps[] } | { type: "comparison"; comparison: ComparisonProps } | { type: "faq"; faq: FaqProps } | { type: "logos"; logos: LogoMarqueeProps } | { type: "pricing"; plans: PricingCardProps[]; billing?: PricingBilling } | { type: "testimonials"; testimonials: TestimonialWallProps }) | - | Type. One section. Bento draws a BentoGrid of cards, comparison a Comparison, faq a FAQ, logos a Logo Marquee, testimonials a Testimonial Wall, and pricing a row of PricingCards, with an optional monthly or yearly switch. |
Accessibility
- The content sits in a main landmark, between the navbar's nav and the footer, so skip links and screen readers find it.
- The Hero renders the page's one h1. Each section's Headline is an h2.
- Sections with an `id` keep clear of the floating navbar when a link jumps to them.
- Each part keeps its own accessibility, listed on its page.
Examples
A short landing page
<LandingPage
navbar={{
brand: "Workspace",
links: [{ href: "#features", label: "Features" }, { href: "#pricing", label: "Pricing" }],
actions: <Button tone="brand" size="sm">Create a team</Button>,
}}
hero={{
title: "The app your team",
accent: "is missing.",
description: "Plan the week, see who is coming, and keep everyone in one place.",
actions: <Button tone="brand" size="lg">Create a team</Button>,
}}
sections={[
{
id: "features",
type: "bento",
headline: { title: "Everything in one place." },
cards: [{ title: "Reminders", description: "Emails go to whoever hasn't answered." }],
},
{
id: "pricing",
type: "pricing",
headline: { title: "One plan.", muted: "Every team." },
plans: [{ title: "Team", price: "$12", period: "a month", action: <Button tone="brand">Start</Button> }],
},
]}
footer={{
brand: "Workspace",
columns: [{ title: "Product", links: [{ href: "#pricing", label: "Pricing" }] }],
legal: "© 2026 Workspace",
}}
/>