featkpr
Private demo

57 open-source web apps: how many screens, how many end-to-end spec files

14 of the 57 have no end-to-end spec file in their repository, and 32 of the 40 whose screens could be counted have fewer spec files than screens: the median is 0.25 spec files per screen, about one for every 4 screens.

Download CSVDownload JSONCite thisHow we counted

Spec files per screen, app by app #

Each row is one app with both counts: its end-to-end spec files divided by its screens, on a log scale. Left of the solid line, the app has fewer spec files than screens.

  1. Akaunting none0 / 121
  2. BookStack none0 / 93
  3. FreshRSS none0 / 63
  4. Hoppscotch none0 / 32
  5. Kanboard none0 / 102
  6. Kimai none0 / 48
  7. Medusa none0 / 186
  8. NocoDB none0 / 66
  9. Outline none0 / 32
  10. Plane none0 / 72
  11. Snipe-IT none0 / 154
  12. Weblate 0.0081 / 120
  13. Linkwarden 0.0281 / 36
  14. Mealie 0.0302 / 66
  15. Twenty 0.0489 / 186
  16. Wagtail 0.0488 / 165
  17. Redmine 0.1328 / 223
  18. Umami 0.148 / 59
  19. Supabase Studio 0.1529 / 190
  20. Paperless-ngx 0.245 / 21
  21. PostHog 0.2543 / 169
  22. Gitea 0.2730 / 111
  23. InvenTree 0.3026 / 87
  24. GLPI 0.34107 / 315
  25. Uptime Kuma 0.477 / 15
  26. Mastodon 0.50107 / 214
  27. Formbricks 0.6348 / 76
  28. Taiga 0.6547 / 72
  29. Cal.diy 0.6853 / 78
  30. Baserow 0.6937 / 54
  31. Keycloak 0.8681 / 94
  32. Immich 0.8849 / 56
  33. Documenso 1.15132 / 115
  34. Vikunja 1.2272 / 59
  35. Directus 1.3699 / 73
  36. Discourse 1.78295 / 166
  37. OpenProject 1.94787 / 406
  38. Grafana 2.37213 / 90
  39. n8n 4.66284 / 61
  40. Appsmith 31.8667 / 21
1 spec file per screen: 32 of 40 apps are left of it the median, 0.25 per screen no end-to-end spec file (11 here) the right column: spec files per screen, then spec files / screens

Not in the picture (17): the apps whose pages are declared in code or generated from records, so there is no page file to count. Their spec files are in the table. Of those, ERPNext, Firefly III, Sylius have no end-to-end spec file either.

Every app, every count #

All 57, with the repository, the commit or tag counted and the date. Sort by any column; the downloads hold the same rows with the rule behind each number.

A zero means the rule found no end-to-end spec file in the repository, not that the project is untested. Many projects test in other ways, and a count of spec files says nothing about a project's quality.

