dyrected 2.5.53 → 2.5.56
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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dyrected",
|
|
3
|
-
"version": "2.5.
|
|
3
|
+
"version": "2.5.56",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"files": [
|
|
6
6
|
"dist"
|
|
@@ -16,9 +16,9 @@
|
|
|
16
16
|
"jiti": "^2.7.0",
|
|
17
17
|
"prettier": "^3.2.5",
|
|
18
18
|
"prompts": "^2.4.2",
|
|
19
|
-
"@dyrected/core": "^2.5.
|
|
20
|
-
"@dyrected/
|
|
21
|
-
"@dyrected/
|
|
19
|
+
"@dyrected/core": "^2.5.56",
|
|
20
|
+
"@dyrected/knowledge": "^0.2.10",
|
|
21
|
+
"@dyrected/sdk": "^2.5.56"
|
|
22
22
|
},
|
|
23
23
|
"devDependencies": {
|
|
24
24
|
"@types/fs-extra": "^11.0.4",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ai-rules-template.d.ts","sourceRoot":"","sources":["../../src/utils/ai-rules-template.ts"],"names":[],"mappings":"AAAA,wBAAgB,YAAY,IAAI,MAAM,CAyZrC"}
|
|
@@ -1,411 +0,0 @@
|
|
|
1
|
-
export function buildAiRules() {
|
|
2
|
-
return `# Dyrected AI Rules
|
|
3
|
-
|
|
4
|
-
> This is the canonical instruction file for AI coding agents working with Dyrected.
|
|
5
|
-
> The Dyrected CLI also creates tool-specific pointer files so supported agents load it automatically.
|
|
6
|
-
>
|
|
7
|
-
> Full documentation: https://docs.dyrected.com
|
|
8
|
-
|
|
9
|
-
---
|
|
10
|
-
|
|
11
|
-
## Before writing any code
|
|
12
|
-
|
|
13
|
-
1. Read https://docs.dyrected.com before writing any integration code
|
|
14
|
-
2. Check the installed package version and its exported types — do not assume API shape from memory
|
|
15
|
-
3. Use only APIs that exist in the installed version; if the docs and the package disagree, use the package
|
|
16
|
-
4. Read the existing \`dyrected.config.ts\` before suggesting any schema change
|
|
17
|
-
5. Never invent field types, hook names, config options, or API methods
|
|
18
|
-
|
|
19
|
-
---
|
|
20
|
-
|
|
21
|
-
## Core imports
|
|
22
|
-
|
|
23
|
-
\`\`\`ts
|
|
24
|
-
import { defineCollection, defineGlobal, defineConfig } from '@dyrected/core'
|
|
25
|
-
import { DyrectedClient } from '@dyrected/sdk'
|
|
26
|
-
\`\`\`
|
|
27
|
-
|
|
28
|
-
---
|
|
29
|
-
|
|
30
|
-
## Available field types
|
|
31
|
-
|
|
32
|
-
\`text\`, \`textarea\`, \`richText\`, \`number\`, \`boolean\`, \`date\`, \`datetime\`, \`time\`,
|
|
33
|
-
\`email\`, \`url\`, \`icon\`, \`json\`, \`select\`, \`multiSelect\`, \`radio\`,
|
|
34
|
-
\`relationship\`, \`image\`, \`object\`, \`array\`, \`blocks\`, \`row\`, \`join\`
|
|
35
|
-
|
|
36
|
-
Do not invent field types that are not in this list.
|
|
37
|
-
|
|
38
|
-
Docs: https://docs.dyrected.com/docs/concepts/fields
|
|
39
|
-
|
|
40
|
-
---
|
|
41
|
-
|
|
42
|
-
## Never do these things
|
|
43
|
-
|
|
44
|
-
- **Never use \`client.collections\`** — the only correct entry point is \`client.collection('slug')\`
|
|
45
|
-
- **Never add custom auth or session middleware on admin routes** — Dyrected handles authentication internally; adding your own breaks the dashboard
|
|
46
|
-
- **Never define \`email\` or \`password\` fields on an \`auth: true\` collection** — they are injected automatically
|
|
47
|
-
- **Never delete a field from the config** — existing documents store data under that key; removing it orphans the data permanently
|
|
48
|
-
- **Never rename a field directly** — use \`renameTo\` for a lazy, zero-downtime migration (see Schema Evolution below)
|
|
49
|
-
- **Never add a new field to an existing collection without \`defaultValue\`** — existing documents need a safe read fallback
|
|
50
|
-
- **Never use function callbacks in \`admin.condition\`** if the project uses Dyrected Cloud — use Jexl string expressions instead; functions are stripped on cloud sync
|
|
51
|
-
|
|
52
|
-
---
|
|
53
|
-
|
|
54
|
-
## Schema evolution
|
|
55
|
-
|
|
56
|
-
Full guide: https://docs.dyrected.com/docs/concepts/schema
|
|
57
|
-
|
|
58
|
-
### Renaming a field safely
|
|
59
|
-
|
|
60
|
-
\`\`\`ts
|
|
61
|
-
{
|
|
62
|
-
name: 'fullName', // new name
|
|
63
|
-
type: 'text',
|
|
64
|
-
renameTo: 'name', // old name — fallback on read until all docs are resaved
|
|
65
|
-
}
|
|
66
|
-
\`\`\`
|
|
67
|
-
|
|
68
|
-
Remove \`renameTo\` once all documents in production have been resaved under the new name.
|
|
69
|
-
|
|
70
|
-
### Indexing a field for fast queries
|
|
71
|
-
|
|
72
|
-
\`\`\`ts
|
|
73
|
-
{ name: 'slug', type: 'text', unique: true, promoted: true }
|
|
74
|
-
\`\`\`
|
|
75
|
-
|
|
76
|
-
After adding \`promoted: true\`, run \`npx @dyrected/cli sync:schema\` (Cloud) or restart the server (self-hosted).
|
|
77
|
-
Supported types: \`text\`, \`number\`, \`boolean\`, \`date\`, \`datetime\`.
|
|
78
|
-
|
|
79
|
-
---
|
|
80
|
-
|
|
81
|
-
## Zero-state resilience
|
|
82
|
-
|
|
83
|
-
Always write frontend data fetches with \`initialData\` fallbacks so the page renders when the backend
|
|
84
|
-
is unreachable or the collection is empty.
|
|
85
|
-
|
|
86
|
-
\`\`\`ts
|
|
87
|
-
const { docs } = await client.collection('posts').find({ initialData: [] })
|
|
88
|
-
const settings = await client.global('site-settings').get({ initialData: { siteName: 'My Site' } })
|
|
89
|
-
\`\`\`
|
|
90
|
-
|
|
91
|
-
---
|
|
92
|
-
|
|
93
|
-
## Relationships and depth
|
|
94
|
-
|
|
95
|
-
Docs: https://docs.dyrected.com/docs/concepts/relationships | https://docs.dyrected.com/docs/concepts/depth
|
|
96
|
-
|
|
97
|
-
A \`relationship\` field stores the ID of a document in another collection (the owning side).
|
|
98
|
-
A \`join\` field is a virtual reverse lookup — it stores nothing; it queries the other collection at read time.
|
|
99
|
-
|
|
100
|
-
\`\`\`ts
|
|
101
|
-
// relationship — stores an ID
|
|
102
|
-
{ name: 'author', type: 'relationship', relationTo: 'users' }
|
|
103
|
-
{ name: 'tags', type: 'relationship', relationTo: 'tags', hasMany: true }
|
|
104
|
-
|
|
105
|
-
// join — virtual reverse lookup (no storage)
|
|
106
|
-
{
|
|
107
|
-
name: 'posts',
|
|
108
|
-
type: 'join',
|
|
109
|
-
collection: 'posts', // the collection to look in
|
|
110
|
-
on: 'author', // the relationship field on that collection
|
|
111
|
-
limit: 20,
|
|
112
|
-
}
|
|
113
|
-
\`\`\`
|
|
114
|
-
|
|
115
|
-
Control how many levels of relationships are hydrated with \`depth\`:
|
|
116
|
-
|
|
117
|
-
- \`depth: 0\` — return IDs only
|
|
118
|
-
- \`depth: 1\` (default) — hydrate direct relationships; nested ones remain IDs
|
|
119
|
-
- \`depth: 2\` — hydrate two levels deep
|
|
120
|
-
|
|
121
|
-
Use \`depth: 0\` on list pages to keep payloads small. Use \`depth: 1\` (the default) when you need related field values.
|
|
122
|
-
|
|
123
|
-
---
|
|
124
|
-
|
|
125
|
-
## Auth collections
|
|
126
|
-
|
|
127
|
-
Docs: https://docs.dyrected.com/docs/concepts/auth-model
|
|
128
|
-
|
|
129
|
-
\`auth: true\` turns a collection into an authentication provider. Dyrected automatically injects
|
|
130
|
-
\`email\` (required, unique) and \`password\` (hashed, never returned in responses) — do not define them yourself.
|
|
131
|
-
|
|
132
|
-
\`\`\`ts
|
|
133
|
-
export const Users = defineCollection({
|
|
134
|
-
slug: 'users',
|
|
135
|
-
auth: true,
|
|
136
|
-
fields: [
|
|
137
|
-
{ name: 'name', type: 'text' },
|
|
138
|
-
{ name: 'role', type: 'select', options: ['member', 'editor', 'admin'] },
|
|
139
|
-
],
|
|
140
|
-
})
|
|
141
|
-
\`\`\`
|
|
142
|
-
|
|
143
|
-
Generated endpoints (all under \`/dyrected/api/{slug}/\`): \`login\`, \`logout\`, \`me\`, \`refresh-token\`,
|
|
144
|
-
\`forgot-password\`, \`reset-password\`, \`invite\`, \`accept-invite\`, \`first-user\`, \`init\`.
|
|
145
|
-
|
|
146
|
-
The admin dashboard uses a **separate** auth collection by convention. Define it as:
|
|
147
|
-
|
|
148
|
-
\`\`\`ts
|
|
149
|
-
export const Admins = defineCollection({
|
|
150
|
-
slug: '__admins',
|
|
151
|
-
auth: true,
|
|
152
|
-
fields: [], // email + password are automatic
|
|
153
|
-
})
|
|
154
|
-
\`\`\`
|
|
155
|
-
|
|
156
|
-
Do not mix app user auth and admin auth in the same collection unless you explicitly want editors to log into both.
|
|
157
|
-
|
|
158
|
-
---
|
|
159
|
-
|
|
160
|
-
## Upload collections
|
|
161
|
-
|
|
162
|
-
Docs: https://docs.dyrected.com/docs/guides/file-uploads
|
|
163
|
-
|
|
164
|
-
\`upload: true\` turns a collection into a media library. Dyrected automatically injects \`filename\`,
|
|
165
|
-
\`mimeType\`, \`url\`, \`filesize\`, \`width\`, \`height\`, and \`blurhash\`.
|
|
166
|
-
|
|
167
|
-
\`\`\`ts
|
|
168
|
-
export const Media = defineCollection({
|
|
169
|
-
slug: 'media',
|
|
170
|
-
upload: {
|
|
171
|
-
allowedMimeTypes: ['image/*'],
|
|
172
|
-
maxFileSize: 5_000_000, // bytes
|
|
173
|
-
imageSizes: [
|
|
174
|
-
{ name: 'thumbnail', width: 300, height: 300, crop: 'cover' },
|
|
175
|
-
{ name: 'card', width: 800 },
|
|
176
|
-
],
|
|
177
|
-
},
|
|
178
|
-
fields: [
|
|
179
|
-
{ name: 'alt', type: 'text' },
|
|
180
|
-
],
|
|
181
|
-
})
|
|
182
|
-
\`\`\`
|
|
183
|
-
|
|
184
|
-
---
|
|
185
|
-
|
|
186
|
-
## Dynamic options (select / multiSelect / radio)
|
|
187
|
-
|
|
188
|
-
Docs: https://docs.dyrected.com/docs/concepts/dynamic-options
|
|
189
|
-
|
|
190
|
-
Three ways to populate options — pick the right one:
|
|
191
|
-
|
|
192
|
-
| Approach | Where it runs | Use when |
|
|
193
|
-
|---|---|---|
|
|
194
|
-
| Static array | — | Fixed list known at build time |
|
|
195
|
-
| Server-side resolver (async function) | Server | DB queries, API keys, user-filtered lists, caching |
|
|
196
|
-
| \`admin.hooks.options\` (UI hook) | Browser | Instant dependent/cascading dropdowns |
|
|
197
|
-
|
|
198
|
-
\`\`\`ts
|
|
199
|
-
// Server-side resolver — runs on the server, never sent to the browser
|
|
200
|
-
{
|
|
201
|
-
name: 'category',
|
|
202
|
-
type: 'select',
|
|
203
|
-
options: async ({ db }) => {
|
|
204
|
-
const result = await db.find({ collection: 'categories' })
|
|
205
|
-
return result.docs.map(c => ({ label: c.name, value: c.id }))
|
|
206
|
-
},
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
// Client-side UI hook — runs in the browser, instant, no network round-trip
|
|
210
|
-
{
|
|
211
|
-
name: 'region',
|
|
212
|
-
type: 'select',
|
|
213
|
-
options: [],
|
|
214
|
-
admin: {
|
|
215
|
-
hooks: {
|
|
216
|
-
options: ({ siblingData }) =>
|
|
217
|
-
siblingData.country === 'us'
|
|
218
|
-
? [{ label: 'California', value: 'CA' }, { label: 'New York', value: 'NY' }]
|
|
219
|
-
: [],
|
|
220
|
-
},
|
|
221
|
-
},
|
|
222
|
-
}
|
|
223
|
-
\`\`\`
|
|
224
|
-
|
|
225
|
-
---
|
|
226
|
-
|
|
227
|
-
## Conditional fields
|
|
228
|
-
|
|
229
|
-
Docs: https://docs.dyrected.com/docs/admin/configuration#condition--conditional-fields
|
|
230
|
-
|
|
231
|
-
Use \`admin.condition\` to show or hide a field based on sibling values. Use Jexl string expressions
|
|
232
|
-
(not functions) for cloud compatibility:
|
|
233
|
-
|
|
234
|
-
\`\`\`ts
|
|
235
|
-
// Only show 'scheduledAt' when status is 'scheduled'
|
|
236
|
-
{
|
|
237
|
-
name: 'scheduledAt',
|
|
238
|
-
type: 'datetime',
|
|
239
|
-
admin: {
|
|
240
|
-
condition: 'status == "scheduled"',
|
|
241
|
-
},
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
// Complex logic
|
|
245
|
-
{
|
|
246
|
-
name: 'salePrice',
|
|
247
|
-
type: 'number',
|
|
248
|
-
admin: {
|
|
249
|
-
condition: 'onSale == true && price > 0',
|
|
250
|
-
},
|
|
251
|
-
}
|
|
252
|
-
\`\`\`
|
|
253
|
-
|
|
254
|
-
---
|
|
255
|
-
|
|
256
|
-
## Custom field components and component slots
|
|
257
|
-
|
|
258
|
-
Docs: https://docs.dyrected.com/docs/admin/configuration
|
|
259
|
-
|
|
260
|
-
### Custom field input
|
|
261
|
-
|
|
262
|
-
Replace any field's default input with a custom component. Declare a unique string key in the config:
|
|
263
|
-
|
|
264
|
-
\`\`\`ts
|
|
265
|
-
{
|
|
266
|
-
name: 'brandColor',
|
|
267
|
-
type: 'text',
|
|
268
|
-
admin: {
|
|
269
|
-
component: 'products.brandColor',
|
|
270
|
-
},
|
|
271
|
-
}
|
|
272
|
-
\`\`\`
|
|
273
|
-
|
|
274
|
-
Register the component in your \`<DyrectedAdmin>\` wrapper:
|
|
275
|
-
|
|
276
|
-
\`\`\`tsx
|
|
277
|
-
// React / Next.js
|
|
278
|
-
<DyrectedAdmin components={{ fields: { 'products.brandColor': BrandColorPicker } }} />
|
|
279
|
-
|
|
280
|
-
// Vue / Nuxt
|
|
281
|
-
<DyrectedAdmin :components="{ fields: { 'products.brandColor': BrandColorPicker } }" />
|
|
282
|
-
\`\`\`
|
|
283
|
-
|
|
284
|
-
The component receives \`value\`, \`onChange\`, \`field\`, \`path\`, \`disabled\`, and \`collection\` as props.
|
|
285
|
-
|
|
286
|
-
### Component slots (dashboard and collection pages)
|
|
287
|
-
|
|
288
|
-
Inject custom panels into the dashboard or collection list pages by declaring slot keys in the config
|
|
289
|
-
and providing the matching components to \`<DyrectedAdmin>\`:
|
|
290
|
-
|
|
291
|
-
\`\`\`ts
|
|
292
|
-
// dyrected.config.ts
|
|
293
|
-
defineConfig({
|
|
294
|
-
admin: {
|
|
295
|
-
components: ['dashboard.analytics'], // slot key
|
|
296
|
-
},
|
|
297
|
-
...
|
|
298
|
-
})
|
|
299
|
-
\`\`\`
|
|
300
|
-
|
|
301
|
-
\`\`\`tsx
|
|
302
|
-
<DyrectedAdmin
|
|
303
|
-
components={{
|
|
304
|
-
slots: { 'dashboard.analytics': AnalyticsDashboard }
|
|
305
|
-
}}
|
|
306
|
-
/>
|
|
307
|
-
\`\`\`
|
|
308
|
-
|
|
309
|
-
---
|
|
310
|
-
|
|
311
|
-
## Intent → pattern
|
|
312
|
-
|
|
313
|
-
Translate plain-language goals to the correct Dyrected pattern. Make the decision yourself
|
|
314
|
-
— do not ask the developer to choose between Dyrected concepts.
|
|
315
|
-
|
|
316
|
-
| If the user wants to… | Use this pattern |
|
|
317
|
-
|--------------------------------------------------------------------|------------------|
|
|
318
|
-
| Auto-generate a slug from a title | \`beforeChange\` collection hook (server) + \`admin.hooks.onChange\` on the slug field (live preview) |
|
|
319
|
-
| Validate data before saving | \`beforeChange\` collection hook — throw to abort |
|
|
320
|
-
| Run logic after a document is saved | \`afterChange\` collection hook — never \`await\` slow ops inline; use \`.catch()\` |
|
|
321
|
-
| Send a webhook or email when content changes | \`afterChange\` collection hook |
|
|
322
|
-
| Revalidate a Next.js / Nuxt page after a save | \`afterChange\` collection hook posting to the revalidation endpoint |
|
|
323
|
-
| Only admins can see a field | Field-level \`access: { read: ({ user }) => user?.roles?.includes('admin') ?? false }\` |
|
|
324
|
-
| Different roles can edit different fields | Field-level \`access.update\` |
|
|
325
|
-
| Restrict who can create / edit / delete | Collection-level \`access\` config |
|
|
326
|
-
| Track who created or changed a document | \`audit: true\` on the collection |
|
|
327
|
-
| Content approval / draft-publish flow | \`workflow: publishingWorkflow()\` on the collection |
|
|
328
|
-
| Guard a workflow transition | \`workflow.hooks.beforeTransition\` — throw to cancel |
|
|
329
|
-
| Notify someone after a workflow state change | \`workflow.hooks.afterTransition\` |
|
|
330
|
-
| Different content per site (multi-tenant) | \`siteId\` on the collection + \`beforeRead\` hook to scope queries |
|
|
331
|
-
| Share content across all sites | \`shared: true\` on the collection |
|
|
332
|
-
| Show a dependent dropdown based on another field (instant) | \`admin.hooks.options\` on the dependent select field |
|
|
333
|
-
| Populate a dropdown from a database query or external API | Server-side \`options\` async resolver function |
|
|
334
|
-
| Show a live computed value in the admin form | \`admin.hooks.onChange\` on the output field |
|
|
335
|
-
| Show or hide a field based on another field's value | \`admin.condition\` with a Jexl string expression |
|
|
336
|
-
| Query or sort a field efficiently at scale | \`promoted: true\` on the field, then run \`sync:schema\` |
|
|
337
|
-
| One fixed set of content (site name, logo, tagline…) | \`defineGlobal\` |
|
|
338
|
-
| Multiple entries the client can add or remove | \`defineCollection\` |
|
|
339
|
-
| Flexible page layouts (hero, cards, testimonials…) | \`blocks\` field — one block definition per layout type |
|
|
340
|
-
| Seed default content on first run | \`initialData\` on the collection or global |
|
|
341
|
-
| Reference a document in another collection | \`relationship\` field with \`relationTo: 'slug'\` |
|
|
342
|
-
| Store multiple references (tags, categories…) | \`relationship\` field with \`hasMany: true\` |
|
|
343
|
-
| Show all related documents on the other side (reverse lookup) | \`join\` field with \`collection\` and \`on\` |
|
|
344
|
-
| Fetch a document with its related data populated | Use \`depth: 1\` (default) on the query |
|
|
345
|
-
| Allow users to log in to the app | \`auth: true\` on a collection |
|
|
346
|
-
| Separate admin login from app user login | Define a \`__admins\` collection with \`auth: true\` |
|
|
347
|
-
| Allow file / image uploads | \`upload: true\` (or an upload config object) on a collection |
|
|
348
|
-
| Replace the default input for a field with a custom component | \`admin.component\` string key + register in \`<DyrectedAdmin>\` |
|
|
349
|
-
| Inject a custom panel into the dashboard or a collection page | Component slots in \`admin.components\` config + register in \`<DyrectedAdmin>\` |
|
|
350
|
-
|
|
351
|
-
---
|
|
352
|
-
|
|
353
|
-
## Canonical recipe: generate a slug from a title
|
|
354
|
-
|
|
355
|
-
When the developer asks for automatic URLs, friendly URLs, or a slug derived from a title, implement both layers below. The server hook guarantees API writes are correct; the Admin hook gives editors immediate feedback.
|
|
356
|
-
|
|
357
|
-
\`\`\`ts
|
|
358
|
-
const toSlug = (value: unknown) =>
|
|
359
|
-
String(value ?? '')
|
|
360
|
-
.toLowerCase()
|
|
361
|
-
.trim()
|
|
362
|
-
.replace(/[^a-z0-9]+/g, '-')
|
|
363
|
-
.replace(/(^-|-$)/g, '')
|
|
364
|
-
|
|
365
|
-
export const Posts = defineCollection({
|
|
366
|
-
slug: 'posts',
|
|
367
|
-
hooks: {
|
|
368
|
-
beforeChange: [({ data, operation }) => {
|
|
369
|
-
if (operation === 'create' || data.title !== undefined) {
|
|
370
|
-
return { ...data, slug: toSlug(data.title) }
|
|
371
|
-
}
|
|
372
|
-
return data
|
|
373
|
-
}],
|
|
374
|
-
},
|
|
375
|
-
fields: [
|
|
376
|
-
{ name: 'title', type: 'text', required: true },
|
|
377
|
-
{
|
|
378
|
-
name: 'slug', type: 'text', required: true, unique: true, promoted: true,
|
|
379
|
-
admin: { hooks: { onChange: ({ siblingData }) => toSlug(siblingData.title) } },
|
|
380
|
-
},
|
|
381
|
-
],
|
|
382
|
-
})
|
|
383
|
-
\`\`\`
|
|
384
|
-
|
|
385
|
-
Do not implement only the browser hook: API-created documents would bypass it. Do not implement only the server hook when editors need to see the resulting URL while typing.
|
|
386
|
-
|
|
387
|
-
---
|
|
388
|
-
|
|
389
|
-
## Access control
|
|
390
|
-
|
|
391
|
-
Docs: https://docs.dyrected.com/docs/concepts/access-control
|
|
392
|
-
|
|
393
|
-
- Create the smallest set of permissions needed for the approved use case
|
|
394
|
-
- Editors may access only the content they are approved to edit
|
|
395
|
-
- Do not grant delete or publish access unless explicitly required
|
|
396
|
-
- Enforce access in the server-side config — not only by hiding controls in the Admin UI
|
|
397
|
-
|
|
398
|
-
---
|
|
399
|
-
|
|
400
|
-
## Working approach
|
|
401
|
-
|
|
402
|
-
- Work in small verified batches — no more than three related content areas at a time
|
|
403
|
-
- Verify lint, types, and build pass before moving to the next batch
|
|
404
|
-
- Fix a failing batch before starting new content types
|
|
405
|
-
- Ask plain-language questions when you need clarification:
|
|
406
|
-
e.g. "Should the client be able to add more items, or only edit the ones already there?"
|
|
407
|
-
Never ask: "Should this be a collection or a global?"
|
|
408
|
-
- Use the intent → pattern table above to make technical decisions without asking the developer
|
|
409
|
-
`;
|
|
410
|
-
}
|
|
411
|
-
//# sourceMappingURL=ai-rules-template.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ai-rules-template.js","sourceRoot":"","sources":["../../src/utils/ai-rules-template.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,YAAY;IAC1B,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAuZR,CAAC;AACF,CAAC"}
|