Create an Angular 19 application called state-demo that demonstrates the difference between classic Angular data management and NgRx Signal Store. Use json-server with a db.json for the fake API with an 800ms artificial delay. The app has two features accessible via routing, both implementing identical functionality. The data model: A small product catalog. products have id, name, price, categoryId, and stock. categories have id and name. Seed db.json with ~8 products across 3 categories. This gives us two separate endpoints to fetch and combine, which is important for showing the pain. Shared UI: A simple AppComponent with a navbar showing two nav links: "Classic" and "Signal Store". Also put a cart icon with a badge in the navbar showing the total number of items in the cart — this badge must be wired up in both features so that adding a product to the cart updates the navbar badge. This is the "shared global state" pain point: in the classic feature it's annoying to keep in sync, in the store feature it just works. Feature 1 — /classic route Implement this the "old way" — no NgRx, no Signal Store. Use a ClassicProductService that makes raw HttpClient calls. The feature should have: A product list component that fetches products and categories simultaneously using forkJoin, manually sets an isLoading boolean, resolves the category name per product, and renders a table/list with name, category, price, stock An "Add to cart" button per product that updates a cart count. The cart count lives in a CartService using a plain BehaviorSubject. The navbar badge subscribes to this — works fine, but note the wiring needed An inline "Edit price" interaction per product (a small input + save button) that calls a PUT endpoint and then manually updates the local array to reflect the change — this is the key pain point to highlight. If the same product data were shown in two places, you'd have to update both manually An ngOnDestroy with takeUntil / Subject for cleanup A loading spinner shown via *ngIf="isLoading" and an error message if the request fails Error state: if the API fails, show an error message. To demonstrate, add a "Break API" button that points the service at a bad URL temporarily Add comments in the code like // 😬 manual loading flag, // 😬 have to manually sync the array, // 😬 need to remember to unsubscribe — these will show up during the VS Code demo and get a laugh. Feature 2 — /store route Implement the same functionality using NgRx Signal Store (@ngrx/signals). Structure: A ProductStore using signalStore with withState, withComputed, withMethods, and withHooks for initial load. State holds: products, categories, isLoading, error A CartStore also as a Signal Store, provided in root, holding cart items as a signal. The navbar badge reads directly from cartStore.totalItems() — no subscription needed, just a signal The product list component injects ProductStore and CartStore. The template reads productStore.productsWithCategory() (a computed signal that joins products with their category name) — no combining streams in the component, no local state The same "Edit price" interaction — calls a method on the store (productStore.updatePrice(id, price)), which does the PUT and then patches state. The UI updates everywhere automatically because it's a signal No ngOnDestroy, no isLoading boolean in the component, no subscriptions Loading and error state come from the store — productStore.isLoading() and productStore.error() Add comments like // ✅ computed automatically, // ✅ no subscription needed, // ✅ update once, reflects everywhere Project setup requirements: Angular 19 with standalone components throughout, no NgModules @ngrx/signals installed json-server installed as a dev dependency with a start:api npm script that serves db.json on port 3000 with a --delay 800 flag A start:all script that runs both the Angular dev server and json-server concurrently using concurrently Proxy config so Angular dev server forwards /api to localhost:3000 Basic styling — doesn't need to be beautiful, but should be clean enough to present. Tailwind or simple scoped CSS, your choice README.md explaining the two features and what to look for in each