Every app counted, with its screens, API operations, end-to-end spec files, spec files per screen, and the commit or tag counted. Sorted by app name.
applicencescreensAPI opse2e spec filesper screencounted at (2026)
Akauntingaccounting · Laravel BSL-1.1 121 no spec 0 0 github.com/akaunting/akaunting 0c7792b2e, 27 Sep · script 28 Sep · correct this row
Appsmithinternal-tool builder · Java · React Apache-2.0 21 no spec 667 31.8 github.com/appsmithorg/appsmith c7e65f8f8, 28 Sep · script 28 Sep · correct this row
Baserowno-code database · Django · Nuxt MIT + premium 54 no spec 37 0.69 gitlab.com/baserow/baserow default branch · by hand 17 Sep · correct this row
BookStackwiki · PHP · Laravel MIT 93 77 0 0 codeberg.org/bookstack/bookstack v26.05.5, 14 Sep · by hand 17 Sep · correct this row
Cal.diyscheduling · Next.js MIT 78 121 53 0.68 github.com/calcom/cal.diy default branch · by hand 17 Sep · correct this row
Chatwootcustomer support · Rails · Vue MIT + enterprise no count 154 3 github.com/chatwoot/chatwoot default branch · by hand 17 Sep · correct this row
Directusdata platform · Node · Vue MSCL-1.0 (source-available) 73 136 99 1.36 github.com/directus/directus 1694b1904, 25 Sep · script 28 Sep · correct this row
Discourseforum · Rails · Ember GPL-2.0 166 no spec 295 1.78 github.com/discourse/discourse 3b6713ef7, 28 Sep · script 28 Sep · correct this row
Documensodocument signing · React Router 7 AGPL-3.0 + ee 115 no spec 132 1.15 github.com/documenso/documenso default branch · by hand 17 Sep · correct this row
ERPNextERP · Frappe (Python) GPL-3.0 no count no spec 0 github.com/frappe/erpnext 89f490f72, 28 Sep · script 28 Sep · correct this row
Firefly IIIpersonal finance · PHP AGPL-3.0 no count no spec 0 github.com/firefly-iii/firefly-iii default branch · by hand 17 Sep · correct this row
Formbrickssurveys · Next.js AGPL-3.0 + ee 76 72 48 0.63 github.com/formbricks/formbricks default branch · by hand 17 Sep · correct this row
FreshRSSfeed reader · PHP AGPL-3.0 63 no spec 0 0 github.com/FreshRSS/FreshRSS a8e5e6300, 28 Sep · script 28 Sep · correct this row
Ghostpublishing · Node · Ember/React MIT no count no spec 101 github.com/TryGhost/Ghost 7c3067680, 28 Sep · script 28 Sep · correct this row
Giteacode hosting · Go templates MIT 111 537 30 0.27 github.com/go-gitea/gitea fba8d7eac, 28 Sep · script 28 Sep · correct this row
GLPIIT service desk · PHP · Twig GPL-3.0 315 no spec 107 0.34 github.com/glpi-project/glpi af37be7a7, 28 Sep · script 28 Sep · correct this row
Grafanadashboards · Go · React AGPL-3.0 90 314 213 2.37 github.com/grafana/grafana 5f4490098, 28 Sep · script 28 Sep · correct this row
HoppscotchAPI client · Vue · NestJS MIT 32 no spec 0 0 github.com/hoppscotch/hoppscotch a9ffa29ce, 23 Sep · script 28 Sep · correct this row
Immichphotos · NestJS · SvelteKit AGPL-3.0 56 276 49 0.88 github.com/immich-app/immich default branch · by hand 17 Sep · correct this row
InvenTreeinventory · Django · React MIT 87 670 26 0.30 github.com/inventree/InvenTree default branch · by hand 17 Sep · correct this row
Kanboardkanban · PHP MIT 102 no spec 0 0 github.com/kanboard/kanboard cf53b5459, 11 Sep · script 28 Sep · correct this row
Keycloakidentity and access · Java · React Apache-2.0 94 no spec 81 0.86 github.com/keycloak/keycloak 9f8eb2d23, 28 Sep · script 28 Sep · correct this row
Kimaitime tracking · Symfony · Twig AGPL-3.0 48 no spec 0 0 github.com/kimai/kimai 8528bb174, 27 Sep · script 28 Sep · correct this row
Linkwardenbookmarks · Next.js AGPL-3.0 36 no spec 1 0.028 github.com/linkwarden/linkwarden 952ac4540, 9 Sep · script 28 Sep · correct this row
Mastodonsocial network · Rails · React AGPL-3.0 214 no spec 107 0.50 github.com/mastodon/mastodon 35c345010, 28 Sep · script 28 Sep · correct this row
Mattermostteam chat · Go · React Apache-2.0 + ee no count 605 996 github.com/mattermost/mattermost 05553d083, 28 Sep · script 28 Sep · correct this row
Mealierecipes · FastAPI · Nuxt AGPL-3.0 66 no spec 2 0.030 github.com/mealie-recipes/mealie 86aec702a, 28 Sep · script 28 Sep · correct this row
Medusacommerce · Node · React MIT + ee 186 486 0 0 github.com/medusajs/medusa default branch · by hand 17 Sep · correct this row
Metabaseanalytics · Clojure · React AGPL-3.0 + ee no count 637 427 github.com/metabase/metabase 1a0ff4340, 28 Sep · script 28 Sep · correct this row
n8nworkflow automation · Node · Vue Sustainable Use (fair-code) + ee 61 32 284 4.66 github.com/n8n-io/n8n 41dbfd987, 28 Sep · script 28 Sep · correct this row
Nextcloud serverfile sync and share · PHP · Vue AGPL-3.0 no count 301 102 github.com/nextcloud/server c41a9138d, 28 Sep · script 28 Sep · correct this row
NocoDBno-code database · Node · Nuxt Sustainable Use (fair-code) 66 278 0 0 github.com/nocodb/nocodb 8cfa45dcb, 28 Sep · script 28 Sep · correct this row
Odoobusiness suite · Python · OWL LGPL-3.0 no count no spec 525 github.com/odoo/odoo a240a91eb, 28 Sep · script 28 Sep · correct this row
OpenProjectproject management · Rails · Angular GPL-3.0 406 331 787 1.94 github.com/opf/openproject c0146dbdd, 28 Sep · script 28 Sep · correct this row
Outlineteam wiki · Node · React BSL-1.1 32 no spec 0 0 github.com/outline/outline 179d7dd7b, 27 Sep · script 28 Sep · correct this row
Paperless-ngxdocuments · Django · Angular GPL-3.0 21 no spec 5 0.24 github.com/paperless-ngx/paperless-ngx 88000aab4, 28 Sep · script 28 Sep · correct this row
Penpotdesign tool · Clojure MPL-2.0 no count no spec 65 github.com/penpot/penpot f9b8f1ba7, 28 Sep · script 28 Sep · correct this row
Planeproject tracking · Django · Next.js AGPL-3.0 72 no spec 0 0 github.com/makeplane/plane default branch · by hand 17 Sep · correct this row
Plausibleweb analytics · Elixir · React AGPL-3.0 no count no spec 12 github.com/plausible/analytics ee3a27bb3, 28 Sep · script 28 Sep · correct this row
PostHogproduct analytics · Django · React MIT + ee 169 no spec 43 0.25 github.com/PostHog/posthog cb4522375, 28 Sep · script 28 Sep · correct this row
Redmineproject tracking · Rails GPL-2.0+ 223 no spec 28 0.13 github.com/redmine/redmine c9008f4ce, 28 Sep · script 28 Sep · correct this row
Rocket.Chatteam chat · Meteor · React MIT + ee no count no spec 280 github.com/RocketChat/Rocket.Chat b149e10ee, 28 Sep · script 28 Sep · correct this row
Saleor dashboardcommerce admin · React (GraphQL API) BSD no count no spec 40 github.com/saleor/saleor-dashboard 8d678ea21, 28 Sep · script 28 Sep · correct this row
Snipe-ITasset management · Laravel AGPL-3.0 154 no spec 0 0 github.com/grokability/snipe-it d5bf95c02, 26 Sep · script 28 Sep · correct this row
Strapiheadless CMS · Node · React MIT + ee no count no spec 100 github.com/strapi/strapi bba9685b9, 28 Sep · script 28 Sep · correct this row
Supabase Studiodatabase dashboard · Next.js Apache-2.0 190 170 29 0.15 github.com/supabase/supabase 8e2071247, 28 Sep · script 28 Sep · correct this row
Syliuscommerce · PHP MIT no count no spec 0 github.com/Sylius/Sylius default branch · by hand 17 Sep · correct this row
Taigaagile boards · Django · AngularJS AGPL-3.0 front · MPL-2.0 back 72 no spec 47 0.65 github.com/taigaio/taiga-front d2da06116, 4 Sep · script 28 Sep · correct this row
TwentyCRM · NestJS · React AGPL-3.0 + ee 186 no spec 9 0.048 github.com/twentyhq/twenty default branch · by hand 17 Sep · correct this row
Umamiweb analytics · Next.js MIT 59 no spec 8 0.14 github.com/umami-software/umami ec0ff5038, 16 Sep · script 28 Sep · correct this row
Uptime Kumauptime monitor · Node · Vue MIT 15 no spec 7 0.47 github.com/louislam/uptime-kuma b6adc19d0, 23 Sep · script 28 Sep · correct this row
Vikunjatasks · Go · Vue AGPL-3.0 59 172 72 1.22 github.com/go-vikunja/vikunja 18f3572ed, 28 Sep · script 28 Sep · correct this row
WagtailCMS · Django BSD 165 no spec 8 0.048 github.com/wagtail/wagtail e57ccdbc0, 25 Sep · script 28 Sep · correct this row
Weblatetranslation · Django GPL-3.0 120 202 1 0.008 github.com/WeblateOrg/weblate 6ff77533c, 27 Sep · script 28 Sep · correct this row
Wiki.jswiki · Node · Vue AGPL-3.0 no count no spec 1 github.com/requarks/wiki 712a3a5bb, 22 Sep · script 28 Sep · correct this row
Zammadhelpdesk · Rails · Vue AGPL-3.0 no count no spec 286 github.com/zammad/zammad 619ef87bb, 28 Sep · script 28 Sep · correct this row
Zulipteam chat · Django · Tornado Apache-2.0 no count no spec 20 github.com/zulip/zulip default branch · by hand 17 Sep · correct this row

