# bloomberg-terminal: a Next.js replica of the terminal interface, with the market data simulated

> A Bloomberg-styled trading interface built with Next.js 15 and React 19, using Upstash Redis and AlphaVantage, where the feature list admits that the real-time data is simulated to avoid burning through API limits.

**feremabraz/bloomberg-terminal** — Bloomberg-like terminal with AI. It uses Redis with AlphaVantage data and local simulations to avoid hitting the API too much.

- Repository: https://github.com/feremabraz/bloomberg-terminal
- Website: https://bloomberg-terminal-nine.vercel.app
- Stars: 1,573 · Forks: 266
- Language: TypeScript
- License: not declared
- Published: 2026-10-06 · Updated: 2026-10-06 · Language: en
- Canonical page: https://hysenlabs.com/projects/feremabraz-bloomberg-terminal

## The README says the market data is simulated, and that matters

The project description leads with the honest part: it uses Redis with AlphaVantage data and local simulations to avoid hitting the API too much. The feature list repeats it in the first bullet, calling the real-time market updates simulated with configurable refresh rates.

That single word changes what this repository is. A Bloomberg-style interface is mostly presentation, so a simulation layer lets the author build the whole thing without an entitlement, without rate limit anxiety, and without a market data contract. The cost is that nothing on screen is a real quote. The refresh rate is a simulation parameter, not a feed setting.

This is worth stating plainly because the interface is convincing. Terminal layout, keyboard shortcuts, watchlists, a news view, market movers and a volatility view are all real implementations, and the polish on the demo at the Vercel URL makes it easy to assume the numbers are too. They are not, and the README is upfront about it.

What you can take from the project is the structure and the refresh strategy. What you cannot take is the data layer, because there is nothing to take.

## Four environment variables and where the API key goes

Setup is a `.env.local` file with four things in it. The README lists them with placeholder values:

```text
UPSTASH_REDIS_REST_URL=your_upstash_redis_url
UPSTASH_REDIS_REST_TOKEN=your_upstash_redis_token
ALPHA_VANTAGE_API_KEY=your_alpha_vantage_api_key
OPENAI_API_KEY=your_openai_api_key
```

A fifth line is not a key but a policy: `ALLOWED_ORIGINS` takes a comma-separated list with no spaces, defaulting in the example to the production domain plus `http://localhost:3000`. Prerequisites are Node LTS and pnpm.

The split of responsibilities is sensible. Upstash Redis holds the watchlists, which is server-side state you want to survive a refresh and a device change. AlphaVantage supplies the actual market data, and its free tier is rate-limited, which is the whole reason the simulation exists. The OpenAI key is for the AI features the README mentions in passing rather than details.

`package.json` names the packages behind each of those: `@upstash/redis` for storage, the Vercel AI SDK with `@ai-sdk/openai` and the `ai` package for the model calls, `@tanstack/react-query` for server state, and `zustand`-era local state handled by Jotai, which appears in the README's stack list and in the `atoms` directory under the components tree.

One thing the README does not give you is a seed dataset. With a fresh Redis instance the watchlist is empty, so the most interesting view is the one you have to populate by hand.

## Components organised by role instead of by page

The component tree is the most transferable part of the repository, and the README explains the organising philosophy explicitly. Everything terminal-specific lives under `components/bloomberg`, split into four roles.

`core` holds the foundational terminal UI, including the buttons and modals, and the interaction components such as keyboard shortcuts and the watchlist. `layout` defines the frame: terminal container, header, footer, navigation. `ui` holds the visualisation pieces, tables and sparklines, plus terminal elements that do not belong to core. `views` holds complete screens, the market view, the news view, the volatility view.

Underneath those sit `api` for market data fetching and simulation, `atoms` for Jotai state, `hooks` for data fetching and UI state, `lib` for terminal utilities and configuration, and `providers` for the React Query and other global context.

The distinction between `core`, `ui` and `views` is the part that generalises past this project. A terminal is a dense layout with a small number of screens, so the reusable pieces are the widgets in the frame, and a screen is an assembly of them. Getting that boundary right is most of the work in a dense UI, and this repository has made the decision explicitly rather than by accident.

Outside that folder, `components/ui` is the unmodified shadcn/ui base layer and `lib` at the root is application-wide shared code. Keeping those separate is what stops a terminal-specific change from leaking into the design system.

## Why it is a single page application with no URL structure

The README offers a one-sentence justification for the architecture that is more interesting than the architecture itself. It is structured as an SPA because for a terminal with constantly mutating financial data, URL structure and browser history have limited utility compared with a traditional page-based approach.

The argument holds up. In an application where the meaningful state is which view is active and what the watchlist contains, a route per screen buys you shareable links that nobody wants, since a colleague opening your market view URL would not see your selection or your scroll position. It also costs you a routing layer you would then have to keep in sync with keyboard shortcuts.

