Lucky Cat

Tier 3 ChirpUI capstone — simulated trading-floor demo on server-owned signals

Page actions AI-ready formats and sharing
Open LLM text
Share with AI
Ask Claude Ask ChatGPT Ask Gemini Ask Copilot

What it is

Lucky Cat is the tier 3 capstone example: $MEOW, a simulated Maneki-neko trading floor built entirely on Chirp and ChirpUI. Full pages, HTML fragments, a streaming portfolio dashboard, and a live cross-page ticker — with no client-side framework and no build step. Prices, fills, and balances are simulated in memory, so you can clone it, run it offline, and read the code.

Reach for it when you want to see how a real, multi-page product wires return types, live server state, and the secure-by-default stack together.

Live demo: luckycat-production.up.railway.app

Location:examples/chirpui/lucky_cat/

It ships:

  • a full-viewport app shell — brand topbar, cross-page ticker strip, and a collapsible navigation rail
  • a Markets Home lobby and a market-detail page (/markets/{symbol}) with a server-rendered SVG price chart, a depth-bar order book, and a recent-trades tape
  • a place/cancel-order trade flow built on Chirp return types
  • a Suspense portfolio dashboard whose panels paint as skeletons and stream in as their data resolves
  • a cross-page ticker, balance, and notification bell bound to server-owned signals over one SSE connection
  • public-browse / gated-trading authentication across three gating levels

What this replaces

If you would reach for React/Next (or a separate SPA + API) for a trading-floor product UI, Lucky Cat shows the Chirp alternative.

Concern Typical React / Next stack Lucky Cat on Chirp
Tooling npm install, bundler, build step, node_modules No build step, nonode_modules— Python + static CSS/JS only
Live chrome Client state + WebSocket or client-managed SSE handlers Server-ownedsignal() values on one /_chirp/liveSSE connection
Navigation Client router, hydration, layout re-fetch Boosted htmx swaps#main; server re-renders the rail from the current path
Forms & validation Client form lib + separate API routes Return type as intent in one handler:ValidationError (422) or FormAction
Page-local live data WebSocket subscriptions + client reconciliation EventStreampushes HTML fragments — no client state graph
Slow dashboard Loading spinners or client suspense boundaries Suspense: shell paints with skeletons, panels stream as OOB swaps resolve
Auth JWT in storage, client route guards Session cookie,@login_required, AuthMiddlewarein the secure stack
Charts Chart.js / Recharts in the browser Server-rendered SVG — no JS chart library
Deploy surface Node server (+ often a separate API tier) Single Python process; demo pinsworkers=1for in-memory state
Tests Jest/RTL + mocked fetch/WebSocket pytest against a deterministic SimFeed— offline, CI-safe
Real exchange / web3 Wallet-connect, chain RPC, matching engine Out of scope — simulated prices, in-memory wallet, no chain

Try it

Run the example, test it, or scaffold the same foundation for a new app.

pip install "bengal-chirp[ui]"
PYTHONPATH=src python examples/chirpui/lucky_cat/app.py
# open http://127.0.0.1:8000/  —  sign in with neko / luckycat to trade
pytest examples/chirpui/lucky_cat/
pip install "bengal-chirp[ui]"
chirp new myapp --shell
cd myapp && python app.py

Browsing the markets needs no account. Sign in (demo creds:neko/ luckycat) to trade, deposit, and view your portfolio. chirp new --shell wiresuse_chirp_ui(app), boosted navigation, and the secure-by-default stack — the same foundation Lucky Cat builds on.

Authentication

Lucky Cat is public-browse, gated-trading: anyone can browse the markets grid and a coin's detail page, but the account section and every mutation require sign-in. It shows the full range of gating, not a blanket lock:

  • Full-page gating@login_required on the account handlers (/trade, /portfolio, /activity, /markets/favorites, /settings). An anonymous hit is a 302 to/login?next=<path>.
  • Component gatingcurrent_user()conditionals: the topbar swaps "Sign in" for the user menu, and the watchlist star on the public grid becomes a "sign in to star" link.
  • Action gating@login_requiredon the mutation routes as the backstop.

How it's wired

Deploy it

The example ships aDockerfile and railway.tomlso it runs as a standalone Railway service:python app.py binds 0.0.0.0:$PORTthrough AppConfig.from_env(), and the healthcheck targets /health.

See Production Deployment for the full production shape.

Source

Build along

Build a Live Trade Panel in 20 Minutes — a from-scratch walkthrough of the markets grid (Page at GET /) and the POST /trade/order return-type pair (ValidationError422 in place → FormActionmulti-target OOB). Grounded in this example's real code paths.