If a row is wrong, write to hello@featkpr.com with the app and the column; we correct it and date the fix on this page. How corrections work.

"no count": the screens cannot be counted from the files, or no API spec is committed; hover for the reason, and the downloads carry it. "by hand": report T2, 17 Sep 2026. "script": tools/library_count.py, 28 Sep 2026.

How we counted #

The protocol of our research report T2 (17 Sep 2026), made mechanical on 28 Sep 2026 in one script. Every number is a count of files in the repository, at the commit shown, with the rule that produced it.

A screen
a page a person can land on: one page file or one route declaration, never a component. In file-routed front ends (Next.js, SvelteKit, Nuxt, React Router route modules, a Vue app's views), page files minus layouts, API routes and _app/_document. Where the router is code (React Router, Vue Router, Angular, Ember, AngularJS), the route declarations in the router file the rule names. In server-rendered apps (Rails, Django, Laravel, Twig, Go templates, plain PHP), the templates that render a whole page: ones that extend a layout, or a Rails view that is not a partial, a layout or a mail.
No screen count
an app whose pages cannot be counted either way from its files (routes spread across the code, or screens generated from records) gets none, with the reason, rather than a guess.
An API operation
a (path, method) pair in the OpenAPI or Swagger spec committed to the repository, following a spec split into files through its $refs. No committed spec (GraphQL, RPC, a spec generated only at runtime or kept in another repository): no count.
An end-to-end spec file
a file of the suite the project runs against the running app from outside, through a browser (Playwright, Cypress, Puppeteer, Selenium, Protractor, Capybara system specs, Odoo tours) or over HTTP, in the directory the project names for it. Unit, component and in-process HTTP tests are not counted.

Spec files are not tests. One spec file can hold one test or fifty. We count files because a file is what the rule can see without running anything.

Screens are not features. A screen is a page file. One screen can carry many features, and one feature can span many screens.

Two counts: report T2 counted 14 apps by hand on 17 Sep 2026 (BookStack at its v26.05.5 tag, the others at their default branch that day, with no commit recorded). On 28 Sep 2026 the script counted 43 more at each repository's default branch, and recounted 4 of T2's apps to check the rules against T2's figures.

Where both counts exist #

T2's hand count (17 Sep) beside the script's (28 Sep). The table and the picture use T2's; the downloads carry both.

appcountT2, 17 Sep 2026script, 28 Sep 2026
Documensoa1d4bec14 screens 115 112 differs
API operations no count no count
e2e spec files 132 135 differs
Formbricks43db6ad83 screens 76 78 differs
API operations 72 72
e2e spec files 48 49 differs
Immichaa0233784 screens 56 56
API operations 276 276
e2e spec files 49 49
InvenTreec2b7f71f2 screens 87 87
API operations 670 no count differs
e2e spec files 26 26

InvenTree's API count differs because its spec is kept in another repository (inventree/schema): T2 read it there, and the script reads only the repository it counts.

What this does not show #

  • Not a sample of all open-source apps. The apps were picked as candidates for featkpr to map, plus well-known self-hosted apps across stacks. Nothing here says what share of all projects have end-to-end suites.
  • Not a measure of quality. Fewer spec files than screens does not mean a screen is untested: unit and integration tests are not counted, and one spec file can cover many screens.
  • Rules differ by stack. A screen in a Rails app (a template) and in a React app (a route declaration) are counted by different rules, so compare apps within a stack with more care than across stacks.
  • One moment in time. Each count is at one commit. Repositories move every day; run the rule again and the number may differ.
  • Rules, not a reading of every file. Each number is what its rule matched, and the 4 recounted apps are checked against T2's hand counts. A rule can still count a file it should not, or miss one.

How to count it again #

Every row names the repository, the commit and the rule, so any one number can be checked with a clone and a file listing.

  1. Clone the repository and check out the commit in the row.
  2. List the files: git ls-tree -r --name-only HEAD.
  3. Apply the row's rule: the files whose path matches the pattern, minus the exclusion, or the files whose text matches it. The count is the number of files (or of route declarations, where the rule says occurrences).

The script that did it, tools/library_count.py (Python, no dependencies beyond an optional YAML reader), shallow-clones each repository with no blobs, fetches only the files a rule must read and prints one JSON record per app. Its output of 28 Sep 2026 is the receipt the site reads. Run today, it counts today's default branch, so the numbers move with the repositories.

The data are also on GitHub: github.com/featkpr/open-source-apps-counted (CC BY 4.0). The counting script follows there.

receipt: research/reports/library-count-2026-09-28.json · 47 records, one per repository counted on 28 Sep 2026

A neighbour dataset: E2EGit #

The closest published dataset we know of, and how this one differs.

E2EGit: A Dataset of End-to-End Web Tests in Open Source Projects (Sergio Di Meglio, Luigi Libero Lucio Starace, Valeria Pontillo, Ruben Opdebeeck, Coen De Roover, Sergio Di Martino) publishes a dataset of GitHub repositories written in Java, JavaScript, TypeScript or Python that depend on a web framework. It finds Selenium, Playwright, Puppeteer and Cypress tests (and JMeter and Locust performance tests) and counts test cases per file.

aspectE2EGitthis count
What is countedtest cases, inside each test fileend-to-end spec files, not the tests inside them
Which projects5,563 web repositories (at least 2,000 commits, 10 contributors and 100 stars, not a fork); the 472 with web GUI tests are listed57 apps, chosen one by one; the 14 with no end-to-end spec file are in the data
The app's sizecommits, contributors, lines of code and stars, not its pagesscreens, and API operations where a spec is committed
What it found43,670 web GUI test cases in 472 repositories, and 271 performance tests in 846,233 end-to-end spec files in 43 apps
Whenmined May 2024; published 26 Nov 2024counted 17 Sep 2026 and 28 Sep 2026
LicenceCC BY 4.0, on ZenodoCC BY 4.0, on this page

Paper: doi 10.1109/MSR66628.2025.00121 (the authors' PDF). Data: Zenodo, doi 10.5281/zenodo.14221860, CC BY 4.0. Every E2EGit figure above is from the paper, read 28 Sep 2026.

Download and cite #

The same rows as the table, with the rule behind every number, generated from the site's data when the site is built.

Licence: Creative Commons Attribution 4.0 International (CC BY 4.0). Use it for anything, including commercially; name featkpr as the source and link to this page.

Cite this #

featkpr, 57 open-source web apps counted, 28 Sep 2026, CC BY 4.0, https://featkpr.com/library/counted

BibTeX
@misc{featkpr_counted_20260928,
  author       = {{featkpr}},
  title        = {57 open-source web apps counted: screens, API operations and end-to-end spec files},
  year         = {2026},
  month        = {sep},
  howpublished = {\url{https://featkpr.com/library/counted}},
  note         = {Dataset, CC BY 4.0. Counted 17 Sep 2026 and 28 Sep 2026}
}

See featkpr map an app #

We counted these apps to choose which ones featkpr maps first. featkpr maps a web app's features, the flows people take through them and the goals they reach, and tests sit on top of that map. The counts are published as they are, so anyone can check them, reuse them or count more.

Ask for a private demo

↑ ↓ to move, Enter to open, Esc to close