power-stack
npx skills add https://github.com/avantmedialtd/skills --skill power-stack
Agent 安装分布
Skill 文档
Power Stack
A self-contained blueprint for reconstructing this monorepo stack from scratch.
1. Monorepo Layout
Bun workspaces. Root package.json declares "workspaces": ["apps/*", "packages/*"].
âââ apps/
â âââ api/ # REST backend (Bun + Elysia)
â âââ web/ # SPA frontend (React + Vite)
âââ packages/
â âââ shared/ # Shared types, validators, permission utils
âââ e2e/ # Playwright E2E test suite
âââ openspec/ # Spec-driven change management
âââ docker-compose.yml # PostgreSQL + app + test containers
âââ tsconfig.json # Project references root
âââ vitest.config.ts # Multi-project test config
TypeScript project references: root tsconfig.json uses "files": [] + "references" to delegate to each workspace. Each workspace tsconfig has "composite": true. Type-check with tsc --build --noEmit.
2. Runtime & Language
- Bun 1.x as runtime and package manager (
bun install,bun run) - TypeScript 5.9 with strict mode, ESM everywhere (
"type": "module") - Target: ES2022, module resolution:
bundler experimentalDecorators+emitDecoratorMetadataenabled for TypeORM
3. Backend (apps/api)
Framework
Elysia 1.4 â lightweight Bun-native HTTP framework. Entry point imports reflect-metadata first, initializes TypeORM DataSource, then calls app.listen(port).
App composition via .use() plugin pattern:
new Elysia()
.use(cors())
.get('/health', () => ({ status: 'ok' }))
.use(authRoutes)
.use(adminRoutes);
Route groups use new Elysia({ prefix: '/auth' }) with request body validation via Elysia’s t.Object() schema.
Error Handling
Use set.status pattern, not error():
async ({ body, set }) => {
set.status = 400;
return { error: 'Bad Request', message: 'Details' };
};
Auth Middleware
Elysia .derive() extracts Bearer token from Authorization header, verifies JWT via jose, and injects { user, auth } into context. .macro() defines requireAuth, requireAdmin, and requireAppPermission guards that check permissions and return 401/403.
Database
- PostgreSQL 17 via TypeORM 0.3 with
DataSourceconfig - Connection from env vars:
POSTGRES_HOST,POSTGRES_PORT,POSTGRES_USER,POSTGRES_PASSWORD,POSTGRES_DB synchronize: falsealways, schema changes via migrations only (src/db/migrations/*.ts)- Entities: User (and domain-specific entities as needed)
Entity Conventions
- UUID primary keys (
@PrimaryGeneratedColumn('uuid')) - Explicit column types always (
@Column({ type: 'text' }),@Column({ type: 'boolean' })) @CreateDateColumn({ type: 'timestamptz' })/@UpdateDateColumn- String-based relations to avoid circular imports:
@OneToMany('UserPermission', 'user') - Wrap relation types in
Relation<T>from TypeORM
Auth Flow
- Password hashing: Argon2 via
@node-rs/argon2 - JWT:
joselibrary. Access tokens (short-lived) + refresh tokens (rotated, family-tracked for reuse detection). Revocation on reuse.
Route Groups
| Prefix | Purpose |
|---|---|
/auth |
Register, login, logout, refresh, me, password reset, email verification |
/admin |
User management, app management (requires admin permission) |
4. Frontend (apps/web)
Stack
- React 19 with
react-dom/client(createRoot) - MUI 7 + Emotion for styling
- React Router 7 (
react-router-dom) withBrowserRouter - Vite 7 as dev server and bundler (
@vitejs/plugin-react)
App Structure
src/
âââ main.tsx # Entry: StrictMode > ThemeModeProvider > BrowserRouter > AuthProvider > App
âââ App.tsx # Route definitions
âââ theme.ts # MUI createTheme (dark-only, neon brutalist)
âââ api/
â âââ authFetch.ts # Fetch wrapper with auto token refresh
â âââ admin.ts # Admin API calls
âââ context/
â âââ AuthContext.tsx # Auth state (login, register, logout, permissions)
â âââ ThemeContext.tsx # Theme mode provider
âââ pages/ # Route pages (Login, Register, Dashboard, admin/*)
âââ components/ # Shared components (AdminRoute, Logo, etc.)
Auth Client Pattern
AuthContext stores JWT tokens in localStorage (accessToken, refreshToken, tokenExpiresAt). authFetch wraps fetch() to:
- Proactively refresh if token expires within 60s
- Add
Authorization: Bearerheader - Retry once on 401 after refresh
- Dispatch
auth:logoutcustom event on unrecoverable failure
Proactive refresh timer runs every 13 minutes. Visibility change handler refreshes on tab focus if token is near expiry.
Theme
Dark-only neon brutalist design: borderRadius: 0 everywhere, heavy borders (2-4px), box shadows offset to bottom-right (4px 4px 0 #000), hover transforms (translate(-2px, -2px)), uppercase headings/buttons with tight letter-spacing. Palette: deep navy backgrounds (#0f0f23, #1a1a2e), indigo primary (#6366f1), amber secondary (#f59e0b), neon green success (#00ff88), hot pink error (#ff3366).
Production
Vite builds static files. Served by nginx:alpine with a custom nginx.conf.
5. Shared Package (packages/shared)
Pure TypeScript, no runtime dependencies. Exports via subpath: . (root), ./types, ./utils. Contains shared types, interfaces, and utility functions used by both backend and frontend. Built with tsc to dist/.
6. Testing
Unit Tests
Vitest 4, configured as multi-project workspace in root vitest.config.ts. Three projects: shared, api, web. Each runs src/**/*.test.ts files. Run with bun run test.
E2E Tests
Playwright 1.58 in a dedicated e2e/ package. Three categories:
*Api.spec.tsâ API-only (no browser)*.spec.tsâ UI tests (Chromium + mobile viewports)visual-*.spec.tsâ Visual regression (baselines ine2e/tests/visual-baselines/)
Runs in Docker Compose with --profile testing: spins up PostgreSQL, API, web (nginx), runs migrations, then executes Playwright.
7. Docker
API Container
Multi-stage oven/bun:1 image:
depsâ install workspace dependenciesbuildâ copy source, build shared packagerunnerâ copy built artifacts, runbun run src/index.tsdirectly (no compile step for API)
Web Container
Multi-stage build, final stage is nginx:alpine serving the Vite output from /usr/share/nginx/html.
Compose Services
| Service | Image/Build | Purpose | Profile |
|---|---|---|---|
postgres |
postgres:17-alpine | Database | (default) |
api |
apps/api/Dockerfile | REST backend | apps, testing |
web |
apps/web/Dockerfile | Static frontend (nginx) | apps, testing |
migrate-seed |
(same as api) | Run migrations once | testing |
e2e |
e2e/Dockerfile | Playwright test runner | testing |
Health checks on all services. E2E waits for postgres + api + web to be healthy before running.
8. CI/CD
Jenkins pipeline (Groovy Jenkinsfile):
- Checkout â clean workspace, full clone
- Install â
bun installper workspace - Unit test â
bun run test - E2E â Docker Compose up with testing profile, run Playwright, publish HTML report
- Deploy â SSH to production server,
git pull && docker compose --profile apps up -d --build
9. Code Quality
| Tool | Config | Purpose |
|---|---|---|
| oxlint | oxlint . |
Fast Rust-based linter |
| Prettier | prettier --write . |
Code formatting |
| tsc –build | Project references mode | Type checking |
10. OpenSpec
Spec-driven change management. Initialize with bunx openspec init. Structure:
openspec/
âââ config.yaml # Schema and project context
âââ specs/ # Living specifications (one dir per feature)
âââ changes/ # Change proposals and artifacts
âââ archive/ # Completed changes
Each feature has a spec.md describing its current state. Changes go through a structured workflow: proposal â artifacts (tasks, delta specs) â implementation â verification â archive. Specs are updated as changes land.
11. Key Dependencies Summary
Backend
| Package | Purpose |
|---|---|
| elysia | HTTP framework |
| @elysiajs/cors | CORS middleware |
| typeorm | ORM (PostgreSQL) |
| pg | PostgreSQL driver |
| jose | JWT signing/verification |
| @node-rs/argon2 | Password hashing |
| reflect-metadata | TypeORM decorator support |
Frontend
| Package | Purpose |
|---|---|
| react / react-dom | UI library |
| @mui/material | Component library |
| @emotion/react | CSS-in-JS (MUI peer dep) |
| @emotion/styled | Styled components |
| @mui/icons-material | Icon set |
| react-router-dom | Client routing |
| vite | Dev server + bundler |
Dev Tooling
| Package | Purpose |
|---|---|
| typescript | Type checking |
| vitest | Unit test framework |
| @playwright/test | E2E test framework |
| oxlint | Linting |
| prettier | Formatting |
| bun run –parallel | Parallel dev scripts (built-in) |