Inverted Company Announcement

Company news

02 May 2026

We are profitable, and we are staying at eighteen people

No second raise, no growth target we do not believe, and no plan to hire a sales team. The long version explains what that decision costs us and why we are making it anyway.

18

people, nine of whom write code

Q3 2025

the quarter we stopped losing money

1

funding round, with no plans for another

0

salespeople, now or intended

Portrait of Elena Rourke

Elena Rourke

Co-founder, press contact

Usually replies same day

Based inBristol, UK
EmbargoHonoured, always

Writing about this?

Speak to a founder rather than to a communications team. We will also give you the names of practices who did not enjoy working with us.

About this block

Inverted Company AnnouncementPRO

A company update held in one dark panel, pairing a light heading and four supporting figures over a hairline rule with a bordered column that floats a live press contact card.

News39: Inverted Company Announcement

A company update held in one dark panel, pairing a light heading and four supporting figures over a hairline rule with a bordered column that floats a live press contact card.

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/news39?email=YOUR_EMAIL&license_key=YOUR_KEY"

Base UI flavor

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

This installs the block to components/beste/block/news39.tsx, the card31 person piece it floats in the right column (installed to components/beste/piece/card31.tsx), and the badge23 and button21 components it uses for the eyebrow and the actions.

Quick start

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

tsx
import { News39, news39Demo } from "@/components/beste/block/news39";

export default function CompanyNewsPage() {
  return <News39 {...news39Demo} />;
}

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

tsx
import { Card31 } from "@/components/beste/piece/card31";
import { News39 } from "@/components/beste/block/news39";

export default function CompanyNewsPage() {
  return (
    <News39
      badge={{ label: "Company news" }}
      kicker="02 May 2026"
      heading="We are profitable, and we are staying at eighteen people"
      description="No second raise, no growth target we do not believe, and no plan to hire a sales team."
      figures={[
        { value: "18", label: "people, nine of whom write code" },
        { value: "Q3 2025", label: "the quarter we stopped losing money" },
      ]}
      buttons={[
        { label: "Read the full note", href: "/news/profitable" },
        { label: "See the company facts", href: "/about" },
      ]}
      contactTitle="Writing about this?"
      contactBody="Speak to a founder rather than to a communications team."
      media={
        <Card31
          avatar={{ src: "/people/elena.jpg", alt: "Portrait of Elena Rourke" }}
          name="Elena Rourke"
          role="Co-founder, press contact"
          status="Usually replies same day"
          availability="free"
          rows={[{ label: "Email", value: "[email protected]" }]}
        />
      }
    />
  );
}

Props

PropTypeDefaultDescription
badge{ label: string }–Eyebrow at the top of the panel, retoned for the dark surface
kickerstring–Date line above the heading
headingstring–Announcement heading
descriptionstring–Supporting paragraph, capped at max-w-xl
figuresFigure[][]Supporting numbers under a hairline
buttonsActionLink[][]Actions, first solid and the rest outlined
contactTitlestring–Heading under the press card
contactBodystring–Paragraph under that heading
mediaReactNode–Live asset in the right column, card31 in the demo
classNamestring–Extra classes for the outer section
ts
type ActionLink = {
  label: string;
  href: string;
};

type Figure = {
  value: string;
  label: string;
};

Behavior notes

  • The panel is bg-foreground inside the normal page container, so it reads as an inverted card rather than a full-bleed band. Every text token inside is a fixed background value, since the surface is fixed.
  • Badge23 is retoned inline with border-background/30 text-background/70, since the component's own tones assume a light surface.
  • Hairlines use border-background/20 rather than border-border, which is close to invisible on an inverted surface.
  • Button tones are positional and not overridable: the first is primary, later ones are outline plus an added border-background/30 so they read on the dark panel.
  • figures accepts any string, so a value can be a count like "18" or a period like "Q3 2025". Because the mix is expected, the figures do not use tabular-nums.
  • The figures grid is two-up from sm regardless of count, so four is the number the layout is tuned for.
  • The panel is a lg:grid-cols-5 split, three columns of copy against two of media. Below lg it stacks and the divider flips from lg:border-l to border-t.
  • The press column is justify-center, so the card and contact copy stay centered against a copy column whose height varies with the number of figures.

More News blocks

View all News
PRO

news38

Announcement Story

PRO

news21

Split-Flap Display

PRO

news9

Trending Cards Grid

Get Pro access