This is a TypeScript monorepo for applications on the Tempo blockchain applications. Applications in this repo run on Cloudflare, unless explicitly declared otherwise.
| Workspace | Description |
|---|---|
apps/explorer |
Chain explorer UI |
apps/fee-payer |
Transaction fee sponsorship service |
apps/key-manager |
WebAuthn key management service |
apps/tokenlist |
Token registry API |
apps/contract-verification |
Smart contract verification |
apps/og |
OpenGraph image generation |
pnpm install # Install all dependencies
pnpm check # Run Biome lint + format (with auto-fix), then type check (via postcheck)
pnpm check:types # Type check all workspaces (uses tsgo, the native TypeScript compiler)
pnpm build # Build all apps- ✅ Type check:
pnpm check:types- ZERO errors - ✅ Lint/Format:
pnpm check- ZERO errors (auto-fixes applied) - ✅ Tests pass:
pnpm testin affected apps - ✅ Pre-commit hooks pass:
pnpm precommit
- You must use wagmi, viem, or ox to interact with tempo
- When adding a new dependency, look at other apps and see if there is a similar dependency
- Type imports: Use
import typefor type-only imports - Props pattern: Use namespace declarations for component props:
export function MyComponent(props: MyComponent.Props): React.JSX.Element {
// ...
}
export declare namespace MyComponent {
type Props = {
value: string
optional?: string | undefined
}
}- Function components only (no classes)
- Explicit return type
React.JSX.Element - Use
cx()helper for conditional classNames (from#lib/css) - Icons from
unplugin-icons:import XIcon from '~icons/lucide/x'
- Use Tailwind v4 syntax
- Custom variants:
@custom-variant,@theme - Prefer utility classes over custom CSS
- Understand which app(s) you're modifying
- Check existing patterns in similar files
- Identify affected tests
- Run
pnpm checkfrom repo root - Run
pnpm check:typesfrom repo root - Fix ALL type/lint errors before proceeding
- Run tests in affected apps:
pnpm test - Only THEN declare task complete
- All above checks must pass
- All related tests must pass
- No outstanding type or lint errors
- No console.log statements left (except in tests)
When creating PRs that include UI changes (e.g., apps/explorer), include a before/after comparison table in the PR description:
## Screenshots
| Before | After |
|--------|-------|
|  |  |Add multiple rows if the change affects different views or states.
- Create a new directory under
apps/ - Add a
package.jsonwith scripts:dev,build,check,check:types - Add a
tsconfig.jsonextending strict TypeScript settings - Add a
wrangler.jsonfor Cloudflare Workers deployment - Add
.env.examplewith required environment variables - Update this file's "Existing Apps" table
apps/my-app/
├── src/
│ └── index.ts # Entry point
├── package.json # Must include standard scripts
├── tsconfig.json # TypeScript config
├── wrangler.json # Cloudflare Workers config
└── .env.example # Environment template{
"scripts": {
"dev": "vite dev",
"build": "vite build",
"check": "pnpm check:biome && pnpm check:types",
"check:biome": "biome check --write --unsafe",
"check:types": "tsgo --project tsconfig.json --noEmit",
"gen:types": "wrangler types"
}
}Note:
devvaries per app (e.g.,wrangler devfor worker-only apps). Adapt to fit the app's runtime.
You can find the documentation for common libraries at the following links:
- Cloudflare Workers
- TanStack Start
- TanStack Router
- React
- Tailwind CSS v4
- Wagmi React reference
- Wagmi Tempo reference
- Viem general reference
- Viem Tempo reference
- Ox
- Hono
- Zod
To capture a page load from the very first frame using MCP tools:
- Navigate to about:blank first to reset the page state
- Call
navigate_pageandtake_screenshotin parallel - usetimeout=0on navigate so both execute simultaneously - Continue taking sequential screenshots for the remaining frames
- Combine frames with ImageMagick:
magick -delay 50 -loop 0 /tmp/frame_*.png -resize 650x /tmp/recording.gif - Upload to imgbb:
curl --location --request POST "https://api.imgbb.com/1/upload?key=API_KEY" --form "image=@/tmp/recording.gif"
Example parallel tool call (MCP pseudo-syntax, not bash):
navigate_page(url="https://...", timeout=0)
take_screenshot(filePath="/tmp/frame_01.png")Then sequential screenshots for frames 02-10, combine, and upload.