A public registry for browsing deployed Stellar smart contracts, built with React Router v7 and deployed to Cloudflare Workers.
Copy the example env file and start the dev server:
cp .dev.vars.example .dev.vars
npm install
npm run devThe dev server runs at http://localhost:5173 using the Cloudflare Workers
runtime locally (via miniflare), so behaviour matches production.
| Command | Description |
|---|---|
npm run dev |
Start local dev server |
npm run build |
Production build |
npm run typecheck |
Type-check (generates CF + RR types first) |
npm run lint |
Run ESLint |
npm run format |
Run Prettier |
npm run cf-typegen |
Regenerate Cloudflare types from wrangler.jsonc |
npm run generate:registry-client |
Regenerate clients/registry-client from the deployed Registry contract |
- React Router v7 (SSR framework mode)
- TanStack Query — client-side caching; loaders provide
initialData - Cloudflare Workers — edge-deployed, no cold starts
- CSS Modules — no Tailwind; design tokens in
app/app.css - shadcn/css — copy-paste components (badge, button, card, input)
Merges to main automatically deploy via GitHub Actions. A single worker serves
all environments — the network config (API URL, network label) is derived from
the request hostname at runtime. Custom domains are configured once in the
Cloudflare dashboard.
app/
routes/
_index.tsx # / — hero + search + about
contracts._index.tsx # /contracts — contract list with search
contracts.$contract_name.tsx # /contracts/:contract_name — contract detail
wasms._index.tsx # /wasms — WASM list with search
wasms.$wasm_name.tsx # /wasms/:wasm_name — WASM detail
api.$.tsx # /api/* — server-side proxy to backend API
components/ # Shared UI components
lib/
api.ts # API client (uses /api proxy client-side)
queries.ts # TanStack Query queryOptions
types.ts # TypeScript types
entry.server.tsx # SSR entry point
root.tsx # Root layout
app.css # Global styles and design tokens
workers/
app.ts # Cloudflare Worker entry
clients/
registry-client/ # Generated Registry contract bindings (see below)
wrangler.jsonc # Cloudflare config (vars + env per network)
Data is fetched from the Stellar Registry Indexer API. The base URL is set per
environment via the REGISTRY_API_URL variable in wrangler.jsonc. All
client-side requests are proxied through /api/* to avoid CORS issues.
app/lib/deploy.ts (the "Deploy a contract using this Wasm" flow) talks to the
Registry contract itself through generated TypeScript bindings at
clients/registry-client, an npm workspace package (registry-client) — not
hand-written. It's checked in, so you don't need to regenerate it just to work
on the app.
Regenerate it after a Registry contract release with:
npm run generate:registry-clientThis runs two steps under the hood:
stellar registry download registry -o /tmp/registry.wasm --network testnet -s me— fetches the currentregistryWasm (the Registry contract publishes itself into the registry, channelroot) via thestellar-registryCLIstellar contract bindings typescript --wasm /tmp/registry.wasm --output-dir clients/registry-client --overwrite— regenerates the client package from that binary viastellar-cli
Requires both CLIs installed (cargo install --locked stellar-registry-cli,
cargo install --locked stellar-cli or equivalent) and a configured identity
for -s/--source-account (e.g.
stellar keys generate me --network testnet --fund) — download simulates a
read call, which still needs a source account. The contract's interface is the
same on testnet and mainnet (deployed deterministically, see
app/lib/network.ts), so generating from testnet is fine either way.