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