The consequence is that view state lives in Jotai atoms rather than in the router, and the keyboard shortcut handler is a first-class component in `core` rather than a route change. For a dense interface where an analyst expects to move between views without the browser's back button behaving oddly, that is the right trade.

The cost is the ordinary SPA cost: no deep links, no per-view sharing, and a harder time with browser back behaviour after a modal opens. The README does not mention how it handles back navigation, which is the question I would want answered before adopting this pattern.

## The security section is short and points at real concerns

The README lists five security measures, and they are the right five for an application with a model API behind it.

Origin restriction limits which domains can call the API routes, configured through the comma-separated `ALLOWED_ORIGINS` variable. Rate limiting caps requests per IP address. Input validation runs every API input through Zod schemas, and `zod` is in the dependency list. Response limiting caps AI responses in token count, which is both a cost control and an abuse control. And the sensitive keys stay in environment variables rather than reaching the client bundle.

Together those address the realistic failure modes for this shape of application: someone else's page driving your API and your model bill, and malformed input reaching a route that shells out to a data provider. The origin check is the weakest of the five as a security boundary, since an allowlist of origins is trivially bypassed by a server-side caller, but it does stop the browser case, which is the common one.

Rate limiting per IP is also the wrong granularity if your users are behind a shared NAT, which in a corporate environment is most of them. The README does not say whether the limiter keys on IP alone.

## Maintenance state and what this repository is for

Here the facts are thin, and it is better to say so than to guess. The repository has no tagged releases, and its last push was on 2026-03-05. The README states the project is MIT licensed, but there is no LICENSE file in the tree, so the licence claim rests on the README text alone.

Given that, the sensible way to use this project is as a reference implementation. Read the view components to see how a market table, a sparkline and a news list are laid out inside a fixed terminal frame. Read the API layer to see how a real provider is wrapped with simulation to stay inside a rate limit. Copy the component role split if it helps you. Do not plan a product on top of it.

The alternatives worth naming are not other GitHub clones. The real Bloomberg Terminal is a licensed product with instrument coverage, entitlements and support that no open interface can approach, and the SERP data for this project shows people searching for its price, its login and free alternatives, which is the right question to keep asking rather than the wrong repository to clone. If you want free market data in a browser, the honest answer is to combine a real provider key with a charting library and accept the data licensing terms.

What this repository offers that those do not is a complete, readable example of the dense financial interface pattern, and for that it is more useful than its simulation layer is misleading.

## Conclusion

This project is worth reading if you are building a dense, keyboard-driven financial interface and want to see how the layout, the view switching and the data refresh cycle are put together, because the component tree under `components/bloomberg` is organised by role rather than by page. It is not a market data product and should not be mistaken for one: the README states the updates are simulated to avoid hitting the AlphaVantage limit, which means every price on screen is a placeholder between fetches. It also has no licence file, its last push was on 2026-03-05 and it ships no tagged releases, so treat it as a study project rather than something to fork into production. If you want the real thing, the questions to ask a vendor are about instrument coverage and entitlements, not about React version.

## FAQ

### Is the market data in this Bloomberg Terminal clone real?

No, and the README says so. The feature list describes simulated market updates with configurable refresh rates, and the project description explains that local simulations are used alongside AlphaVantage data to avoid hitting the API limit too often.

### What stack is this Bloomberg Terminal clone built on?

Next.js 15 with the App Router, React 19 with shadcn/ui components, Tailwind CSS for styling, Jotai for local state and React Query for server state, Upstash Redis for storage, Motion for animation and Biome.js for linting and formatting.

### What environment variables does this project need?

Four keys plus an origin policy: `UPSTASH_REDIS_REST_URL` and `UPSTASH_REDIS_REST_TOKEN` for storage, `ALPHA_VANTAGE_API_KEY` for market data, `OPENAI_API_KEY` for the AI features, and `ALLOWED_ORIGINS` as a comma-separated list of allowed origins. Node LTS and pnpm are the stated prerequisites.

### How is this project different from the real Bloomberg Terminal?

The real terminal is a licensed product with instrument coverage, entitlements and vendor support. This is a front-end study built with Next.js and React whose market updates are simulated and whose watchlists live in Upstash Redis, so it is a UI reference rather than a market data source.

### Does this project protect its API routes?

The README lists five measures: origin restriction through `ALLOWED_ORIGINS`, per-IP rate limiting, Zod schema validation on all API inputs, token limits on AI responses to control cost and abuse, and keeping sensitive keys in environment variables rather than the client bundle.

## Sources

- [feremabraz/bloomberg-terminal on GitHub](https://github.com/feremabraz/bloomberg-terminal)
- [Issues](https://github.com/feremabraz/bloomberg-terminal/issues)
- [Project website](https://bloomberg-terminal-nine.vercel.app)
- [README](https://github.com/feremabraz/bloomberg-terminal/blob/main/README.md)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/feremabraz-bloomberg-terminal
