Build a real Angular admin dashboard without paying for anything
The Base UI free tier isn't a demo with the good parts removed. It's every primitive, all 19 form blocks, 390 icons, and the full service layer — enough to ship a production dashboard end to end.
Most "free tier" component libraries are a trailer. You get buttons and cards, and the moment you need a working select, a dialog that traps focus, or a form that isn't a toy, you hit the wall. The free tier exists to show you the wall.
Base UI's free tier is drawn differently, and on purpose. All the primitives are free. All 19 form blocks are free. Every directive, service, pipe, and utility is free. All 390 icons are free. 102 of the 187 items in the catalog, no account, no license key, no trial clock.
Paid starts where pre-composed page-level work starts — the marketing blocks, the media and social widgets, the full page layouts, and a handful of heavy widgets like the data table and rich text editor. The line is "did we design an entire screen for you," not "did we cripple the button."
Here's what you can actually build on the free side.
Setup: about two minutes
npx base-ui-cli init
That writes base-ui.json, creates a base-ui.css with the CDK overlay styles, keyframes, and autofill fixes, and downloads the icon sprites into your assets folder. Add --yes to accept defaults non-interactively.
Base UI runs on standard Tailwind CSS 4 — no custom theme file. If you've already got Tailwind set up, point @source at your templates and you're done:
@import "tailwindcss";
@source "./src/**/*.{html,ts}";
Then add what you need:
npx base-ui-cli add card stat-card paginator toast dialog sidenav
Component dependencies resolve recursively and missing npm packages install automatically. npx base-ui-cli list prints the whole catalog with its tier.
The shell
A dashboard needs a collapsible sidebar, a header with a theme toggle, and a content region. All free:
<base-sidenav>
<base-nav-list>
<a base-list-item routerLink="/overview">
<base-icon name="home" class="stroke-slate-500"></base-icon>
Overview
</a>
<a base-list-item routerLink="/orders">
<base-icon name="cart" class="stroke-slate-500"></base-icon>
Orders
</a>
</base-nav-list>
</base-sidenav>
<base-page-main>
<base-page-main-header>
<h1 class="text-2xl font-bold !mt-0">Overview</h1>
</base-page-main-header>
<base-page-main-body class="p-6">
<!-- content -->
</base-page-main-body>
</base-page-main>
SidebarService and ThemeService are both free and both providedIn: 'root':
export class ShellComponent {
protected readonly sidebar = inject(SidebarService);
protected readonly theme = inject(ThemeService);
}
<button base-icon-button (click)="theme.toggleTheme()">
<base-icon [name]="theme.isDarkMode() ? 'light' : 'dark'"
class="stroke-slate-500"></base-icon>
</button>
Dark mode is a class on <html>, persisted for you. Every component in the library ships paired light and dark styles, so the toggle works across your whole app without you writing a second theme.
The metrics row
<div class="grid gap-4 sm:grid-cols-2 lg:grid-cols-4 mb-8">
<base-stat-card
label="Revenue"
[value]="revenue()"
icon="cart"
color="primary"
trend="12.5%"
[trendUp]="true"
caption="vs. last month">
</base-stat-card>
<base-stat-card
label="Active users"
[value]="activeUsers()"
icon="user"
color="success"
trend="4.1%"
[trendUp]="true"
caption="vs. last month">
</base-stat-card>
</div>
base-animated-counter is free too, if you want the numbers to count up on load. So are base-progress, base-meter-group, base-skeleton for loading states, and base-empty-state for the zero-data case that everyone forgets until QA finds it.
Forms — the part that's usually paywalled
All 19 form blocks are free. Login, signup, both tabbed variants, checkout, billing, shipping, payment, cart, profile settings, notifications, team invite, newsletter, feedback, review, filter, delete account, success message, and a multi-step wizard.
These aren't screenshots. They're working Angular components wired to reactive forms:
npx base-ui-cli add form-login form-team-invite form-profile-settings
And underneath them, the individual controls are free as well — base-select, base-custom-select, base-input-autocomplete, base-checkbox, base-radio-group, base-toggle, base-otp-input, base-phone-input, base-color-picker, base-range-slider, base-dual-range-slider, base-input-spinner, base-tri-state-checkbox, base-password-strength, base-floating-input.
Twenty-one of those implement ControlValueAccessor, so they drop into a FormGroup and behave like native inputs:
form = inject(FormBuilder).group({
email: ['', [Validators.required, Validators.email]],
role: ['member', Validators.required],
phone: [''],
notify: [true],
});
<form [formGroup]="form" (ngSubmit)="invite()">
<base-input-group class="mb-6">
<base-label>Email</base-label>
<input base-input type="email" formControlName="email" />
<base-error>A valid email is required</base-error>
</base-input-group>
<base-custom-select formControlName="role" [options]="roles" />
<base-phone-input formControlName="phone" />
<base-toggle formControlName="notify" />
<button base-button color="primary" [disabled]="form.invalid">
Send invite
</button>
</form>
Overlays, done properly
Dialogs, drawers, toasts, tooltips, popovers, dropdown menus, context menus, and the bottom sheet are all free — and they're built on Angular CDK rather than hand-rolled position: fixed.
export class OrdersComponent {
private readonly dialog = inject(DialogService);
private readonly toast = inject(ToastService);
confirmDelete(order: Order) {
this.dialog.open(ConfirmDialogComponent, { order })
.subscribe(confirmed => {
if (confirmed) {
this.toast.success('Order deleted');
}
});
}
}
DialogService.open() returns a Subject, so the result is just a stream. And dialogs use the CDK's FocusTrapFactory to keep keyboard focus inside while open — drawer panels use cdkTrapFocus with auto-capture. That's the kind of detail that's tedious to build and conspicuous when it's missing.
ToastService gives you success(), error(), warning(), info(), plus dismiss(id) and clearAll().
Tables and navigation
The full-featured Pro data table is paid, but the free tier has what most internal dashboards actually need: base-paginator, base-tabs, base-accordion, base-breadcrumb, base-stepper, base-timeline, base-tree-adjacent nav via base-nav-list, plus base-chips, base-badge, base-avatar, and base-avatar-group for row decoration.
Add base-command-palette's free cousin patterns — base-input-autocomplete and base-dropdown-menu — and you have search and quick actions covered.
See it running
There's a complete admin dashboard built entirely on the free tier, deployed and open source:
- Live demo: base-ui-free-dashboard-demo.pages.dev/app/dashboard
- Source: github.com/lussos/base-ui-free-dashboard
Clone it, run it, and read the components — they're plain Angular files in the repo, because that's how Base UI installs.
Where the paid line actually is
To be straightforward about it, here's what you'd reach for Pro to get:
- 17 full page layouts — dashboard, kanban board, inbox, scheduler, file manager, admin data table, settings, onboarding flow, docs/KB, pricing, and more
- Advanced widgets — data table, datepicker, date range picker, command palette, mega menu, file upload, multi-select, rich text editor, image cropper, product gallery, tree, mention input, splitter, knob, pick list
- Marketing and content blocks — blog and article cards, ecommerce blocks, media players, social widgets
That's 85 items, and it's a one-time $99 with lifetime updates — not a subscription and not per-seat-per-year.
But you don't need any of it to ship the dashboard above. Start free, and buy Pro when a specific block would save you a week — not before.
Browse the free catalog at base-ui.net →
npx base-ui-cli init
Start with the free tier
All primitives, all 19 form blocks, and 390 icons — no account, no licence key.
Get started