Skip to main content

22 — The map and the gaps

Read this first: this is the closing chapter, and it is deliberately the least flattering one. The first half is the map — what you can now recognize on sight anywhere in frontend/src/pages/. The second half is the honest list of what this course skipped, what the codebase itself has not finished, and where the weight actually sits when something breaks.

Time: about 15 minutes. Assumes lesson 21.

The map: three systems and a one-glance test​

The course README made you one testable promise: by the end you can open any page in frontend/src/pages/ and say which system it is built on. Twenty-one lessons and four parts later, here is the whole map, small enough to hold in your head:

  1. The enterprise grid — lesson 07 through lesson 13. One hook, useEnterpriseGrid, turns a column contract into a server-side AG Grid with toolbar, tabs, saved views, bulk actions, and export.
  2. The analytics component system — lesson 14 through lesson 20. Tokens, panels, chart wrappers, the drilldown drawer, URL-as-state. It lives in components/analytics/ and it is used by exactly one page: HR Analytics.
  3. The older generation — everything else. Raw AgGridReact imports, local StatCard components, hard-coded hex palettes. Less a system than the sediment the other two grew out of.

The count is real. Run it yourself from the repo root:

grep -rl "useEnterpriseGrid" frontend/src/pages frontend/src/components | wc -l

As this chapter is written, the answer is 43 — 42 pages plus one embedded component (RunPayslipsGrid, the payslip grid inside the payroll-run detail page). The clusters: eight HR pages, seven payroll, six CRM, fourteen inventory, six recruitment, and the super-admin Tenants page. That is what the README means by "some forty list pages", out of 107 .tsx files under pages/ in total.

The test takes one glance. Open any page file and read the imports. useEnterpriseGrid means system one. Anything from components/analytics/ means system two. AgGridReact imported directly, or Recharts fed from a local color array, means system three.

Predict: pages/hr/Users.tsx — the user-account admin page, permission-gated, obviously list-shaped. Which system?

Still off the grid​

System three. Users.tsx imports AgGridReact directly, and so do Roles.tsx, Permissions.tsx, and AuditLogs.tsx beside it. All four use the shared plumbing you met in lesson 08 — motorphGridTheme, GridPaginationBar, the auto-size hook — but none of them call useEnterpriseGrid, so none of them have the toolbar, saved views, tab counts, or server-side filtering. AuditLogs is the one that hurts: it is exactly the high-volume, filter-heavy page the grid system was built for, and it has simply not been migrated.

The same is true of all nine pages in pages/self-service/ — MyPayslips, MyLeave, MyTimesheet, and the rest. There the gap is more defensible: each page shows one user's own rows, so saved views and bulk actions earn less. But the code does not say "we chose this"; it says nothing, which usually means "nobody got to it yet".

Two gaps inside the grid system itself​

The Employees import modal is still bespoke. Lesson 13 told this story in full: the shared ImportModal serves the other import buttons, while EmployeeBulkImportModal remains its own hand-built implementation. Two versions of "upload a CSV" coexist, and the lesson's advice stands — copy the shared one.

Grid pages have no URL deep links. Filter an employee list down to one department, copy the address bar, send it to a colleague — they get the unfiltered page. Search text, filter model, and active tab live in component state and die with it; saved views (lesson 10) persist per user, which is not the same thing as a shareable link. Lesson 19 showed the fix working on the analytics page, where every cross-filter and even the open drilldown drawer round-trips through search params. Nothing stops that pattern from reaching the grid pages except that nobody has done it.

Analytics is a one-page system​

Part 3 read the newest corner of the frontend, and it is worth being blunt about how small that corner is. The other analytics pages predate it and never migrated:

None of them have the token file, the silent-zero guard from lesson 16, the drilldown drawer, or URL state. If you are looking for a first substantial contribution, migrating one of these three onto the analytics component system is it — Part 3 of this course is effectively the spec.

The surfaces this course never entered​

The README's honest-limits section said this on day one, and it stayed true. The course covered the ERP-facing frontend and nothing else:

  • The customer portal — pages/portal/, nine pages of storefront (catalog, cart, orders, wishlist) with its own login and its own rules.
  • The super-admin surface — pages/admin/, the tenant provisioning portal. One page today, and it is on the grid, but the multi-tenancy machinery behind it went untoured.
  • The public marketing site — pages/marketing/, ten pages with code-split three.js scenes and their own performance discipline.

Auth and billing pages exist too, touched only where lesson 03 needed the login flow. Treat everything in this list as territory where the course's rules may not apply.

Where the tests are — and are not​

Count the frontend unit tests yourself; the number is four. Four .test.ts files in the entire frontend/src/ tree — seo.test.ts, templateRegistry.test.ts, and two for the ag-grid helpers, filterUtils.test.ts and legacyGridState.test.ts. Zero component tests. Refactor a drawer or a chart wrapper and no unit test will catch you.

What carries the weight instead is the Playwright end-to-end suite: 36 spec files under e2e/ at the repo root, driving the real stack through a real browser. That is a deliberate trade — the suite tests what users do rather than what components render — but it means feedback needs a running stack, and a page without e2e coverage has no safety net at all. Before you change anything, read the e2e guide and find out which of the two kinds of page you are standing on.

The code moves; this chapter does not​

Every number above — 43 grid files, 107 page files, four unit tests, 36 specs — was measured against the working tree on the day this course shipped, and the tree has not stopped moving. The gaps listed here are the most likely lines to go stale: someone migrates AuditLogs, and this chapter is wrong in the best possible way. When prose and code disagree, the code is right. The comment trail inside the files is the primary documentation; this course was only ever a guided reading of it.

Where to go next​

You have the map. Four hand-offs, depending on what you want to do with it:

  • Build something. Build a module page is the step-by-step recipe for putting a new page on the grid system — or migrating one of the off-grid pages above.
  • Trace the whole stack. The employees walkthrough follows one request from the browser through the controller and service down to SQL — the half of the story this frontend course stopped at the network boundary.
  • Look things up. The Frontend reference is the "what props does this take" complement to everything here.
  • Read the decisions. The ADRs behind the three biggest calls this course kept citing: ADR 0009 for the three-store state split, ADR 0010 for the AG Grid subsystem, ADR 0011 for permission authorities and activeRole — with the full index at the ADR list.

That is the course. The tree is in front of you, and the comments inside it are the rest of the documentation.