# Beste UI

> Beautiful, accessible blocks, pieces and components for shadcn/ui and Tailwind CSS, built for React and Next.js. Install one with the shadcn CLI and the code is yours to edit: no runtime dependency, nothing to upgrade.

Markdown rendition of https://ui.beste.co/block/fitness40. Every page on the site has one: add `.md` to any address, or send `Accept: text/markdown`.

Last updated: 2026-08-07

Whole catalog for LLMs: https://ui.beste.co/llms.txt. Registry index: https://ui.beste.co/r/registry.json

---
1. /
2. [Blocks](/blocks)
3. /
4. [Fitness](/blocks/fitness)
5. /
6. Honest Programme Match

# Honest Programme MatchFREE

A programme finder that argues with you: three questions land on one training block, and the card overlapping the photographic band answers in two columns, who it is for beside who should not take it, before the practical facts.

ViewCodeDocs

Base UI

![](https://oud.pics/sm/l/npm.svg)`npx shadcn add https://ui.beste.co/r-base/fitness40`

## Fitness40: Honest Programme Match

A programme finder that argues with you. Three questions land on one training block, and the card overlapping the photographic band answers in two columns, who it is for beside who should not take it, before the practical facts.

Free block

This block is free. No license or account is required: install it with the CLI and use it in unlimited projects.

### Installation

**Radix flavor**

bashCopy

```
npx shadcn add "https://ui.beste.co/r/fitness40"
```

**Base UI flavor**

bashCopy

```
npx shadcn add "https://ui.beste.co/r-base/fitness40"
```

That installs the block file, the `badge23` eyebrow and `button21` action button it is built from, and the `questionnaire` primitive.

### Quick start

tsxCopy

```
import { Fitness40, fitness40Demo } from "@/components/beste/block/fitness40";

export default function Page() {
  return <Fitness40 {...fitness40Demo} />;
}
```

tsxCopy

```
import { Fitness40 } from "@/components/beste/block/fitness40";

export default function Page() {
  return (
    <Fitness40
      badge={{ label: "Find your programme" }}
      heading="Three questions, and one of them we will talk you out of"
      description="Every programme here says who it is not for."
      shortcuts="numbers"
      image={{
        src: "https://images.unsplash.com/photo-1534438327276-14e5300c3a48",
        alt: "Empty gym floor in morning light",
      }}
      caption="One room, four coaches, and nobody filming themselves."
      questions={[
        {
          name: "now",
          title: "Where are you starting from?",
          choices: [
            { value: "none", label: "Nothing for a year or more" },
            { value: "regular", label: "Already training weekly" },
          ],
        },
        {
          name: "goal",
          title: "What would make this worth doing?",
          choices: [
            { value: "strength", label: "Being stronger than I am" },
            { value: "stamina", label: "Not being out of breath" },
          ],
        },
      ]}
      programmes={[
        {
          // checked before the looser ones below it
          match: { now: "none" },
          title: "Return, eight weeks",
          summary: "Two supervised sessions a week, deliberately easier than you want them to be.",
          image: {
            src: "https://images.unsplash.com/photo-1571019613454-1cb2f99b2d8b",
            alt: "Coach setting up equipment in a quiet gym",
          },
          caption: "Return groups are capped at six.",
          suits: ["You have not trained in a year", "Two mornings is what you can protect"],
          avoid: ["You are chasing a number by a fixed date", "You already train weekly"],
          facts: [
            { label: "Sessions", value: "Two a week, 50 minutes" },
            { label: "Group size", value: "Six people" },
          ],
          button: { label: "See the eight week plan", href: "https://beste.co" },
        },
        {
          // no match: the catch-all, and it has to be last
          title: "General, two mornings",
          summary: "Mixed sessions, no target, and the only measure is whether you keep coming.",
          suits: ["You want to train without signing up to a goal"],
          avoid: ["You have a date and a number in mind"],
          button: { label: "See what a week looks like", href: "https://beste.co" },
        },
      ]}
      labels={{ suitsTitle: "Take this if", avoidTitle: "Do not take this if" }}
    />
  );
}
```

### Props

| Prop        | Type                   | Default | Description                                                        |
| ----------- | ---------------------- | ------- | ------------------------------------------------------------------ |
| badge       | Badge                  | –       | Eyebrow above the rule, rendered with Badge23.                     |
| heading     | string                 | –       | Section heading.                                                   |
| description | string                 | –       | Lead paragraph, set opposite the heading.                          |
| image       | BandImage              | –       | Standing band behind the card, shown until a programme is matched. |
| caption     | string                 | –       | Centred line under the card.                                       |
| questions   | IntakeQuestion\[\]     | \[\]    | The questions, in the order they are asked.                        |
| shortcuts   | "letters" \| "numbers" | –       | Prints a shortcut on every choice of the active question.          |
| programmes  | Programme\[\]          | \[\]    | Checked in order; the first one whose match fits wins.             |
| labels      | Fitness40Labels        | {}      | Overrides for the buttons and the three panel headings.            |
| className   | string                 | –       | Merged onto the section element.                                   |

tsCopy

```
type Badge = { label: string };
type ActionLink = { label: string; href: string };
type BandImage = { src: string; alt: string };
type Fact = { label: string; value: string };

type IntakeQuestion = {
  name: string;
  title: string;
  description?: string;
  choices?: IntakeChoice[];
};

type IntakeChoice = { value: string; label: string; description?: string };

type Programme = {
  match?: Record<string, string>;
  title: string;
  summary: string;
  image?: BandImage;
  caption?: string;
  suits?: string[];
  avoid?: string[];
  facts?: Fact[];
  button?: ActionLink;
};

type Fitness40Labels = {
  previous?: string;
  next?: string;
  submit?: string;
  restart?: string;
  matchTitle?: string;
  suitsTitle?: string;
  avoidTitle?: string;
};
```

### Behavior notes

* The result is deliberately two-sided. `suits` and `avoid` are given equal width, and the block reads as a recommendation only when both are written honestly. A programme with an empty `avoid` list looks like a sales page.
* A programme's `match` maps a question's `name` to the value it needs, and every pair has to fit. A starting-point rule belongs above a goal rule, because where somebody is starting from overrules what they want.
* The last programme stands in when nothing fits, so a submit never dead-ends. The unglamorous option is the right catch-all here.
* The card overlaps the band by design. The band is the only full-width element, and the card sits on it so the section reads as one object rather than a photograph with a form under it.
* A programme without its own `image` keeps the standing band, which suits the catch-all and anything without a picture worth showing.
* Every question is required, so the recommendation is never made from a partial answer.

## More Fitness blocks

[View all Fitness](/blocks/fitness)

[](/block/fitness39)

PRO

fitness39

### Training Program Cards

Program grid with images, duration, frequency, skill level, and enrollment buttons. Perfect for fitness program catalogs and workout plan selection.

[](/block/fitness6)

PRO

fitness6

### Personal Trainer Profile

Trainer showcase with photo, certifications, rating, and client stats in a floating card. Perfect for personal training services and fitness coaching pages.

[](/block/fitness5)

PRO

fitness5

### Class Schedule Hero

Full-screen hero showcasing today's fitness classes with instructor info and available spots. Perfect for gym landing pages and class booking systems.

[](/block/fitness32)

FREE

fitness32

### Gym Location Finder

Location section with map preview, address, hours, parking, and public transit info. Perfect for gym contact pages and multi-location fitness centers.

## Ship the interface, keep the code.

New blocks, pieces and components every week. Install one with a command and it is yours to edit. No runtime dependency, no upgrade path to fight.

[Browse the libraryBrowse the library](/blocks)[See pricingSee pricing](/pricing)

### Library

* [Blocks](/blocks)
* [Pages](/pages)
* [Pieces](/pieces)
* [Components](/components)
* [Search](/search)

### Learn

* [Docs](/docs)
* [AI & MCP](/docs/mcp)
* [Blog](/blog)
* [Free tools](/tools)
* [What's new?](/changelog)
* [Website Builder](https://beste.co)

### More

* [Pricing](/pricing)
* [Referrals](/referrals)
* [License](/license)
* [GitHub](https://github.com/beste-co/beste-ui)

### Shadcn Blocks

* [Shadcn Hero Blocks](/blocks/hero)
* [Shadcn Feature Blocks](/blocks/feature)
* [Shadcn Pricing Blocks](/blocks/pricing)
* [Shadcn CTA Blocks](/blocks/cta)
* [Shadcn FAQ Blocks](/blocks/faq)
* [Shadcn About Blocks](/blocks/about)
* [Shadcn Stats Blocks](/blocks/stats)
* [Shadcn Footer Blocks](/blocks/footer)
* [Shadcn Navigation Blocks](/blocks/navigation)
* [Shadcn Auth Blocks](/blocks/auth)
* [Shadcn Ecommerce Blocks](/blocks/ecommerce)
* [Shadcn Portfolio Blocks](/blocks/portfolio)
* [Shadcn Showcase Blocks](/blocks/showcase)
* [Shadcn Careers Blocks](/blocks/careers)
* [Shadcn Onboarding Blocks](/blocks/onboarding)
* [Shadcn Coming Soon Blocks](/blocks/coming-soon)
* [Shadcn Post Blocks](/blocks/post)
* [Shadcn Legal Blocks](/blocks/legal)
* [Shadcn Workflow Blocks](/blocks/workflow)
* [Shadcn News Blocks](/blocks/news)

© 2026, [Beste](https://beste.co). All rights reserved.