A real open-source product, not a mock
Shlink, read from its code
Shlink is a self-hosted URL shortener. Nobody wrote this list of features. It was read out of Shlink's own source at one commit, and every entry points back at the line it came from.
What the map holds, as of 2026-09-24
And these are zero, drawn as zero: 0 scenarios, 0 tests, 0 merge requests, 0 flows. Shlink has been read, not crawled and not run — so the sheet below carries no status colour, because there is no status to report yet. That is the honest state of this demo, and it is why nothing here is green.
One sheet, every feature
The whole product, at once
One band per module, one chip per feature. Bands are ordered by how many features they hold — in the live app they are ordered by meaning (scenarios, open questions, what a request touched), and none of those exist here yet.
Where each one came from
Every feature, anchored to a line
A name with nothing behind it is a guess. Each row below carries the HTTP operation the feature was read from and the exact file and line it was found on, at commit 4a8fee47d48b. Open a name for every citation it has, the adapter that found it, and what is empty under it. This page has a markdown twin at /map/shlink.md, and so does every one of those 20 pages.
Visit 6
| Orphan visits | DELETE /rest/v{version:1|2|3}/visits/orphan | module/Rest/src/Action/Visit/DeleteOrphanVisitsAction.php:16 |
|---|---|---|
| Non-orphan visits | GET /rest/v{version:1|2|3}/visits/non-orphan | module/Rest/src/Action/Visit/NonOrphanVisitsAction.php:14 |
| Overall visit stats | GET /rest/v{version:1|2|3}/visits | module/Rest/src/Action/Visit/GlobalVisitsAction.php:16 |
| Domain visit stats | GET /rest/v{version:1|2|3}/domains/{domain}/visits | module/Rest/src/Action/Visit/DomainVisitsAction.php:17 |
| Short URL visit stats | GET /rest/v{version:1|2|3}/short-urls/{shortCode}/visits | module/Rest/src/Action/Visit/ShortUrlVisitsAction.php:15 |
| Tag visit stats | GET /rest/v{version:1|2|3}/tags/{tag}/visits | module/Rest/src/Action/Visit/TagVisitsAction.php:14 |
ShortUrl 5
| Delete short URL | DELETE /rest/v{version:1|2|3}/short-urls/{shortCode} | module/Rest/src/Action/ShortUrl/DeleteShortUrlAction.php:17 |
|---|---|---|
| Delete short URL visits | DELETE /rest/v{version:1|2|3}/short-urls/{shortCode}/visits | module/Rest/src/Action/ShortUrl/DeleteShortUrlVisitsAction.php:17 |
| Edit short URL | PATCH /rest/v{version:1|2|3}/short-urls/{shortCode} | module/Rest/src/Action/ShortUrl/EditShortUrlAction.php:20 |
| List short URLs | GET /rest/v{version:1|2|3}/short-urls | module/Rest/src/Action/ShortUrl/ListShortUrlsAction.php:20 |
| Shorten URL | POST /rest/v{version:1|2|3}/short-urls | module/Rest/src/Action/ShortUrl/CreateShortUrlAction.php:13 |
Core 2
| Redirect short URL | GET /{shortCode}/track | config/autoload/routes.config.php:88 |
|---|---|---|
| Robots.txt | GET /robots.txt | config/autoload/routes.config.php:80 |
Domain 2
| Domain redirects | PATCH /rest/v{version:1|2|3}/domains/redirects | module/Rest/src/Action/Domain/DomainRedirectsAction.php:18 |
|---|---|---|
| List domains | GET /rest/v{version:1|2|3}/domains | module/Rest/src/Action/Domain/ListDomainsAction.php:18 |
Rest 2
| Health check | GET /rest/v{version:1|2|3}/health | module/Rest/src/Action/HealthAction.php:20 |
|---|---|---|
| Real-time updates info | GET /rest/v{version:1|2|3}/mercure-info | module/Rest/src/Action/MercureInfoAction.php:18 |
Tag 2
| Manage tags | DELETE /rest/v{version:1|2|3}/tags | module/Rest/src/Action/Tag/DeleteTagsAction.php:16 |
|---|---|---|
| Tag stats | GET /rest/v{version:1|2|3}/tags/stats | module/Rest/src/Action/Tag/TagsStatsAction.php:18 |
RedirectRule 1
| Short URL redirect rules | GET /rest/v{version:1|2|3}/short-urls/{shortCode}/redirect-rules | module/Rest/src/Action/RedirectRule/ListRedirectRulesAction.php:18 |
|---|
So you can check it
Where these numbers come from
- Commit
- 4a8fee47d48bcb949d6a5729ef32994f1f41464e
- Read at
- 2026-09-24T00:15:47Z · store sequence 78
- Events hash
- 94dd0b7f8b14cfcc343621afa488b4c894c89e44920e5cd245e8617c2ea2e1c7
- View hash
- 2100871e52c9ef1eb925163f933ccf397c663b2ef7af46b66cdf42579202d6b3
- Events behind it
- candidate.extracted 28 · blob.seen 25 · feature.named 20 · admission.rejected 2 · spend.recorded 1 · judge.recorded 1
- Extractors
- mezzio.action_routes 25 · mezzio.config_routes 3
- Refused batches
- 2 — so 28 citations is what was admitted, not what was
attempted.
- endpoint_known: api operation matches no route-list candidate at its commit
- row_level_security: new row violates row-level security policy for table "events"
- Naming
- The 20 names are a model's, recorded as advice with its confidence on each. 1 call · anthropic/claude-sonnet-5 · 1508 tokens in, 859 out · $0.011606
- Grouping
- the founding candidate's component (candidate.extracted.component, invariant 26's module). The judge's module_overlay is 'Settings' for every feature in this store: the naming run was given the BookStack target config (its spend.recorded is titled 'auto-e2e init_naming bookstack'), so it answered in BookStack's module vocabulary. The API's own /spine still returns that one Settings band; this bundle does not.
- Repository
- https://github.com/shlinkio/shlink — declared when this bundle was exported, not a fact the store holds. The store carries the commit above and nothing else.
See it on a real product
A live walkthrough of the BookStack map first, then read-only access once invites exist.