Repository navigation
Releases: programmishka/watchlist
Release list
v3.2.1 — Frontend Architecture Refactoring & UI Polish
Version 3.2.1 focuses on internal frontend quality. The Watchlist UI has been restructured into smaller, clearly defined responsibilities while preserving existing product behavior.
The goal of this release is improved readability, traceability, testability, and maintainability for human developers.
Clearer Frontend Architecture
The main SvelteKit page previously combined page composition with a growing amount of reactive state and workflow lifecycle management.
The frontend now follows a clearer responsibility model:
+page.svelte
↓
WatchlistWorkspace
↓
watchlistShell
↓
watchlistApi
↓
HTTP
Presentation remains separated into focused Svelte components, while deterministic filtering, sorting, formatting, and validation continue to live in pure helpers.
Dedicated Watchlist Workspace
A new Svelte 5 rune-based WatchlistWorkspace owns the reactive lifecycle of a single Watchlist workspace, including:
- server-derived Watchlist state;
- filter and sort state;
- investment allocation state;
- operation and error states;
- derived visible stock data;
- busy-state aggregation;
- Watchlist transition rules;
- mutation and invalidation workflows.
The Workspace is instantiated per page instance rather than implemented as global mutable state, preserving clear SvelteKit/SSR isolation.
watchlistShell remains stateless application orchestration, while watchlistApi remains responsible solely for HTTP communication.
Directly Testable State Transitions
Important frontend state transitions that were previously exercised mainly through end-to-end tests can now be tested directly through the Workspace API.
This includes behavior such as:
- filter and sort resets when changing the active Watchlist;
- allocation invalidation after relevant mutations;
- state preservation after failed operations;
- Target Price partial-success handling;
- mutation serialization;
- successful and failed Watchlist/stock operations.
The new Workspace has dedicated unit coverage while the existing Playwright suite continues to verify full browser integration.
Smaller, Cohesive Components
Several UI responsibilities were extracted from the route into focused components:
StockAddFormInvestmentAllocationControlsStockPresentation
StockPresentation now owns the responsive switch between the desktop table and Stock Cards, including the established 1120px breakpoint.
Local interaction state remains local where appropriate—for example Target Price editing, Watchlist navigation disclosure, and responsive presentation state.
As a result, +page.svelte is now primarily a composition root rather than the implementation location for the complete workspace lifecycle.
Stable Destructive Action Icons
Font- and emoji-dependent delete symbols have been replaced with deterministic SVG icons.
This improves rendering consistency for:
- stock removal in Table and Card views;
- active Watchlist removal.
The controls retain their existing accessible names, busy states, keyboard behavior, focus styling, and destructive-action semantics while providing more reliable sizing and centering across platforms.
No Product Behavior Changes
This release is intentionally focused on maintainability and presentation robustness.
It does not change:
- Watchlist business rules;
- investment-allocation calculations;
- market-data or FX behavior;
- REST API contracts;
- persistence;
- authentication.
The existing unit and Playwright test suites continue to protect the application's established behavior.
v3.2.0 — Production Diagnostics for Market Data & FX
Version 3.2.0 introduces structured production diagnostics for incomplete market data and currency conversion.
The goal of this release is not to hide or replace unavailable financial data, but to make its actual upstream cause observable in production.
Structured Market Data Diagnostics
The application now emits structured diagnostic events when financial data cannot be composed completely.
Diagnostics distinguish between conditions such as:
- missing market-data fields;
- missing quotes or prices;
- unavailable FX conversions;
- market-data provider failures;
- FX-provider failures;
- unexpected composition failures.
Normal successful provider operations are intentionally not logged, keeping production logs focused on anomalies that require investigation.
Cloudflare Workers Observability
Cloudflare Workers observability is now explicitly enabled for the production Worker.
Structured diagnostics are written through a small application logging abstraction and captured by Cloudflare Workers Logs. No external logging service or additional production dependency is required.
Diagnostic events intentionally exclude authentication tokens, cookies, email addresses, user IDs, complete Watchlists, and raw provider responses.
Real-World Market Data Findings
The new diagnostics were immediately used to investigate several stocks with unavailable Market Cap data:
- 2330.TW — Yahoo Finance provides Market Cap in TWD, but the current Frankfurter/ECB-based FX provider does not support TWD. The USD Market Cap therefore cannot currently be calculated.
- ASSA-B.ST — Yahoo Finance does not provide Market Cap in the quote data used by the application. The missing value is unrelated to FX conversion.
- AZO — Yahoo Finance likewise does not provide Market Cap in the quote data. Because the stock is USD-denominated, FX conversion is definitively not involved.
No symbol-specific workarounds were introduced. The diagnostics instead provide evidence for future improvements to market-data and FX coverage.
Production Troubleshooting
Missing-data cases can now be investigated through Cloudflare Workers Logs or Wrangler's live log tooling.
This makes it possible to trace a displayed — back through the provider and composition pipeline without exposing technical diagnostics in the user interface.
Small Table Improvement
Large Savings Amount values in the desktop table now expose their complete formatted value through a native tooltip when the compact column visually truncates them.
The complete value remains in the document, and the responsive Stock Card presentation continues to show the full amount normally.
Quality
The new diagnostic paths are covered by automated tests for market-data failures, missing provider fields, FX failures, successful no-warning cases, and composition anomalies.
The diagnostic behavior was also verified against real Yahoo Finance and Frankfurter data for the representative production cases above.
No financial calculations, API contracts, authentication behavior, or persistence semantics were changed in this release.
v3.1.0 — Responsive Workspace & Security Hardening
Version 3.1.0 significantly improves the Watchlist as a day-to-day financial workspace.
The release focuses on three areas: more efficient portfolio presentation, responsive interaction across screen sizes, and systematic hardening of all application input boundaries.
Data-First Watchlist Workspace
The Watchlist UI has been redesigned to give financial data priority over management controls.
The workspace now uses available screen space much more efficiently:
- wider desktop layout with less unused space;
- compact Watchlist, stock, filter, and allocation controls;
- removal of redundant active-Watchlist headings;
- Watchlist creation integrated directly into the navigation area;
- compact Watchlist and stock removal actions;
Investedrenamed to the more accurate Allocated savings;- Target Price inputs and other controls sized according to their actual content.
On sufficiently wide screens, the complete stock table fits without unnecessary horizontal scrolling.
Improved Table Presentation
The stock table received several financial presentation improvements:
- default sorting by Company Name ascending whenever a Watchlist becomes active;
- clearer
Market Cap (USD bn)label; Dividend Yieldinstead of the abbreviatedDiv;Actionsinstead ofDelete;- Currency positioned directly after Price;
- financial values consistently displayed with two decimal places;
- signed Target Price distances such as
-15.20%,0.00%, and+15.20%; - stocks below their Target Price receive a favorable green Distance presentation;
- stocks above their Target Price receive an unfavorable red presentation;
- clearer
TotalandFilteredstock counts.
Sorting continues to use the underlying numeric values rather than formatted display strings.
Responsive Watchlist Navigation
Horizontal scrolling through Watchlist tabs has been eliminated.
Navigation now uses direct tabs plus a responsive overflow menu:
- the active Watchlist is always directly visible;
- additional inactive Watchlists move into
More/Watchlists; - selecting an overflowed Watchlist brings it into the directly visible navigation;
- newly created Watchlists remain immediately visible even with many existing Watchlists;
- mobile layouts show the active Watchlist prominently instead of a horizontally scrolling tab strip;
- Watchlist creation remains directly accessible;
- long and duplicate Watchlist names remain supported.
Responsive Stock Cards
The 10-column financial table is retained where it works best: on larger displays.
Below the empirically determined 1120 px breakpoint, the application now switches to responsive Stock Cards instead of requiring horizontal table scrolling.
Cards preserve the complete Watchlist functionality:
- Symbol and Company Name;
- Price and Currency;
- editable Target Price;
- favorable/unfavorable Distance to Target;
- Market Cap;
- Dividend Yield;
- Savings Amount;
- stock removal;
- filtering;
- sorting;
- allocation results.
Card layouts adapt further from two columns to one column as space becomes constrained.
Table and Card views use the same underlying filtered and sorted stock state, so resizing the application does not reset state or trigger additional API requests.
Input Boundary Hardening
Version 3.1.0 introduces systematic bounds for externally controlled application data.
Server-side validation is authoritative; browser limits mirror the same rules for immediate UX feedback.
The application now enforces:
- Watchlist names: maximum 50 characters;
- Stock Symbols: maximum 20 characters plus the existing syntax rules;
- Target Prices: finite values greater than
0and no greater than1,000,000; - Total Savings: safe integers from
0through10,000,000; - Watchlist IDs: maximum 64 characters;
- company-name filters: maximum 100 characters;
- Watchlists: maximum 1,000 stocks.
The 1,000-stock capacity is enforced before market-data resolution, avoiding unnecessary external requests when a Watchlist is already full.
Consistent Symbol Boundaries
Stock Symbol normalization is now consistently applied to Target Price operations as well.
For example:
aapl
→ AAPL
This closes an edge case where different casing could previously create separate Target Price persistence identities.
Malformed and oversized symbols are rejected before reaching the market-data provider.
Request Body Protection
All JSON API endpoints now enforce a 4 KiB application-level request-body limit before JSON parsing.
The protection:
- rejects oversized requests with
413 PAYLOAD_TOO_LARGE; - uses
Content-Lengthfor immediate rejection when possible; - does not trust
Content-Lengthas the sole protection; - incrementally counts actual request bytes;
- also protects streamed/chunked requests without
Content-Length; - stops processing oversized payloads before application services, persistence, or external providers are reached.
This complements the field-level validation rather than replacing it.
Quality and Verification
The release extends permanent unit and Playwright coverage across the new responsive layouts, navigation behavior, validation boundaries, resource limits, and API protections.
Responsive behavior was verified across mobile, tablet, and desktop widths, including the Table/Card breakpoint. Request-body protection was additionally verified against the real local Cloudflare workerd runtime, including an oversized chunked request without a Content-Length header.
No financial allocation formulas, authentication model, or persistence architecture were changed in this release.
v2.0.0 — Stronger Stock Validation and Target Price Semantics
Version 2.0.0 improves the reliability of stock admission and Target Price calculations based on findings from real-world use of the production application.
Highlights
Canonical Stock Symbols
Stock-symbol input is now normalized before processing:
- leading and trailing whitespace is removed;
- symbols are automatically converted to uppercase;
- common Yahoo-style symbols containing letters, numbers, dots, and hyphens are supported;
- syntactically invalid symbols are rejected before contacting the market-data provider.
Examples:
aapl → AAPL
sap.de → SAP.DE
hexa-b.st → HEXA-B.ST
0700.hk → 0700.HK
Invalid syntax, unknown symbols, and market-data-provider failures are now represented as distinct error conditions.
Equity-Only Symbol Resolution
The Watchlist is intended for individually valued companies, so new symbols must now resolve to an equity before they can be added.
A new provider-neutral resolveSymbol() abstraction separates stock admission from ordinary market-data retrieval.
The current Yahoo Finance implementation accepts a symbol only when:
- Yahoo resolves the exact normalized symbol; and
- the instrument is classified as an equity.
Known non-equity instruments such as ETFs are therefore rejected even when Yahoo Finance recognizes their symbols.
The application remains independent of Yahoo-specific instrument metadata, allowing the provider implementation to evolve without changing the application layer.
Correct Handling of Unavailable Target Price Distance
Target Price distance now distinguishes between a real calculated zero and unavailable data.
Previously, missing or invalid market-price data could be represented as a numeric distance, including 0, and in one edge case could result in a misleading percentage being displayed.
The new semantics are:
Valid Price + Valid Target Price
→ calculated distance
Price == Target Price
→ 0%
Missing/invalid Price or Target Price
→ —
A stock whose distance cannot be calculated remains visible in the Watchlist but does not participate in savings allocation:
Distance to Target: —
Savings Amount: €0
This preserves the existing investment-allocation behavior while making the displayed financial information semantically correct.
Quality
The V2 changes are covered across domain, application, API, client, and browser levels, including regression tests for the production issues that motivated the release.
The release retains the existing server-side financial calculations, Cloudflare deployment architecture, Yahoo Finance market-data integration, responsive SvelteKit UI, and permanent Playwright E2E suite.
First production-ready version
Value-oriented stock portfolio watchlist with target prices, market data, and savings allocation based on each stock's distance to its target price.