算法艺术创作
algorithmic-art
通过代码和可调参数创作生成艺术与交互式视觉效果。
backend-building【设计与创意】Backend building that grafts tRPC + Drizzle ORM + Hono onto an existing webapp-building frontend. Supports incremental features (db, auth). Use when the user needs a backend, API, database, server, authentication, or wants to add tRPC/Drizzle to their webapp-building project. Requires webapp-building first.
独立 GitHub 快照 · 自动分类 · 以原作者文档为准
Stack: tRPC + Drizzle ORM + Hono + MySQL + OAuth 2.0
A backend-only skill that grafts onto an existing webapp-building project. It adds api/, contracts/ directories and optionally db/ — but never replaces or modifies existing frontend files.
Prerequisite: An existing project created by webapp-building.
Features can be installed incrementally. Base infrastructure (Hono server, tRPC, contracts) is always installed automatically on first run.
| Feature | What it provides | Dependencies |
|---|---|---|
db | Drizzle ORM + MySQL — adds db/, api/queries/connection.ts, drizzle.config.ts | — |
auth | Kimi OAuth + user management — adds api/kimi/, Login page, useAuth, AuthLayout | requires db (auto-included) |
Default: init.sh "App" with no --features → defaults to auth (= db + auth), preserving backward compat.
Frontend-first (recommended when UI is already built):
webapp-building init → develop UI pages and componentsbackend-building graft (this skill) — auto-wires tRPC providers and routesnpm run check, then add tRPC routers, database tables, wire frontend to APIFull-stack from scratch (recommended when backend is needed immediately):
webapp-building init → immediately graft backend-buildingnpm run checkIncremental features (add capabilities over time):
--features db for database onlyinit.sh "App" --features authbash /app/.agents/skills/webapp-building/scripts/init-webapp.sh "My App"
cd /mnt/agents/output/app
# Full stack with auth (default, same as before):
bash /app/.agents/skills/backend-building/scripts/init.sh "My App"
# Database only (no auth):
bash /app/.agents/skills/backend-building/scripts/init.sh "My App" --features db
# Add auth later:
bash /app/.agents/skills/backend-building/scripts/init.sh "My App" --features auth
What this does (base, always on first run):
api/, contracts/ into the projectvite.config.ts in-place (adds @contracts alias, envDir, build.outDir)tsconfig.server.json and merges @contracts/* path into existing tsconfigspackage.json (adds backend deps and scripts).env with portal credentialsnpm installAdditional per feature:
db/ directory, drizzle.config.ts, database connection, DATABASE_URL env var, and db/seed.ts (scaffold for seeding — run with npx tsx db/seed.ts). Do not overwrite the generated api/queries/connection.ts, drizzle.config.ts, or .env — they are complete and correct. Only add your tables to db/schema.tsapi/kimi/, auth router, client patches (Login, useAuth, AuthLayout, TRPCProvider), auto-wires Login/NotFound routes into App.tsxnpm run db:push # sync schema to database (recommended for development)
npm run dev
Start development server with HMR at http://localhost:3000
On first run, init.sh auto-wires TRPCProvider into src/main.tsx. When auth feature is installed, it also adds Login/NotFound routes to src/App.tsx. Check the init output:
If manual wiring is needed, it typically means:
import { TRPCProvider } from "@/providers/trpc" to src/main.tsx<BrowserRouter> with <TRPCProvider>src/App.tsxAfter init (and manual wiring if needed), verify everything works:
npm run check — must pass with zero type errorsnpm run dev — server should start at http://localhost:3000| Command | Description | Requires |
|---|---|---|
npm run dev | Start development server with HMR at http://localhost:3000 | base |
npm run build | Build for production (outputs to dist/) | base |
npm start | Start production server | base |
npm run check | Type-check all TypeScript files | base |
npm run format | Format code with Prettier | base |
npm run test | Run tests with Vitest | base |
npm run db:push | Sync schema to DB during development (recommended) | db |
npm run db:generate | Generate migration SQL for production deployment | db |
npm run db:migrate | Apply pending migration files to the database | db |
getDb() connection, ready to usetypeof table.$inferSelect from db/schema.ts to keep types aligned with superjson's Date serialization via tRPC. Hand-written createdAt: string will conflict with the actual Date objects delivered by superjsongetDb().query.*, getDb().select(), getDb().insert())api/lib/ or api/kimi/ — these are framework internals (auth, static file serving). Build on top of them, not inside themapi/ from frontend code — use @contracts/ for types/constants that cross the boundary. The only exception is the type import in src/providers/trpc.tsxapi as the tRPC client name — it's trpc (imported from @/providers/trpc).input(z.object({...})) for mutations and parameterized queriesserial() for foreign key columns — serial() creates bigint unsigned auto_increment, and MySQL only allows one auto-increment column per table. FK columns must use bigint("col", { mode: "number", unsigned: true }) to match the PK typeint() for foreign keys referencing serial() PKs — int is signed 4-byte, serial() is bigint unsigned 8-byte. MySQL rejects the type mismatch. Use bigint("col", { mode: "number", unsigned: true })schema.ts and run npm run db:push to sync. See Troubleshooting belowdb:push --force — it auto-accepts destructive changes (dropping columns/tables) which can destroy user data.env values — .env is generated by init.sh with valid, working credentials. All values (API keys, OAuth URLs, secrets, database URL) are pre-configured and ready to use. Do not overwrite, regenerate, or placeholder-ify themapi/queries/connection.ts, api/middleware.ts, api/lib/, drizzle.config.ts, src/providers/trpc.tsx, and .env are generated by init.sh with correct configuration. Read the init output to see what was created. Build on top of these files (e.g., add routers, schemas), but do not rewrite themhttp://localhost:3000. Do not change this in vite.config.ts, api/boot.ts, or anywhere elseRequired reading before implementing features — read these docs (under docs/) for the features you're working with:
When building features on this stack:
src/ to understand the app structuredb/schema.ts, then run npm run db:push (requires db feature)api/ and register them in api/router.tssrc/ using the existing @/ aliasWhen to use which features:
--features db--features auth (includes db automatically)--features flag) = auth, which is backward compatible| Path | What to do |
|---|---|
src/main.tsx | TRPCProvider auto-wired here (verify after init) |
src/App.tsx | Login/NotFound routes auto-wired here (verify after init, auth feature only) |
src/pages/ | Route-level page components (one per route in App.tsx) |
src/sections/ | Visual sections within a page (Hero, Footer, etc.) — from webapp-building templates |
src/components/ | Create new UI components |
api/router.ts | Register new tRPC routers |
api/queries/ | Add query functions for new tables (db feature) |
db/schema.ts | Add new database tables (db feature) |
contracts/ | Shared types/constants (frontend + backend) |
api/lib/ | Framework internals — don't modify |
api/kimi/ | Kimi SDK modules — don't modify (auth feature) |
Full directory tree: Project Structure
This template uses react-router v7.
// Navigation
import { useNavigate } from "react-router";
const navigate = useNavigate();
navigate("/dashboard");
// Current location
import { useLocation } from "react-router";
const location = useLocation();
console.log(location.pathname);
// Route params
import { useParams } from "react-router";
const { id } = useParams<{ id: string }>();
// Links
import { Link } from "react-router";
<Link to="/about">About</Link>
// Route definitions (in App.tsx)
import { Routes, Route } from "react-router";
<Routes>
<Route path="/" element={<Home />} />
<Route path="/users/:id" element={<UserProfile />} />
<Route path="*" element={<NotFound />} />
</Routes>
// BrowserRouter wraps the app in main.tsx
import { BrowserRouter } from "react-router";
<BrowserRouter>
<App />
</BrowserRouter>
Port 3000 already in use — Another process is using the port. Kill it with lsof -ti:3000 | xargs kill.
Database connection refused — Check DATABASE_URL in .env is correct and MySQL is running. Run npm run db:push before npm run dev.
OAuth callback fails — The callback URL must be {origin}/api/oauth/callback. Verify VITE_KIMI_AUTH_URL and VITE_APP_ID in .env match the portal app config.
npm run db:migrate fails — NEVER drop tables to recover. MySQL doesn't support transactional DDL, so a failed migration can leave the DB in a partial state. To recover:
schema.ts (e.g., correct FK types)npm run db:push — it introspects the actual DB state and syncs it to your corrected schemadb/migrations/meta/_journal.jsonnpm run db:generate to create a clean baseline migrationType errors after adding a new router — Make sure you registered the router in api/router.ts inside appRouter. The AppRouter type is derived from there and propagates to the frontend automatically.