Almost every product eventually grows a dashboard — an admin panel, an analytics overview, a billing page, a team board. And most teams build it the same expensive way: pull in a component library, wire up a grid plugin, add a charting dependency, and end up shipping a few hundred kilobytes of JavaScript to render six numbers and a list. Below are 10 free dashboard snippets you can preview live and copy in seconds: a full admin shell, KPI cards that count up on scroll, a drag-to-rearrange widget grid that remembers its layout, an activity timeline, a grouped transaction history, a drag-and-drop kanban board, a week-view scheduler, a notification bell, a plan-usage quota meter, and a service status widget.
Each one comes with how it actually works, when to reach for it, and a quick tip for adapting it. They're all plain HTML, CSS, and vanilla JavaScript — no framework, no grid library, no drag-and-drop package.
Every snippet below is a live, interactive preview — drag it, filter it, click it right in the article. When you find one you like, hit View / Edit Code to grab the HTML/CSS/JS or export it to React, Vue, Angular or Tailwind.
What separates a dashboard people use from one they ignore
Dashboards fail for predictable reasons, and every snippet below is built around at least one of the fixes:
- The most important number should be readable in under a second. A dashboard is scanned, not read. Big values, a colour-coded delta, and an icon per metric let someone answer "is anything wrong?" before they've focused on a single word.
- Data should live in data, not in markup. The good snippets here keep events, transactions, services and quotas in a plain JavaScript array and render from it. Swapping the demo content for your API response becomes a one-line change instead of a rewrite of the HTML.
- State the user sets should survive a reload. Widget order, filter tabs, read/unread — if the dashboard forgets what the user did the moment they refresh, it feels like a mockup rather than a tool.
Keep those three in mind as you scroll.
1. Dashboard Layout
The frame everything else sits inside: a fixed dark sidebar with navigation and a user profile, a scrollable main area, a stats row across the top, and a data table underneath.
How it works: the app shell is a single flex container at height: 100vh. The sidebar gets a fixed width and flex-shrink: 0 so it never collapses; the main area gets flex: 1 plus overflow-y: auto, which is what makes the content scroll independently while the navigation stays put. There's no JavaScript in the whole layout — the stats row is a four-column CSS grid and the table is a real semantic <table> with a status column of coloured badge chips.
Best for: the starting skeleton for any admin panel, analytics tool, or SaaS app — build it once, then drop the other nine snippets into the main area. Tip: on mobile, don't shrink the sidebar — take it out of flow entirely with position: fixed and slide it in from off-screen behind a hamburger toggle, so the content gets the full viewport width.
Grab the code: Dashboard Layout
2. Stats Card
The KPI row every dashboard opens with — revenue, users, conversion rate — except the numbers count up from zero the moment they scroll into view, each with a coloured icon and a change indicator.
How it works: each value element carries its final number in a data-target attribute, and an IntersectionObserver fires the animation when the card enters the viewport — then disconnects, so the count-up runs exactly once instead of replaying every time you scroll past. The animation itself is a requestAnimationFrame loop over roughly 1200 ms with a cubic ease-out, so the number sprints early and decelerates into its final value rather than ticking up linearly.
Best for: the metric row at the top of an analytics page, or a "by the numbers" block on a marketing site. Tip: the change indicator does more work than the value itself — "12,480" means nothing without "+18% vs last month" beside it, so always render the delta and colour it green or red.
Grab the code: Stats Card
3. Dashboard Widget Grid
A customisable dashboard where users drag widgets to reorder them, toggle each one between single and double width, and find their layout exactly as they left it after a reload.
How it works: reordering uses the native HTML5 drag-and-drop API with all five events handled by delegation on the grid container, so widgets added later work without registering new listeners. The drag preview is honest — instead of faking a placeholder, the real CSS Grid reflows live as you move — and the two classic API gotchas are handled explicitly: the dimming class is applied inside requestAnimationFrame so the browser doesn't snapshot the faded widget as the drag image, and setData() is called because Firefox refuses to start a drag without it. The final order is persisted to localStorage as a simple ordered list of widget IDs.
Best for: product dashboards where different roles care about different metrics, and "let me arrange my own view" is a real feature request rather than a nice-to-have. Tip: persist the order as IDs, never as HTML — that way you can add, remove or redesign widgets later and old saved layouts still resolve correctly.
Grab the code: Dashboard Widget Grid
4. Activity Feed
A vertical timeline of what's been happening — deploys, comments, alerts — with a connecting spine, coloured event icons, avatars, quoted comment previews, timestamps, and filter tabs by event type.
How it works: the timeline spine is a 1px div with a pseudo-element circle for each node, and the last item gets a class that hides the line while preserving the spacing — so the timeline ends cleanly instead of trailing into nothing. Each event type has its own tinted icon background and inline SVG (no icon library), which is what lets you scan the feed by colour without reading a word. Filtering is pure client-side class toggling based on a data-type attribute, so switching tabs is instant on a static feed.
Best for: audit logs, project-management activity streams, CI/CD histories, and the "recent activity" panel on a team dashboard. Tip: the colour coding only works if you keep the palette small — three or four event types maximum. Once every event has its own colour, nothing stands out and you're back to reading line by line.
Grab the code: Activity Feed
5. Transaction List
The screen at the heart of every banking and fintech app: transactions grouped under sticky date headers, each day showing its own net total, with category icons and income/spending filter tabs.
How it works: the data is one flat array, and the render pass folds it into day buckets in a single walk, accumulating each day's running total as it goes. Because grouping happens at render time rather than in the data, re-filtering regroups instantly — switching to "Spending" recomputes each header's total to show that day's outflow rather than a stale mixed net. Amounts go through Intl.NumberFormat for correct currency formatting, and each day header uses position: sticky so the date pins to the top of the scroll container as you move through it.
Best for: fintech apps, billing histories, expense trackers, and any admin screen that lists dated money movements. Tip: let Intl.NumberFormat handle the currency rather than string-concatenating a symbol — it gets separators, decimal places, and symbol placement right for every locale you'll ever ship to.
Grab the code: Transaction List
6. Kanban Board
Three columns, draggable cards, live count badges in each column header — the full To Do / In Progress / Done board with no library behind it.
How it works: every card is draggable="true", dragstart stores the node being dragged, and each column body listens for dragover — where preventDefault() is mandatory, because without it the browser never fires a drop event at all. The drop handler simply appends the dragged element into the new column and recounts, so column badges are always derived from the DOM rather than tracked in a separate variable that can drift out of sync. The semi-transparent dragging state is applied via a setTimeout(0) so the drag ghost captures the card at full opacity.
Best for: task boards, hiring pipelines, CRM deal stages, editorial calendars — anywhere work moves through fixed stages. Tip: the DOM move is the easy half; the real work is persisting it. Fire your API call from the drop handler and update optimistically, so the card lands where the user dropped it instead of snapping back while a request is in flight.
Grab the code: Kanban Board
7. Week View Scheduler
A Google-Calendar-style week grid: five day columns over a time gutter, events positioned by their start time and duration, drag-to-reschedule across days with 30-minute snapping, and a red line marking the current time.
How it works: the whole component is one coordinate transform applied in both directions. Two CSS custom properties — the pixel height of an hour and the day's start hour — define the coordinate system, mirrored by matching JavaScript constants, so events stored as plain { day, start, dur } objects, with times as fractional hours, convert to pixel offsets by pure function, and a drag converts pixels back into a snapped time. Even the horizontal hour lines cost zero elements: a repeating-linear-gradient paints a 1px line every hour-height, which means the grid can never drift out of alignment with the events sitting on top of it.
Best for: booking systems, shift schedulers, meeting planners, and internal tools where a month grid doesn't give enough time resolution. Tip: keep the hour height and start hour as CSS variables when you adapt it — changing the visible day range or zoom level then becomes a two-value edit rather than a hunt through hard-coded pixel maths.
Grab the code: Week View Scheduler
8. Notification Bell
The header bell with an unread count badge, a dropdown panel listing recent notifications, per-item read state, mark-all-read, and click-outside-to-close.
How it works: the panel is always in the DOM and toggled with a class that transitions opacity and a small translateY — and critically, it sets pointer-events: none while closed, so the invisible panel can't swallow clicks meant for the page behind it. Unread items are driven entirely by a single class that controls both the dot indicator and the tinted row background, so marking one read is a class removal plus a badge recount rather than a re-render.
Best for: the top-right corner of any app header, paired with a full notification centre page for the complete history. Tip: cap the badge at "9+" and the panel at the most recent handful of items — a bell showing 247 unread is a number people learn to ignore, which defeats the entire point of the component.
Grab the code: Notification Bell
9. Quota Usage Meter
The plan-usage panel every usage-based product needs: a meter per resource — API calls, storage, seats — with tiered warning colours as each one approaches its cap, and an upgrade nudge that only appears when it's actually relevant.
How it works: every tracked resource is an object with a used value, a limit, a unit and an icon key, and the render pass turns that array into labelled meters — so adding a new tracked resource is a data edit, not new markup. The warning tier is computed from the percentage rather than stored: under 80% stays indigo, 80–99% turns amber and reads "running low", and 100% or over goes red with "Limit reached". The overall status badge then reflects whichever resource is in the worst state. Numbers format themselves intelligently, so "86,500 / 100,000" and "41.5 GB / 50 GB" both read naturally from the same code path.
Best for: billing and settings pages on API platforms, storage products, and any per-seat or metered SaaS. Tip: the amber tier is the whole feature — a meter that only turns red once the customer is already blocked has told them nothing they didn't discover from the error message.
Grab the code: Quota Usage Meter
10. System Status Dashboard Widget
A service-health widget with a row per service, a 30-bar histogram summarising the last 90 days of uptime, operational/degraded/outage badges, and an active incident callout with a pulsing live dot.
How it works: the uptime bars aren't hand-written markup — they're generated from a data object mapping each service to an array of 30 values between 0 and 1, where 1 is fully operational, 0 is an outage, and anything between represents degraded performance. That single number drives both the bar's height and its colour, which is why swapping in real uptime data from your monitoring API means replacing one array and nothing else. The incident box only renders when there's an active incident, so a healthy system shows a clean board.
Best for: public status pages, internal ops dashboards, and the service-health panel of an infrastructure product. Tip: show degraded as a distinct colour rather than folding it into "down" — most real incidents are partial, and a board that only knows green and red will either under-report a slowdown or panic everyone over one.
Grab the code: System Status Dashboard Widget
How to drop these into your project
Every snippet is framework-agnostic, so the workflow is the same wherever you're building:
- Open the snippet and hit View / Edit Code to see the HTML, CSS and JS in separate tabs.
- Paste the HTML into your markup, the CSS into your stylesheet, and the JS before your closing
</body>tag — none of these ten need a CDN script or a build step. - Prefer a component? Use the one-click export to React, Vue, Angular or Tailwind right from the snippet page.
- Find the demo data array near the top of the JS and replace it with your API response — most of these are built so that's the only change needed to go from mockup to working panel.
A few dashboard principles worth keeping
- Render from data, always. The snippets here that scale — the transaction list, the quota meter, the status widget — all share one shape: an array at the top, a render function underneath. Hand-written rows are fine for a demo and painful the day real data arrives.
- Derive state instead of tracking it. The kanban board counts cards by querying the DOM and the quota meter computes its warning tier from a percentage. Neither can go stale, because neither stores a second copy of something it can calculate.
- Don't reach for a library until the vanilla version actually breaks. Drag-and-drop reordering, a week calendar, and a working uptime chart are all here in a few dozen lines each. Add the dependency when you hit a real limitation, not on the assumption you will.
Final Thought
These ten cover a complete admin panel end to end — the shell to hold it, KPI cards up top, a rearrangeable widget grid, an activity timeline, a grouped money list, a task board, a scheduler, notifications, plan usage, and system health. Start with the Dashboard Layout as your frame and fill the main area with whichever of the rest match your product; for developer-facing tools, the API Key Manager and Todo Widget slot into the same grid, and a Bar Chart or Donut Chart covers the visualisations that go beside them — also dependency-free.
Preview any of them live, tweak the code, and export to your framework of choice in one click. Browse the full collection at FWD Tools UI Snippets — it's free and runs entirely in your browser.
