Project Estimate Ledger

(Starting points)

What a project like yours has cost before.

Real ranges from the last two years of work, not a calculator. Yours will land somewhere near one of these rows, and we will say which on the first call.

Usually includesTimelineFrom

Identity refresh

Mark, type, colour and a short usage guide for a team already trading.

6 to 8 weeks

€18,000

Marketing site

Architecture, eight to twelve templates, copy support and build supervision.

10 to 14 weeks

€32,000

Product launch

Naming, packaging, launch film direction and the pages that carry it.

12 to 16 weeks

€48,000

Annual report

Editorial design, data drawing, print supervision and a digital edition.

5 to 7 weeks

€14,000

Ranges assume one decision maker and content that exists. Both of those change the number more than anything we do.

Get a written estimate
About this block

Project Estimate LedgerPRO

Range-based pricing for project work: a ruled table of project types listing what each usually includes, its timeline and a starting figure, with unruled column headers on desktop and stacked rows on mobile.

Pricing70: Project Estimate Ledger

Range-based pricing for studios that quote per project instead of per seat. Each project type is a ruled row listing what it usually includes, how long it runs and the figure it starts from, with column headers appearing only where there is room for them.

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.

Upgrade Now

Installation

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

bash
npx shadcn add "https://ui.beste.co/r/pricing70?email=YOUR_EMAIL&license_key=YOUR_KEY"

Base UI flavor

bash
npx shadcn add "https://ui.beste.co/r-base/pricing70?email=YOUR_EMAIL&license_key=YOUR_KEY"

This installs the block to components/beste/block/pricing70.tsx plus the badge7 eyebrow and button12 pill button it uses.

Quick start

The installed file exports pricing70Demo alongside the block: the exact props behind the preview above. Spread it to get a working estimate table in one line.

tsx
import { Pricing70, pricing70Demo } from "@/components/beste/block/pricing70";

export default function Page() {
  return <Pricing70 {...pricing70Demo} />;
}

Then replace the demo with your own props. Written out, a trimmed setup looks like this:

tsx
import { Pricing70 } from "@/components/beste/block/pricing70";

export default function Page() {
  return (
    <Pricing70
      badge={{ label: "Starting points" }}
      heading="What a project like yours has cost before."
      description="Real ranges from the last two years of work, not a calculator."
      rows={[
        {
          title: "Marketing site",
          scope: "Architecture, templates, copy support and build supervision.",
          duration: "10 to 14 weeks",
          price: "€32,000",
        },
      ]}
      button={{ label: "Get a written estimate", href: "/estimate" }}
      labels={{
        columnScope: "Usually includes",
        columnDuration: "Timeline",
        columnPrice: "From",
        note: "Ranges assume one decision maker and content that exists.",
      }}
    />
  );
}

Props

PropTypeDefaultDescription
badge{ label: string }Eyebrow label rendered as a Badge7
headingstringSection heading in the left column
descriptionstringSupporting paragraph, right-aligned from md up
rowsEstimateRow[][]One ruled row per project type
buttonActionButtonPill CTA on the closing rule, rendered as Button12
labelsPricing70Labels{}Fixed strings that are not content: the three column headers and the closing note
classNamestringExtra classes for the outer <section>
ts
type EstimateRow = {
  title: string;
  scope: string;
  duration: string;
  price: string;
};

type ActionButton = {
  label: string;
  href: string;
};

type Pricing70Labels = {
  columnScope?: string;
  columnDuration?: string;
  columnPrice?: string;
  note?: string;
};

Behavior notes

  • The header row is hidden below md and only becomes a grid from md up, because stacked rows repeat their meaning in the copy and a floating set of column titles would read as noise on a phone.
  • The headers carry no rule of their own and sit on pb-6: the first rule in the block belongs to the first data row, so the labels read as column titles rather than as another entry, and the copy never crowds the line under it.
  • Header and body share the same md:grid-cols-[1.1fr_1.6fr_0.7fr_0.7fr] track list, so the columns line up without a table element or fixed widths.
  • The first header cell is an empty aria-hidden span: the project name column needs the grid slot but not a label.
  • price is a plain string, so a row can read €32,000, From £9k or On application without the block parsing numbers or applying a locale.
  • Rows stack into title, scope, duration and price below md with a gap-8 between them, which keeps four fields legible without horizontal scrolling.
  • Timeline is deliberately a range rather than a number: the block never implies a precision the estimate does not have.

More Pricing blocks

View all Pricing
PRO

pricing24

Startup Stage Pricing

Startup-focused pricing tiers based on funding stage from bootstrapped to Series B+. Perfect for B2B tools offering startup programs.

PRO

pricing46

Skeleton Loading State

Pricing cards with skeleton placeholders demonstrating loading states. Perfect for async pricing data or dynamic plan fetching.

PRO

pricing11

Usage-Based Slider

Usage-based pricing calculator with interactive slider showing tiered breakpoints. Perfect for API services and consumption-based products.

PRO

pricing27

API Tiered Rates

API pricing table showing tiered rate per request with volume discount breakdown. Perfect for developer APIs and infrastructure services.

PRO

pricing69

Engagement Tier Rails

Boxless pricing where each tier is a ruled column: the name, an oversized figure with its period, a fit line, an inclusion list under a second rule and a pill CTA, with subgrid keeping every internal rule aligned across the three columns.

PRO

pricing42

Grouped Feature Sections

Single plan pricing with features organized into separated category groups. Perfect for products with many features to categorize.