The frontend catches up. Angular 18 through 22 in one run, change detection without Zone.js, and every screen but the landing page loaded on demand, which halves what a first visit downloads. Along the way the screens gained a little: the budget listing says how many transactions each budget holds, the budget you are reading follows you from screen to screen, and changing a transaction filter returns you to the first page instead of an empty one. Charts follow the window again, unhandled errors reach Angular's handler, and a signed-out browser can fetch the favicon. No migration: the database schema is unchanged since 9. 🐛 Debounce the transactions screen's live filters 📝 Publish the demo database image and streamline the docs 🔧 Modernize the Angular 18 build tooling and add ESLint ⬆️ Update to Angular 19 core and CLI ♻️ Replace APP_INITIALIZER with provideAppInitializer ⬆️ Update Angular Material/CDK to 19 and ngx-charts to 24 ✨ Use @let for repeated template reads ✨ Convert AccountScreenComponent to signals + OnPush ✨ Add OnPush to components with no mutable local state ✨ Add OnPush to the already signal-driven auth screens ✨ Convert small dialogs to signals + OnPush ✨ Convert transaction-edit, overview-screen and remaining dialogs to signals + OnPush ✨ Convert BudgetScreenComponent to signals + OnPush ✨ Convert AccountImportDialogComponent to signals + OnPush ✨ Convert TransactionScreenComponent to signals + OnPush ✨ Adopt withComponentInputBinding() for the transactions screen's linked filters ⬆️ Upgrade to Angular 20 🔥 Drop fp-ts for a plain ternary ⬆️ Bring jasmine/karma up to Angular 20's own scaffold pins ✨ Adopt linkedSignal() for the transactions screen's budget-line filter ✨ Forward unhandled window errors to Angular's ErrorHandler ⬆️ Upgrade to Angular 21 ⬆️ Bump ngx-charts to 25.0.1 now that it fits Angular 21 ⬆️ Bring jasmine/karma up to Angular 21's own scaffold pins 🔥 Drop provideAnimations() — Material no longer needs it 🐛 Bump the Docker build image from node:18 to node:24 ⬆️ Bump typescript-eslint to 8.68 for TypeScript 6 support ⬆️ Upgrade to Angular 22 ⬆️ Bump angular-eslint to 22 🐛 Bring the arm64 build image to node:24 and build with the pinned CLI 🔥 Keep v22's new template diagnostics switched on 🔥 Adopt v22's fetch backend for HttpClient 🔥 Drop src/test.ts and let the builder bootstrap the tests 🔥 Go zoneless ⬆️ Build with @angular/build instead of the webpack facade 🔥 Drop the color attributes M3 ignores ♻️ Move to Material's unified button selectors 🔥 Drop the redundant standalone: true ⚡ Load every screen but the landing page on demand ♻️ Hold the accounts list in an rxResource ♻️ Give the account dialog a typed result 🐛 Recompute the year's progress when the budget changes ♻️ Hold the budget screen's three fetches in resources ✨ Count each budget's transactions on the listing ✨ Open every screen on the same budget ♻️ Build BudgetRm rather than count its arguments ♻️ Hold the overview screen's three fetches in resources ♻️ Make the last five transaction filters signals ♻️ Derive the transaction screen's budget lines from the year 🐛 Send a filter of zero rather than dropping it ♻️ Derive the transaction screen's accounts and page currencies ♻️ Derive the transactions page from its filters ✨ Return to the first page when a filter changes ♻️ Hold the dialogs' reads in resources 🐛 Provide the animations ngx-charts still asks for 🐛 Watch the cumulative chart's size instead of reading it once 🔒 Let signed-out browsers fetch the favicon 🐛 Stop confirmation snackbars rejecting when nobody answers 👷 Run the frontend in CI 🐛 Let the budget pie charts follow the window ♻️ Replace ngClass with class bindings