@kyro-cms/core 0.1.0 → 0.1.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 +470 -131
- package/dist/templates/index.cjs +543 -0
- package/dist/templates/index.cjs.map +1 -0
- package/dist/templates/index.d.cts +11 -0
- package/dist/templates/index.d.ts +11 -0
- package/dist/templates/index.js +537 -0
- package/dist/templates/index.js.map +1 -0
- package/package.json +21 -2
package/README.md
CHANGED
|
@@ -1,205 +1,524 @@
|
|
|
1
1
|
# Kyro CMS
|
|
2
2
|
|
|
3
|
+
<div align="center">
|
|
4
|
+
|
|
3
5
|
**Astro-Native Headless CMS with Multi-Database Adapters, Multi-Protocol APIs, and Multi-Vendor Support**
|
|
4
6
|
|
|
5
|
-
|
|
7
|
+
[](https://www.npmjs.com/package/@kyro-cms/core)
|
|
8
|
+
[](https://opensource.org/licenses/MIT)
|
|
9
|
+
[](https://www.typescriptlang.org/)
|
|
10
|
+
|
|
11
|
+
</div>
|
|
6
12
|
|
|
7
13
|
---
|
|
8
14
|
|
|
9
|
-
##
|
|
15
|
+
## Why Kyro?
|
|
10
16
|
|
|
11
|
-
|
|
12
|
-
```typescript
|
|
13
|
-
import { createKyro, LocalAdapter } from '@kyro-cms/core';
|
|
17
|
+
Kyro is built for **Astro** from the ground up. Unlike other CMS solutions that bolt on Astro support, Kyro is architected to leverage Astro's islands architecture, server output modes, and performance-first approach.
|
|
14
18
|
|
|
15
|
-
|
|
16
|
-
adapter: new LocalAdapter({ path: './data.db' }),
|
|
17
|
-
collections: [productsCollection],
|
|
18
|
-
});
|
|
19
|
-
```
|
|
20
|
-
Works out of the box - no external database required.
|
|
21
|
-
|
|
22
|
-
### Deploy Anywhere with Adapters
|
|
23
|
-
- **Local/SQLite**: Zero-config local development
|
|
24
|
-
- **PostgreSQL/MySQL/SQLite**: Via Drizzle ORM
|
|
25
|
-
- **MongoDB**: NoSQL flexibility
|
|
19
|
+
### Key Features
|
|
26
20
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
-
|
|
30
|
-
-
|
|
31
|
-
-
|
|
32
|
-
-
|
|
33
|
-
-
|
|
21
|
+
- **Local-First** - SQLite for zero-config development, no external database needed
|
|
22
|
+
- **Multi-Database** - SQLite, PostgreSQL, MySQL, MongoDB via unified adapter interface
|
|
23
|
+
- **Multi-Protocol API** - REST, GraphQL, tRPC, and WebSocket from a single config
|
|
24
|
+
- **Multi-Vendor** - Built-in tenant scoping and row-level access control
|
|
25
|
+
- **E-Commerce Ready** - Products, orders, customers, inventory, coupons out of the box
|
|
26
|
+
- **Plugin System** - Extend with SEO, analytics, reviews, and more
|
|
27
|
+
- **Any Styling** - Tailwind, CSS Modules, Styled Components, or plain CSS
|
|
34
28
|
|
|
35
|
-
|
|
36
|
-
- **REST**: Hono-based with query params
|
|
37
|
-
- **GraphQL**: Dynamic schema
|
|
38
|
-
- **tRPC**: Type-safe RPC (zero inference)
|
|
39
|
-
- **WebSocket**: Real-time pub/sub
|
|
29
|
+
---
|
|
40
30
|
|
|
41
|
-
|
|
42
|
-
Row-level access control with tenant scoping built-in.
|
|
31
|
+
## Quick Start
|
|
43
32
|
|
|
44
|
-
###
|
|
45
|
-
Extend with:
|
|
46
|
-
- SEO (sitemaps, structured data)
|
|
47
|
-
- Analytics
|
|
48
|
-
- Reviews & Comments
|
|
49
|
-
- Wishlists
|
|
33
|
+
### Option 1: Create New Project (Recommended)
|
|
50
34
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
- CSS-in-JS
|
|
55
|
-
- Styled Components
|
|
56
|
-
- Vanilla Extract
|
|
35
|
+
```bash
|
|
36
|
+
npm create kyro@latest
|
|
37
|
+
```
|
|
57
38
|
|
|
58
|
-
|
|
39
|
+
This launches an interactive wizard that asks:
|
|
40
|
+
- Project name
|
|
41
|
+
- Database (SQLite, PostgreSQL, MySQL, MongoDB)
|
|
42
|
+
- API protocols (REST, GraphQL, tRPC, WebSocket)
|
|
43
|
+
- Styling (Tailwind, CSS Modules, Styled Components, None)
|
|
44
|
+
- Authentication (JWT)
|
|
45
|
+
- Versioning/Drafts
|
|
46
|
+
- Admin dashboard
|
|
47
|
+
- Starting template (Minimal, Blog, E-commerce)
|
|
59
48
|
|
|
60
|
-
|
|
49
|
+
### Option 2: Add to Existing Project
|
|
61
50
|
|
|
62
51
|
```bash
|
|
63
52
|
npm install @kyro-cms/core
|
|
64
53
|
```
|
|
65
54
|
|
|
66
|
-
|
|
55
|
+
```typescript
|
|
56
|
+
// kyro.config.ts
|
|
57
|
+
import { defineConfig, localAdapter } from '@kyro-cms/core';
|
|
58
|
+
|
|
59
|
+
export default defineConfig({
|
|
60
|
+
name: 'my-app',
|
|
61
|
+
adapter: localAdapter({ path: './data.db' }),
|
|
62
|
+
collections: {
|
|
63
|
+
posts: {
|
|
64
|
+
slug: 'posts',
|
|
65
|
+
label: 'Posts',
|
|
66
|
+
fields: [
|
|
67
|
+
{ name: 'title', type: 'text', required: true },
|
|
68
|
+
{ name: 'slug', type: 'text', required: true },
|
|
69
|
+
{ name: 'content', type: 'richtext' },
|
|
70
|
+
{ name: 'published', type: 'checkbox', defaultValue: false },
|
|
71
|
+
],
|
|
72
|
+
},
|
|
73
|
+
},
|
|
74
|
+
api: {
|
|
75
|
+
rest: true,
|
|
76
|
+
graphql: true,
|
|
77
|
+
},
|
|
78
|
+
});
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
---
|
|
82
|
+
|
|
83
|
+
## Database Adapters
|
|
84
|
+
|
|
85
|
+
### SQLite (Local-First)
|
|
67
86
|
|
|
68
87
|
```typescript
|
|
69
|
-
import {
|
|
88
|
+
import { localAdapter } from '@kyro-cms/core';
|
|
70
89
|
|
|
71
|
-
const
|
|
72
|
-
|
|
73
|
-
collections: [{
|
|
74
|
-
slug: 'posts',
|
|
75
|
-
fields: [
|
|
76
|
-
{ name: 'title', type: 'text', required: true },
|
|
77
|
-
{ name: 'content', type: 'richtext' },
|
|
78
|
-
],
|
|
79
|
-
}],
|
|
90
|
+
const adapter = localAdapter({
|
|
91
|
+
path: './data.db', // or ':memory:' for in-memory
|
|
80
92
|
});
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
Perfect for development and small projects. Zero configuration required.
|
|
81
96
|
|
|
82
|
-
|
|
97
|
+
### PostgreSQL/MySQL (Production)
|
|
98
|
+
|
|
99
|
+
```typescript
|
|
100
|
+
import { drizzleAdapter } from '@kyro-cms/core';
|
|
101
|
+
|
|
102
|
+
const adapter = drizzleAdapter({
|
|
103
|
+
connectionString: process.env.DATABASE_URL,
|
|
104
|
+
});
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
### MongoDB (Flexible Schemas)
|
|
108
|
+
|
|
109
|
+
```typescript
|
|
110
|
+
import { mongoAdapter } from '@kyro-cms/core';
|
|
111
|
+
|
|
112
|
+
const adapter = mongoAdapter({
|
|
113
|
+
connectionString: process.env.MONGODB_URI,
|
|
114
|
+
});
|
|
83
115
|
```
|
|
84
116
|
|
|
117
|
+
---
|
|
118
|
+
|
|
119
|
+
## API Protocols
|
|
120
|
+
|
|
121
|
+
Kyro exposes your data through multiple protocols simultaneously.
|
|
122
|
+
|
|
85
123
|
### REST API
|
|
86
124
|
|
|
87
125
|
```bash
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
126
|
+
# List documents
|
|
127
|
+
GET /api/posts
|
|
128
|
+
|
|
129
|
+
# Get single document
|
|
130
|
+
GET /api/posts/:id
|
|
131
|
+
|
|
132
|
+
# Create document
|
|
133
|
+
POST /api/posts
|
|
134
|
+
{ "title": "Hello World" }
|
|
135
|
+
|
|
136
|
+
# Update document
|
|
137
|
+
PATCH /api/posts/:id
|
|
138
|
+
{ "title": "Updated Title" }
|
|
139
|
+
|
|
140
|
+
# Delete document
|
|
141
|
+
DELETE /api/posts/:id
|
|
92
142
|
```
|
|
93
143
|
|
|
94
144
|
### GraphQL
|
|
95
145
|
|
|
96
146
|
```graphql
|
|
97
|
-
query {
|
|
98
|
-
|
|
147
|
+
query {
|
|
148
|
+
postsFind(where: {}, page: 1, limit: 10) {
|
|
149
|
+
docs {
|
|
150
|
+
id
|
|
151
|
+
title
|
|
152
|
+
slug
|
|
153
|
+
}
|
|
154
|
+
totalDocs
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
mutation {
|
|
159
|
+
postsCreate(data: { title: "New Post", slug: "new-post" }) {
|
|
160
|
+
doc {
|
|
161
|
+
id
|
|
162
|
+
title
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
### tRPC
|
|
169
|
+
|
|
170
|
+
```typescript
|
|
171
|
+
const client = createTRPCClient({
|
|
172
|
+
router: kyro.router,
|
|
173
|
+
transformer: superjson,
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
// Type-safe queries
|
|
177
|
+
const posts = await client.posts.find.query({ page: 1 });
|
|
178
|
+
const newPost = await client.posts.create.mutate({
|
|
179
|
+
title: "Hello",
|
|
180
|
+
slug: "hello"
|
|
181
|
+
});
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
### WebSocket (Real-time)
|
|
185
|
+
|
|
186
|
+
```typescript
|
|
187
|
+
const ws = new WebSocket('ws://localhost:4321/api/ws');
|
|
188
|
+
|
|
189
|
+
ws.send(JSON.stringify({
|
|
190
|
+
type: 'subscribe',
|
|
191
|
+
collection: 'posts',
|
|
192
|
+
event: 'create'
|
|
193
|
+
}));
|
|
194
|
+
|
|
195
|
+
ws.onmessage = (event) => {
|
|
196
|
+
const data = JSON.parse(event.data);
|
|
197
|
+
// Handle real-time updates
|
|
198
|
+
};
|
|
99
199
|
```
|
|
100
200
|
|
|
101
201
|
---
|
|
102
202
|
|
|
103
|
-
##
|
|
203
|
+
## Field Types
|
|
204
|
+
|
|
205
|
+
Kyro supports 21 field types:
|
|
206
|
+
|
|
207
|
+
| Type | Description |
|
|
208
|
+
|------|-------------|
|
|
209
|
+
| `text` | Single-line text input |
|
|
210
|
+
| `textarea` | Multi-line text |
|
|
211
|
+
| `richtext` | Rich text editor content |
|
|
212
|
+
| `markdown` | Markdown content |
|
|
213
|
+
| `number` | Numeric values |
|
|
214
|
+
| `email` | Email with validation |
|
|
215
|
+
| `password` | Hashed password storage |
|
|
216
|
+
| `checkbox` | Boolean toggle |
|
|
217
|
+
| `date` | Date/time picker |
|
|
218
|
+
| `select` | Dropdown selection |
|
|
219
|
+
| `radio` | Radio button group |
|
|
220
|
+
| `color` | Color picker |
|
|
221
|
+
| `json` | JSON data |
|
|
222
|
+
| `code` | Code editor content |
|
|
223
|
+
| `array` | Repeatable field groups |
|
|
224
|
+
| `group` | Nested field groups |
|
|
225
|
+
| `relationship` | Link to other documents |
|
|
226
|
+
| `upload` | File/media uploads |
|
|
227
|
+
| `blocks` | Structured content blocks |
|
|
228
|
+
| `row` | Horizontal field layout |
|
|
229
|
+
| `collapsible` | Collapsible field sections |
|
|
230
|
+
| `tabs` | Tabbed interface |
|
|
231
|
+
|
|
232
|
+
### Example: Complex Fields
|
|
104
233
|
|
|
105
234
|
```typescript
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
235
|
+
fields: [
|
|
236
|
+
{ name: 'title', type: 'text', required: true },
|
|
237
|
+
|
|
238
|
+
{
|
|
239
|
+
name: 'author',
|
|
240
|
+
type: 'relationship',
|
|
241
|
+
relationTo: 'users',
|
|
242
|
+
required: true
|
|
243
|
+
},
|
|
244
|
+
|
|
245
|
+
{
|
|
246
|
+
name: 'tags',
|
|
247
|
+
type: 'array',
|
|
248
|
+
fields: [
|
|
249
|
+
{ name: 'name', type: 'text' },
|
|
250
|
+
{ name: 'slug', type: 'text' },
|
|
251
|
+
]
|
|
252
|
+
},
|
|
253
|
+
|
|
254
|
+
{
|
|
255
|
+
name: 'metadata',
|
|
256
|
+
type: 'group',
|
|
257
|
+
fields: [
|
|
258
|
+
{ name: 'views', type: 'number', defaultValue: 0 },
|
|
259
|
+
{ name: 'featured', type: 'checkbox' },
|
|
260
|
+
]
|
|
261
|
+
}
|
|
262
|
+
]
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
---
|
|
266
|
+
|
|
267
|
+
## E-Commerce Collections
|
|
268
|
+
|
|
269
|
+
Pre-built collections for building online stores:
|
|
270
|
+
|
|
271
|
+
```typescript
|
|
272
|
+
import { ecommerceCollections } from '@kyro-cms/core';
|
|
113
273
|
|
|
114
274
|
const kyro = createKyro({
|
|
115
|
-
adapter:
|
|
275
|
+
adapter: localAdapter({ path: './store.db' }),
|
|
116
276
|
collections: ecommerceCollections,
|
|
117
|
-
tenantScoped: true, // Multi-vendor
|
|
118
277
|
});
|
|
119
278
|
|
|
120
|
-
|
|
279
|
+
// Includes:
|
|
280
|
+
// - products (with variants, pricing, inventory)
|
|
281
|
+
// - categories (hierarchical)
|
|
282
|
+
// - customers (with addresses)
|
|
283
|
+
// - orders (with items, status tracking)
|
|
284
|
+
// - coupons (percentage, fixed, free shipping)
|
|
285
|
+
// - store settings (globals)
|
|
121
286
|
```
|
|
122
287
|
|
|
123
288
|
---
|
|
124
289
|
|
|
290
|
+
## Authentication
|
|
291
|
+
|
|
292
|
+
Built-in JWT authentication:
|
|
293
|
+
|
|
294
|
+
```typescript
|
|
295
|
+
import { Auth, createAuth } from '@kyro-cms/core';
|
|
296
|
+
|
|
297
|
+
const auth = createAuth(adapter, {
|
|
298
|
+
secret: process.env.JWT_SECRET,
|
|
299
|
+
expiresIn: '24h',
|
|
300
|
+
refreshExpiresIn: '7d',
|
|
301
|
+
});
|
|
302
|
+
|
|
303
|
+
// Register
|
|
304
|
+
await auth.register({
|
|
305
|
+
email: 'user@example.com',
|
|
306
|
+
password: 'secure123',
|
|
307
|
+
role: 'customer',
|
|
308
|
+
});
|
|
309
|
+
|
|
310
|
+
// Login
|
|
311
|
+
const result = await auth.login({
|
|
312
|
+
email: 'user@example.com',
|
|
313
|
+
password: 'secure123',
|
|
314
|
+
});
|
|
315
|
+
|
|
316
|
+
console.log(result.token); // JWT token
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
---
|
|
320
|
+
|
|
321
|
+
## Version History & Drafts
|
|
322
|
+
|
|
323
|
+
Track document changes with built-in versioning:
|
|
324
|
+
|
|
325
|
+
```typescript
|
|
326
|
+
import { createVersionManager } from '@kyro-cms/core';
|
|
327
|
+
|
|
328
|
+
const versions = createVersionManager(adapter, {
|
|
329
|
+
versioningEnabled: true,
|
|
330
|
+
maxVersionsPerDocument: 50,
|
|
331
|
+
});
|
|
332
|
+
|
|
333
|
+
// Create a new version
|
|
334
|
+
const version = await versions.createVersion({
|
|
335
|
+
collection: 'posts',
|
|
336
|
+
documentId: 'abc123',
|
|
337
|
+
data: { title: 'Updated Post' },
|
|
338
|
+
status: 'draft',
|
|
339
|
+
createdBy: 'user123',
|
|
340
|
+
});
|
|
341
|
+
|
|
342
|
+
// Publish
|
|
343
|
+
await versions.publishVersion({
|
|
344
|
+
collection: 'posts',
|
|
345
|
+
documentId: 'abc123',
|
|
346
|
+
versionId: version.id,
|
|
347
|
+
publishedBy: 'user123',
|
|
348
|
+
});
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
---
|
|
352
|
+
|
|
353
|
+
## Admin Dashboard
|
|
354
|
+
|
|
355
|
+
Kyro includes a full admin dashboard:
|
|
356
|
+
|
|
357
|
+
```bash
|
|
358
|
+
npm install @kyro-cms/admin
|
|
359
|
+
```
|
|
360
|
+
|
|
361
|
+
```astro
|
|
362
|
+
---
|
|
363
|
+
// admin/index.astro
|
|
364
|
+
import { Admin } from '@kyro-cms/admin';
|
|
365
|
+
import config from '../kyro.config';
|
|
366
|
+
---
|
|
367
|
+
|
|
368
|
+
<Admin client:load config={config} />
|
|
369
|
+
```
|
|
370
|
+
|
|
371
|
+
Features:
|
|
372
|
+
- Collection browser with filtering and sorting
|
|
373
|
+
- Document editor with all field types
|
|
374
|
+
- Media library
|
|
375
|
+
- Global settings editor
|
|
376
|
+
- Dark mode support
|
|
377
|
+
|
|
378
|
+
---
|
|
379
|
+
|
|
125
380
|
## Plugin System
|
|
126
381
|
|
|
382
|
+
Extend Kyro with plugins:
|
|
383
|
+
|
|
127
384
|
```typescript
|
|
128
|
-
import {
|
|
385
|
+
import {
|
|
386
|
+
KyroPlugin,
|
|
387
|
+
SEOPLugin,
|
|
388
|
+
AnalyticsPlugin,
|
|
389
|
+
CommentsPlugin,
|
|
390
|
+
ReviewsPlugin,
|
|
391
|
+
WishlistPlugin
|
|
392
|
+
} from '@kyro-cms/core';
|
|
129
393
|
|
|
130
394
|
const kyro = createKyro({
|
|
131
|
-
adapter:
|
|
395
|
+
adapter: localAdapter(),
|
|
132
396
|
collections: [...],
|
|
133
397
|
plugins: [
|
|
134
|
-
new SEOPLugin(
|
|
398
|
+
new SEOPLugin({
|
|
399
|
+
sitemap: true,
|
|
400
|
+
robotsTxt: true,
|
|
401
|
+
}),
|
|
402
|
+
new AnalyticsPlugin({
|
|
403
|
+
providers: ['google', 'plausible'],
|
|
404
|
+
}),
|
|
405
|
+
new CommentsPlugin(),
|
|
135
406
|
new ReviewsPlugin(),
|
|
136
407
|
],
|
|
137
408
|
});
|
|
138
409
|
```
|
|
139
410
|
|
|
411
|
+
### Creating Plugins
|
|
412
|
+
|
|
413
|
+
```typescript
|
|
414
|
+
import { KyroPlugin } from '@kyro-cms/core';
|
|
415
|
+
|
|
416
|
+
class MyPlugin extends KyroPlugin {
|
|
417
|
+
name = 'my-plugin';
|
|
418
|
+
|
|
419
|
+
hooks = {
|
|
420
|
+
'collection.beforeCreate': async (args) => {
|
|
421
|
+
// Transform data before creation
|
|
422
|
+
return { ...args, data: { ...args.data, source: 'my-plugin' } };
|
|
423
|
+
},
|
|
424
|
+
|
|
425
|
+
'document.afterSave': async (args) => {
|
|
426
|
+
// Send webhook, log analytics, etc.
|
|
427
|
+
await sendWebhook(args);
|
|
428
|
+
},
|
|
429
|
+
};
|
|
430
|
+
}
|
|
431
|
+
```
|
|
432
|
+
|
|
140
433
|
---
|
|
141
434
|
|
|
142
|
-
## Styling
|
|
435
|
+
## Styling System
|
|
436
|
+
|
|
437
|
+
Kyro ships with a complete styling system:
|
|
143
438
|
|
|
144
439
|
```typescript
|
|
145
|
-
import {
|
|
440
|
+
import {
|
|
441
|
+
ecommerce2026Theme,
|
|
442
|
+
generateCSSVariables,
|
|
443
|
+
generateTailwindConfig
|
|
444
|
+
} from '@kyro-cms/core';
|
|
146
445
|
|
|
147
446
|
// Generate CSS variables
|
|
148
|
-
const
|
|
447
|
+
const cssVars = generateCSSVariables(ecommerce2026Theme);
|
|
448
|
+
|
|
449
|
+
// Generate Tailwind config
|
|
450
|
+
const tailwindConfig = generateTailwindConfig(ecommerce2026Theme);
|
|
451
|
+
|
|
452
|
+
// Custom themes
|
|
453
|
+
import { createAdminStyling } from '@kyro-cms/core';
|
|
454
|
+
|
|
455
|
+
const myTheme = createAdminStyling({
|
|
456
|
+
primaryColor: '#6366f1',
|
|
457
|
+
borderRadius: 'medium',
|
|
458
|
+
fontFamily: 'Inter',
|
|
459
|
+
});
|
|
149
460
|
```
|
|
150
461
|
|
|
151
462
|
---
|
|
152
463
|
|
|
153
|
-
##
|
|
464
|
+
## Deployment
|
|
154
465
|
|
|
466
|
+
### Vercel
|
|
467
|
+
|
|
468
|
+
```bash
|
|
469
|
+
vercel --prod
|
|
155
470
|
```
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
│ Local/SQLite │ │ Drizzle │ │ MongoDB │
|
|
173
|
-
│ (Local-first) │ │ (SQL) │ │ (NoSQL) │
|
|
174
|
-
└─────────────────┘ └─────────────┘ └─────────────────┘
|
|
175
|
-
│
|
|
176
|
-
▼
|
|
177
|
-
┌──────────────────────────────────────────────────────────────┐
|
|
178
|
-
│ Multi-Protocol API Gateway │
|
|
179
|
-
│ • REST (Hono) • GraphQL • tRPC • WebSocket │
|
|
180
|
-
└──────────────────────────────────────────────────────────────┘
|
|
471
|
+
|
|
472
|
+
Environment variables:
|
|
473
|
+
- `DATABASE_URL` - PostgreSQL connection string
|
|
474
|
+
- `JWT_SECRET` - JWT signing secret
|
|
475
|
+
|
|
476
|
+
### Railway
|
|
477
|
+
|
|
478
|
+
```bash
|
|
479
|
+
railway up
|
|
480
|
+
```
|
|
481
|
+
|
|
482
|
+
### Docker
|
|
483
|
+
|
|
484
|
+
```bash
|
|
485
|
+
cd deployments/docker
|
|
486
|
+
docker-compose up -d
|
|
181
487
|
```
|
|
182
488
|
|
|
489
|
+
See `deployments/` for complete configuration.
|
|
490
|
+
|
|
183
491
|
---
|
|
184
492
|
|
|
185
493
|
## Project Structure
|
|
186
494
|
|
|
187
495
|
```
|
|
188
496
|
kyro-cms/
|
|
497
|
+
├── packages/
|
|
498
|
+
│ └── create-kyro/ # Project scaffolding CLI
|
|
189
499
|
├── src/
|
|
190
|
-
│ ├── index.ts
|
|
191
|
-
│ ├──
|
|
192
|
-
│ ├──
|
|
193
|
-
│ ├──
|
|
194
|
-
│ ├──
|
|
195
|
-
│ ├──
|
|
196
|
-
│ ├──
|
|
197
|
-
│ └──
|
|
198
|
-
├──
|
|
199
|
-
├──
|
|
200
|
-
│ ├──
|
|
201
|
-
│
|
|
202
|
-
└──
|
|
500
|
+
│ ├── index.ts # Main exports
|
|
501
|
+
│ ├── createKyro.ts # Factory function
|
|
502
|
+
│ ├── registry/ # Config registry & validation
|
|
503
|
+
│ ├── fields/ # 21 field type definitions
|
|
504
|
+
│ ├── database/ # Adapter implementations
|
|
505
|
+
│ │ ├── local/ # SQLite adapter
|
|
506
|
+
│ │ ├── drizzle/ # SQL adapters
|
|
507
|
+
│ │ └── mongodb/ # MongoDB adapter
|
|
508
|
+
│ ├── api/ # Multi-protocol gateway
|
|
509
|
+
│ │ ├── rest/ # Hono REST
|
|
510
|
+
│ │ ├── graphql/ # GraphQL schema
|
|
511
|
+
│ │ ├── trpc/ # tRPC router
|
|
512
|
+
│ │ └── ws/ # WebSocket server
|
|
513
|
+
│ ├── auth/ # JWT authentication
|
|
514
|
+
│ ├── versions/ # Version history
|
|
515
|
+
│ ├── plugins/ # Plugin system
|
|
516
|
+
│ ├── styling/ # Theming
|
|
517
|
+
│ └── cli/ # CLI tools
|
|
518
|
+
├── admin/ # Admin dashboard (Astro)
|
|
519
|
+
├── examples/ # Example configurations
|
|
520
|
+
├── docs/ # Documentation
|
|
521
|
+
└── deployments/ # Deployment configs
|
|
203
522
|
```
|
|
204
523
|
|
|
205
524
|
---
|
|
@@ -207,9 +526,20 @@ kyro-cms/
|
|
|
207
526
|
## CLI Commands
|
|
208
527
|
|
|
209
528
|
```bash
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
529
|
+
# Initialize a new project
|
|
530
|
+
npm create kyro@latest
|
|
531
|
+
|
|
532
|
+
# Generate TypeScript types
|
|
533
|
+
kyro generate
|
|
534
|
+
|
|
535
|
+
# Push schema to database
|
|
536
|
+
kyro push
|
|
537
|
+
|
|
538
|
+
# Open database studio
|
|
539
|
+
kyro studio
|
|
540
|
+
|
|
541
|
+
# Check system health
|
|
542
|
+
kyro health
|
|
213
543
|
```
|
|
214
544
|
|
|
215
545
|
---
|
|
@@ -220,22 +550,31 @@ kyro health # Check system health
|
|
|
220
550
|
- [API Reference](docs/api.md)
|
|
221
551
|
- [E-Commerce Guide](docs/ecommerce.md)
|
|
222
552
|
- [Plugin Development](docs/plugins.md)
|
|
223
|
-
- [
|
|
553
|
+
- [Deployment Guide](docs/deployment.md)
|
|
554
|
+
|
|
555
|
+
---
|
|
556
|
+
|
|
557
|
+
## Contributing
|
|
558
|
+
|
|
559
|
+
Contributions are welcome! Please read our contributing guide before submitting PRs.
|
|
560
|
+
|
|
561
|
+
1. Fork the repository
|
|
562
|
+
2. Create your feature branch (`git checkout -b feature/amazing`)
|
|
563
|
+
3. Commit your changes (`git commit -m 'Add amazing feature'`)
|
|
564
|
+
4. Push to the branch (`git push origin feature/amazing`)
|
|
565
|
+
5. Open a Pull Request
|
|
224
566
|
|
|
225
567
|
---
|
|
226
568
|
|
|
227
569
|
## License
|
|
228
570
|
|
|
229
|
-
MIT
|
|
571
|
+
MIT License - see [LICENSE](LICENSE) for details.
|
|
230
572
|
|
|
231
573
|
---
|
|
232
574
|
|
|
233
|
-
##
|
|
575
|
+
## Acknowledgments
|
|
234
576
|
|
|
235
|
-
|
|
236
|
-
- [
|
|
237
|
-
- [
|
|
238
|
-
- [
|
|
239
|
-
- [ ] Full admin dashboard
|
|
240
|
-
- [ ] Authentication
|
|
241
|
-
- [ ] Version history
|
|
577
|
+
Built with inspiration from:
|
|
578
|
+
- [Payload CMS](https://payloadcms.com/) - The headless CMS that pushed the industry forward
|
|
579
|
+
- [Strapi](https://strapi.io/) - Open source headless CMS
|
|
580
|
+
- [Sanity](https://www.sanity.io/) - Real-time content infrastructure
|