Skip to content

Documentation

neelam-ui

Search documentation

Getting Started
Forms
Overlays
Navigation
Data Display
Layout
AI & Chat
Blocks
GitHub repository
Blocks

Pricing tiers

Jump to source

Pricing that stops at the seat count

Every plan includes the whole product. What changes is how many projects and people it has to carry.

MonthlyAnnualSave 20%

Starter

For a side project that hasn't found its shape yet.

$0/seat /month

Billed annually

  • Up to 3 projects
  • One seat
  • Community support
  • 7-day activity history

Pro

Most popular

For a small team shipping to real users every week.

$19/seat /month

Billed annually · $228/year

  • Unlimited projects
  • 10 seats included
  • Priority email support
  • 12-month activity history
  • Custom domains

Extra seats prorated

Team

For an organisation with compliance to answer to.

$77/seat /month

Billed annually · $924/year

  • Everything in Pro
  • SAML single sign-on
  • Audit log and data export
  • Dedicated environment
  • 99.9% uptime SLA

Extra seats prorated

Prices exclude VAT. Non-profits and students get 50% off — apply here.

Source

Three plans with a monthly/annual switch, a highlighted recommendation, and a per-plan feature list. Built from Card, Switch, Badge, Button, Tooltip and Separator.

import { useState } from "react";
import { Check, Info } from "lucide-react";
import {
  Badge,
  Button,
  Card,
  CardContent,
  CardDescription,
  CardFooter,
  CardHeader,
  CardTitle,
  Separator,
  Switch,
  Tooltip,
  TooltipContent,
  TooltipTrigger,
} from "neelam-ui";

interface Plan {
  name: string;
  monthly: number;
  description: string;
  cta: string;
  featured?: boolean;
  features: string[];
}

const plans: Plan[] = [
  {
    name: "Starter",
    monthly: 0,
    description: "For a side project that hasn't found its shape yet.",
    cta: "Start for free",
    features: [
      "Up to 3 projects",
      "One seat",
      "Community support",
      "7-day activity history",
    ],
  },
  {
    name: "Pro",
    monthly: 24,
    description: "For a small team shipping to real users every week.",
    cta: "Start free trial",
    featured: true,
    features: [
      "Unlimited projects",
      "10 seats included",
      "Priority email support",
      "12-month activity history",
      "Custom domains",
    ],
  },
  {
    name: "Team",
    monthly: 96,
    description: "For an organisation with compliance to answer to.",
    cta: "Talk to sales",
    features: [
      "Everything in Pro",
      "SAML single sign-on",
      "Audit log and data export",
      "Dedicated environment",
      "99.9% uptime SLA",
    ],
  },
];

export default function Pricing01() {
  const [annual, setAnnual] = useState(true);

  return (
    <div className="mx-auto w-full max-w-5xl px-4 py-12 sm:px-6">
      <div className="text-center">
        <h1 className="text-3xl font-bold tracking-tight text-slate-950 sm:text-4xl dark:text-white">
          Pricing that stops at the seat count
        </h1>
        <p className="mx-auto mt-3 max-w-xl text-slate-600 dark:text-slate-400">
          Every plan includes the whole product. What changes is how many
          projects and people it has to carry.
        </p>

        {/* The switch is the control, so the two period names sit beside it
            as labels rather than as a pair of competing buttons. Neither is
            the switch's accessible name — "Annual" alone wouldn't say what
            turning it on does. */}
        <div className="mt-8 flex items-center justify-center gap-3">
          <span
            className={
              annual
                ? "text-sm text-slate-500 dark:text-slate-400"
                : "text-sm font-medium text-slate-950 dark:text-white"
            }
          >
            Monthly
          </span>
          <Switch
            checked={annual}
            onCheckedChange={setAnnual}
            aria-label="Bill annually"
          />
          <span
            className={
              annual
                ? "text-sm font-medium text-slate-950 dark:text-white"
                : "text-sm text-slate-500 dark:text-slate-400"
            }
          >
            Annual
          </span>
          <Badge variant="secondary">Save 20%</Badge>
        </div>
      </div>

      <div className="mt-10 grid gap-6 lg:grid-cols-3">
        {plans.map((plan) => {
          const price = annual
            ? Math.round(plan.monthly * 0.8)
            : plan.monthly;

          return (
            <Card
              key={plan.name}
              className={
                plan.featured
                  ? "flex flex-col border-slate-950 dark:border-white"
                  : "flex flex-col"
              }
            >
              <CardHeader>
                <div className="flex items-start justify-between gap-2">
                  <CardTitle>{plan.name}</CardTitle>
                  {plan.featured ? <Badge>Most popular</Badge> : null}
                </div>
                <CardDescription>{plan.description}</CardDescription>
              </CardHeader>

              <CardContent className="flex-1">
                <p className="flex items-baseline gap-1">
                  <span className="text-4xl font-bold tracking-tight text-slate-950 dark:text-white">
                    ${price}
                  </span>
                  <span className="text-sm text-slate-500 dark:text-slate-400">
                    /seat /month
                  </span>
                </p>
                <p className="mt-1 text-xs text-slate-500 dark:text-slate-400">
                  {annual ? "Billed annually" : "Billed monthly"}
                  {annual && price > 0 ? ` · $${price * 12}/year` : null}
                </p>

                <Separator className="my-5" />

                <ul className="flex flex-col gap-2.5 text-sm text-slate-700 dark:text-slate-300">
                  {plan.features.map((feature) => (
                    <li key={feature} className="flex items-start gap-2.5">
                      <Check
                        className="mt-0.5 h-4 w-4 shrink-0 text-slate-950 dark:text-white"
                        aria-hidden="true"
                      />
                      {feature}
                    </li>
                  ))}
                </ul>
              </CardContent>

              <CardFooter className="flex-col items-stretch gap-3">
                <Button
                  className="w-full"
                  variant={plan.featured ? "default" : "outline"}
                >
                  {plan.cta}
                </Button>
                {plan.monthly > 0 ? (
                  <p className="text-center text-xs text-slate-500 dark:text-slate-400">
                    Extra seats{" "}
                    <Tooltip>
                      <TooltipTrigger className="underline decoration-dotted underline-offset-4">
                        prorated
                        <Info
                          className="ml-1 inline h-3 w-3 align-[-0.1em]"
                          aria-hidden="true"
                        />
                      </TooltipTrigger>
                      <TooltipContent>
                        Added mid-cycle, charged only for the days remaining.
                      </TooltipContent>
                    </Tooltip>
                  </p>
                ) : null}
              </CardFooter>
            </Card>
          );
        })}
      </div>

      <p className="mt-10 text-center text-sm text-slate-600 dark:text-slate-400">
        Prices exclude VAT. Non-profits and students get 50% off —{" "}
        <a
          href="#"
          className="font-medium text-slate-950 underline underline-offset-4 dark:text-white"
        >
          apply here
        </a>
        .
      </p>
    </div>
  );
}