The Operating Model: From User Intent to Market Context
OpenStock’s operating model begins before a quote appears. The user first establishes an identity and a set of interests, then enters a protected environment where market information, saved symbols, and background work meet. The useful question is not which framework or service appears in the repository, but how responsibility moves from user intent to a visible piece of market context. That distinction lets us trace a normal session and see what OpenStock owns, what its providers render, and what becomes durable user state.
Sign-up creates a monitoring context, not just an account
A conventional sign-up form asks for an email address and password because its immediate job is to create credentials. OpenStock asks for more. Alongside a name and email, its onboarding flow collects country, investment goal, risk tolerance, and preferred industry. Those selections are not yet a financial plan. They are a compact description of the kind of market experience a person expects to have.
The server-side sign-up action passes the credentials to Better Auth. If account creation succeeds, it emits an app/user.created event containing the profile fields. That event is the first important transition in the operating model: preferences leave the synchronous form submission and become input to background work. The event does not alter a quote or create an order. It gives a later workflow enough context to compose a personalized welcome message.
This separation matters. A preference is not the same as a recommendation. OpenStock’s captured code demonstrates that the information can shape onboarding communication; it does not demonstrate that a “Growth” goal changes which stocks appear, that “Low” risk filters the market, or that a preferred industry produces an investment strategy. Treating the form as a recommendation engine would confuse declared intent with calculated advice.
After sign-up or sign-in, the application treats the user as someone entering a protected monitoring environment. Better Auth is configured with MongoDB, and the application’s root layout obtains a session before rendering its main shell. The middleware adds an earlier, simpler check: requests without a session cookie are redirected away from protected paths, while sign-in, sign-up, password-reset, static assets, and framework internals remain public. The page-level session lookup is the stronger part of the normal route flow because it establishes which user is being served.
The shell is more than decoration. It is the stable frame around several different kinds of activity: broad market scanning, symbol search, detailed inspection, saved watchlists, alerts, and supporting project information. A user does not need to understand which service supplies each panel in order to move between them. The shell’s job is to make those transitions feel like one continuous product. Its architectural job is to keep an authenticated identity available as the context for personal actions.
That identity also gives the application a time dimension. A successful sign-in updates lastActiveAt, which is later used by the inactive-user workflow. The user’s session therefore affects both what they can see now and how the system may decide to re-engage them later. In OpenStock, identity is not a front door that disappears after login; it is a signal reused by persistence and automation.
The dashboard scans; the detail page investigates
Once the session exists, the dashboard supplies breadth. OpenStock’s root surface combines TradingView widgets for market overview, a stock heatmap, market quotes, and a market timeline. These are not four separate products that the user must assemble. They are a broad scanning surface: a way to notice sectors, symbols, price movement, and stories before choosing where to look more closely.
This breadth is also the first clear example of divided responsibility. The application chooses which widgets to place, how to size them, and how to style the surrounding experience. TradingView supplies the embedded market views and controls much of their actual content. OpenStock can create a coherent page around those views, but it does not own every number, chart behavior, or symbol that appears inside them.
Search forms a bridge between the broad dashboard and a particular company. Finnhub-backed actions return symbol candidates, company descriptions, exchange labels, and types. When no query is present, the search path can populate popular symbols from a configured set of profiles. When a query is present, it asks Finnhub for matching results and maps them into a common shape for the interface. The user experiences “search for a stock,” but the system is actually translating provider output into an OpenStock search model.
Selecting a symbol moves from scanning to investigation. The stock-details surface combines a symbol-information widget, advanced and baseline charts, technical analysis, a company profile, financial views, and an optional sentiment card. It also checks whether the symbol is already in the user’s watchlist. That mix creates a focused context around one identifier: a current view, a company view, a financial view, a personal-state view, and, when available, a cross-source signal view.
The difference between dashboard and detail is therefore not only layout. It is a change in the question the user is asking. The dashboard asks, “What is happening across the market?” Search asks, “Where is the symbol I care about?” The detail page asks, “What kinds of context can I place around this symbol, and should I keep monitoring it?” OpenStock’s application layer carries the same identity and symbol across those questions while relying on different providers and data paths underneath.
The sentiment card makes the distinction between context and conclusion especially important. Adanos can provide structured snapshots from Reddit, X.com, news, and Polymarket. OpenStock normalizes the available sources, computes average buzz and, when possible, average bullish percentage, then labels the relationship among sources as aligned, mixed, divergent, or single-source. That is a way to show the shape of available signals. It is not evidence that a stock will rise or fall, and it does not replace the company, price, or financial views beside it.
A user can therefore move through the product without changing systems, but the underlying ownership changes at every step. OpenStock owns the page composition and the normalization decisions. Finnhub supplies much of the search, quote, profile, and news material. TradingView supplies embedded visual market views. Adanos supplies an optional sentiment input. The database records personal state. The page is unified; the responsibilities are not.
The diagram’s most important feature is not the number of boxes. It is the direction of ownership. The user initiates intent. OpenStock coordinates the experience. Providers supply or render market information. MongoDB holds the parts that should survive a browser session. Inngest acts later, on a schedule or in response to an event. A feature can look local in the interface while its next update is controlled elsewhere.
Watchlists are the point where context becomes personal
A dashboard view is useful even when it is entirely public. A watchlist changes the relationship between the user and the market. In OpenStock, a watchlist item stores a user ID, an uppercase and trimmed symbol, a company label, and an added timestamp. A compound uniqueness rule prevents the same symbol from being duplicated for the same stored user. The application can upsert an item, retrieve one user’s items, remove a symbol, and revalidate relevant pages after a change.
Those details turn attention into state. A search result answers a momentary question; a watchlist records a continuing interest. The watchlist page can use the saved symbols to request related company news rather than displaying only general market stories. If the list is empty, general news remains the fallback. If it contains symbols, OpenStock attempts to distribute company news across them before sorting the selected articles by time. The saved list therefore influences not only what the user sees in a table or widget, but also which surrounding information the application tries to assemble.
The watchlist also demonstrates why a provider-rendered widget and a user-owned record should not be treated as equivalent. TradingView can display a visual watchlist, but MongoDB is what gives OpenStock a persistent relationship between a symbol and a user ID. The external widget is a view. The database record is the personal context that lets the application reconstruct the view, attach news, and support later actions.
Alerts extend that context one step further. Instead of saying “I want to remember this symbol,” a user can say “evaluate this condition for me.” The alert stores a target price, an above-or-below condition, active and triggered state, and an expiry. A scheduled Inngest function later checks the condition against fetched prices. The rule belongs to the user’s monitoring state, but the value against which it is evaluated remains provider data.
This division explains why the product can be easy to use and still require careful analysis. The user does not have to manually poll every company page, yet the alert cannot be more current than the price it receives or the schedule that evaluates it. A visible control can represent several layers of state: the user’s intention, the database record, the provider’s current response, and the workflow’s next run.
Background jobs complete the operating loop
The onboarding event shows how a user action can continue after the form has finished. Inngest registers an event-driven welcome workflow, a weekly news-summary workflow, a recurring alert check, and a daily inactive-user check. These jobs let OpenStock perform work that would be awkward or unreliable inside a page request. They also make the product’s relationship with time explicit.
A welcome workflow can use the onboarding profile to generate an introduction and then send an email. A weekly workflow retrieves market news, asks an AI provider to produce a formatted summary, and sends a Kit broadcast. The alert workflow revisits stored rules. The inactive-user workflow reads activity timestamps and prepares re-engagement content. Each job starts from a different trigger, but all of them extend the user’s monitoring context beyond the screen they are currently viewing.
That extension has a cost: the system now depends on more than the page can show. The application must know which user or subscriber is the target, which provider is available, whether a generated message is valid, and whether the final side effect actually happened. A workflow can be correctly triggered while its external email or broadcast still depends on credentials, service behavior, or targeting configuration. The presence of an Inngest function proves that the path is designed; it does not by itself prove successful delivery in production.
The same principle applies to authentication. A protected layout can ensure that a normal page is rendered for a session, but personal-state safety also depends on the actions that create, change, or delete records. In the captured code, several watchlist actions accept a user ID supplied by the caller, while alert deletion and update operations are keyed by alert ID. That observation belongs to the system model even before a later security-focused discussion: page gating and mutation authorization are related, but they are not the same boundary.
A single product, several kinds of dependence
OpenStock’s operating model is strongest when it makes transitions that would otherwise be fragmented feel continuous. Preferences become an event. A session becomes the context for personal state. A symbol moves from search to chart to watchlist. A saved rule becomes a scheduled check. Market news becomes a personalized or broadcast message. The application gives these movements a common surface and a common vocabulary.
But continuity should not be mistaken for uniform control. The dashboard can be assembled by OpenStock while its widgets depend on TradingView. Search can be shaped locally while its results depend on Finnhub. A watchlist can be stored locally while its prices and news remain external. A background job can be registered locally while its AI response or email delivery depends on another service. The user sees one workflow; the system crosses several boundaries.
That is the operating model to carry forward: user identity and intent enter the application, providers supply changing market context, OpenStock normalizes and composes it, MongoDB preserves personal choices, and Inngest revisits those choices over time. When the experience succeeds, those layers disappear into a smooth path from interest to monitoring. When something fails, the same model tells us where to look: the session, the application adapter, the stored state, the provider, or the scheduled side effect.
The next question is how OpenStock makes raw external information consistent enough to cross those boundaries. Search results, quotes, profiles, and news do not arrive with identical freshness or structure. Understanding the application’s data path will show which inconsistencies it absorbs and which ones remain visible to the user.