A full-stack exchange simulator with a light trading interface, a price-time matching engine, simulated wallets, double-entry accounting, and live reference market data.
Atlas is built for learning and private demonstration. All funds and trades are simulated. It does not hold real money or cryptocurrency, send orders to an external exchange, or provide brokerage services. Coinbase reference prices are separate from Atlas order execution.
- Local registration, email verification, authentication, rotating sessions, and account security.
- BTC, ETH, and USD wallets with simulated deposits and withdrawals.
- BTC-USD and ETH-USD spot limit orders, cancellation, price-time matching, and atomic settlement.
- Simulated order books, executions, tickers, and candlestick history.
- Separately labeled Coinbase reference prices and candles when the feed is enabled.
- Light/grey Dashboard, Trade, Orders, Portfolio, Funds, and Profile pages.
- Notifications and role-protected, audited administration tools.
There is no automatic liquidity provider: a fill requires a compatible order from another Atlas account. Market orders, real deposits/withdrawals, and external order routing are not supported.
Atlas is a pnpm monorepo. The API is a modular monolith with business-owned modules and explicit public interfaces; sharing a repository does not make applications one deployment.
| Area | Technology |
|---|---|
| Web | React, TypeScript, Vite |
| API | Node.js, Express, TypeScript |
| Persistence | PostgreSQL, Kysely, pg, committed migrations |
| Contracts | Shared TypeScript and Zod schemas |
| Market updates | REST snapshots and WebSockets |
| Tests | Vitest, React Testing Library, Supertest, Playwright |
| Local services | Docker Compose, PostgreSQL, Mailpit |
| Demo hosting topology | Cloudflare Worker + Static Assets, Render API, Neon PostgreSQL |
apps/
web/ React application
api/ API, business modules, and database migrations
gateway/ Cloudflare Worker and static-asset gateway
packages/
contracts/ Shared runtime schemas and transport types
infra/ Local services and deployment configuration
tests/e2e/ Cross-application browser journeys
scripts/ Repository automation and validation
docs/ Architecture decisions and engineering runbooks
- Node.js 24.19.0, matching
.node-version,.nvmrc, andpackage.json. - pnpm 11.20.0, matching the root
packageManagerfield. - Docker with Docker Compose available and running.
Select the pinned Node runtime before installing dependencies. Browser-test dependencies are only needed when running E2E tests.
git clone https://github.com/Ashutosh-code-arch/AtlasExchange.git
cd AtlasExchange
pnpm install --frozen-lockfile
cp apps/api/.env.example apps/api/.env
cp apps/web/.env.example apps/web/.envThe copy commands are for a fresh checkout. Preserve existing .env files and compare them with
the examples instead of overwriting them. Never commit credentials or operator environment files.
The example database credentials are for disposable local development only.
docker compose -f infra/compose.yaml up -d --wait postgres mailpit
pnpm db:migrate
pnpm devKeep the development command running. It builds shared contracts and starts the development tasks.
| Service | Local address |
|---|---|
| Atlas UI | localhost:5173 |
| API | localhost:3000 |
| Mailpit verification/recovery inbox | localhost:8025 |
If PostgreSQL port 5432 is occupied, set ATLAS_POSTGRES_PORT before starting Compose and change
the port in apps/api/.env → DATABASE_URL to match. If you change the API or web port, also update
VITE_API_BASE_URL or WEB_ORIGIN, respectively. Restart the servers after environment changes.
- Open the UI and choose Create account.
- Enter an email address and a password meeting the displayed requirements.
- Open Mailpit and follow the verification link in the captured message.
- Return to Atlas and sign in.
Local messages stay in Mailpit; they are not delivered to a real email inbox. There are no default user or administrator credentials. Local registration is separate from the restricted hosted demo.
Use two distinct verified accounts. Sign out and switch accounts, or use separate browser profiles so their session cookies remain independent. Two ordinary tabs in one profile share an account.
This walkthrough assumes fresh wallets and an empty BTC-USD book. Existing matching orders can change the fill sequence and result.
- Sign in as the seller and open Funds.
- Select BTC, open the BTC wallet, and Add simulated funds of
1BTC. - Select USD and open a USD wallet to receive proceeds.
- Open Trade, select BTC-USD, and submit a Sell limit order for
0.5BTC at50000USD. - Without a matching buyer, the order stays open and
0.5BTC is reserved.
- Sign in as the other account and open Funds.
- Open both USD and BTC wallets; add
60000simulated USD to the USD wallet. - Open Trade, select BTC-USD, and submit a Buy limit order for
0.5BTC at51000USD. - Inspect Orders, executions, and Funds for both accounts.
The buy limit crosses the resting sell order. Execution occurs at the resting order's price:
50000 USD per BTC, so 0.5 BTC costs 25000 simulated USD.
| Account | BTC after settlement | USD after settlement |
|---|---|---|
| Seller | 0.5 |
25000 |
| Buyer | 0.5 |
35000 |
Financial quantities are handled exactly, not with authoritative floating-point money values. Reservation, execution, and ledger settlement are coordinated transactionally.
- Orders can stay open or fill partially when matching liquidity is insufficient.
- A limit is a price constraint, not a promise of execution.
- Self-trading is prevented: when an incoming order encounters its owner's matching resting order, its remaining quantity is cancelled rather than traded with itself.
- Cancelling an open order releases the unfilled reservation; it does not reverse completed trades.
- Simulated withdrawals only change Atlas ledger state. They never transfer funds externally.
This flow is covered by the trading browser journey.
In apps/api/.env, set:
REFERENCE_MARKET_DATA_ENABLED=trueRestart the API. The configured adapter connects to Coinbase's public market-data WebSocket for BTC-USD and ETH-USD without a trading API key. Outbound network access and provider availability are required.
The Trade page labels this as reference data. It is not Atlas liquidity, does not execute orders, and does not determine simulated settlement or portfolio valuation. Atlas's own candles and ticker derive from committed simulated trades, so a fresh exchange may have no trade history. An unavailable external feed is reported as unavailable rather than replaced with an invented price.
Run commands from the repository root:
| Command | Purpose |
|---|---|
pnpm dev |
Run API, web, and contract development tasks |
pnpm db:up / pnpm mail:up |
Start the normal local database / mail service |
pnpm db:migrate |
Apply committed API-owned migrations |
pnpm test |
Run repository and workspace tests, excluding browser E2E |
pnpm verify |
Type-check, lint, check boundaries/formatting, and run tests |
pnpm test:e2e |
Run isolated full-stack browser journeys |
pnpm build |
Build contracts, API, web, and gateway artifacts |
pnpm security:secrets |
Scan source-control candidates for likely secrets |
pnpm db:down |
Stop/remove local Compose containers; retain the database volume |
API integration tests use real PostgreSQL and create/drop uniquely named test databases. Keep local
PostgreSQL running for pnpm test, pnpm verify, and API tests. The default connection matches
Compose; export a custom DATABASE_URL to the test process if needed. Its database role must be able
to create test databases. Never point tests at a hosted, shared, or production server.
Workspaces can be tested independently:
pnpm --filter @atlas/web test
pnpm --filter @atlas/api test
pnpm --filter @atlas/contracts test
pnpm --filter @atlas/gateway testBefore the first browser-test run:
pnpm --filter @atlas/e2e exec playwright install chromium
pnpm test:e2eE2E provisions disposable PostgreSQL and Mailpit services, starts applications on available ports, and cleans up its services afterward. It does not reuse the normal development database. Security scans, performance tests, and deployed-environment checks have separate requirements; see the testing strategy.
The demo topology uses Cloudflare for web assets and the gateway, Render for the API, and Neon for PostgreSQL. Hosted signup and recovery remain disabled by default. The capped-beta implementation supports at most 20 total demo accounts, including existing, pending, and suspended identities. When full, signup stops while existing users can still sign in. Enabling the beta requires working hosted email and the activation checks in the capped-beta runbook. This is not a claim that public signup has been deployed. Use local development for the two-account walkthrough until hosted activation is complete.
A local build, Git push, or local tunnel does not by itself update the hosted UI. Web-only changes need a web build and deployment to the intended Worker. API changes need a new API artifact/deployment; schema changes need explicit migrations. Migrations never run automatically on API startup.
Follow the demo hosting runbook for secrets, environment configuration, deployment targets, and recorded evidence. Verify the Worker name against the existing deployment and preserve its configured variables when deploying; do not assume the checkout's default Worker name identifies the live service.
The hosting policy is zero recurring cost, with no paid-plan or overage authorization. Free-tier availability is not guaranteed. The application is not approved for real trading or custody. See the release runbook for image publication and promotion.
- Identity services cannot be reached / Offline: inspect the API terminal first. Check PostgreSQL,
migrations, and
apps/api/.env. Locally, useNODE_ENV=developmentandATLAS_ENV=local; ensure the web/API origins and ports match. - Database connection fails: check Docker, port conflicts, and
DATABASE_URL. - Verification email missing: check Mailpit,
pnpm mail:logs, and the API SMTP configuration. - Order does not fill: check opposite-side liquidity, compatible prices, and distinct owners. An external reference price is not a counterparty.
- Charts are empty: simulated charts need Atlas trades; reference charts need the enabled, connected external feed. Check the displayed source and freshness state.
- Hosted UI is old: check the deployed Worker and the URL you opened. Local builds do not publish assets.
- Architecture decisions
- Testing strategy
- Interface release acceptance
- Database recovery
- Operational readiness
- Phase delivery and scope
- Documentation governance
Classification: Reference
Status: Active
Last reviewed: 2026-09-04
Canonical owner/source: Accepted architecture decisions and the linked engineering runbooks. This README is an onboarding guide, not a replacement for those decision records.
Atlas Exchange is licensed under the MIT License.
This project is a simulated trading platform for educational and demonstration purposes. It does not execute real trades or provide financial advice.