create-creek-app 0.0.0-dev.0 → 0.1.6
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/AGENTS.md +136 -0
- package/README.md +353 -0
- package/dist/apply-data.d.ts +5 -0
- package/dist/apply-data.js +33 -0
- package/dist/fetch.d.ts +20 -0
- package/dist/fetch.js +35 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +171 -0
- package/dist/prompts.d.ts +8 -0
- package/dist/prompts.js +29 -0
- package/dist/scaffold.d.ts +14 -0
- package/dist/scaffold.js +76 -0
- package/dist/templates.d.ts +19 -0
- package/dist/templates.js +38 -0
- package/dist/validate.d.ts +13 -0
- package/dist/validate.js +20 -0
- package/package.json +41 -2
- package/bin/create-creek-app.js +0 -3
package/AGENTS.md
ADDED
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
# create-creek-app — Agent Reference
|
|
2
|
+
|
|
3
|
+
You are interacting with `create-creek-app`, a CLI that scaffolds Creek projects from templates. Creek deploys to Cloudflare Workers.
|
|
4
|
+
|
|
5
|
+
## Capabilities
|
|
6
|
+
|
|
7
|
+
- Scaffold a new project from a built-in or third-party template
|
|
8
|
+
- Discover available templates and their schemas (JSON output)
|
|
9
|
+
- Validate template parameters before scaffolding
|
|
10
|
+
- Customize templates via JSON data (inline or file)
|
|
11
|
+
|
|
12
|
+
## Command Reference
|
|
13
|
+
|
|
14
|
+
All commands output JSON to **stdout**. Progress/errors go to **stderr**.
|
|
15
|
+
|
|
16
|
+
### Discovery (read-only, no side effects)
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
npx create-creek-app --list
|
|
20
|
+
```
|
|
21
|
+
Returns JSON array to stdout:
|
|
22
|
+
```json
|
|
23
|
+
[
|
|
24
|
+
{ "name": "blank", "description": "Minimal Creek project (no UI)", "capabilities": [] },
|
|
25
|
+
{ "name": "landing", "description": "Landing page with hero and CTA", "capabilities": [] },
|
|
26
|
+
{ "name": "blog", "description": "Blog with posts (D1 database)", "capabilities": ["d1"] }
|
|
27
|
+
]
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
npx create-creek-app --template landing --schema
|
|
32
|
+
```
|
|
33
|
+
Returns the template's JSON Schema to stdout:
|
|
34
|
+
```json
|
|
35
|
+
{
|
|
36
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
37
|
+
"type": "object",
|
|
38
|
+
"properties": {
|
|
39
|
+
"title": { "type": "string", "default": "My Product" },
|
|
40
|
+
"theme": { "type": "string", "enum": ["light", "dark"], "default": "dark" }
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
npx create-creek-app --template landing --validate --data '{"theme":"dark"}'
|
|
47
|
+
```
|
|
48
|
+
Returns validation result to stdout:
|
|
49
|
+
```json
|
|
50
|
+
{ "valid": true, "errors": [] }
|
|
51
|
+
```
|
|
52
|
+
On failure:
|
|
53
|
+
```json
|
|
54
|
+
{ "valid": false, "errors": [{ "path": "/theme", "message": "must be equal to one of the allowed values" }] }
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### Scaffold (creates files)
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
# Non-interactive scaffold
|
|
61
|
+
npx create-creek-app <dir> --template <name> --yes
|
|
62
|
+
|
|
63
|
+
# With custom parameters
|
|
64
|
+
npx create-creek-app <dir> --template <name> --data '<json>' --yes
|
|
65
|
+
|
|
66
|
+
# From a JSON config file
|
|
67
|
+
npx create-creek-app <dir> --template <name> --data-file <path> --yes
|
|
68
|
+
|
|
69
|
+
# Skip install and git init (faster, useful for testing)
|
|
70
|
+
npx create-creek-app <dir> --template <name> --yes --no-install --no-git
|
|
71
|
+
|
|
72
|
+
# Third-party template from GitHub
|
|
73
|
+
npx create-creek-app <dir> --template github:user/repo --yes
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### Deploy (after scaffolding)
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
cd <dir> && npx creek deploy --yes
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## Recommended Workflow
|
|
83
|
+
|
|
84
|
+
1. **`--list`** → pick a template based on description and capabilities
|
|
85
|
+
2. **`--schema`** → read the JSON Schema to know valid parameters
|
|
86
|
+
3. **`--validate`** → check your generated data (optional, scaffold validates too)
|
|
87
|
+
4. **Scaffold** with `--template`, `--data`, `--yes`
|
|
88
|
+
5. **Deploy** with `npx creek deploy --yes`
|
|
89
|
+
|
|
90
|
+
## Exit Codes
|
|
91
|
+
|
|
92
|
+
| Code | Meaning |
|
|
93
|
+
|------|---------|
|
|
94
|
+
| `0` | Success |
|
|
95
|
+
| `1` | Error (validation failure, bad arguments, network error) |
|
|
96
|
+
|
|
97
|
+
## Available Templates
|
|
98
|
+
|
|
99
|
+
| Name | Capabilities | Use when |
|
|
100
|
+
|------|-------------|----------|
|
|
101
|
+
| `blank` | — | Agent generates all code from scratch |
|
|
102
|
+
| `landing` | — | Marketing/product landing page |
|
|
103
|
+
| `blog` | D1 | Content site with database |
|
|
104
|
+
| `link-in-bio` | — | Social links page |
|
|
105
|
+
| `api` | D1 | REST API backend |
|
|
106
|
+
| `todo` | D1, Realtime | Full-stack app with WebSocket |
|
|
107
|
+
| `dashboard` | D1, Realtime | Data visualization with live updates |
|
|
108
|
+
| `form` | D1 | Form submissions with database storage |
|
|
109
|
+
| `chatbot` | D1, AI | AI-powered chat with conversation history |
|
|
110
|
+
|
|
111
|
+
## Template Parameters
|
|
112
|
+
|
|
113
|
+
Parameters are template-specific. Always run `--schema` to discover them. Common patterns:
|
|
114
|
+
|
|
115
|
+
- `name` — project name (auto-populated from directory name)
|
|
116
|
+
- `title`, `tagline`, `description` — display text
|
|
117
|
+
- `theme` — typically `"light"` or `"dark"` (enum-constrained)
|
|
118
|
+
- `accentColor` — hex color string
|
|
119
|
+
- `features` — array of `{ title, description }` objects
|
|
120
|
+
|
|
121
|
+
## What Creek Provides After Deploy
|
|
122
|
+
|
|
123
|
+
The scaffolded project deploys to Cloudflare's edge network via `creek deploy`. Depending on template capabilities:
|
|
124
|
+
|
|
125
|
+
- **All templates**: Global CDN, HTTPS, preview URLs
|
|
126
|
+
- **D1**: SQLite database — use `import { db } from "creek"` (no connection strings)
|
|
127
|
+
- **Realtime**: WebSocket — use `import { usePresence } from "creek/react"`
|
|
128
|
+
- **AI**: Workers AI — use `import { ai } from "creek"`
|
|
129
|
+
|
|
130
|
+
## Important Notes
|
|
131
|
+
|
|
132
|
+
- Always use `--yes` to skip interactive prompts
|
|
133
|
+
- The `--data` flag accepts inline JSON; use `--data-file` for complex data
|
|
134
|
+
- Templates use runtime config (`creek-data.json`) — users can customize after scaffold by editing this file
|
|
135
|
+
- `creek-template.json` is metadata only — it's removed from the scaffolded project
|
|
136
|
+
- No API keys or credentials needed for scaffolding; `creek deploy` handles auth via OAuth
|
package/README.md
ADDED
|
@@ -0,0 +1,353 @@
|
|
|
1
|
+
# create-creek-app
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/create-creek-app)
|
|
4
|
+
[](https://github.com/solcreek/creek/blob/main/LICENSE)
|
|
5
|
+
|
|
6
|
+
Scaffold a new [Creek](https://creek.dev) project from a template — deploy to the edge in two commands.
|
|
7
|
+
|
|
8
|
+
## What is Creek?
|
|
9
|
+
|
|
10
|
+
Creek is a deployment platform built on [Cloudflare Workers](https://developers.cloudflare.com/workers/). It replaces the manual setup of `wrangler.toml`, bindings, and resource provisioning with a single `creek.toml` config and zero-config CLI.
|
|
11
|
+
|
|
12
|
+
- **`creek.toml`** replaces `wrangler.toml` — Creek manages Workers, routes, and bindings for you
|
|
13
|
+
- **`creek deploy`** replaces `wrangler deploy` — one command provisions D1 databases, KV namespaces, R2 buckets, and deploys your code
|
|
14
|
+
- **You own the Cloudflare account** — Creek deploys to your CF account via OAuth, no vendor lock-in
|
|
15
|
+
|
|
16
|
+
If you already use Wrangler, Creek is a higher-level abstraction. If you're new to Cloudflare, Creek is the fastest way to get started.
|
|
17
|
+
|
|
18
|
+
## Prerequisites
|
|
19
|
+
|
|
20
|
+
- **Node.js 18+** (LTS recommended)
|
|
21
|
+
- **Cloudflare account** — free tier works. Not needed for scaffolding, only for `creek deploy` (you'll be prompted to sign in via OAuth on first deploy)
|
|
22
|
+
|
|
23
|
+
> **`creek` vs `create-creek-app`**: `create-creek-app` scaffolds a new project. `creek` is the CLI that deploys, runs dev server, and manages your project. Both are installed on-demand via `npx`.
|
|
24
|
+
|
|
25
|
+
## Quick Start
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
# 1. Scaffold a landing page
|
|
29
|
+
npx create-creek-app my-site --template landing --yes
|
|
30
|
+
|
|
31
|
+
# 2. Local development
|
|
32
|
+
cd my-site && npx creek dev
|
|
33
|
+
# → http://localhost:5173 with hot reload
|
|
34
|
+
|
|
35
|
+
# 3. Deploy to production
|
|
36
|
+
npx creek deploy
|
|
37
|
+
# → https://my-site-your-team.bycreek.com (live in ~10 seconds)
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
You get a globally distributed site on Cloudflare's edge network, with optional D1 database, KV storage, R2 files, AI inference, and Realtime WebSockets — all managed by Creek.
|
|
41
|
+
|
|
42
|
+
## Usage
|
|
43
|
+
|
|
44
|
+
### Interactive (human)
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
npx create-creek-app
|
|
48
|
+
# prompts: template → project name → scaffold → install → git init
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### Non-interactive (agent / CI)
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
npx create-creek-app my-blog --template blog --data '{"name":"Alice"}' --yes
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### From a JSON config file
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
npx create-creek-app my-site --template landing --data-file config.json --yes
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
```json
|
|
64
|
+
// config.json
|
|
65
|
+
{
|
|
66
|
+
"title": "Acme Corp",
|
|
67
|
+
"tagline": "The best widgets",
|
|
68
|
+
"theme": "light",
|
|
69
|
+
"features": [
|
|
70
|
+
{ "title": "Fast", "description": "Edge-powered performance" },
|
|
71
|
+
{ "title": "Secure", "description": "Built-in DDoS protection" }
|
|
72
|
+
]
|
|
73
|
+
}
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### Template discovery
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
# List all templates
|
|
80
|
+
npx create-creek-app --list
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
```json
|
|
84
|
+
[
|
|
85
|
+
{ "name": "blank", "description": "Minimal Creek project (no UI)", "capabilities": [] },
|
|
86
|
+
{ "name": "landing", "description": "Landing page with hero and CTA", "capabilities": [] },
|
|
87
|
+
{ "name": "blog", "description": "Blog with posts (D1 database)", "capabilities": ["d1"] },
|
|
88
|
+
...
|
|
89
|
+
]
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
# Print a template's JSON Schema
|
|
94
|
+
npx create-creek-app --template landing --schema
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
```json
|
|
98
|
+
{
|
|
99
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
100
|
+
"type": "object",
|
|
101
|
+
"properties": {
|
|
102
|
+
"title": { "type": "string", "default": "My Product" },
|
|
103
|
+
"theme": { "type": "string", "enum": ["light", "dark"], "default": "dark" }
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
# Validate data before scaffolding
|
|
110
|
+
npx create-creek-app --template landing --validate --data '{"theme":"dark"}'
|
|
111
|
+
# → { "valid": true, "errors": [] }
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
### Third-party templates
|
|
115
|
+
|
|
116
|
+
```bash
|
|
117
|
+
npx create-creek-app --template github:user/my-template
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
## Options
|
|
121
|
+
|
|
122
|
+
```
|
|
123
|
+
npx create-creek-app [dir] [options]
|
|
124
|
+
|
|
125
|
+
dir Project directory (default: prompted or "my-creek-app")
|
|
126
|
+
|
|
127
|
+
-t, --template <name|github:user/repo> Template to use
|
|
128
|
+
--data <json> JSON data for template params
|
|
129
|
+
--data-file <path> JSON file for template params
|
|
130
|
+
--list List available templates (JSON)
|
|
131
|
+
--schema Print template JSON Schema
|
|
132
|
+
--validate Validate data against schema
|
|
133
|
+
--registry <url> Private template registry (enterprise)
|
|
134
|
+
-y, --yes Skip prompts, use defaults
|
|
135
|
+
--no-install Skip dependency installation
|
|
136
|
+
--no-git Skip git init
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
## Templates
|
|
140
|
+
|
|
141
|
+
Each template is a complete, deployable project — not a skeleton. Capabilities indicate which Creek-managed resources are pre-configured:
|
|
142
|
+
|
|
143
|
+
| Template | Description | Capabilities |
|
|
144
|
+
|----------|-------------|-------------|
|
|
145
|
+
| `blank` | Minimal Creek project (no UI) | — |
|
|
146
|
+
| `landing` | Landing page with hero and CTA | — |
|
|
147
|
+
| `blog` | Blog with posts | D1 database |
|
|
148
|
+
| `link-in-bio` | Social links page | — |
|
|
149
|
+
| `api` | REST API with Hono | D1 database |
|
|
150
|
+
| `todo` | Realtime todo app | D1 + WebSocket |
|
|
151
|
+
| `dashboard` | Data dashboard | D1 + WebSocket |
|
|
152
|
+
| `form` | Form collector | D1 database |
|
|
153
|
+
| `chatbot` | AI chatbot | D1 + Workers AI |
|
|
154
|
+
|
|
155
|
+
**Capabilities explained:**
|
|
156
|
+
- **D1** — SQLite database at the edge, managed by Creek (no connection strings, no migrations)
|
|
157
|
+
- **Realtime** — WebSocket connections via Creek's Realtime service (presence, broadcast)
|
|
158
|
+
- **AI** — Inference via Cloudflare Workers AI (LLMs, embeddings, image generation)
|
|
159
|
+
|
|
160
|
+
## Template Schema
|
|
161
|
+
|
|
162
|
+
Each template defines customizable parameters via [JSON Schema](https://json-schema.org/) in `creek-template.json`. This enables both human prompts and programmatic validation.
|
|
163
|
+
|
|
164
|
+
### creek-template.json
|
|
165
|
+
|
|
166
|
+
```json
|
|
167
|
+
{
|
|
168
|
+
"name": "landing",
|
|
169
|
+
"description": "Landing page with hero, features, and CTA",
|
|
170
|
+
"capabilities": [],
|
|
171
|
+
"schema": {
|
|
172
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
173
|
+
"type": "object",
|
|
174
|
+
"properties": {
|
|
175
|
+
"title": { "type": "string", "default": "My Product" },
|
|
176
|
+
"tagline": { "type": "string", "default": "Ship faster with Creek" },
|
|
177
|
+
"theme": {
|
|
178
|
+
"type": "string",
|
|
179
|
+
"enum": ["light", "dark"],
|
|
180
|
+
"default": "dark"
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
### Fields
|
|
188
|
+
|
|
189
|
+
| Field | Type | Required | Description |
|
|
190
|
+
|-------|------|----------|-------------|
|
|
191
|
+
| `name` | string | yes | Template identifier |
|
|
192
|
+
| `description` | string | yes | Short description |
|
|
193
|
+
| `capabilities` | string[] | yes | Creek resources used: `d1`, `kv`, `r2`, `ai`, `realtime` |
|
|
194
|
+
| `thumbnail` | string | no | Path or URL to thumbnail image (400x300 recommended) |
|
|
195
|
+
| `screenshot` | string | no | Path or URL to full screenshot image |
|
|
196
|
+
| `schema` | object | no | JSON Schema defining customizable parameters |
|
|
197
|
+
|
|
198
|
+
### creek-data.json
|
|
199
|
+
|
|
200
|
+
Default values for the schema parameters. Your app reads this file at runtime — no build-time string replacement. Users customize their project by editing this one file.
|
|
201
|
+
|
|
202
|
+
```json
|
|
203
|
+
{
|
|
204
|
+
"title": "My Product",
|
|
205
|
+
"tagline": "Ship faster with Creek",
|
|
206
|
+
"theme": "dark"
|
|
207
|
+
}
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
```tsx
|
|
211
|
+
// src/App.tsx — reads config at runtime
|
|
212
|
+
import data from "../creek-data.json";
|
|
213
|
+
|
|
214
|
+
export function App() {
|
|
215
|
+
return <h1>{data.title}</h1>;
|
|
216
|
+
}
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
## Validation
|
|
220
|
+
|
|
221
|
+
Data is validated against the template's JSON Schema using [ajv](https://ajv.js.org/). Validation runs automatically during scaffold and can be triggered independently with `--validate`.
|
|
222
|
+
|
|
223
|
+
### Supported constraints
|
|
224
|
+
|
|
225
|
+
- **type** — `string`, `number`, `integer`, `boolean`, `array`, `object`
|
|
226
|
+
- **enum** — fixed set of allowed values
|
|
227
|
+
- **default** — applied when the property is omitted
|
|
228
|
+
- **required** — within object items (array entries, nested objects)
|
|
229
|
+
- **items** — schema for array elements
|
|
230
|
+
- **nested objects** — full recursive validation
|
|
231
|
+
|
|
232
|
+
### Validation examples
|
|
233
|
+
|
|
234
|
+
```bash
|
|
235
|
+
# Valid — passes (exit code 0)
|
|
236
|
+
npx create-creek-app --template landing --validate --data '{"theme":"dark"}'
|
|
237
|
+
# → { "valid": true, "errors": [] }
|
|
238
|
+
|
|
239
|
+
# Invalid enum — fails (exit code 1)
|
|
240
|
+
npx create-creek-app --template landing --validate --data '{"theme":"invalid"}'
|
|
241
|
+
# → { "valid": false, "errors": [{ "path": "/theme", "message": "must be equal to one of the allowed values" }] }
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
## Exit Codes
|
|
245
|
+
|
|
246
|
+
| Code | Meaning |
|
|
247
|
+
|------|---------|
|
|
248
|
+
| `0` | Success |
|
|
249
|
+
| `1` | Error — validation failure, invalid arguments, scaffold failure, or network error |
|
|
250
|
+
|
|
251
|
+
All structured output (`--list`, `--schema`, `--validate`) goes to **stdout** as JSON. Progress messages and errors go to **stderr**.
|
|
252
|
+
|
|
253
|
+
## Creating Custom Templates
|
|
254
|
+
|
|
255
|
+
A Creek template is a directory with at minimum a `package.json` and `creek.toml`. Add `creek-template.json` for schema-driven customization.
|
|
256
|
+
|
|
257
|
+
### Template structure
|
|
258
|
+
|
|
259
|
+
```
|
|
260
|
+
my-template/
|
|
261
|
+
├── creek-template.json ← schema + metadata (removed on scaffold)
|
|
262
|
+
├── creek-data.json ← default values (optional)
|
|
263
|
+
├── creek.toml ← Creek project config
|
|
264
|
+
├── package.json
|
|
265
|
+
├── src/ ← your code
|
|
266
|
+
├── worker/index.ts ← edge worker (if needed)
|
|
267
|
+
└── .gitignore
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
### Best practices
|
|
271
|
+
|
|
272
|
+
1. **Use JSON Schema defaults** — every property should have a `default` so the template works without any `--data`
|
|
273
|
+
2. **Read config at runtime** — import `creek-data.json` in your code instead of build-time placeholders
|
|
274
|
+
3. **Keep schemas flat** — prefer top-level string/number/boolean properties
|
|
275
|
+
4. **Use `enum` for constrained choices** — themes, layouts, color schemes. Agents discover valid options via `--schema`
|
|
276
|
+
5. **Include a `name` property** — `create-creek-app` auto-populates it from the project directory
|
|
277
|
+
|
|
278
|
+
### Publishing
|
|
279
|
+
|
|
280
|
+
Host your template on GitHub and use it directly:
|
|
281
|
+
|
|
282
|
+
```bash
|
|
283
|
+
npx create-creek-app --template github:yourname/my-template
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
Or submit it to the [Creek template gallery](https://github.com/solcreek/templates) via pull request.
|
|
287
|
+
|
|
288
|
+
## Agent Workflow
|
|
289
|
+
|
|
290
|
+
`create-creek-app` is designed for both humans and AI agents. Typical agent flow:
|
|
291
|
+
|
|
292
|
+
```bash
|
|
293
|
+
# 1. Discover templates
|
|
294
|
+
npx create-creek-app --list
|
|
295
|
+
# → JSON array to stdout
|
|
296
|
+
|
|
297
|
+
# 2. Read schema for chosen template
|
|
298
|
+
npx create-creek-app --template landing --schema
|
|
299
|
+
# → JSON Schema to stdout
|
|
300
|
+
|
|
301
|
+
# 3. Validate generated data
|
|
302
|
+
npx create-creek-app --template landing --validate --data '{"title":"Acme","theme":"dark"}'
|
|
303
|
+
# → { "valid": true, "errors": [] }
|
|
304
|
+
|
|
305
|
+
# 4. Scaffold
|
|
306
|
+
npx create-creek-app my-site --template landing --data '{"title":"Acme"}' --yes
|
|
307
|
+
|
|
308
|
+
# 5. Deploy
|
|
309
|
+
cd my-site && npx creek deploy --yes
|
|
310
|
+
# → { "ok": true, "url": "https://my-site-team.bycreek.com", ... }
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
All discovery and validation commands output JSON to stdout for programmatic consumption. Use `--yes` to skip all interactive prompts.
|
|
314
|
+
|
|
315
|
+
## Contributing Templates
|
|
316
|
+
|
|
317
|
+
The template ecosystem is open to everyone. We welcome contributions from individual developers, agencies, and framework authors.
|
|
318
|
+
|
|
319
|
+
### How to submit
|
|
320
|
+
|
|
321
|
+
1. Fork [solcreek/templates](https://github.com/solcreek/templates)
|
|
322
|
+
2. Create your template directory following the [template structure](#template-structure)
|
|
323
|
+
3. Ensure it scaffolds and deploys cleanly: `npx create-creek-app test-dir --template ./your-template --yes && cd test-dir && creek deploy`
|
|
324
|
+
4. Open a pull request
|
|
325
|
+
|
|
326
|
+
### Acceptance criteria
|
|
327
|
+
|
|
328
|
+
- **Works out of the box** — `--yes` with no `--data` must produce a deployable project
|
|
329
|
+
- **Has `creek-template.json`** — with description, capabilities, and schema (if customizable)
|
|
330
|
+
- **No secrets or API keys** — templates must not require external service credentials to scaffold
|
|
331
|
+
- **English** — template names, descriptions, and code comments in English
|
|
332
|
+
|
|
333
|
+
### Template tiers
|
|
334
|
+
|
|
335
|
+
| Tier | Badge | Maintained by | Review |
|
|
336
|
+
|------|-------|--------------|--------|
|
|
337
|
+
| **Official** | `solcreek/templates` | Creek team | Creek team review |
|
|
338
|
+
| **Community** | `github:author/repo` | Author | Self-published, no review required |
|
|
339
|
+
|
|
340
|
+
Official templates are held to a higher standard: they must stay compatible with the latest Creek CLI and are tested in CI. Community templates can be used by anyone via `--template github:author/repo` — no approval process needed.
|
|
341
|
+
|
|
342
|
+
### Ideas for templates
|
|
343
|
+
|
|
344
|
+
We'd especially love to see:
|
|
345
|
+
- Framework-specific starters (Astro + Creek, SvelteKit + Creek)
|
|
346
|
+
- Industry verticals (restaurant menu, event page, portfolio)
|
|
347
|
+
- Backend patterns (webhook receiver, cron job, queue processor)
|
|
348
|
+
|
|
349
|
+
See the [templates repo](https://github.com/solcreek/templates) for the full contribution guide.
|
|
350
|
+
|
|
351
|
+
## License
|
|
352
|
+
|
|
353
|
+
Apache-2.0
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Merge user-supplied data into creek-data.json (and update creek.toml project name).
|
|
3
|
+
* `defaults` is what was already in the template's creek-data.json.
|
|
4
|
+
*/
|
|
5
|
+
export declare function applyData(dir: string, userData: Record<string, unknown>, defaults: Record<string, unknown>): void;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { join } from "node:path";
|
|
2
|
+
import { existsSync, readFileSync, writeFileSync } from "node:fs";
|
|
3
|
+
/**
|
|
4
|
+
* Merge user-supplied data into creek-data.json (and update creek.toml project name).
|
|
5
|
+
* `defaults` is what was already in the template's creek-data.json.
|
|
6
|
+
*/
|
|
7
|
+
export function applyData(dir, userData, defaults) {
|
|
8
|
+
const merged = { ...defaults, ...userData };
|
|
9
|
+
// Write merged creek-data.json
|
|
10
|
+
const dataPath = join(dir, "creek-data.json");
|
|
11
|
+
writeFileSync(dataPath, JSON.stringify(merged, null, 2) + "\n");
|
|
12
|
+
// If "name" was provided, also update creek.toml and package.json
|
|
13
|
+
if (typeof merged.name === "string") {
|
|
14
|
+
updateCreekTomlName(dir, merged.name);
|
|
15
|
+
updatePackageJsonName(dir, merged.name);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
function updateCreekTomlName(dir, name) {
|
|
19
|
+
const tomlPath = join(dir, "creek.toml");
|
|
20
|
+
if (!existsSync(tomlPath))
|
|
21
|
+
return;
|
|
22
|
+
let content = readFileSync(tomlPath, "utf-8");
|
|
23
|
+
content = content.replace(/^name\s*=\s*"[^"]*"/m, `name = "${name}"`);
|
|
24
|
+
writeFileSync(tomlPath, content);
|
|
25
|
+
}
|
|
26
|
+
function updatePackageJsonName(dir, name) {
|
|
27
|
+
const pkgPath = join(dir, "package.json");
|
|
28
|
+
if (!existsSync(pkgPath))
|
|
29
|
+
return;
|
|
30
|
+
const pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
|
|
31
|
+
pkg.name = name;
|
|
32
|
+
writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + "\n");
|
|
33
|
+
}
|
package/dist/fetch.d.ts
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export interface FetchResult {
|
|
2
|
+
dir: string;
|
|
3
|
+
templateConfig: TemplateConfig | null;
|
|
4
|
+
defaultData: Record<string, unknown>;
|
|
5
|
+
}
|
|
6
|
+
export interface TemplateConfig {
|
|
7
|
+
name: string;
|
|
8
|
+
description: string;
|
|
9
|
+
capabilities: string[];
|
|
10
|
+
thumbnail?: string;
|
|
11
|
+
screenshot?: string;
|
|
12
|
+
schema?: Record<string, unknown>;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Download a template into `dest`.
|
|
16
|
+
*
|
|
17
|
+
* Built-in templates: "landing" → github:solcreek/templates/landing
|
|
18
|
+
* Third-party: "github:user/repo" → passed to giget directly
|
|
19
|
+
*/
|
|
20
|
+
export declare function fetchTemplate(template: string, dest: string): Promise<FetchResult>;
|
package/dist/fetch.js
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { downloadTemplate } from "giget";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
4
|
+
const TEMPLATE_REPO = "github:solcreek/templates";
|
|
5
|
+
/**
|
|
6
|
+
* Download a template into `dest`.
|
|
7
|
+
*
|
|
8
|
+
* Built-in templates: "landing" → github:solcreek/templates/landing
|
|
9
|
+
* Third-party: "github:user/repo" → passed to giget directly
|
|
10
|
+
*/
|
|
11
|
+
export async function fetchTemplate(template, dest) {
|
|
12
|
+
const source = isThirdParty(template)
|
|
13
|
+
? template
|
|
14
|
+
: `${TEMPLATE_REPO}/${template}`;
|
|
15
|
+
const { dir } = await downloadTemplate(source, {
|
|
16
|
+
dir: dest,
|
|
17
|
+
force: true,
|
|
18
|
+
});
|
|
19
|
+
// Read creek-template.json if present
|
|
20
|
+
const configPath = join(dir, "creek-template.json");
|
|
21
|
+
let templateConfig = null;
|
|
22
|
+
if (existsSync(configPath)) {
|
|
23
|
+
templateConfig = JSON.parse(readFileSync(configPath, "utf-8"));
|
|
24
|
+
}
|
|
25
|
+
// Read creek-data.json defaults if present
|
|
26
|
+
const dataPath = join(dir, "creek-data.json");
|
|
27
|
+
let defaultData = {};
|
|
28
|
+
if (existsSync(dataPath)) {
|
|
29
|
+
defaultData = JSON.parse(readFileSync(dataPath, "utf-8"));
|
|
30
|
+
}
|
|
31
|
+
return { dir, templateConfig, defaultData };
|
|
32
|
+
}
|
|
33
|
+
function isThirdParty(template) {
|
|
34
|
+
return (template.includes(":") || template.includes("/") || template.startsWith("."));
|
|
35
|
+
}
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { defineCommand, runMain } from "citty";
|
|
3
|
+
import consola from "consola";
|
|
4
|
+
import { mkdtempSync, readFileSync } from "node:fs";
|
|
5
|
+
import { tmpdir } from "node:os";
|
|
6
|
+
import { join } from "node:path";
|
|
7
|
+
import { TEMPLATES } from "./templates.js";
|
|
8
|
+
import { scaffold } from "./scaffold.js";
|
|
9
|
+
import { validateData } from "./validate.js";
|
|
10
|
+
import { fetchTemplate } from "./fetch.js";
|
|
11
|
+
import { promptTemplate, promptDir } from "./prompts.js";
|
|
12
|
+
const main = defineCommand({
|
|
13
|
+
meta: {
|
|
14
|
+
name: "create-creek-app",
|
|
15
|
+
description: "Create a new Creek project from a template",
|
|
16
|
+
},
|
|
17
|
+
args: {
|
|
18
|
+
dir: {
|
|
19
|
+
type: "positional",
|
|
20
|
+
description: "Project directory",
|
|
21
|
+
required: false,
|
|
22
|
+
},
|
|
23
|
+
template: {
|
|
24
|
+
type: "string",
|
|
25
|
+
alias: "t",
|
|
26
|
+
description: "Template name or github:user/repo",
|
|
27
|
+
},
|
|
28
|
+
data: {
|
|
29
|
+
type: "string",
|
|
30
|
+
description: "JSON data for template params",
|
|
31
|
+
},
|
|
32
|
+
"data-file": {
|
|
33
|
+
type: "string",
|
|
34
|
+
description: "Path to JSON file for template params",
|
|
35
|
+
},
|
|
36
|
+
list: {
|
|
37
|
+
type: "boolean",
|
|
38
|
+
description: "List available templates (JSON)",
|
|
39
|
+
default: false,
|
|
40
|
+
},
|
|
41
|
+
schema: {
|
|
42
|
+
type: "boolean",
|
|
43
|
+
description: "Print template JSON Schema",
|
|
44
|
+
default: false,
|
|
45
|
+
},
|
|
46
|
+
validate: {
|
|
47
|
+
type: "boolean",
|
|
48
|
+
description: "Validate data against template schema",
|
|
49
|
+
default: false,
|
|
50
|
+
},
|
|
51
|
+
registry: {
|
|
52
|
+
type: "string",
|
|
53
|
+
description: "Private template registry URL (enterprise)",
|
|
54
|
+
},
|
|
55
|
+
yes: {
|
|
56
|
+
type: "boolean",
|
|
57
|
+
alias: "y",
|
|
58
|
+
description: "Skip prompts, use defaults",
|
|
59
|
+
default: false,
|
|
60
|
+
},
|
|
61
|
+
install: {
|
|
62
|
+
type: "boolean",
|
|
63
|
+
description: "Install dependencies (use --no-install to skip)",
|
|
64
|
+
default: true,
|
|
65
|
+
},
|
|
66
|
+
git: {
|
|
67
|
+
type: "boolean",
|
|
68
|
+
description: "Initialize git repo (use --no-git to skip)",
|
|
69
|
+
default: true,
|
|
70
|
+
},
|
|
71
|
+
},
|
|
72
|
+
async run({ args }) {
|
|
73
|
+
// --registry: enterprise placeholder
|
|
74
|
+
if (args.registry) {
|
|
75
|
+
console.log(JSON.stringify({
|
|
76
|
+
error: "Private template registry is an enterprise feature. Coming soon — creek.dev/enterprise",
|
|
77
|
+
}));
|
|
78
|
+
process.exit(0);
|
|
79
|
+
}
|
|
80
|
+
// --list: output JSON array of templates
|
|
81
|
+
if (args.list) {
|
|
82
|
+
console.log(JSON.stringify(TEMPLATES, null, 2));
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
// --schema: print template's JSON Schema
|
|
86
|
+
if (args.schema) {
|
|
87
|
+
const templateName = args.template;
|
|
88
|
+
if (!templateName) {
|
|
89
|
+
consola.error("--schema requires --template <name>");
|
|
90
|
+
process.exit(1);
|
|
91
|
+
}
|
|
92
|
+
const { templateConfig } = await fetchTemplate(templateName, makeTempDir());
|
|
93
|
+
if (!templateConfig?.schema) {
|
|
94
|
+
consola.error(`Template "${templateName}" has no schema`);
|
|
95
|
+
process.exit(1);
|
|
96
|
+
}
|
|
97
|
+
console.log(JSON.stringify(templateConfig.schema, null, 2));
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
// Parse user data from --data or --data-file
|
|
101
|
+
let userData = {};
|
|
102
|
+
if (args.data) {
|
|
103
|
+
try {
|
|
104
|
+
userData = JSON.parse(args.data);
|
|
105
|
+
}
|
|
106
|
+
catch {
|
|
107
|
+
consola.error("Invalid JSON in --data");
|
|
108
|
+
process.exit(1);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
else if (args["data-file"]) {
|
|
112
|
+
try {
|
|
113
|
+
userData = JSON.parse(readFileSync(args["data-file"], "utf-8"));
|
|
114
|
+
}
|
|
115
|
+
catch {
|
|
116
|
+
consola.error(`Cannot read --data-file: ${args["data-file"]}`);
|
|
117
|
+
process.exit(1);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
// --validate: validate data and exit
|
|
121
|
+
if (args.validate) {
|
|
122
|
+
const templateName = args.template;
|
|
123
|
+
if (!templateName) {
|
|
124
|
+
consola.error("--validate requires --template <name>");
|
|
125
|
+
process.exit(1);
|
|
126
|
+
}
|
|
127
|
+
const { templateConfig, defaultData } = await fetchTemplate(templateName, makeTempDir());
|
|
128
|
+
if (!templateConfig?.schema) {
|
|
129
|
+
console.log(JSON.stringify({ valid: true, errors: [] }));
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
const merged = { ...defaultData, ...userData };
|
|
133
|
+
const result = validateData(templateConfig.schema, merged);
|
|
134
|
+
console.log(JSON.stringify(result, null, 2));
|
|
135
|
+
process.exit(result.valid ? 0 : 1);
|
|
136
|
+
}
|
|
137
|
+
// Interactive or direct scaffold
|
|
138
|
+
let template = args.template;
|
|
139
|
+
let dir = args.dir;
|
|
140
|
+
if (!args.yes) {
|
|
141
|
+
// Interactive mode
|
|
142
|
+
if (!template) {
|
|
143
|
+
template = await promptTemplate();
|
|
144
|
+
}
|
|
145
|
+
if (!dir) {
|
|
146
|
+
dir = await promptDir();
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
else {
|
|
150
|
+
// Non-interactive: require --template, default dir
|
|
151
|
+
if (!template) {
|
|
152
|
+
template = "blank";
|
|
153
|
+
}
|
|
154
|
+
if (!dir) {
|
|
155
|
+
dir = "my-creek-app";
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
await scaffold({
|
|
159
|
+
template,
|
|
160
|
+
dir,
|
|
161
|
+
data: userData,
|
|
162
|
+
install: args.install,
|
|
163
|
+
git: args.git,
|
|
164
|
+
silent: false,
|
|
165
|
+
});
|
|
166
|
+
},
|
|
167
|
+
});
|
|
168
|
+
function makeTempDir() {
|
|
169
|
+
return mkdtempSync(join(tmpdir(), "creek-tpl-"));
|
|
170
|
+
}
|
|
171
|
+
runMain(main);
|
package/dist/prompts.js
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import consola from "consola";
|
|
2
|
+
import { TEMPLATES } from "./templates.js";
|
|
3
|
+
/**
|
|
4
|
+
* Interactive template picker — used when no --template flag is given.
|
|
5
|
+
*/
|
|
6
|
+
export async function promptTemplate() {
|
|
7
|
+
const choices = TEMPLATES.map((t) => ({
|
|
8
|
+
label: `${t.name} — ${t.description}`,
|
|
9
|
+
value: t.name,
|
|
10
|
+
hint: t.capabilities.length ? t.capabilities.join(", ") : undefined,
|
|
11
|
+
}));
|
|
12
|
+
const selected = await consola.prompt("Select a template:", {
|
|
13
|
+
type: "select",
|
|
14
|
+
options: choices,
|
|
15
|
+
});
|
|
16
|
+
// consola.prompt returns the value string for select type
|
|
17
|
+
return selected;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Prompt for project directory name.
|
|
21
|
+
*/
|
|
22
|
+
export async function promptDir() {
|
|
23
|
+
const dir = await consola.prompt("Project name:", {
|
|
24
|
+
type: "text",
|
|
25
|
+
default: "my-creek-app",
|
|
26
|
+
placeholder: "my-creek-app",
|
|
27
|
+
});
|
|
28
|
+
return dir;
|
|
29
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export interface ScaffoldOptions {
|
|
2
|
+
template: string;
|
|
3
|
+
dir: string;
|
|
4
|
+
data?: Record<string, unknown>;
|
|
5
|
+
install?: boolean;
|
|
6
|
+
git?: boolean;
|
|
7
|
+
silent?: boolean;
|
|
8
|
+
}
|
|
9
|
+
export interface ScaffoldResult {
|
|
10
|
+
dir: string;
|
|
11
|
+
template: string;
|
|
12
|
+
name: string;
|
|
13
|
+
}
|
|
14
|
+
export declare function scaffold(opts: ScaffoldOptions): Promise<ScaffoldResult>;
|
package/dist/scaffold.js
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { resolve, basename } from "node:path";
|
|
2
|
+
import { existsSync, unlinkSync } from "node:fs";
|
|
3
|
+
import { execSync } from "node:child_process";
|
|
4
|
+
import consola from "consola";
|
|
5
|
+
import { fetchTemplate } from "./fetch.js";
|
|
6
|
+
import { applyData } from "./apply-data.js";
|
|
7
|
+
import { validateData } from "./validate.js";
|
|
8
|
+
export async function scaffold(opts) {
|
|
9
|
+
const dest = resolve(opts.dir);
|
|
10
|
+
const projectName = basename(dest);
|
|
11
|
+
// 1. Fetch template
|
|
12
|
+
if (!opts.silent)
|
|
13
|
+
consola.start(`Downloading template: ${opts.template}`);
|
|
14
|
+
const { dir, templateConfig, defaultData } = await fetchTemplate(opts.template, dest);
|
|
15
|
+
// 2. Validate user data against schema (if schema exists)
|
|
16
|
+
const userData = { name: projectName, ...(opts.data ?? {}) };
|
|
17
|
+
if (templateConfig?.schema) {
|
|
18
|
+
const result = validateData(templateConfig.schema, { ...defaultData, ...userData });
|
|
19
|
+
if (!result.valid) {
|
|
20
|
+
consola.error("Data validation failed:");
|
|
21
|
+
for (const err of result.errors) {
|
|
22
|
+
consola.error(` ${err.path}: ${err.message}`);
|
|
23
|
+
}
|
|
24
|
+
throw new Error("Template data validation failed");
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
// 3. Apply data
|
|
28
|
+
applyData(dir, userData, defaultData);
|
|
29
|
+
// 4. Remove creek-template.json from output (metadata, not project file)
|
|
30
|
+
const templateConfigPath = resolve(dir, "creek-template.json");
|
|
31
|
+
if (existsSync(templateConfigPath)) {
|
|
32
|
+
unlinkSync(templateConfigPath);
|
|
33
|
+
}
|
|
34
|
+
// 6. Install dependencies
|
|
35
|
+
if (opts.install !== false) {
|
|
36
|
+
const pkgPath = resolve(dir, "package.json");
|
|
37
|
+
if (existsSync(pkgPath)) {
|
|
38
|
+
if (!opts.silent)
|
|
39
|
+
consola.start("Installing dependencies...");
|
|
40
|
+
try {
|
|
41
|
+
execSync("npm install", { cwd: dir, stdio: "pipe" });
|
|
42
|
+
if (!opts.silent)
|
|
43
|
+
consola.success("Dependencies installed");
|
|
44
|
+
}
|
|
45
|
+
catch {
|
|
46
|
+
consola.warn("Failed to install dependencies. Run `npm install` manually.");
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
// 7. Git init
|
|
51
|
+
if (opts.git !== false) {
|
|
52
|
+
try {
|
|
53
|
+
execSync("git init", { cwd: dir, stdio: "pipe" });
|
|
54
|
+
execSync("git add -A", { cwd: dir, stdio: "pipe" });
|
|
55
|
+
execSync('git commit -m "Initial commit from create-creek-app"', {
|
|
56
|
+
cwd: dir,
|
|
57
|
+
stdio: "pipe",
|
|
58
|
+
});
|
|
59
|
+
if (!opts.silent)
|
|
60
|
+
consola.success("Git repository initialized");
|
|
61
|
+
}
|
|
62
|
+
catch {
|
|
63
|
+
// git not available or failed — that's fine
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
if (!opts.silent) {
|
|
67
|
+
console.log("");
|
|
68
|
+
consola.success(`Created ${projectName} with template "${opts.template}"`);
|
|
69
|
+
console.log("");
|
|
70
|
+
consola.info(" Next steps:");
|
|
71
|
+
consola.info(` cd ${projectName}`);
|
|
72
|
+
consola.info(" creek deploy Deploy to production");
|
|
73
|
+
consola.info(" creek dev Start local development");
|
|
74
|
+
}
|
|
75
|
+
return { dir, template: opts.template, name: projectName };
|
|
76
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Template catalog — used for --list, interactive prompt, and gallery.
|
|
3
|
+
*
|
|
4
|
+
* Four types by output:
|
|
5
|
+
* site — Visual pages (deploy → shareable URL)
|
|
6
|
+
* app — Interactive UI + backend logic
|
|
7
|
+
* workflow — Background process (no/minimal UI), trigger + steps
|
|
8
|
+
* connector — Data bridge pattern (ingestion → storage)
|
|
9
|
+
*/
|
|
10
|
+
export interface Template {
|
|
11
|
+
name: string;
|
|
12
|
+
description: string;
|
|
13
|
+
type: "site" | "app" | "workflow" | "connector" | "developer";
|
|
14
|
+
capabilities: string[];
|
|
15
|
+
trigger?: string;
|
|
16
|
+
}
|
|
17
|
+
export declare const TEMPLATES: Template[];
|
|
18
|
+
export type TemplateName = (typeof TEMPLATES)[number]["name"];
|
|
19
|
+
export type TemplateType = Template["type"];
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Template catalog — used for --list, interactive prompt, and gallery.
|
|
3
|
+
*
|
|
4
|
+
* Four types by output:
|
|
5
|
+
* site — Visual pages (deploy → shareable URL)
|
|
6
|
+
* app — Interactive UI + backend logic
|
|
7
|
+
* workflow — Background process (no/minimal UI), trigger + steps
|
|
8
|
+
* connector — Data bridge pattern (ingestion → storage)
|
|
9
|
+
*/
|
|
10
|
+
export const TEMPLATES = [
|
|
11
|
+
// --- Sites (Level 4 — deploy → shareable) ---
|
|
12
|
+
{ name: "landing", description: "Landing page with hero and CTA", type: "site", capabilities: [] },
|
|
13
|
+
{ name: "blog", description: "Blog with image uploads", type: "site", capabilities: ["database", "storage"] },
|
|
14
|
+
{ name: "link-in-bio", description: "Social links page", type: "site", capabilities: [] },
|
|
15
|
+
{ name: "waitlist", description: "Waitlist with AI user segmentation", type: "site", capabilities: ["database", "ai"] },
|
|
16
|
+
// --- Apps (Level 3 — working data pipeline + UI) ---
|
|
17
|
+
{ name: "form", description: "Form collector with admin dashboard", type: "app", capabilities: ["database"] },
|
|
18
|
+
{ name: "dashboard", description: "Data dashboard with scheduled refresh", type: "app", capabilities: ["database", "realtime", "cron"] },
|
|
19
|
+
{ name: "chatbot", description: "AI chatbot with conversation history", type: "app", capabilities: ["database", "ai"] },
|
|
20
|
+
{ name: "survey", description: "Survey with AI-powered analysis", type: "app", capabilities: ["database", "ai"] },
|
|
21
|
+
{ name: "knowledge-base", description: "Knowledge base with AI search", type: "app", capabilities: ["database", "ai", "storage"] },
|
|
22
|
+
{ name: "status-page", description: "Service status page with uptime monitoring", type: "app", capabilities: ["database", "realtime", "cron", "cache"] },
|
|
23
|
+
{ name: "file-share", description: "File upload/download with expiring links", type: "app", capabilities: ["database", "storage"] },
|
|
24
|
+
{ name: "todo", description: "Realtime todo app (learning example)", type: "app", capabilities: ["database", "realtime"] },
|
|
25
|
+
// --- Workflows (Level 2-3 — trigger + steps, no/minimal UI) ---
|
|
26
|
+
{ name: "approval-flow", description: "Approval workflow — leave, expense, procurement", type: "workflow", capabilities: ["database", "realtime", "queue"], trigger: "webhook" },
|
|
27
|
+
{ name: "invoice-processor", description: "Email invoice → AI extract → DB → notify", type: "workflow", capabilities: ["database", "ai", "storage", "email"], trigger: "email" },
|
|
28
|
+
{ name: "scheduled-report", description: "Scheduled query → AI summary → PDF report", type: "workflow", capabilities: ["database", "ai", "storage", "cron"], trigger: "cron" },
|
|
29
|
+
{ name: "data-sync", description: "Scheduled API pull → diff → DB → notify", type: "workflow", capabilities: ["database", "cron"], trigger: "cron" },
|
|
30
|
+
{ name: "ai-classifier", description: "Input → AI classify → route to queue", type: "workflow", capabilities: ["database", "ai", "queue"], trigger: "webhook" },
|
|
31
|
+
// --- Connectors (Level 2 — pure platform wiring) ---
|
|
32
|
+
{ name: "api", description: "REST API with Hono", type: "connector", capabilities: ["database"], trigger: "http" },
|
|
33
|
+
{ name: "webhook-receiver", description: "Receive and process external webhooks", type: "connector", capabilities: ["database", "queue"], trigger: "webhook" },
|
|
34
|
+
{ name: "email-to-db", description: "Email → parse → attachments to R2 → DB", type: "connector", capabilities: ["database", "storage", "email"], trigger: "email" },
|
|
35
|
+
{ name: "ftp-sync", description: "Scheduled FTP/SFTP pull → parse → DB", type: "connector", capabilities: ["database", "storage", "cron", "ftp"], trigger: "cron" },
|
|
36
|
+
// --- Developer ---
|
|
37
|
+
{ name: "blank", description: "Minimal Creek project (empty canvas)", type: "developer", capabilities: [] },
|
|
38
|
+
];
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export interface ValidationResult {
|
|
2
|
+
valid: boolean;
|
|
3
|
+
errors: ValidationError[];
|
|
4
|
+
}
|
|
5
|
+
export interface ValidationError {
|
|
6
|
+
path: string;
|
|
7
|
+
message: string;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Validate data against a JSON Schema from creek-template.json.
|
|
11
|
+
* Returns { valid, errors }.
|
|
12
|
+
*/
|
|
13
|
+
export declare function validateData(schema: Record<string, unknown>, data: Record<string, unknown>): ValidationResult;
|
package/dist/validate.js
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import Ajv from "ajv";
|
|
2
|
+
const ajv = new Ajv({ allErrors: true, useDefaults: true });
|
|
3
|
+
/**
|
|
4
|
+
* Validate data against a JSON Schema from creek-template.json.
|
|
5
|
+
* Returns { valid, errors }.
|
|
6
|
+
*/
|
|
7
|
+
export function validateData(schema, data) {
|
|
8
|
+
// Strip $schema meta field — ajv doesn't support 2020-12 meta-schema by default
|
|
9
|
+
const { $schema: _, ...schemaWithoutMeta } = schema;
|
|
10
|
+
const validate = ajv.compile(schemaWithoutMeta);
|
|
11
|
+
const valid = validate(data);
|
|
12
|
+
if (valid) {
|
|
13
|
+
return { valid: true, errors: [] };
|
|
14
|
+
}
|
|
15
|
+
const errors = (validate.errors ?? []).map((err) => ({
|
|
16
|
+
path: err.instancePath || "/",
|
|
17
|
+
message: err.message ?? "unknown error",
|
|
18
|
+
}));
|
|
19
|
+
return { valid: false, errors };
|
|
20
|
+
}
|
package/package.json
CHANGED
|
@@ -1,8 +1,47 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-creek-app",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.1.6",
|
|
4
|
+
"description": "Create a new Creek project from a template",
|
|
4
5
|
"type": "module",
|
|
5
6
|
"bin": {
|
|
6
|
-
"create-creek-app": "./
|
|
7
|
+
"create-creek-app": "./dist/index.js"
|
|
8
|
+
},
|
|
9
|
+
"main": "./dist/index.js",
|
|
10
|
+
"files": [
|
|
11
|
+
"dist",
|
|
12
|
+
"AGENTS.md"
|
|
13
|
+
],
|
|
14
|
+
"scripts": {
|
|
15
|
+
"build": "tsc",
|
|
16
|
+
"dev": "tsc --watch",
|
|
17
|
+
"test": "vitest run"
|
|
18
|
+
},
|
|
19
|
+
"keywords": [
|
|
20
|
+
"creek",
|
|
21
|
+
"create",
|
|
22
|
+
"scaffold",
|
|
23
|
+
"template",
|
|
24
|
+
"cloudflare",
|
|
25
|
+
"workers",
|
|
26
|
+
"d1"
|
|
27
|
+
],
|
|
28
|
+
"author": "SolCreek",
|
|
29
|
+
"license": "Apache-2.0",
|
|
30
|
+
"homepage": "https://creek.dev",
|
|
31
|
+
"repository": {
|
|
32
|
+
"type": "git",
|
|
33
|
+
"url": "https://github.com/solcreek/creek.git",
|
|
34
|
+
"directory": "packages/create-creek-app"
|
|
35
|
+
},
|
|
36
|
+
"dependencies": {
|
|
37
|
+
"citty": "^0.1.6",
|
|
38
|
+
"consola": "^3.4.2",
|
|
39
|
+
"giget": "^2.0.0",
|
|
40
|
+
"ajv": "^8.17.1"
|
|
41
|
+
},
|
|
42
|
+
"devDependencies": {
|
|
43
|
+
"@types/node": "^22.0.0",
|
|
44
|
+
"typescript": "^5.8.2",
|
|
45
|
+
"vitest": "^4.1.1"
|
|
7
46
|
}
|
|
8
47
|
}
|
package/bin/create-creek-app.js
DELETED