clawfire 0.1.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -2,56 +2,183 @@
2
2
 
3
3
  **AI-First Firebase App Framework — Speak. Build. Deploy.**
4
4
 
5
- Clawfire는 "말하면 완성되는 Firebase 앱 플랫폼"입니다. 코드를 작성하지 않고, AI(Claude Skills)에게 말하며 앱을 만듭니다.
5
+ [![npm version](https://img.shields.io/npm/v/clawfire)](https://www.npmjs.com/package/clawfire)
6
+ [![license](https://img.shields.io/npm/l/clawfire)](./LICENSE)
7
+
8
+ Clawfire lets you build Firebase apps by talking to AI. Define your API contracts with Zod, and get type-safe routing, auto-generated clients, security rules, and deployment — all from a single source of truth.
9
+
10
+ ---
6
11
 
7
12
  ## Features
8
13
 
9
- - **Contract-based API** — Zod 스키마로 input/output 계약 정의
10
- - **File-based Routing** — `app/routes/` 디렉터리 = API 경로
11
- - **Auto Client Generation** — 타입 안전한 `api.xxx.yyy()` 클라이언트 자동 생성
12
- - **Firebase-Only Stack** — Firestore, Auth, Functions, Hosting 완전 통합
13
- - **Security by Default** — 입력 검증, CORS, Rate Limit, 로그 마스킹 기본 제공
14
- - **AI Skills System** — `/clawfire-*` 커맨드로 프로젝트 관리
15
- - **API Playground** — 기반 API 탐색기 내장
16
- - **Auto Security Rules** — 모델 정의에서 Firestore Rules 자동 생성
14
+ - **Contract-based API** — Define input/output with Zod schemas. Runtime validation, type safety, and docs come for free.
15
+ - **File-based Routing** — `app/routes/todos/create.ts` becomes `POST /api/todos/create`. No configuration.
16
+ - **Page Routing** — `app/pages/about.html` becomes `/about`. Layouts, components, and SPA navigation built in.
17
+ - **Layouts & Components** — `_layout.html` wraps pages via `<slot />`. `<c-nav />` inserts `app/components/nav.html`.
18
+ - **SPA Navigation** — Internal links swap page content without full reload. Tailwind CSS via CDN.
19
+ - **Two-Port Dev Server** — Frontend app on port 3000, API + Playground on port 3456. One command.
20
+ - **Hot Reload** — API, page, and CSS changes reload instantly. No manual refresh needed.
21
+ - **API Playground** — Interactive API explorer auto-generated from your route definitions.
22
+ - **Auto Client Generation** — Type-safe `api.todos.create({ title })` client generated from your contracts.
23
+ - **Firebase-Native** — Firestore, Auth, Functions, Hosting. Fully integrated, no alternatives needed.
24
+ - **Security by Default** — Input validation, CORS deny, rate limiting, XSS sanitization, log masking — all ON.
25
+ - **Auto Security Rules** — Firestore rules generated from model definitions.
26
+ - **AI Skills** — Six `/clawfire-*` Claude Code commands to manage your entire project.
27
+
28
+ ---
17
29
 
18
30
  ## Quick Start
19
31
 
32
+ ### 1. Create a New Project
33
+
20
34
  ```bash
21
- # 프로젝트 초기화
35
+ mkdir my-app && cd my-app
22
36
  npx clawfire init
37
+ npm install
38
+ ```
23
39
 
24
- # 또는 기존 프로젝트에 설치
25
- npm install clawfire
40
+ ### 2. Start the Dev Server
41
+
42
+ ```bash
43
+ npm run dev
26
44
  ```
27
45
 
28
- ## Usage
46
+ This starts **two servers** in a single process:
29
47
 
30
- ### Define a Model
48
+ ```
49
+ ⚡ Clawfire Dev Server
50
+ ─────────────────────────────────────
51
+ App : http://localhost:3000
52
+ API : http://localhost:3456/api/...
53
+ Playground : http://localhost:3456
54
+ Pages : ON (app/pages/)
55
+
56
+ Routes (5):
57
+ POST /api/health [public] Health check endpoint
58
+ POST /api/todos/create [public] Create a new todo
59
+ POST /api/todos/delete [public] Delete a todo
60
+ POST /api/todos/list [public] List all todos
61
+ POST /api/todos/update [public] Update a todo
62
+
63
+ Hot Reload : ON
64
+ Watching: app/routes/, app/schemas/, app/pages/, app/components/, public/
65
+ ```
31
66
 
32
- ```typescript
33
- // app/schemas/product.ts
34
- import { defineModel } from "clawfire";
67
+ ### 3. Open in Your Browser
35
68
 
36
- export const Product = defineModel({
37
- collection: "products",
38
- fields: {
39
- name: { type: "string", required: true },
40
- price: { type: "number", required: true },
41
- category: { type: "string", enum: ["electronics", "clothing"] },
42
- },
43
- timestamps: true,
44
- rules: {
45
- read: "public",
46
- create: "role",
47
- createRoles: ["admin"],
48
- },
49
- });
69
+ | URL | What You'll See |
70
+ |-----|-----------------|
71
+ | [http://localhost:3000](http://localhost:3000) | Your app (Todo starter) |
72
+ | [http://localhost:3456](http://localhost:3456) | API Playground |
73
+
74
+ ### 4. Test the API
75
+
76
+ ```bash
77
+ # Via the API server directly
78
+ curl -s -X POST http://localhost:3456/api/health \
79
+ -H 'Content-Type: application/json' -d '{}' | jq
80
+
81
+ # Or via the frontend proxy (same result, no CORS issues)
82
+ curl -s -X POST http://localhost:3000/api/todos/create \
83
+ -H 'Content-Type: application/json' \
84
+ -d '{"title":"Learn Clawfire"}' | jq
50
85
  ```
51
86
 
87
+ ---
88
+
89
+ ## Dev Server Architecture
90
+
91
+ Clawfire runs a **two-port dev server** in a single process:
92
+
93
+ ```
94
+ DevServer (single process)
95
+ ├─ PageCompiler (compiles app/pages/ + app/components/ → HTML)
96
+ ├─ Frontend Server (port 3000)
97
+ │ ├─ Serves compiled pages (app/pages/ → routes)
98
+ │ ├─ Serves public/ directory (static assets)
99
+ │ ├─ Auto-injects HMR script into HTML
100
+ │ ├─ Proxies /api/* → API server (no CORS)
101
+ │ └─ SPA fallback with partial page loading
102
+
103
+ └─ API Server (port 3456)
104
+ ├─ API routes at /api/*
105
+ ├─ Playground UI at /
106
+ └─ SSE for live reload
107
+ ```
108
+
109
+ **Key behaviors:**
110
+
111
+ - **HMR auto-injection** — Every HTML response gets a `<script>` tag injected automatically. You never write SSE code.
112
+ - **CSS hot replace** — Edit a `.css` file in `public/` and see changes instantly without page reload.
113
+ - **API proxy** — Your frontend can call `fetch('/api/todos/list')` — the frontend server proxies it to the API server. No CORS configuration needed.
114
+ - **SPA fallback** — Unknown paths serve `index.html`, supporting client-side routing.
115
+ - **Playground** — Always available at the API server root. Auto-discovers routes, shows auth levels, generates example payloads.
116
+
117
+ ### Custom Ports
118
+
119
+ ```bash
120
+ npx clawfire dev --port=4000 --api-port=5000
121
+ ```
122
+
123
+ Or in `clawfire.config.ts`:
124
+
125
+ ```ts
126
+ dev: {
127
+ port: 4000,
128
+ apiPort: 5000,
129
+ }
130
+ ```
131
+
132
+ ---
133
+
134
+ ## Project Structure
135
+
136
+ ```
137
+ my-app/
138
+ app/
139
+ store.ts In-memory data store (works without Firebase)
140
+ pages/ File-based page routing (frontend)
141
+ _layout.html Root layout (wraps all pages via <slot />)
142
+ _404.html 404 error page
143
+ index.html Home page (/)
144
+ about.html /about page
145
+ todos/
146
+ index.html /todos page
147
+ components/ Reusable HTML components
148
+ nav.html <c-nav /> navigation bar
149
+ footer.html <c-footer /> page footer
150
+ routes/ API route handlers (file-based routing)
151
+ health.ts → POST /api/health
152
+ todos/
153
+ list.ts → POST /api/todos/list
154
+ create.ts → POST /api/todos/create
155
+ update.ts → POST /api/todos/update
156
+ delete.ts → POST /api/todos/delete
157
+ schemas/ Firestore model definitions
158
+ todo.ts
159
+ public/ Static assets (CSS, images, fonts)
160
+ generated/ Auto-generated files (DO NOT EDIT)
161
+ api-client.ts Typed API client
162
+ manifest.json API manifest
163
+ functions/
164
+ index.ts Firebase Functions entry point (for deploy)
165
+ dev.ts Dev server entry point
166
+ clawfire.config.ts Configuration
167
+ firebase.json Firebase config
168
+ firestore.rules Firestore security rules
169
+ firestore.indexes.json Firestore indexes
170
+ CLAUDE.md Project guide for Claude AI
171
+ ```
172
+
173
+ ---
174
+
175
+ ## Core Concepts
176
+
52
177
  ### Define an API
53
178
 
54
- ```typescript
179
+ Every API endpoint is a file in `app/routes/` that exports a `defineAPI` contract:
180
+
181
+ ```ts
55
182
  // app/routes/products/list.ts
56
183
  import { defineAPI, z } from "clawfire";
57
184
 
@@ -69,20 +196,137 @@ export default defineAPI({
69
196
  hasMore: z.boolean(),
70
197
  }),
71
198
  meta: {
72
- description: "상품 목록 조회",
199
+ description: "List products",
73
200
  auth: "public",
74
201
  tags: ["products"],
75
202
  },
76
203
  handler: async (input, ctx) => {
77
- // Your business logic here
78
204
  return { products: [], hasMore: false };
79
205
  },
80
206
  });
81
207
  ```
82
208
 
83
- ### Server Setup (Firebase Functions)
209
+ **Rules:**
210
+ - All APIs are **POST only** — no HTTP method routing
211
+ - `input` and `output` must be `z.object({})`
212
+ - `meta.description` is required
213
+ - `handler` must be `async`
214
+ - File path = API path: `app/routes/products/list.ts` → `POST /api/products/list`
215
+
216
+ ### Define a Model
84
217
 
85
- ```typescript
218
+ Models define Firestore collections and auto-generate security rules:
219
+
220
+ ```ts
221
+ // app/schemas/product.ts
222
+ import { defineModel } from "clawfire";
223
+
224
+ export const Product = defineModel({
225
+ collection: "products",
226
+ fields: {
227
+ name: { type: "string", required: true },
228
+ price: { type: "number", required: true },
229
+ category: { type: "string", enum: ["electronics", "clothing"] },
230
+ },
231
+ timestamps: true,
232
+ rules: {
233
+ read: "public",
234
+ create: "role",
235
+ createRoles: ["admin"],
236
+ update: "authenticated",
237
+ delete: "role",
238
+ deleteRoles: ["admin"],
239
+ ownerField: "userId",
240
+ },
241
+ });
242
+ ```
243
+
244
+ ### Error Handling
245
+
246
+ ```ts
247
+ import { Errors } from "clawfire";
248
+
249
+ throw Errors.notFound("Product not found"); // 404
250
+ throw Errors.validation("Invalid input", err); // 400
251
+ throw Errors.forbidden("No access"); // 403
252
+ throw Errors.unauthorized("Login required"); // 401
253
+ throw Errors.conflict("Already exists"); // 409
254
+ throw Errors.rateLimited("Too many requests"); // 429
255
+ ```
256
+
257
+ **Response format:**
258
+
259
+ ```json
260
+ // Success
261
+ { "data": { "products": [...], "hasMore": false } }
262
+
263
+ // Error
264
+ { "error": { "code": "NOT_FOUND", "message": "Product not found" } }
265
+ ```
266
+
267
+ ---
268
+
269
+ ## Auth Levels
270
+
271
+ Every API endpoint declares an auth level in `meta.auth`:
272
+
273
+ | Level | Description | Header Required |
274
+ |-------|-------------|-----------------|
275
+ | `public` | No authentication | None |
276
+ | `authenticated` | Must be logged in | `Authorization: Bearer <token>` |
277
+ | `role` | Specific role required | Bearer token + role match |
278
+ | `reauth` | Recent login required (5 min) | Bearer token + fresh |
279
+
280
+ ```ts
281
+ meta: {
282
+ description: "Delete user account",
283
+ auth: "reauth", // Must have re-authenticated within 5 minutes
284
+ }
285
+ ```
286
+
287
+ ---
288
+
289
+ ## Configuration
290
+
291
+ All settings in `clawfire.config.ts`:
292
+
293
+ ```ts
294
+ import { configureClawfire } from "clawfire";
295
+
296
+ export default configureClawfire({
297
+ firebase: {
298
+ apiKey: "...",
299
+ authDomain: "myapp.firebaseapp.com",
300
+ projectId: "my-project",
301
+ appId: "1:123:web:abc",
302
+ },
303
+ server: {
304
+ region: "us-central1",
305
+ cors: ["https://myapp.web.app"],
306
+ rateLimit: 100,
307
+ },
308
+ security: {
309
+ validateInput: true,
310
+ safeHeaders: true,
311
+ maskLogs: true,
312
+ },
313
+ playground: {
314
+ enabled: true,
315
+ },
316
+ dev: {
317
+ port: 3000, // Frontend server
318
+ apiPort: 3456, // API server + Playground
319
+ },
320
+ });
321
+ ```
322
+
323
+ ---
324
+
325
+ ## Production Deployment
326
+
327
+ ### Firebase Functions Entry Point
328
+
329
+ ```ts
86
330
  // functions/index.ts
87
331
  import * as admin from "firebase-admin";
88
332
  import * as functions from "firebase-functions";
@@ -106,10 +350,10 @@ export const api = functions.https.onRequest((req, res) => {
106
350
  });
107
351
  ```
108
352
 
109
- ### Client Usage
353
+ ### Auto-Generated Client
110
354
 
111
- ```typescript
112
- // Generated api-client.ts provides typed access
355
+ ```ts
356
+ // In your frontend code
113
357
  import { api, configureClient } from "./generated/api-client";
114
358
  import { getAuth } from "firebase/auth";
115
359
 
@@ -118,64 +362,118 @@ configureClient("https://us-central1-myapp.cloudfunctions.net", async () => {
118
362
  return user ? user.getIdToken() : null;
119
363
  });
120
364
 
365
+ // Fully typed — autocomplete and compile-time checking
121
366
  const result = await api.products.list({ category: "electronics", limit: 10 });
122
367
  ```
123
368
 
124
- ## Project Structure
369
+ ---
125
370
 
126
- ```
127
- app/
128
- routes/ API route handlers (file-based routing)
129
- schemas/ Model definitions (Firestore collections)
130
- generated/ Auto-generated files (DO NOT EDIT)
131
- api-client.ts Typed API client
132
- manifest.json API manifest
133
- functions/ Firebase Functions entry point
134
- public/ Static files for Firebase Hosting
135
- firebase.json Firebase config
136
- firestore.rules Firestore security rules
137
- clawfire.config.ts Clawfire configuration
371
+ ## CLI Reference
372
+
373
+ ```bash
374
+ clawfire init # Initialize a new project (starter template)
375
+ clawfire dev # Start dev server (frontend + API + Playground)
376
+ clawfire dev --port=4000 # Custom frontend port
377
+ clawfire dev --api-port=5000 # Custom API port
378
+ clawfire codegen # Generate route imports
379
+ clawfire playground # Generate standalone playground HTML
380
+ clawfire rules # Info about rules generation
381
+ clawfire help # Show help
138
382
  ```
139
383
 
140
- ## AI Skills (Claude Code)
384
+ ---
141
385
 
142
- | Command | Description |
143
- |---------|-------------|
144
- | `/clawfire-init` | Initialize project / connect Firebase |
145
- | `/clawfire-model` | Create/modify data models |
146
- | `/clawfire-api` | Create/modify APIs |
147
- | `/clawfire-auth` | Configure authentication |
148
- | `/clawfire-deploy` | Deploy to Firebase |
149
- | `/clawfire-diagnose` | Diagnose and fix issues |
386
+ ## AI Skills (Claude Code)
150
387
 
151
- ## Auth Levels
388
+ When using [Claude Code](https://claude.ai/claude-code), these slash commands are available:
152
389
 
153
- | Level | Description |
154
- |-------|-------------|
155
- | `public` | No authentication required |
156
- | `authenticated` | Login required |
157
- | `role` | Specific role required |
158
- | `reauth` | Recent re-authentication required |
159
-
160
- ## Exports
161
-
162
- | Path | Description |
163
- |------|-------------|
164
- | `clawfire` | Core types, defineAPI, defineModel, Zod |
165
- | `clawfire/functions` | Server-side: Router, DB, Auth, Security |
166
- | `clawfire/client` | Client-side: Auth helpers |
167
- | `clawfire/admin` | Admin: Rules, Indexes, User management |
168
- | `clawfire/codegen` | Code generation utilities |
169
- | `clawfire/playground` | Playground HTML generator |
170
-
171
- ## Tech Stack (Fixed)
172
-
173
- - **DB**: Firestore
174
- - **Auth**: Firebase Auth
175
- - **Hosting**: Firebase Hosting
176
- - **Backend**: Firebase Functions
177
- - **Schema**: Zod
178
- - **Language**: TypeScript
390
+ | Command | What It Does |
391
+ |---------|-------------|
392
+ | `/clawfire-init` | Initialize project, connect Firebase, set up config |
393
+ | `/clawfire-model` | Create/modify Firestore models → auto-generates rules + indexes |
394
+ | `/clawfire-api` | Create/modify API endpoints → auto-generates typed client |
395
+ | `/clawfire-auth` | Configure auth policies, roles, guards |
396
+ | `/clawfire-deploy` | Deploy to Firebase (explicit request only) |
397
+ | `/clawfire-diagnose` | Detect missing indexes, rule denials, permission issues |
398
+
399
+ ---
400
+
401
+ ## Package Exports
402
+
403
+ | Import Path | Contents |
404
+ |-------------|----------|
405
+ | `clawfire` | `defineAPI`, `defineModel`, `z`, `Errors`, `configureClawfire`, `ClawfireError` |
406
+ | `clawfire/functions` | `createRouter`, `createAdminDB`, `verifyToken`, `createSecurityMiddleware` |
407
+ | `clawfire/client` | `createClientAuth` |
408
+ | `clawfire/admin` | `generateFirestoreRules`, `generateFirestoreIndexes`, `setUserRole` |
409
+ | `clawfire/codegen` | `generateClientCode`, `discoverRoutes`, `generateRouteImports` |
410
+ | `clawfire/playground` | `generatePlaygroundHtml` |
411
+ | `clawfire/dev` | `DevServer`, `startDevServer`, `FileWatcher`, `PageCompiler` |
412
+
413
+ ---
414
+
415
+ ## Security Defaults
416
+
417
+ All security features are **ON by default**:
418
+
419
+ | Feature | Default | Description |
420
+ |---------|---------|-------------|
421
+ | Input Validation | ON | Zod schema validation on every request |
422
+ | CORS | Deny all | Must explicitly allow origins |
423
+ | Rate Limiting | 100 req/min/IP | Per-endpoint configurable |
424
+ | XSS Sanitization | ON | `<` `>` auto-escaped in string inputs |
425
+ | Safe Headers | ON | `X-Frame-Options`, `X-Content-Type-Options` |
426
+ | Log Masking | ON | `password`, `token`, `secret` fields masked |
427
+
428
+ ---
429
+
430
+ ## Dev vs Production
431
+
432
+ | | Dev Server | Production (Firebase) |
433
+ |--|-----------|----------------------|
434
+ | Frontend | `localhost:3000` (static + HMR) | Firebase Hosting |
435
+ | API | `localhost:3456` | Firebase Functions |
436
+ | Playground | Always on at `:3456` | Configurable |
437
+ | CORS | Allow all (`*`) | Configured origins only |
438
+ | Rate Limiting | Disabled | Enabled |
439
+ | Auth | Optional / mockable | Firebase Auth |
440
+ | Hot Reload | Yes (API + CSS + HTML) | N/A |
441
+
442
+ ---
443
+
444
+ ## Documentation
445
+
446
+ Full documentation is in the [`docs/`](./docs/) directory:
447
+
448
+ - [Getting Started](./docs/getting-started.md) — 5-minute quickstart
449
+ - [API Routes](./docs/api-routes.md) — `defineAPI`, file-based routing, handlers
450
+ - [Models](./docs/models.md) — `defineModel`, Firestore collections, rules
451
+ - [Dev Server](./docs/dev-server.md) — Two-port architecture, HMR, Playground
452
+ - [Authentication](./docs/authentication.md) — Auth levels, tokens, roles
453
+ - [Security](./docs/security.md) — Middleware, rate limiting, CORS, sanitization
454
+ - [Configuration](./docs/configuration.md) — All config options and defaults
455
+ - [Client Codegen](./docs/client-codegen.md) — Auto-generated typed API client
456
+ - [Deployment](./docs/deployment.md) — Firebase deploy workflow
457
+ - [CLI Reference](./docs/cli-reference.md) — All CLI commands and flags
458
+ - [Architecture](./docs/architecture.md) — How everything fits together
459
+ - [API Reference](./docs/api-reference.md) — Full TypeScript API reference
460
+
461
+ ---
462
+
463
+ ## Tech Stack
464
+
465
+ | Layer | Technology |
466
+ |-------|-----------|
467
+ | Database | Firestore |
468
+ | Auth | Firebase Auth |
469
+ | Hosting | Firebase Hosting |
470
+ | Backend | Firebase Functions |
471
+ | Schema | Zod |
472
+ | Language | TypeScript |
473
+
474
+ This stack is fixed by design. Clawfire is opinionated — one way to do things, done well.
475
+
476
+ ---
179
477
 
180
478
  ## License
181
479
 
package/dist/admin.d.cts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { e as ModelDefinition } from './schema-BJsictSV.cjs';
2
2
  export { f as ModelField, i as ModelIndex, j as ModelRules, h as defineModel, m as modelToZodSchema } from './schema-BJsictSV.cjs';
3
- import { C as ClawfireConfig } from './config-QMBJRn9G.cjs';
3
+ import { C as ClawfireConfig } from './config-D-Chojiu.cjs';
4
4
  export { g as getUserRole, s as setCustomClaims, b as setUserRole } from './auth-DQ3cifhb.cjs';
5
5
  import 'zod';
6
6
 
package/dist/admin.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { e as ModelDefinition } from './schema-BJsictSV.js';
2
2
  export { f as ModelField, i as ModelIndex, j as ModelRules, h as defineModel, m as modelToZodSchema } from './schema-BJsictSV.js';
3
- import { C as ClawfireConfig } from './config-QMBJRn9G.js';
3
+ import { C as ClawfireConfig } from './config-D-Chojiu.js';
4
4
  export { g as getUserRole, s as setCustomClaims, b as setUserRole } from './auth-DtnUPbXT.js';
5
5
  import 'zod';
6
6
 
package/dist/cli.js CHANGED
@@ -26,6 +26,11 @@ function printHelp() {
26
26
  clawfire rules Generate Firestore security rules
27
27
  clawfire help Show this help
28
28
 
29
+ Dev Server Flags:
30
+ --port=<n> Frontend server port (default: 3000)
31
+ --api-port=<n> API server port (default: 3456)
32
+ --no-hot-reload Disable hot reload
33
+
29
34
  Most tasks are done through AI Skills, not CLI.
30
35
  Run Claude Code and use /clawfire-* commands instead.
31
36
  `);
@@ -112,6 +117,8 @@ async function initProject() {
112
117
  const dirs = [
113
118
  "app/routes",
114
119
  "app/schemas",
120
+ "app/pages",
121
+ "app/components",
115
122
  "generated",
116
123
  "public",
117
124
  "functions"
@@ -179,23 +186,34 @@ export const api = functions.https.onRequest((req, res) => {
179
186
  console.log(" Created functions/index.ts");
180
187
  }
181
188
  console.log("\n \x1B[32m\u2713\x1B[0m Clawfire project initialized!\n");
189
+ console.log(" Project structure:");
190
+ console.log(" \x1B[36mapp/pages/\x1B[0m \u2192 File-based page routing (Tailwind + layouts)");
191
+ console.log(" \x1B[36mapp/components/\x1B[0m \u2192 Reusable HTML components (<c-name />)");
192
+ console.log(" \x1B[36mapp/routes/\x1B[0m \u2192 API endpoints (POST, Zod validation)");
193
+ console.log(" \x1B[36mapp/schemas/\x1B[0m \u2192 Firestore model definitions");
194
+ console.log(" \x1B[36mpublic/\x1B[0m \u2192 Static assets (CSS, images, fonts)");
195
+ console.log("");
182
196
  console.log(" Next steps:");
183
197
  console.log(" \x1B[36m1.\x1B[0m npm install");
184
198
  console.log(" \x1B[36m2.\x1B[0m npm run dev");
185
- console.log(" \x1B[36m3.\x1B[0m Open \x1B[1mhttp://localhost:3456\x1B[0m in your browser");
199
+ console.log(" \x1B[36m3.\x1B[0m Open \x1B[1mhttp://localhost:3000\x1B[0m");
200
+ console.log("");
201
+ console.log(" Your app is ready with a Todo demo, page routing, and API playground.");
186
202
  console.log("");
187
- console.log(" Your Todo app is ready! Try adding, completing, and deleting todos.");
188
- console.log(" Edit files in \x1B[1mapp/routes/\x1B[0m and see changes instantly.\n");
203
+ console.log(" npm: \x1B[4mhttps://www.npmjs.com/package/clawfire\x1B[0m\n");
189
204
  }
190
205
  async function runDevServer() {
191
206
  const projectDir = process.cwd();
192
207
  const portArg = args.find((a) => a.startsWith("--port="));
193
- const port = portArg ? parseInt(portArg.split("=")[1], 10) : 3456;
208
+ const apiPortArg = args.find((a) => a.startsWith("--api-port="));
209
+ const port = portArg ? parseInt(portArg.split("=")[1], 10) : 3e3;
210
+ const apiPort = apiPortArg ? parseInt(apiPortArg.split("=")[1], 10) : 3456;
194
211
  const noHotReload = args.includes("--no-hot-reload");
195
- const { startDevServer } = await import("./dev-server-QAVWINAT.js");
212
+ const { startDevServer } = await import("./dev-server-ZGXJARNY.js");
196
213
  await startDevServer({
197
214
  projectDir,
198
215
  port,
216
+ apiPort,
199
217
  hotReload: !noHotReload
200
218
  });
201
219
  }
@@ -39,6 +39,13 @@ interface ClawfireConfig {
39
39
  /** 경로 */
40
40
  path?: string;
41
41
  };
42
+ /** 개발 서버 설정 */
43
+ dev?: {
44
+ /** 프론트엔드 서버 포트 (기본: 3000) */
45
+ port?: number;
46
+ /** API 서버 포트 (기본: 3456) */
47
+ apiPort?: number;
48
+ };
42
49
  }
43
50
  declare function configureClawfire(config: ClawfireConfig): ClawfireConfig;
44
51
  declare function getConfig(): ClawfireConfig;
@@ -39,6 +39,13 @@ interface ClawfireConfig {
39
39
  /** 경로 */
40
40
  path?: string;
41
41
  };
42
+ /** 개발 서버 설정 */
43
+ dev?: {
44
+ /** 프론트엔드 서버 포트 (기본: 3000) */
45
+ port?: number;
46
+ /** API 서버 포트 (기본: 3456) */
47
+ apiPort?: number;
48
+ };
42
49
  }
43
50
  declare function configureClawfire(config: ClawfireConfig): ClawfireConfig;
44
51
  declare function getConfig(): ClawfireConfig;