Guides / checked on 28 Sep 2026
Feature inventory of a web app: what to list, with a template
A feature inventory is a list of everything a web app lets a person do, one row per feature, with where each feature lives in the code, what it is for and how far it has been checked. It is to an app’s behaviour what a content inventory is to a website’s pages: “a list of every piece of digital content you currently have”, with the characteristics of each (Kaley, NN/g, 2020 · UX research firm).
Tim Derzhavets · published 28 Sep 2026 · checked on 28 Sep 2026
Why list features at all #
In most teams I have worked with, nobody could say how many features the app had. The roadmap lists what is planned, the tracker lists what broke, and the code holds the rest. An inventory is the first place all of it is written down once, in words a person can approve.
It answers questions the other documents can’t:
- What exists? Before a redesign, a migration or a new hire, the list is the map of what must keep working.
- What is checked? A test suite says which code ran. The inventory says which features have a test that would fail if they broke (the guide to reviewing tests explains why that is the better question).
- What does a change touch? With routes on each row, a pull request’s changed files point to the features they reach.
- What is nobody using? A feature with no goal and no flow through it is worth a question.
The five columns #
Keep the inventory to five columns. Each one answers a question someone will ask, and each can be checked.
| Column | What to write | On BookStack |
|---|---|---|
| module | The part of the app it belongs to, as the code groups it | Api |
| feature | One thing a person can do, as a verb and an object | Delete an API token |
| routes | The URLs or requests that carry it, method first | GET /api-tokens/{userId}/{tokenId}/delete |
| goals | What a person gets done with it | Open the user api token (delete) |
| status | How far it is checked: found in the code, seen on a screen, tested, proven | proven by the wrong-user check |
A few rules keep the rows honest:
- One verb, one object per row. “Manage books” is five features: create, view, edit, move, delete. Split it until each row could have one test.
- Name features in the user’s words. “Delete an API token”, not
ApiTokenController@destroy. When you can’t name one yet, write its route and mark it unnamed; don’t guess. - Routes come from the code, not memory. Most web frameworks print a route list. Start there, and every route either belongs to a feature or is a question.
- Status is a fact, not a hope. “Tested” means a test exists that fails when the feature breaks. Anything weaker is “seen” or “found”.
- Date it. An inventory is true on the day it was read, at one commit. Write both at the top.
How to build one #
- Read the routes. Export the route list from the framework. Each route is a candidate feature.
- Group them into modules the way the code already does: controllers, folders, packages.
- Name each feature. Merge routes that are one action (the form and its submit), split routes that are several.
- Walk a running copy. Sign in, visit each screen and tick the features you can reach. What the code holds and no screen shows is either admin-only, unfinished or dead.
- Add the goals. For each feature, write what a person gets done with it. Features with no goal are the ones to ask about.
- Mark the status from your tests, using the checks in the tests guide.
- Have a person approve it. Someone who knows the product reads each row and keeps, renames or drops it. An inventory nobody approved is a draft.
Steps 1 to 5 are mechanical and slow by hand. They are the part featkpr does.
BookStack’s inventory, as an example #
featkpr read BookStack, the open-source wiki, from its code and a crawl of a running copy. Its records hold 298 features in 13 modules (20 Oct 2026). Some are named in words; the rest are still shown by their route, waiting for a name.
BookStack · featkpr's records, read 20 Oct 2026 · 298 features, 245 named in words
Features per module #
- Entities80
- Settings73
- Exports34
- Users27
- Activity25
- Access16
- Uploads16
- Permissions10
- Api7
- References4
- Sorting4
- Search1
- Theming1
How far each one is checked #
- 69 proven by the wrong-user check
- 2 a test written, not proven yet
- 166 a screen found by the crawl
- 61 found in the code only
The Api module, in the five columns #
| module | feature | routes | goals | status |
|---|---|---|---|---|
| Api | Create an API token | GET / | Open the user api token (create) | proven by the wrong-user check |
| Api | Delete an API token | GET / | Open the user api token (delete) | proven by the wrong-user check |
| Api | Edit an API token | GET / | Open the user api token (edit) | proven by the wrong-user check |
| Api | Grant access to the API | none linked yet | none linked yet | proven by the wrong-user check |
| Api | View API documentation | GET / | Open the api docs (display) | a screen found by the crawl |
| Api | DELETE / | DELETE / | Delete the api token | proven by the wrong-user check |
| Api | PUT / | PUT / | Update the api token | proven by the wrong-user check |
The Api rows show a step that is not finished yet. “Delete an API token” holds the confirmation screen, and the request that actually deletes is still its own unnamed row, DELETE /api-tokens/{userId}/{tokenId}, with the goal “Delete the api token”. Merging them is step 3 above, and it is a person’s call, so the inventory shows it as it stands.
The whole list is a download, one row per feature, with the five columns above:
- BookStack's feature inventory (CSV) 298 rows · 28 KB · from featkpr's records, read 20 Oct 2026
- Empty template (CSV) the header row only: module, feature, routes, goals, status · 1 KB
Both files are written at build time from the same records the library of features shows, so the download and the page never disagree. The template has the same header row, so a filled-in copy of your own app lines up with BookStack’s.
Mistakes that make an inventory useless #
Listing screens instead of features. One settings screen can hold twenty features, and one feature (“search”) can appear on every screen. List what a person can do, then note where.
Mixing in the roadmap. A planned feature is not in the app. Keep it off the inventory, or give it its own status so nobody counts it.
No owner, no date. Without a date nobody knows whether the list is stale; without an owner nobody fixes it. The status column rots first.
Writing it once. An inventory that is not re-read from the code drifts from the app with every release. Re-read the routes on each release, and diff the list.
Where featkpr fits #
featkpr builds this inventory for you: it reads the features of your web app from its code, checks them against the running screens, links each to its goals and flows, and asks a person to approve or deny each row. The map in the product tour shows the screens, and BookStack’s page shows the result on a real app.
Sources #
each read on 28 Sep 2026; the date is when it was published, the mark says what kind of source it is
- A. Kaley, Content Inventory and Auditing 101, Nielsen Norman Group, 27 Sep 2020: a content inventory is "a list of every piece of digital content you currently have", with characteristics of each piece.27 Sep 2020 · UX research firm, articlewww.nngroup.com/articles/content-audits/
How this guide was written and checked, and where its numbers come from: how we write and check. Found an error? Report a correction.
See featkpr map a real app #
Half an hour on BookStack, your questions first. Your own app comes after.