surf-app

Installation
SKILL.md

Surf App

Build full-stack crypto data apps with create-surf-app and @surf-ai/sdk.

  • This skill: Build a web app / dashboard / visualization with crypto data.
  • The surf skill: Research, investigate, or fetch data via CLI (no web UI).

Scaffold and Start

Run these commands exactly — do not modify or skip steps:

# 1. Scaffold (ports auto-configured from environment)
npx create-surf-app .

# 2. Install dependencies
npm install --prefix backend
npm install --prefix frontend

# 3. Read the project rules BEFORE writing any code
cat CLAUDE.md

# 4. Start dev servers (backend first, then frontend)
npm run dev --prefix backend &
npm run dev --prefix frontend

# 5. Verify backend is running (port is in frontend/.env)
curl -s http://localhost:$(<frontend/.env grep VITE_BACKEND_PORT | cut -d= -f2)/api/health

IMPORTANT — do NOT:

  • Use npx vite or npx vite --port ... — always use npm run dev
  • Pass --port flag to dev commands — port is pre-configured in frontend/.env
  • Restart dev servers after npm install — Vite auto-discovers new deps, backend uses node --watch

Then read the generated CLAUDE.md at the project root — it has the full SDK reference, built-in endpoints, and rules for which files not to modify.

After npm install, also read SDK and theme docs for detailed patterns:

  • cat frontend/node_modules/@surf-ai/sdk/README.md — database (Drizzle ORM), cron jobs, web search, data strategy (market vs exchange), backend composition patterns
  • cat frontend/node_modules/@surf-ai/theme/CHARTS.mdMUST read before writing any ECharts code — Surf flat style contract, tooltip formatter, chart colors, time series tabs
  • cat frontend/node_modules/@surf-ai/theme/DESIGN-SYSTEM.md — Surf semantic tokens (bg/fg/border), tag colors, visualizer palette

Project Structure

frontend/src/App.tsx           ← Main UI, build here
frontend/src/components/       ← Add components
backend/routes/*.js            ← API routes (auto-mounted at /api/{name})
backend/db/schema.js           ← Database tables (Drizzle ORM)
CLAUDE.md                      ← Project rules (READ FIRST)

Do not modify: vite.config.ts, server.js, entry-client.tsx, entry-server.tsx, index.html, index.css.

Workflow: Data Discovery → Code

Always start by exploring available data with the surf CLI, then map directly to SDK code. The CLI → SDK mapping is mechanical (see Step 2). Do NOT run node -e to test individual endpoints.

Step 1: Discover endpoints with CLI

surf sync                                    # Download API spec (first time)
surf list-operations -g                      # List all endpoints by category
surf market-price --help                     # See params, enums, response schema
surf market-price --symbol BTC --time-range 7d   # Fetch sample data, verify shape

CLI flags use kebab-case (e.g. --time-range). surf is a global command (NOT npx surf).

Step 2: Check SDK exports before writing code

Do not guess hook or method names. After npm install, read actual exports:

grep -o 'function use[A-Za-z]*' frontend/node_modules/@surf-ai/sdk/dist/react/index.js | sort

Naming convention — CLI → SDK:

  • CLI: surf market-ranking --limit 5 → Frontend: useMarketRanking({ limit: 5 }) or useInfiniteMarketRanking({ limit: 5 })
  • CLI: surf market-ranking --limit 5 → Backend: dataApi.market.ranking({ limit: 5 })
  • CLI flags are kebab-case (--time-range), SDK params are snake_case ({ time_range: '7d' })

Key rules:

  • Use exact hook names from the grep output — if only useInfinite* exists (no plain use*), use the infinite version and access data.pages[0] for the first page
  • Backend: const { dataApi } = require('@surf-ai/sdk/server') — method names match CLI commands (surf market.pricedataApi.market.price())
  • Escape hatch: dataApi.get(path, params) if a typed method doesn't exist

Step 3: Write code

Write frontend and backend code using the confirmed names from Step 2. Do not run additional node -e calls to test individual endpoints — the SDK methods are guaranteed to work if the name exists in the export list.

Frontend — SDK Hooks

import { useMarketPrice } from '@surf-ai/sdk/react'

const { data, isLoading } = useMarketPrice({ symbol: 'BTC', time_range: '1d' })
// data.data → items array; data.meta → pagination/credits

The /proxy/* route is built-in — hooks automatically call /proxy/market/price which the Express backend forwards to the data API. No manual fetch needed.

Backend — dataApi

// backend/routes/portfolio.js → /api/portfolio
const { dataApi } = require('@surf-ai/sdk/server')
const { Router } = require('express')
const router = Router()

router.get('/', async (req, res) => {
  const data = await dataApi.wallet.detail({ address: req.query.address })
  res.json(data)
})

module.exports = router

Escape hatch: dataApi.get('any/path', params) / dataApi.post('any/path', body).

Built-in endpoints (do not recreate): /api/health, /api/__sync-schema, /api/cron, /proxy/*.

Styling

Tailwind CSS 4 + @surf-ai/theme (dark default). Use shadcn/ui components (npx shadcn@latest add button), echarts-for-react for charts, lucide-react for icons. All pre-installed.

Weekly Installs
3
GitHub Stars
13
First Seen
8 days ago
Installed on
opencode3
gemini-cli3
deepagents3
antigravity3
github-copilot3
codex3