Frontend at enterprise scale

2020–2026 · Frontend

Big, old, dense apps used by people who can't afford for them to break. Some of my least glamorous and most useful work.

Angular, Angular Material, React, TypeScript, SCSS, Storybook, Jest, axe

The branch I was building phone layouts on had 818 !important declarations, and the root cause was its Sass setup re-emitting a shared layer into every component. The app is a B2B supply-chain SaaS with an Angular frontend, and in August I took the count to 97 on another branch.

Where it started After the cleanup
!important in the SCSS 818 97
Occurrences of one table-cell selector in the dev bundle 2,866 578
Dev bundle 73 MB 47 MB

The app was built for desktop, with dense tables, multi-column dialogs and a fixed sidebar. Making it work on phones meant changing hundreds of files, and desktop had to stay as it was. Angular Material’s specificity, style encapsulation and inline styles fought the card layouts.

Fix the duplication, then gate every removal

Each component stylesheet compiles separately, so every component using the shared partial got its own scoped copy of the table layer. Component rules fought that copy at equal specificity, in a source order their authors couldn’t see, and !important was the one lever that always worked.

When I made the layer emit once, Angular Material took the tables back. Its selectors carry two classes, and the design system’s single class had only won with encapsulation’s added attribute. I repaired the fallout and gated every removal on a computed-style diff of about 75 properties per painted element. A pixel diff wasn’t enough, because three removals once passed a byte-identical one and were still wrong.

Nine stacked MRs instead of one branch

The first mobile redesign merged in June, in a 369-file change that also upgraded Angular. The follow-up branch still carried that redesign’s history and had 444 commits when I cut it into nine stacked merge requests a reviewer could take one at a time. All nine passed CI in September and are in review.

The first two MRs change nothing on screen. One extracts a mixin that turns a data table into labeled stacked cards, and it compiled to byte-identical CSS, which I checked by compiling the stylesheet at both revisions. The other adds a shared foundation, with a breakpoint directive that swaps a table for per-row components, and changes no existing rule. I applied the foundation across six feature areas.

Pressing Back lost your place

Back out of a row, and the list used to forget its page, sort and search. About 10 list tables now keep them in the URL. The facility switcher’s own URL write canceled the table’s attempt to clear the search, so the old term showed up in the new facility’s list. The table now retries once the router settles.

Green CI, broken everywhere else

npm ci failed on every fresh machine while a CI cache that never expired kept the pipeline green. The lockfile was missing peer dependencies. I added them, keyed the cache on the lockfile and checked the install on three operating systems and two npm versions.

Fold the profile editor’s copy-pasted modals into one

At a legal-tech platform, I founded a profile editor’s Angular frontend and wrote more of it than anyone. Its sections carried about 30 copy-pasted edit modals. Folding them into one shell touched about 70 files and had to land without breaking modules already in QA. I also led a vanilla JS product’s move to React and TypeScript.

On the platform, I led most of an accessibility remediation of eight redesigned page templates and a directory search, about 21 fixes across about 15 components. Links opened a new tab only when they left the site, and said so. Div grids got table semantics, pagination marked the current page, focus moved to results after a search, and pages reflowed at 400%.

On the supply-chain app, where I also built the visual-regression system that diffs an MR’s screens against main, the !important branch still sits at 97, with no MR. Of the 97, 21 fight inline styles an overlay writes as it positions itself, and 18 a third-party multiselect’s encapsulated rules.