Why bookmarks rot
Everyone's bookmarks end up the same way: a bar full of favicons with no labels, folders you never open, and a long tail of links that quietly stopped working years ago.
The problem is not storage. Every browser stores bookmarks perfectly well. The problem is that a bookmark collection is write-only: you add to it constantly, you search it almost never, and nothing in the system ever tells you a link has gone. A site that now redirects to a parked page full of ads looks, to your bookmark bar, exactly like the site you saved.
Hosted tools solve the organising part, but they ask for an account and a copy of your links on somebody else's server. That trade never sat right for something as personal, and as boring, as a list of URLs.
My bookmark bar had become a graveyard, so I built a self-hosted dashboard that tells me which links are already dead.
nextDash starts from that diagnosis: a dashboard you actually open, driven entirely from the keyboard so that using it costs nothing, with a health view that treats link rot as a subject in its own right rather than an afterthought.
What nextDash is, in one minute
Seven things it does that a bookmark bar does not. Everything else in this guide is detail hanging off these.
Pages, categories
Unlimited pages holding categories that hold bookmarks. Jump with 1-9.
Every keystroke
j/k move, Enter opens, a shortcut opens a site the moment you finish typing it.
Six ways to search
> / @ : ? * - plus your browser's own address bar, since v1.4.0.
Inbox & sources
Paste, extension, share sheet - or a Source that polls GitHub, Raindrop, HN, YouTube or Mastodon for you.
Health & uptime
Per-bookmark checking, 30 days of history, drift detection, downtime alerts with action buttons.
Widgets
A block on a page can hold a health board, an uptime chart or your inbox count instead of links.
Plain files
JSON in a folder you chose. One ZIP holds everything, your whole data dir since v1.4.0.
Is this for you?
Worth being honest about before you spend an evening on it. nextDash is opinionated, and the opinions rule some people out.
You will probably love it if...
- You already self-host something - a NAS, a VPS, a Raspberry Pi, a Docker host.
- You reach for the keyboard first and resent tools that make you point at things.
- Your bookmarks number in the hundreds or thousands and you have lost track of them.
- You want a start page that is also a dashboard for your own services - now with widgets for that.
- You care that your reading list is not somebody else's dataset.
- You have been burned by a service shutting down and taking your saved links with it.
You should look elsewhere if...
- You need user accounts and permissions. There are none, by design.
- You want to expose it publicly. The README is blunt: do not expose nextDash directly to the public internet.
- You want a read-later app that stores article text. Local copies (v1.4.0) are a safety net, not a reading queue.
- You want a feed reader. Fresh counts new entries; it does not show them.
- You want a hosted service with an app store listing and a support desk.
Running in two minutes
One container, one folder, one port. No database to provision, no migration to run, no account to create.
services:
nextDash:
image: ghcr.io/jordibrouwer/nextdash:latest
container_name: nextDash
ports:
- "8080:8080"
volumes:
- ./data:/app/data
environment:
- PORT=8080
# Optional on LAN/VPS - require X-NextDash-Token on destructive API calls:
# - NEXTDASH_WRITE_TOKEN=change-me-to-a-long-random-string
restart: unless-stopped
Bring it up and open it
docker compose up -d, then http://localhost:8080. No setup wizard, no login. A quick-start card greets a brand-new install; the tour is always available again from Config -> Help.
Bring in what you already have
Export bookmarks from Chrome, Firefox or Edge as HTML - or, new in v1.4.0, from Pocket, Pinboard, Raindrop, linkding, Shiori, Linkwarden or Karakeep, since they all export the same format. Folders become categories; tags, notes and the saved date all survive the trip.
Learn three keys
> to search, : for commands, ! for the cheat sheet. Everything else can wait.
Prefer no Docker?
A single Go binary with two dependencies - gorilla/mux for routing, golang.org/x/net for the rest. go build -o nextDash && ./nextDash is the whole build (Go 1.24). Data goes to ./data unless NEXTDASH_DATA_DIR says otherwise.
Before you go beyond localhost
There are no user accounts. Anyone who can reach the URL can read and change everything. Set NEXTDASH_WRITE_TOKEN and put it behind Tailscale or an authenticating proxy. Section 16 covers this properly.
The mental model
Three levels of structure, five views. Once these click, the rest of the app is discoverable.
page a tab across the top - "main", "work", "media". Keys 1-9.
└─ category a column heading - "vps", "tools", "reading". Collapsible, sortable.
└─ bookmark a row - name, URL, favicon, shortcut, tags, note, health status.
└─ widget since v1.4.0 - a block among the categories, one or two columns wide.
A bookmark belongs to exactly one category on exactly one page. Everything else - tags, smart collections, search filters, the inbox - is a view over that structure rather than a second hierarchy. Widgets share the same ordering list as categories, so there is one answer to where anything sits on a page, not two lists that can disagree.
| View | How to get there | What it is for |
|---|---|---|
| Dashboard | Esc | The grid of categories, bookmarks and widgets. Your start page. |
| Inbox | Shift+I · 0 | The holding area for links you saved before deciding where they belong. |
| Health | Shift+H | Everything that needs attention across all pages. |
| Search | > | Since v1.4.0 has its own address (#search?q=...), so it can be bookmarked or shared like any other view. |
| Config | Shift+S · < | Nine sections, each deep-linkable - including Sources and Widgets. |
A detail that tells you a lot about the project
Reopen config within five minutes and it returns to the exact section and sub-tab you left. After that it starts on Overview, because by then you have probably come back for something else.
Everything is a keystroke
164 shortcuts across a dozen groups - but you need about ten of them to be faster than you were before.
There is one rule holding the whole scheme together: every action on a bookmark is Shift plus a letter. Shift+E edits, Shift+V previews, Shift+L shares, Shift+S always opens config. Bare letters act on the first press. k and j move the highlight.
The first ten
| Key | What it does |
|---|---|
| j k ← → | Move the highlight around the grid. |
| Enter | Open the highlighted bookmark. Ctrl/Cmd+Enter opens it in a new tab. |
| 1-9 | Switch page. Shift+Left/Right cycles, comma shows an overview with counts. |
| > | Search. Start typing; Enter opens the top result. |
| : | Command palette - five collapsible groups, recent commands at the top. |
| & | Quick add. Type name | url | shortcut on one line and it is saved. |
| Ctrl+V | Paste a URL anywhere on the dashboard - pre-fills the new-bookmark form, or goes to the Inbox. |
| Shift+E | Inline-edit the highlighted bookmark. Ctrl+Enter saves, Esc cancels. |
| Shift+H | Health view. Shift+I for the Inbox, Shift+S for config. |
| ! / F1 | The searchable cheat sheet. Everything else is in there. |
Shortcuts that open sites
Give a bookmark a shortcut - GITHU, JELLY, TOWER - and typing it on the dashboard opens the site. No search box, no Enter. The project's own note: "a shortcut that needs Enter to finish is not much of a shortcut."
There is a real collision problem here, and nextDash handles it honestly. On an install with 200 shortcuts, eight of thirteen everyday words got swallowed mid-word by instant opening. So there are three modes under Config -> Behavior -> Search: open instantly (the default), open after a short pause, or require Enter. The default was changed to require Enter in one release and changed back in the next - "making Enter the default treated a rare collision as the normal case."
Overlays are properly modal
While search, the cheat sheet, quick-add or an inline edit is open, keyboard focus stays inside that overlay and the grid behind it is inert, not merely dimmed. That is the difference between a keyboard UI and a mouse UI with hotkeys bolted on.
Search, commands and finders
Six entry points, one bar. The key you press decides what the bar searches.
| Key | Mode | What it searches |
|---|---|---|
| > | Search | This page. Recent queries and saved searches appear as chips. |
| / | Fuzzy search | Ranked prefix -> word-boundary -> substring. Also matches URL domain, tags and note text. |
| @ | Global search | Every page at once; each result shows which page it lives on. |
| : | Command palette | Five collapsible groups - Bookmarks, Search & navigate, Look & layout, Smart collections, Settings & tools. |
| ? | Finders | Your own web searches - "?g rate limiting" searches Google. |
| * | Recent | The bookmarks you opened most recently. |
The filter syntax
Typed straight into the search bar, with autocomplete after each prefix. A leading minus excludes instead of selects, so "tag:dev -status:pinned" is "dev links I have not pinned."
Your browser's address bar is a search box - v1.4.0
Type the keyword, Tab, a term, Enter, and you land in your bookmarks with the results already on screen. No extension, no dashboard to open first - your browser offers this after one visit. It works because a search now has an address of its own (#search?q=...), so it can be bookmarked or shared like any other view.
Getting links in - by hand, and on their own
Saving has to be cheaper than not saving. Eight manual ways in, and - new in v1.4.0 - sources that keep bringing links in without you asking.
By hand
Quick add & paste
& takes name | url | shortcut. Ctrl+V pastes a URL anywhere on the grid.
Browser extension
Pick page, category, tags and note - or save with your last-used defaults.
Bookmarklet
Built for you under Config -> Help -> Inbox, token filled in. Works in Safari, Firefox and mobile browsers.
Share sheet
Install nextDash as an app and it appears in your phone's share sheet. An Apple Shortcut covers iOS Safari.
Raycast, Alfred, Ulauncher
Type a URL, or save the front browser tab.
One shell line
./shell/nextdash-add "https://..." "A title", or GET /add?url=...&title=... directly.
The whole integration contract is one route
Every one of those tools talks to GET /add?url=...&title=.... Two environment variables configure them: NEXTDASH_URL and NEXTDASH_TOKEN - give it NEXTDASH_CAPTURE_TOKEN, which opens capture and nothing else. In the project's own words: "anything that can open a URL or run curl is an integration."
On their own - Sources - v1.4.0
Config -> Data & backups -> Sources is for the places bookmarks keep arriving from, as opposed to the import buttons above, which read a file once. A source remembers what it already brought in and previews what it would write before writing it.
Need a token
GitHub stars and Raindrop.io.
Need nothing at all
Hacker News, YouTube and Mastodon - type a username or channel and that is the whole setup.
Import a browser's own bookmark file and - since it is the format Pocket, Pinboard, Raindrop, linkding, Shiori, Linkwarden and Karakeep all export - those come along for free. Export bookmarks (HTML) sits beside the CSV pair, and reads back into any browser.
What happens when you save something twice
Saving a URL already on the same page is refused. A copy on another page becomes a question instead: nextDash names the page and category it is already filed under, offers to open it, and "Save anyway" keeps the second copy - the add form, quick add, the extension and every Source all ask it the same way.
The Inbox
A holding area for links worth keeping before you know where they belong. The point is that deciding later is a legitimate answer.
Shift+I or 0 opens it. Filter All / Unread / Snoozed / With note, search, and sort - the default is oldest first: "oldest-first is how a backlog actually clears, since the links you have been avoiding are at the bottom."
Snooze z
Three hours, tomorrow, the weekend, next week, or a date of your own. Left out of every count except Snoozed.
Promote p
Opens the full bookmark form pre-filled. The inbox entry disappears once the bookmark is saved - not before.
Triage t
One link at a time: j/k move, o open, p promote, r keep, d delete, Esc leave.
Import / export
CSV or JSON, both directions. Import skips duplicates and reports what did not fit.
A backlog you can actually clear - v1.4.2
Triage used to hand you everything the filter showed, including what you had already read, and looped silently back to the start instead of ending. It now walks only the unread, closes with "that is the lot" once you have, and promoting a link no longer kicks you out of triage - so clearing forty links is forty presses of p, not forty separate trips back in.
Every count follows the active filter, and "Mark all read" honestly renames itself to "Mark shown read" when the view is narrowed.
Health: link rot as its own subject
This is the part no other bookmark manager has, and the reason nextDash was built.
Three levels of checking
| Mode | What it does |
|---|---|
| Off | Never checked. The right answer for most bookmarks. |
| Periodic | Checked in the background on the dashboard's own schedule. |
| Monitor | Checked on its own interval (5 minutes to 24 hours, default 15) with 30 days of history behind it. |
What it can detect
Reachability
Status and ping time, with named causes: DNS, timeout, refused, TLS, redirect or content.
Expectations
Text a page must contain, and which status codes count as healthy - "a site that answers 200 while showing 'Database connection failed' is up by every ordinary measure."
A bot check is not a dead link - v1.4.0
A site asking "are you a robot" used to be counted as gone. Only answers that actually say the page or host no longer exists count now; the rest read as unknown.
Drift
A page can answer 200 forever while stopping being the page you saved. Opt in and every check compares against a recorded baseline.
Certificates
Every monitored HTTPS check already completes a TLS handshake, so expiry costs nothing extra. Warnings at 30, 7 and 3 days.
Maintenance windows
Failures inside a scheduled window raise no alert and do not count against uptime.
Checking a service you have to be signed in to - v1.4.0
A self-hosted service bookmarked at its web interface used to answer "not signed in" to an anonymous check, so the row read broken while the service was fine. Store the sign-in once under Config -> Data & backups -> Sources -> Health sign-ins and point any number of bookmarks at it. The secret stays out of your backups unless you ask for it, and is dropped at the boundary if the service redirects the check elsewhere - the check goes on anonymously rather than handing your credential to a third-party address.
Uptime that does not flatter itself
Uptime pools individual checks rather than averaging per-monitor percentages. Every percentage carries the number of checks behind it: "100% from three checks is a weaker claim than 100% from three hundred." Days you did not open the dashboard leave a gap rather than a straight line through them.
Getting told
A downtime alert fires after N consecutive failures (default 3) and again on recovery.
Buttons on a downtime alert - v1.4.0
An alert reaching your phone through ntfy now carries Open link and Health buttons, so you can act on it without finding a laptop. Give nextDash its own address under Config -> Behavior -> Status -> Downtime alerts for the second button to work.
Tell it to leave one alone - v1.4.2
A bookmark you have already looked at and judged - yes it is stale, leave it - used to raise the same flag on every single check. Press n or z on a row, or use the row menu, and that one condition is set aside; the bookmark keeps being checked, only that flag stops firing. An Ignored filter lists everything you have put aside, and one click brings a bookmark back.
Working the list
- Ten links, two minutes - a corner card names what is waiting and runs "Work through" over the worst ten.
- The rot report - sums up what has gone or moved, readable grouped by site.
- Repair, not just diagnosis - follow redirects in one action after a domain move, or point a dead link at its last Web Archive capture.
Widgets: the dashboard holds more than links now
The largest new feature in v1.4.0. A block on a page can now hold something other than links.
A widget sits among your categories, is dragged into place like one, and can be one or two columns wide. It shares the same ordering list as categories, so there is one answer to where anything sits on the page. Add, name and arrange them under Config -> Widgets, which grew out of a list it started in under Pages & tags and now has its own place in the rail under Data & backups.
Twenty built-in tiles, plus one you build yourself
Grouped in the catalog by the question each one answers.
Are the links still good?
| Widget | Reads |
|---|---|
| Health | The figures the health view reports: broken, down, changed, fine. Click a figure to open that filter. |
| Uptime | Your monitored bookmarks, worst first, with a heartbeat bar per row. |
| Certificates | Certificates about to expire, grouped by host rather than by bookmark. |
| Health trend | Broken links over time as a line, because the direction is what a single number cannot show. |
What is arriving?
| Widget | Reads |
|---|---|
| Inbox | How much is waiting to be filed, and how long the oldest has waited. |
| Feeds | Feeds with new items, and the ones that stopped after repeated failures. |
| Sources | What each import last did, so a failed import is not only visible in config. |
What needs tidying?
| Widget | Reads |
|---|---|
| Neglected | Bookmarks you saved and have not opened, oldest first. |
| Blind spots | Never checked, checked long ago, or not watched at all. |
| Duplicates | The same address stored more than once, and how many copies could go. |
| Archive | How many bookmarks have a copy kept, and which broken ones have none. |
| Trash | What is waiting there, and when retention removes it. |
| Backups | How old the newest automatic backup is, and whether the last run failed. |
How is this machine doing? - v1.4.8
The only four that read something outside nextDash, and the only ones that need setting up - a mounted /proc, a named disk, or a read-only Docker socket, depending which you add.
| Widget | Reads |
|---|---|
| Processor | How hard the processor is working, and whether work is queueing up behind it. |
| Memory | How much memory is really in use, against the total, with the file cache counted as the spare room it is. |
| Disks | How full each disk is, and how much room is actually left on it. |
| Containers | How many containers run, how many do not, and which have a failing healthcheck. |
What's happening around you? - v1.7.0 / v1.7.1
| Widget | Reads |
|---|---|
| Weather | Current conditions beside a forecast, for the location the header already reads. |
| Calendar | What is coming up, from the ICS feed set in Behavior -> Date & weather. |
| RSS | The latest articles from the feeds you give it - headlines, with the whole entry on hover. |
Custom
The escape hatch, for a service that is not in the list: point it at an address that answers with JSON, name the fields, and it draws them - with 28 self-hosted services already filled in, from Sonarr and Plex to Pi-hole, Proxmox and Home Assistant. Can use the same stored sign-in as a health check, so no key ever reaches your browser.
Every widget has its own settings - which page it counts, how many rows, what it is called, how wide. A tile that leaves rows out now says how many, so five of twelve no longer looks like five of five. A figure on a tile opens the rows behind it, and a tile redraws from fresh data the moment its settings change.
Widgets you can operate - v1.4.2
Right-click a widget's title for rename, one or two columns, fold, settings and close - close means disable, not delete, so the widget and its settings survive being put away. Arrow keys step through its rows, Enter opens the one under the cursor, and every menu action has a key of its own.
The Custom tile keeps itself current - v1.4.2
It now has a timer per widget instead of one shared tick, matched to what it is reading - every 60 seconds for a download client, every five minutes for a queue count, hourly for Speedtest Tracker. A Refresh now entry in its menu forces an update on the spot, and a hidden tab asks nothing until you come back.
Keeping a copy of a page
Everything else in the health view is diagnosis - it tells you a link is dead and offers whatever copy somebody else happened to take. For a page nobody else bookmarked, there usually is none.
Ask the Web Archive
Keep a copy the day you save a link. Switch it on under Config -> Data & backups -> Sources, with an archive.org key pair and a one-page test capture to prove them.
Keep a copy on your own disk
Local copies saves a whole page - text, styling and images - as one file, through monolith, so it stays readable even if the site and the Web Archive are both gone.
A tab for what you have saved
Config -> Bookmarks -> Local copies lists them grouped by the bookmark they belong to, since the question is almost always "what do I have of this page".
Local copies are, by far, the largest single thing a backup can carry - Section 17 covers how that stays opt-in.
Collections, tags and Fresh
Three ways the dashboard reorganises itself around what you actually do, without you filing anything.
Today (your keyword sets), Recently opened, Most used, Stale, Recently added (off by default), Fresh (bookmarks whose site published something new), one collection per tag, and your own rules on category, tag, page, status, pinned, untagged, or days since last opened.
Fresh
Switch it on and nextDash reads the head of every page you have saved, notes any RSS or Atom feed advertised there, and polls what it found hourly. "Not a feed reader - no articles are stored, only how many entries are newer than your last visit, because otherwise this is a second product rather than a five-hundred-line feature."
Tags
Shift+T for a quick-tag popover, / for the word cloud, t to filter the grid to a bookmark's own tag.
Cards that say more - v1.4.0
A preview card now shows who published a page, who wrote it and when, alongside the title and image it already had. For video providers, the card includes a player you can start without leaving the dashboard.
Make it look like yours
This is a page you look at every day. nextDash ships 114 built-in theme families - 228 variants counting light and dark - and a colour editor with contrast warnings.
Themes
114 built-in families, each with a dark and light variant - 228 in total: Absinthe, Andromeda Drift, Arctic Cyan, Aurora Glass, Bamboo Panda, Bio Abyss, Cerulean Skylark, Candy Pop and dozens more, each tagged by mood - neutral, cool, warm, high contrast, vivid. Random theme picks a different one on every refresh, or every view change.
Custom colours
A full editor at #config/colors: edit the packaged families, build your own, export and import them, see contrast warnings live.
Layout presets
Seven of them - Default, Compact, Cards, Terminal-ish, Masonry, Detailed List and Launcher (large favicon tiles).
Fonts
Seven UI presets: Source Code Pro (the default), JetBrains Mono, IBM Plex Mono, Inter, IBM Plex Sans, DM Sans, System UI.
The button bar
Five positions, per-button show/hide. Hiding a button leaves its shortcut working. Since v1.4.0, a new install starts with the bar in the corner rather than centred; anyone who has already chosen a position keeps it.
Branding & PWA
A custom title and favicon apply to the browser tab, the web app manifest, and the installed app's name and icon on your home screen.
Two hundred themes that no longer look alike underneath - v1.4.2
The backdrop pattern used to default to dots, and only a handful of themes said otherwise - so 200 of the 214 variants painted the same texture under different colours. Every family now names its own: hatch for paper and earth tones, grid for circuitry and steel, lines for screens and neon, dots for mist and water. Your own choice under Config -> Appearance -> Backdrop still overrides any theme.
Config, and not overwhelming you with it
Nine sections - Overview, Pages & tags, Bookmarks, Appearance, Behavior, Data & backups, Statistics, Help and About - each deep-linkable, with an At a glance panel showing how many settings differ from default, an Only changed filter above every tab, and Ctrl/Cmd+Shift+K to find a setting by name or by its current value.
Two smaller habits landed in v1.4.0: panels fold shut now and remember which were open, and slow actions show progress - refreshing every link preview is one request per bookmark, and it used to just sit there looking hung.
Telling other programs
Everything up to here sends a link in. Since v1.4.0 nextDash can also push out, and let something else ask it questions.
Outgoing webhooks
Config -> Data & backups -> Webhooks. Five events: a bookmark added, changed or removed, and a monitored bookmark going down or coming back. A receiver can subscribe to all of them or to a few.
POST /your-endpoint
content-type: application/json
webhook-id: msg_2b7f...
webhook-timestamp: 1756253400
webhook-signature: v1,K5s0...
{"type":"bookmark.added","timestamp":"2026-08-27T09:30:00Z","data":{...}}
Signed with the Standard Webhooks scheme, so a receiver that already verifies those needs no special case. The id and timestamp are signed rather than merely sent: the id is how a receiver recognises a redelivery it already acted on, the timestamp is how it refuses one replayed a day later. The key is shown once, at save time. A failed delivery is retried twice with a growing gap; a 4xx is not retried. Endpoints are checked at save time and again at delivery - a receiver that answers "go and look over there" is not followed.
An assistant that can search your bookmarks
One MCP endpoint at POST /mcp, JSON-RPC 2.0, four tools: search the collection, look one bookmark up, list the tags in use, add a bookmark. Off until you switch it on - "it answers questions about every bookmark in the install, which is not something to add to a default install quietly." Origin is checked on every request, and adding a bookmark through it goes through the same handler the dashboard itself posts to - duplicate checks, URL validation and outgoing webhooks all still apply.
A note on trust
Your bookmarks are a map of what you care about. That map should live on your own disk - and the way a project handles that question tells you most of what you need to know about it.
Read this before you put it on the internet
nextDash is built for personal or small-team use on a trusted network. There are no user accounts. Do not expose nextDash directly to the public internet.
Three ways to run it safely
Private overlay network
Tailscale or another mesh VPN, so nextDash never gets a public listener at all.
Reverse proxy with auth
Traefik, Caddy or nginx, with basic auth, OAuth2 Proxy or SSO in front.
Local only
Bind to 127.0.0.1 and reach it over SSH port forwarding.
The API now answers this dashboard, not every page on the internet - v1.4.0
Before 1.4, cross-origin responses answered Access-Control-Allow-Origin: * - any site open in a tab could read your bookmarks from a nextDash whose address it could guess, since the read routes need no token. The default is now same-origin. The browser extension is unaffected: a Manifest V3 extension with host permissions gets cross-origin access from the browser itself. Set NEXTDASH_CORS_ORIGINS to an explicit allowlist for other tools, or =* to restore the old behaviour if you understand what you are opting back into.
Two tokens, two jobs
NEXTDASH_WRITE_TOKEN
Every destructive endpoint requires X-NextDash-Token. The dashboard injects it automatically in a browser.
NEXTDASH_CAPTURE_TOKEN
The two capture routes cannot send a header - "a phone's share sheet and a javascript: bookmark have no way to set one." This weaker token opens capture and nothing else.
Other safety details, several new in v1.4.0
- A stored sign-in stays on the service it was stored for. A watched host that redirected a health check elsewhere used to send the credential wherever it was told; dropped at the boundary now.
- A custom widget's address and key stay on the server. They used to come back to the browser with the rest of the page's layout.
- A webhook cannot be talked into delivering somewhere else. Checked at save time, checked again at delivery.
- SSRF defence at dial time for preview, ping, icon fetch and the health check-a-URL box, with IP pinning for ~2 minutes to close the DNS-rebinding window.
- The data directory is not browsable - /data/ publishes data/icons/ and an uploaded favicon or font, and nothing else.
Analytics, and why they are off
Opt-in, off until you turn them on. When off, the tracker script is not emitted into the page at all - never downloaded, no request leaves your machine. When on, no bookmark names, URLs or search queries are ever sent; every number is rounded into a band (500+, never 1274). DISABLE_TELEMETRY=true removes the choice from users entirely, server-wide.
Your data, and getting it back out
There is no database. Your entire installation is a folder of JSON files you can read in a text editor, copy to a USB stick, or put in git.
data/
├── bookmarks-1.json one file per page: the page, its categories, its bookmarks
├── settings.json every setting, saved searches, collections, theme choice
├── colors.json your custom themes
├── finders.json your web search providers
├── inbox.json captured links waiting for triage
├── trash.json deleted bookmarks, kept 30 days
├── health-history.json uptime samples - 30 days raw, 90 days of daily rollups
├── health-trend.json one point per day, 90 days
├── webhooks.json endpoint URLs and signing keys, mode 0600 - v1.4.0
├── icons/ fetched and uploaded favicons, content-named
├── local-copies/ saved page snapshots - v1.4.0
└── auto-backups/ rotating ZIPs, 3 by default (1-50)
A backup now carries your whole data directory - v1.4.0
Files used to be left out one at a time, each for a reason that held on its own - until together they made a restore an install that had lost its history and had to earn it back over weeks. Uptime alone needs thirty days before its chart means anything. Two switches under "What a backup carries" let you leave out the two largest or most sensitive things: local copies (by far the largest single thing in a backup) and stored tokens - including them means a restore needs nothing typed in again, and that the backup file is itself a secret.
Exports for every part
All bookmarks as CSV or, new in v1.4.0, as browser-compatible HTML that reads back into any browser. Inbox as CSV or JSON. Health state as CSV, and the individual up/down checks behind an uptime percentage as their own CSV.
Trash, for thirty days
Deleted bookmarks stay recoverable for 30 days with search and bulk restore.
Configuration reference
Everything that has to be decided before startup is an environment variable. Sources, widgets, webhooks and MCP all live entirely in the UI.
| Variable | Default | What it does |
|---|---|---|
PORT | 8080 | HTTP listen port, validated 1-65535 at boot. |
NEXTDASH_DATA_DIR | ./data | Where pages, bookmarks, settings and uploads live. |
NEXTDASH_WRITE_TOKEN | unset | Require X-NextDash-Token on write and destructive APIs. |
NEXTDASH_CAPTURE_TOKEN | unset | Second, weaker token for /add and /share only. |
NEXTDASH_CORS_ORIGINS | unset (same-origin) | Extra Origin allowlist. Extension origins always allowed; * restores the pre-1.4 open default. |
NEXTDASH_ACTIVITY_LOG | mutate,status | off, mutate, status, open, security. |
NEXTDASH_ACTIVITY_LOG_PERSIST | off | 1 rotates activity.log in the data dir. |
NEXTDASH_OUTBOUND_REQUESTS_PER_MIN | 120 | Rate limit for all server-side outbound fetches. |
NEXTDASH_SSRF_API_RATE_PER_MIN | 60 | Rate limit for preview, ping and icon APIs. |
NEXTDASH_CSP | on | off disables Content-Security-Policy headers. |
NEXTDASH_AUTO_BACKUP_KEEP | 3 | How many automatic backups to keep (1-50). |
DISABLE_TELEMETRY | unset | Server-wide analytics kill switch. |
DISABLE_NEWS_FEED | unset | Server-wide switch for the nextdash.cc news feed. |
A recommended LAN or VPS block
environment:
- PORT=8080
- NEXTDASH_WRITE_TOKEN=change-me-to-a-long-random-string
- NEXTDASH_CORS_ORIGINS=https://dash.example.com,chrome-extension://your-extension-id
- NEXTDASH_ACTIVITY_LOG=mutate,status,security
- NEXTDASH_ACTIVITY_LOG_PERSIST=1
What nextDash deliberately is not
A short list, because knowing where a tool stops is more useful than another page of features.
- Not multi-user. No accounts, no roles, no permissions. Authentication is somebody else's job.
- Not a cloud service. No sync server, no hosted tier, no account to lose access to.
- Not a feed reader. Fresh counts what is new; it does not store or show articles.
- Not a read-later app, even with local copies - a snapshot for when the original disappears, not a reading queue.
- Not a general automation platform. Webhooks and MCP tell other tools what changed and answer questions about your bookmarks - not a workflow engine.
- Not browsable data. The data directory serves icons and an uploaded font, and nothing else.
- Not precious about its own decisions. The Enter-to-open default was introduced in one release and reverted in the next, with the measurement that justified it printed in the changelog.
Where to go next
Roughly three days from installed to habitual.
Day one - get it populated
Import your bookmarks (browser export, or a Source if one of the five fits), delete what you have not opened in two years, and put your ten most-used sites on page one with shortcuts.
Day two - set it as your home page
Install it as an app on your phone, add the browser extension, and set your browser's address-bar keyword so a search is one keystroke away.
Day three - switch on health, and try a widget
Set your most important bookmarks to Periodic, your self-hosted services to Monitor, and drop a Health or Uptime widget on your main page.
The cheat sheet
164 shortcuts, searchable in-app with ! or F1, and printable as a PDF from the repository.
Standing on shoulders. nextDash is based on ThinkDashboard by MatiasDesuu, and released under the MIT licence. Written in Go 1.24 with two dependencies, gorilla/mux and golang.org/x/net.