@dyrected/core 1.0.9 → 2.1.0
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/dist/app-KApbf4XL.d.cts +362 -0
- package/dist/app-KApbf4XL.d.ts +362 -0
- package/dist/chunk-22JTWD74.js +1784 -0
- package/dist/index.cjs +2169 -79
- package/dist/index.d.cts +7 -3
- package/dist/index.d.ts +7 -3
- package/dist/index.js +448 -82
- package/dist/server.d.cts +4 -22
- package/dist/server.d.ts +4 -22
- package/dist/server.js +8 -1715
- package/package.json +2 -1
package/dist/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
|
+
createDyrectedApp,
|
|
2
3
|
normalizeConfig
|
|
3
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-22JTWD74.js";
|
|
4
5
|
|
|
5
6
|
// src/utils/setup-prompt.ts
|
|
6
7
|
function buildEnvironmentSection(frameworkLabel, isSelfHosted, config) {
|
|
@@ -10,41 +11,75 @@ function buildEnvironmentSection(frameworkLabel, isSelfHosted, config) {
|
|
|
10
11
|
\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501
|
|
11
12
|
1. ENVIRONMENT
|
|
12
13
|
\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501
|
|
13
|
-
- Framework : ${frameworkLabel}
|
|
14
|
+
- Framework : ${frameworkLabel || "Detect it"}
|
|
14
15
|
- Host Type : ${isSelfHosted ? "Self-Hosted (Local/Private Server)" : "Managed (Dyrected Cloud)"}
|
|
15
16
|
- API Base : ${config.baseUrl || "http://localhost:3000"}
|
|
16
17
|
${credentialLines}`;
|
|
17
18
|
}
|
|
18
|
-
function buildDiagnosticSection(
|
|
19
|
-
if (existingSite) {
|
|
20
|
-
return `
|
|
21
|
-
\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501
|
|
22
|
-
2. PHASE 0 \u2014 DIAGNOSTIC (EXISTING SITE)
|
|
23
|
-
\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501
|
|
24
|
-
Before writing any code, scan the existing codebase and report:
|
|
25
|
-
- All hardcoded text strings that should be CMS-managed
|
|
26
|
-
- All repeated data structures that should become collections
|
|
27
|
-
- All static pages that marketing will want to edit independently
|
|
28
|
-
- Any existing fetch or API calls that overlap with Dyrected
|
|
29
|
-
|
|
30
|
-
Then propose a backup plan: extract all current content into a
|
|
31
|
-
migration/ folder as structured .md or .json files BEFORE
|
|
32
|
-
modifying any code.
|
|
33
|
-
|
|
34
|
-
Do NOT write any implementation code until you have reported
|
|
35
|
-
your findings and the user has confirmed the content plan.`;
|
|
36
|
-
}
|
|
19
|
+
function buildDiagnosticSection() {
|
|
37
20
|
return `
|
|
38
21
|
\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501
|
|
39
|
-
2. PHASE 0 \u2014 DISCOVERY
|
|
22
|
+
2. PHASE 0 \u2014 DISCOVERY
|
|
40
23
|
\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
Do
|
|
24
|
+
Before writing any code, you MUST ask the user these questions.
|
|
25
|
+
Write them exactly as shown below \u2014 in plain language with examples.
|
|
26
|
+
Wait for the user to answer ALL of them before proceeding.
|
|
27
|
+
|
|
28
|
+
\u2500\u2500\u2500 QUESTION 1 \u2500\u2500\u2500
|
|
29
|
+
Ask:
|
|
30
|
+
"Do you already have a website built, or are we starting fresh?
|
|
31
|
+
|
|
32
|
+
\u2192 Already built: share your project or describe what pages you have
|
|
33
|
+
(e.g. Home, About, Services, Contact)
|
|
34
|
+
\u2192 Starting fresh: just say 'new site' and describe what the site is for"
|
|
35
|
+
|
|
36
|
+
\u2500\u2500\u2500 QUESTION 2 \u2500\u2500\u2500
|
|
37
|
+
Ask:
|
|
38
|
+
"What kind of content will your client need to update regularly?
|
|
39
|
+
|
|
40
|
+
Here are some examples to help you think:
|
|
41
|
+
\u2192 Blog posts or news articles
|
|
42
|
+
\u2192 Team member profiles (name, photo, bio)
|
|
43
|
+
\u2192 Services or product descriptions
|
|
44
|
+
\u2192 Testimonials or reviews
|
|
45
|
+
\u2192 Event listings
|
|
46
|
+
\u2192 FAQs
|
|
47
|
+
\u2192 Homepage text (headline, hero image, call-to-action button)
|
|
48
|
+
|
|
49
|
+
Just list the ones that apply. You can say things like:
|
|
50
|
+
'They need to update blog posts and team members'"
|
|
51
|
+
|
|
52
|
+
\u2500\u2500\u2500 QUESTION 3 \u2500\u2500\u2500
|
|
53
|
+
Ask:
|
|
54
|
+
"Are there any pages on the site that should NEVER change \u2014 like a
|
|
55
|
+
custom-coded page you want to leave exactly as it is?
|
|
56
|
+
|
|
57
|
+
Example answer: 'The homepage has a custom animation, leave that alone.
|
|
58
|
+
Everything else can be managed from the CMS.'
|
|
59
|
+
|
|
60
|
+
If everything should be manageable, just say 'all pages'"
|
|
61
|
+
|
|
62
|
+
\u2500\u2500\u2500 QUESTION 4 \u2500\u2500\u2500
|
|
63
|
+
Ask:
|
|
64
|
+
"What is this website for? Pick the closest description:
|
|
65
|
+
|
|
66
|
+
A) A business or agency marketing site (show services, get leads)
|
|
67
|
+
B) A blog or content site (publish articles regularly)
|
|
68
|
+
C) A SaaS or product site (landing page, pricing, features)
|
|
69
|
+
D) A portfolio (show work, case studies)
|
|
70
|
+
E) An e-commerce or product catalogue
|
|
71
|
+
F) Something else \u2014 describe it in one sentence"
|
|
72
|
+
|
|
73
|
+
\u2500\u2500\u2500 IF EXISTING SITE \u2500\u2500\u2500
|
|
74
|
+
If the user confirms they have an existing site, also:
|
|
75
|
+
- Scan the codebase for all hardcoded text that should be CMS-managed
|
|
76
|
+
- Identify repeated data structures that should become collections
|
|
77
|
+
- Propose saving current content to a migration/ folder as .json files
|
|
78
|
+
BEFORE touching any code
|
|
79
|
+
- Report your findings to the user and get confirmation before proceeding
|
|
80
|
+
|
|
81
|
+
Do NOT write any implementation code until all questions are answered
|
|
82
|
+
and the user has confirmed the content plan.`;
|
|
48
83
|
}
|
|
49
84
|
function buildConstraintsSection() {
|
|
50
85
|
return `
|
|
@@ -74,7 +109,7 @@ function buildSchemaRulesSection() {
|
|
|
74
109
|
- Never drop existing fields from the schema. Mark unused fields as deprecated only.
|
|
75
110
|
- All new fields must have a defaultValue.
|
|
76
111
|
- Never rename a field slug \u2014 add a new field and migrate data separately.
|
|
77
|
-
-
|
|
112
|
+
- For Cloud deployments, run npx @dyrected/cli sync:schema after every config change. Self-hosted deployments sync automatically on startup.`;
|
|
78
113
|
}
|
|
79
114
|
function buildDoNotSection() {
|
|
80
115
|
return `
|
|
@@ -85,7 +120,7 @@ function buildDoNotSection() {
|
|
|
85
120
|
- Do NOT add custom auth middleware to the admin route.
|
|
86
121
|
Dyrected handles admin authentication internally. Do not wrap,
|
|
87
122
|
protect, or redirect the admin route yourself.
|
|
88
|
-
- Do NOT use renderAdminUI in a Nuxt project. Use the DyrectedAdmin
|
|
123
|
+
- Do NOT use renderAdminUI in a Nuxt.js project. Use the DyrectedAdmin
|
|
89
124
|
component which is auto-imported by @dyrected/nuxt.
|
|
90
125
|
- Do NOT modify or overwrite existing pages without first preserving their data.
|
|
91
126
|
- Do NOT drop, rename, or remove fields from an existing schema.
|
|
@@ -100,23 +135,26 @@ function buildTechnicalReferenceSection() {
|
|
|
100
135
|
Use defineCollection, defineGlobal, and defineConfig from '@dyrected/core'.
|
|
101
136
|
|
|
102
137
|
FIELD TYPES:
|
|
103
|
-
- Primitive : text | textarea | richText | number | boolean | date | email | url | json
|
|
138
|
+
- Primitive : text | textarea | richText | number | boolean | date | email | url | json | image
|
|
104
139
|
- Choice : select | multiSelect (requires options: [{ label, value }])
|
|
105
140
|
- Structural : array | object (requires nested fields: [...])
|
|
106
|
-
- Relation : relationship (requires
|
|
141
|
+
- Relation : relationship (requires relationTo: '<slug>')
|
|
107
142
|
- Media : relationship to an upload collection (e.g. 'media')
|
|
108
143
|
- Blocks : blocks (requires blocks: [{ slug, labels, fields }])
|
|
109
144
|
|
|
110
145
|
COLLECTION OPTIONS:
|
|
111
146
|
- upload: true \u2014 media library with file upload support
|
|
112
147
|
- auth: true \u2014 adds login/me endpoints; password field is auto-managed
|
|
148
|
+
- audit: true \u2014 enables activity logging
|
|
113
149
|
- admin.useAsTitle \u2014 field used as display title in admin list view
|
|
114
150
|
- admin.group \u2014 groups collection under a sidebar heading
|
|
115
151
|
- admin.hidden \u2014 hides collection from the sidebar (internal/system use)
|
|
116
152
|
|
|
117
153
|
FIELD OPTIONS:
|
|
154
|
+
- label \u2014 user-friendly display name (REQUIRED for all fields)
|
|
118
155
|
- required \u2014 validation
|
|
119
156
|
- unique \u2014 database-level uniqueness constraint
|
|
157
|
+
- hasMany \u2014 allow multiple values (for relationship, select, image)
|
|
120
158
|
- defaultValue \u2014 fallback value (required on all new fields added to existing schemas)
|
|
121
159
|
- admin.condition \u2014 Jexl expression string to conditionally show/hide field
|
|
122
160
|
e.g. "status == \\"published\\""
|
|
@@ -138,14 +176,13 @@ Always include a default case in your switch for unknown block types.
|
|
|
138
176
|
COMPLETE SCHEMA EXAMPLE:
|
|
139
177
|
\`\`\`ts
|
|
140
178
|
import { defineCollection, defineGlobal, defineConfig } from '@dyrected/core'
|
|
141
|
-
import {
|
|
142
|
-
import { S3StorageAdapter } from '@dyrected/storage-s3'
|
|
179
|
+
import { SqliteAdapter } from '@dyrected/db-sqlite'
|
|
143
180
|
|
|
144
181
|
const media = defineCollection({
|
|
145
182
|
slug: 'media',
|
|
146
183
|
upload: true,
|
|
147
184
|
fields: [
|
|
148
|
-
{ name: 'alt',
|
|
185
|
+
{ name: 'alt', label: 'Alt Text', type: 'text' },
|
|
149
186
|
],
|
|
150
187
|
})
|
|
151
188
|
|
|
@@ -153,44 +190,45 @@ const pages = defineCollection({
|
|
|
153
190
|
slug: 'pages',
|
|
154
191
|
admin: { useAsTitle: 'title', group: 'Content' },
|
|
155
192
|
fields: [
|
|
156
|
-
{ name: 'title', type: 'text', required: true },
|
|
157
|
-
{ name: 'slug', type: 'text', required: true, unique: true },
|
|
158
|
-
{ name: 'seo', type: 'object', fields: [
|
|
159
|
-
{ name: 'metaTitle', type: 'text' },
|
|
160
|
-
{ name: 'metaDescription', type: 'textarea' },
|
|
161
|
-
{ name: 'ogImage', type: 'relationship',
|
|
193
|
+
{ name: 'title', label: 'Title', type: 'text', required: true },
|
|
194
|
+
{ name: 'slug', label: 'URL Slug', type: 'text', required: true, unique: true },
|
|
195
|
+
{ name: 'seo', label: 'SEO Metadata', type: 'object', fields: [
|
|
196
|
+
{ name: 'metaTitle', label: 'Meta Title', type: 'text' },
|
|
197
|
+
{ name: 'metaDescription', label: 'Meta Description', type: 'textarea' },
|
|
198
|
+
{ name: 'ogImage', label: 'OG Image', type: 'relationship', relationTo: 'media' },
|
|
162
199
|
]},
|
|
163
200
|
{
|
|
164
201
|
name: 'layout',
|
|
202
|
+
label: 'Page Layout',
|
|
165
203
|
type: 'blocks',
|
|
166
204
|
blocks: [
|
|
167
205
|
{
|
|
168
206
|
slug: 'hero',
|
|
169
207
|
labels: { singular: 'Hero', plural: 'Heroes' },
|
|
170
208
|
fields: [
|
|
171
|
-
{ name: 'heading', type: 'text', required: true },
|
|
172
|
-
{ name: 'subheading', type: 'textarea' },
|
|
173
|
-
{ name: 'image', type: 'relationship',
|
|
174
|
-
{ name: 'ctaLabel', type: 'text' },
|
|
175
|
-
{ name: 'ctaLink', type: 'url' },
|
|
209
|
+
{ name: 'heading', label: 'Heading', type: 'text', required: true },
|
|
210
|
+
{ name: 'subheading', label: 'Subheading', type: 'textarea' },
|
|
211
|
+
{ name: 'image', label: 'Hero Image', type: 'relationship', relationTo: 'media' },
|
|
212
|
+
{ name: 'ctaLabel', label: 'Button Label', type: 'text' },
|
|
213
|
+
{ name: 'ctaLink', label: 'Button Link', type: 'url' },
|
|
176
214
|
],
|
|
177
215
|
},
|
|
178
216
|
{
|
|
179
217
|
slug: 'richContent',
|
|
180
218
|
labels: { singular: 'Rich Content', plural: 'Rich Content Blocks' },
|
|
181
219
|
fields: [
|
|
182
|
-
{ name: 'content', type: 'richText', required: true },
|
|
220
|
+
{ name: 'content', label: 'Content', type: 'richText', required: true },
|
|
183
221
|
],
|
|
184
222
|
},
|
|
185
223
|
{
|
|
186
224
|
slug: 'callToAction',
|
|
187
225
|
labels: { singular: 'Call to Action', plural: 'Calls to Action' },
|
|
188
226
|
fields: [
|
|
189
|
-
{ name: 'heading', type: 'text', required: true },
|
|
190
|
-
{ name: 'description', type: 'textarea' },
|
|
191
|
-
{ name: 'buttonLabel', type: 'text' },
|
|
192
|
-
{ name: 'buttonLink', type: 'url' },
|
|
193
|
-
{ name: 'theme', type: 'select', options: [
|
|
227
|
+
{ name: 'heading', label: 'Heading', type: 'text', required: true },
|
|
228
|
+
{ name: 'description', label: 'Description', type: 'textarea' },
|
|
229
|
+
{ name: 'buttonLabel', label: 'Button Text', type: 'text' },
|
|
230
|
+
{ name: 'buttonLink', label: 'Button Link', type: 'url' },
|
|
231
|
+
{ name: 'theme', label: 'Theme', type: 'select', options: [
|
|
194
232
|
{ label: 'Primary', value: 'primary' },
|
|
195
233
|
{ label: 'Secondary', value: 'secondary' },
|
|
196
234
|
{ label: 'Dark', value: 'dark' },
|
|
@@ -206,28 +244,17 @@ const settings = defineGlobal({
|
|
|
206
244
|
slug: 'settings',
|
|
207
245
|
label: 'Site Settings',
|
|
208
246
|
fields: [
|
|
209
|
-
{ name: 'siteName', type: 'text' },
|
|
210
|
-
{ name: 'tagline', type: 'text' },
|
|
211
|
-
{ name: 'logo', type: 'relationship',
|
|
212
|
-
{ name: 'footerText', type: 'textarea' },
|
|
247
|
+
{ name: 'siteName', label: 'Site Name', type: 'text' },
|
|
248
|
+
{ name: 'tagline', label: 'Site Tagline', type: 'text' },
|
|
249
|
+
{ name: 'logo', label: 'Site Logo', type: 'relationship', relationTo: 'media' },
|
|
250
|
+
{ name: 'footerText', label: 'Footer Text', type: 'textarea' },
|
|
213
251
|
],
|
|
214
252
|
})
|
|
215
253
|
|
|
216
254
|
export default defineConfig({
|
|
217
255
|
collections: [media, pages],
|
|
218
|
-
globals:
|
|
219
|
-
db: new
|
|
220
|
-
url: process.env.DATABASE_URL!,
|
|
221
|
-
dbName: 'dyrected_cms',
|
|
222
|
-
}),
|
|
223
|
-
storage: new S3StorageAdapter({
|
|
224
|
-
bucket: process.env.S3_BUCKET!,
|
|
225
|
-
region: process.env.S3_REGION!,
|
|
226
|
-
credentials: {
|
|
227
|
-
accessKeyId: process.env.S3_ACCESS_KEY_ID!,
|
|
228
|
-
secretAccessKey: process.env.S3_SECRET_ACCESS_KEY!,
|
|
229
|
-
},
|
|
230
|
-
}),
|
|
256
|
+
globals: [settings],
|
|
257
|
+
db: new SqliteAdapter({ filename: './dyrected.db' }),
|
|
231
258
|
})
|
|
232
259
|
\`\`\``;
|
|
233
260
|
}
|
|
@@ -246,7 +273,8 @@ Return your response in exactly this order. Do not combine steps. Do not skip st
|
|
|
246
273
|
6. Migration/fallback strategy \u2014 numbered steps
|
|
247
274
|
7. Schema sync command
|
|
248
275
|
|
|
249
|
-
API Reference: https://docs.dyrected.com
|
|
276
|
+
API Reference: https://docs.dyrected.com
|
|
277
|
+
If you are unsure about any syntax or property, refer to the documentation above.`;
|
|
250
278
|
}
|
|
251
279
|
function buildFrameworkSection(activeTab, isSelfHosted, config) {
|
|
252
280
|
const envPrefix = activeTab === "next" ? "NEXT_PUBLIC_" : activeTab === "nuxt" ? "NUXT_PUBLIC_" : "";
|
|
@@ -268,14 +296,14 @@ export const dyrected = createClient({
|
|
|
268
296
|
})
|
|
269
297
|
\`\`\`
|
|
270
298
|
|
|
271
|
-
2. Admin Route (app/
|
|
299
|
+
2. Admin Route (app/cms/page.tsx):
|
|
272
300
|
\`\`\`tsx
|
|
273
301
|
import { DyrectedAdmin } from '@dyrected/next/admin'
|
|
274
302
|
|
|
275
303
|
export default function AdminPage() {
|
|
276
304
|
// DyrectedAdmin handles routing, auth, and CSS automatically.
|
|
277
305
|
// Do NOT wrap this in custom auth middleware.
|
|
278
|
-
return <DyrectedAdmin basename="/
|
|
306
|
+
return <DyrectedAdmin basename="/cms" />
|
|
279
307
|
}
|
|
280
308
|
\`\`\`
|
|
281
309
|
|
|
@@ -300,9 +328,9 @@ export default async function CmsPage({ params }: { params: { slug: string[] } }
|
|
|
300
328
|
\`\`\``,
|
|
301
329
|
nuxt: `
|
|
302
330
|
\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501
|
|
303
|
-
8. IMPLEMENTATION \u2014 Nuxt
|
|
331
|
+
8. IMPLEMENTATION \u2014 Nuxt.js
|
|
304
332
|
\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501
|
|
305
|
-
1. Nuxt Config (nuxt.config.ts):
|
|
333
|
+
1. Nuxt.js Config (nuxt.config.ts):
|
|
306
334
|
\`\`\`ts
|
|
307
335
|
export default defineNuxtConfig({
|
|
308
336
|
modules: ['@dyrected/nuxt'],
|
|
@@ -314,7 +342,7 @@ export default defineNuxtConfig({
|
|
|
314
342
|
})
|
|
315
343
|
\`\`\`
|
|
316
344
|
|
|
317
|
-
2. Admin Route (pages/
|
|
345
|
+
2. Admin Route (pages/cms/index.vue):
|
|
318
346
|
\`\`\`vue
|
|
319
347
|
<script setup lang="ts">
|
|
320
348
|
// DyrectedAdmin is auto-imported by @dyrected/nuxt.
|
|
@@ -326,7 +354,7 @@ definePageMeta({ layout: false })
|
|
|
326
354
|
|
|
327
355
|
<template>
|
|
328
356
|
<ClientOnly>
|
|
329
|
-
<DyrectedAdmin basename="/
|
|
357
|
+
<DyrectedAdmin basename="/cms" />
|
|
330
358
|
</ClientOnly>
|
|
331
359
|
</template>
|
|
332
360
|
\`\`\`
|
|
@@ -373,7 +401,7 @@ export const dyrected = createClient({
|
|
|
373
401
|
})
|
|
374
402
|
\`\`\`
|
|
375
403
|
|
|
376
|
-
2. Admin Route (pages/
|
|
404
|
+
2. Admin Route (pages/cms.tsx):
|
|
377
405
|
\`\`\`tsx
|
|
378
406
|
import { AdminUI } from '@dyrected/admin'
|
|
379
407
|
import '@dyrected/admin/styles'
|
|
@@ -405,7 +433,7 @@ export const dyrected = createClient({
|
|
|
405
433
|
})
|
|
406
434
|
\`\`\`
|
|
407
435
|
|
|
408
|
-
2. Admin Route (pages/
|
|
436
|
+
2. Admin Route (pages/cms.vue):
|
|
409
437
|
\`\`\`vue
|
|
410
438
|
<template>
|
|
411
439
|
<div ref="container" style="height: 100vh" />
|
|
@@ -433,14 +461,350 @@ onUnmounted(() => cleanup?.())
|
|
|
433
461
|
};
|
|
434
462
|
return sections[activeTab] || sections.next;
|
|
435
463
|
}
|
|
464
|
+
function generateFreshSetupPrompt(activeTab, config) {
|
|
465
|
+
const frameworkLabel = activeTab === "next" ? "Next.js" : activeTab === "nuxt" ? "Nuxt.js" : activeTab ? activeTab.charAt(0).toUpperCase() + activeTab.slice(1) : "the project's detected framework";
|
|
466
|
+
const isSelfHosted = config.isSelfHosted === true || !config.apiKey && !config.siteId;
|
|
467
|
+
const frameworkSetup = {
|
|
468
|
+
nuxt: `
|
|
469
|
+
\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501
|
|
470
|
+
3. INSTALLATION STEPS \u2014 Run these in order
|
|
471
|
+
\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501
|
|
472
|
+
Tell the user to follow these steps exactly. Explain each one in plain
|
|
473
|
+
language before showing the command. Do not skip any step.
|
|
474
|
+
|
|
475
|
+
STEP 1 \u2014 Initialize Dyrected
|
|
476
|
+
Tell the user:
|
|
477
|
+
"Run this command in your terminal inside your Nuxt.js project folder.
|
|
478
|
+
It will set everything up for you automatically."
|
|
479
|
+
|
|
480
|
+
\`\`\`bash
|
|
481
|
+
npx @dyrected/cli init
|
|
482
|
+
\`\`\`
|
|
483
|
+
|
|
484
|
+
When it asks questions, tell the user to:
|
|
485
|
+
- Choose: Nuxt.js 3
|
|
486
|
+
- Choose: SQLite (easiest option, no extra setup needed)
|
|
487
|
+
|
|
488
|
+
The CLI will automatically:
|
|
489
|
+
- Install all required packages
|
|
490
|
+
- Create a dyrected.config.ts file
|
|
491
|
+
- Mount the Admin UI at pages/cms/index.vue
|
|
492
|
+
- Generate a .env.example file
|
|
493
|
+
|
|
494
|
+
STEP 2 \u2014 Register the module
|
|
495
|
+
Tell the user to open nuxt.config.ts and add '@dyrected/nuxt' to modules:
|
|
496
|
+
|
|
497
|
+
\`\`\`ts
|
|
498
|
+
export default defineNuxtConfig({
|
|
499
|
+
modules: ['@dyrected/nuxt'],
|
|
500
|
+
})
|
|
501
|
+
\`\`\`
|
|
502
|
+
|
|
503
|
+
STEP 3 \u2014 Set up environment variables
|
|
504
|
+
Tell the user:
|
|
505
|
+
"Find the file called .env.example in your project.
|
|
506
|
+
Make a copy of it and rename the copy to .env
|
|
507
|
+
Then open .env and fill in the values."
|
|
508
|
+
|
|
509
|
+
STEP 4 \u2014 Start the project
|
|
510
|
+
\`\`\`bash
|
|
511
|
+
pnpm dev
|
|
512
|
+
\`\`\`
|
|
513
|
+
|
|
514
|
+
STEP 5 \u2014 Open the dashboard
|
|
515
|
+
Tell the user to open their browser and go to:
|
|
516
|
+
http://localhost:3000/cms
|
|
517
|
+
|
|
518
|
+
If they see the Dyrected admin dashboard, the installation worked.
|
|
519
|
+
Tell them: "You are ready. Now let's set up your content."`,
|
|
520
|
+
next: `
|
|
521
|
+
\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501
|
|
522
|
+
3. INSTALLATION STEPS \u2014 Run these in order
|
|
523
|
+
\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501
|
|
524
|
+
Tell the user to follow these steps exactly. Explain each one in plain
|
|
525
|
+
language before showing the command. Do not skip any step.
|
|
526
|
+
|
|
527
|
+
STEP 1 \u2014 Initialize Dyrected
|
|
528
|
+
Tell the user:
|
|
529
|
+
"Run this command in your terminal inside your Next.js project folder."
|
|
530
|
+
|
|
531
|
+
\`\`\`bash
|
|
532
|
+
npx @dyrected/cli init
|
|
533
|
+
\`\`\`
|
|
534
|
+
|
|
535
|
+
When it asks questions, tell the user to:
|
|
536
|
+
- Choose: Next.js
|
|
537
|
+
- Choose: SQLite (easiest option, no extra setup needed)
|
|
538
|
+
|
|
539
|
+
The CLI will automatically:
|
|
540
|
+
- Install all required packages
|
|
541
|
+
- Create a dyrected.config.ts file
|
|
542
|
+
- Mount the Admin UI at app/cms/page.tsx
|
|
543
|
+
- Generate a .env.example file
|
|
544
|
+
|
|
545
|
+
STEP 2 \u2014 Set up environment variables
|
|
546
|
+
Tell the user:
|
|
547
|
+
"Find the file called .env.example in your project.
|
|
548
|
+
Make a copy of it and rename the copy to .env.local
|
|
549
|
+
Then open .env.local and fill in the values."
|
|
550
|
+
|
|
551
|
+
STEP 3 \u2014 Start the project
|
|
552
|
+
\`\`\`bash
|
|
553
|
+
pnpm dev
|
|
554
|
+
\`\`\`
|
|
555
|
+
|
|
556
|
+
STEP 4 \u2014 Open the dashboard
|
|
557
|
+
Tell the user to open their browser and go to:
|
|
558
|
+
http://localhost:3000/cms
|
|
559
|
+
|
|
560
|
+
If they see the Dyrected admin dashboard, the installation worked.
|
|
561
|
+
Tell them: "You are ready. Now let's set up your content."`,
|
|
562
|
+
react: `
|
|
563
|
+
\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501
|
|
564
|
+
3. INSTALLATION STEPS \u2014 Run these in order
|
|
565
|
+
\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501
|
|
566
|
+
STEP 1 \u2014 Install the SDK and admin packages
|
|
567
|
+
\`\`\`bash
|
|
568
|
+
npm install @dyrected/sdk @dyrected/admin
|
|
569
|
+
\`\`\`
|
|
570
|
+
|
|
571
|
+
STEP 2 \u2014 Set up the client (lib/dyrected.ts):
|
|
572
|
+
\`\`\`ts
|
|
573
|
+
import { createClient } from '@dyrected/sdk'
|
|
574
|
+
|
|
575
|
+
export const dyrected = createClient({
|
|
576
|
+
baseUrl: '${config.baseUrl || "https://api.dyrected.cloud"}',${isSelfHosted ? "" : `
|
|
577
|
+
apiKey: '${config.apiKey}',
|
|
578
|
+
siteId: '${config.siteId}',`}
|
|
579
|
+
})
|
|
580
|
+
\`\`\`
|
|
581
|
+
|
|
582
|
+
STEP 3 \u2014 Mount the Admin UI (pages/cms.tsx):
|
|
583
|
+
\`\`\`tsx
|
|
584
|
+
import { AdminUI } from '@dyrected/admin'
|
|
585
|
+
import '@dyrected/admin/styles'
|
|
586
|
+
|
|
587
|
+
export default function AdminPage() {
|
|
588
|
+
return (
|
|
589
|
+
<div style={{ height: '100vh' }}>
|
|
590
|
+
<AdminUI
|
|
591
|
+
baseUrl="${config.baseUrl || "https://api.dyrected.cloud"}"${isSelfHosted ? "" : `
|
|
592
|
+
apiKey="${config.apiKey}"
|
|
593
|
+
siteId="${config.siteId}"`}
|
|
594
|
+
/>
|
|
595
|
+
</div>
|
|
596
|
+
)
|
|
597
|
+
}
|
|
598
|
+
\`\`\``,
|
|
599
|
+
vue: `
|
|
600
|
+
\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501
|
|
601
|
+
3. INSTALLATION STEPS \u2014 Run these in order
|
|
602
|
+
\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501
|
|
603
|
+
STEP 1 \u2014 Install the SDK and admin packages
|
|
604
|
+
\`\`\`bash
|
|
605
|
+
npm install @dyrected/sdk @dyrected/admin
|
|
606
|
+
\`\`\`
|
|
607
|
+
|
|
608
|
+
STEP 2 \u2014 Set up the client (lib/dyrected.ts):
|
|
609
|
+
\`\`\`ts
|
|
610
|
+
import { createClient } from '@dyrected/sdk'
|
|
611
|
+
|
|
612
|
+
export const dyrected = createClient({
|
|
613
|
+
baseUrl: '${config.baseUrl || "https://api.dyrected.cloud"}',${isSelfHosted ? "" : `
|
|
614
|
+
apiKey: '${config.apiKey}',
|
|
615
|
+
siteId: '${config.siteId}',`}
|
|
616
|
+
})
|
|
617
|
+
\`\`\`
|
|
618
|
+
|
|
619
|
+
STEP 3 \u2014 Mount the Admin UI (pages/cms.vue):
|
|
620
|
+
\`\`\`vue
|
|
621
|
+
<template>
|
|
622
|
+
<div ref="container" style="height: 100vh" />
|
|
623
|
+
</template>
|
|
624
|
+
|
|
625
|
+
<script setup>
|
|
626
|
+
import { ref, onMounted, onUnmounted } from 'vue'
|
|
627
|
+
import { renderAdminUI } from '@dyrected/admin'
|
|
628
|
+
import '@dyrected/admin/styles'
|
|
629
|
+
|
|
630
|
+
const container = ref(null)
|
|
631
|
+
let cleanup
|
|
632
|
+
|
|
633
|
+
onMounted(() => {
|
|
634
|
+
cleanup = renderAdminUI(container.value, {
|
|
635
|
+
baseUrl: '${config.baseUrl || "https://api.dyrected.cloud"}',${isSelfHosted ? "" : `
|
|
636
|
+
apiKey: '${config.apiKey}',
|
|
637
|
+
siteId: '${config.siteId}',`}
|
|
638
|
+
})
|
|
639
|
+
})
|
|
640
|
+
|
|
641
|
+
onUnmounted(() => cleanup?.())
|
|
642
|
+
</script>
|
|
643
|
+
\`\`\``
|
|
644
|
+
};
|
|
645
|
+
return [
|
|
646
|
+
`You are a friendly technical assistant helping someone set up Dyrected CMS for the very first time in a ${frameworkLabel} project. They have NOT installed anything yet.
|
|
647
|
+
|
|
648
|
+
Your job is to:
|
|
649
|
+
1. Understand who you are talking to before giving any instructions
|
|
650
|
+
2. Ask simple questions about their project and content needs
|
|
651
|
+
3. Walk them through setup in a way that matches their technical level
|
|
652
|
+
4. Confirm each step worked before moving to the next
|
|
653
|
+
5. Help them design their content so their client can manage it
|
|
654
|
+
|
|
655
|
+
Speak in plain language at all times. Never assume technical knowledge.
|
|
656
|
+
Never show more than one step at a time.
|
|
657
|
+
Never mention the terminal, command line, or any commands until you have
|
|
658
|
+
confirmed the user is comfortable running them.`,
|
|
659
|
+
`
|
|
660
|
+
\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501
|
|
661
|
+
1. ENVIRONMENT
|
|
662
|
+
\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501
|
|
663
|
+
- Framework : ${frameworkLabel}
|
|
664
|
+
- Host Type : ${isSelfHosted ? "Self-Hosted" : "Dyrected Cloud"}
|
|
665
|
+
- API Base : ${config.baseUrl || "http://localhost:3000"}
|
|
666
|
+
${isSelfHosted ? "" : `- Site ID : ${config.siteId}
|
|
667
|
+
- API Key : ${config.apiKey}`}`.trim(),
|
|
668
|
+
`
|
|
669
|
+
\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501
|
|
670
|
+
2. PHASE 0 \u2014 UNDERSTAND THE USER FIRST
|
|
671
|
+
\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501
|
|
672
|
+
Ask these questions one at a time. Wait for each answer before asking the next.
|
|
673
|
+
Never ask more than one question at a time.
|
|
674
|
+
|
|
675
|
+
\u2500\u2500\u2500 QUESTION 1 \u2014 TECH LEVEL \u2500\u2500\u2500
|
|
676
|
+
This is the most important question. Ask it first.
|
|
677
|
+
|
|
678
|
+
Ask exactly this:
|
|
679
|
+
"Before we dive in \u2014 how would you describe yourself?
|
|
680
|
+
|
|
681
|
+
A) I write code myself (I'm comfortable with the terminal and editing files)
|
|
682
|
+
B) I use tools like Lovable, Bolt, or v0 to build with AI \u2014 I don't write much code myself
|
|
683
|
+
C) I'm a designer or project manager \u2014 someone else usually handles the technical stuff
|
|
684
|
+
D) Something else \u2014 just describe how you work"
|
|
685
|
+
|
|
686
|
+
Use their answer to decide how to guide them for the rest of the setup:
|
|
687
|
+
- If A \u2192 they are TECHNICAL. You may show terminal commands and code directly.
|
|
688
|
+
- If B \u2192 they are SEMI-TECHNICAL. Explain what each step does before showing
|
|
689
|
+
any code or commands. Ask before running anything in the terminal.
|
|
690
|
+
For Lovable users specifically: guide them to use the built-in
|
|
691
|
+
terminal or ask them to paste code into the right file in their editor.
|
|
692
|
+
- If C \u2192 they are NON-TECHNICAL. Do not show terminal commands at all.
|
|
693
|
+
Generate all the code and config for them. Walk them through
|
|
694
|
+
copy-pasting into specific files by name. If a terminal step is
|
|
695
|
+
unavoidable, warn them first and offer to write the exact command
|
|
696
|
+
with a clear explanation of what it does and where to run it.
|
|
697
|
+
- If D \u2192 ask one follow-up question to understand their workflow before
|
|
698
|
+
deciding which path above fits best.
|
|
699
|
+
|
|
700
|
+
\u2500\u2500\u2500 QUESTION 2 \u2014 PROJECT STATUS \u2500\u2500\u2500
|
|
701
|
+
Ask after Q1 is answered:
|
|
702
|
+
|
|
703
|
+
"Do you already have a ${frameworkLabel} project open,
|
|
704
|
+
or are we starting from scratch?
|
|
705
|
+
|
|
706
|
+
\u2192 Already have a project: tell me what the site is about or
|
|
707
|
+
share the folder name
|
|
708
|
+
\u2192 Starting fresh: just say 'new project' and I will help you
|
|
709
|
+
create one first"
|
|
710
|
+
|
|
711
|
+
\u2500\u2500\u2500 QUESTION 3 \u2014 SITE PURPOSE \u2500\u2500\u2500
|
|
712
|
+
Ask after Q2 is answered:
|
|
713
|
+
|
|
714
|
+
"What kind of website is this?
|
|
715
|
+
|
|
716
|
+
A) A business or agency site (show services, get enquiries)
|
|
717
|
+
B) A blog or news site (publish articles regularly)
|
|
718
|
+
C) A SaaS or product landing page (features, pricing, sign up)
|
|
719
|
+
D) A portfolio (show work and past projects)
|
|
720
|
+
E) Something else \u2014 describe it in one sentence"
|
|
721
|
+
|
|
722
|
+
\u2500\u2500\u2500 QUESTION 4 \u2014 CONTENT NEEDS \u2500\u2500\u2500
|
|
723
|
+
Ask after Q3 is answered:
|
|
724
|
+
|
|
725
|
+
"What will your client need to update themselves \u2014 without calling you?
|
|
726
|
+
|
|
727
|
+
Some examples to help you think:
|
|
728
|
+
\u2192 Blog posts or news articles
|
|
729
|
+
\u2192 Team member profiles (name, photo, bio)
|
|
730
|
+
\u2192 Services or product descriptions
|
|
731
|
+
\u2192 Homepage text (headline, buttons, images)
|
|
732
|
+
\u2192 Testimonials or reviews
|
|
733
|
+
\u2192 FAQs
|
|
734
|
+
\u2192 Event listings or announcements
|
|
735
|
+
|
|
736
|
+
Just list the ones that apply. Or say 'not sure yet'
|
|
737
|
+
and we will figure it out together."
|
|
738
|
+
|
|
739
|
+
\u2500\u2500\u2500 AFTER ALL QUESTIONS \u2500\u2500\u2500
|
|
740
|
+
Once all four questions are answered:
|
|
741
|
+
1. Summarise what you understood in plain English
|
|
742
|
+
2. Ask the user to confirm before touching any code
|
|
743
|
+
3. Then move to the installation steps using the correct path
|
|
744
|
+
for their tech level from Question 1`,
|
|
745
|
+
frameworkSetup[activeTab] || frameworkSetup.nuxt,
|
|
746
|
+
`
|
|
747
|
+
\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501
|
|
748
|
+
4. AFTER INSTALLATION \u2014 CONTENT SETUP
|
|
749
|
+
\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501
|
|
750
|
+
Once the dashboard is confirmed working, help the user design their
|
|
751
|
+
content model in dyrected.config.ts based on what they told you in
|
|
752
|
+
Phase 0.
|
|
753
|
+
|
|
754
|
+
RULES for this phase:
|
|
755
|
+
- Use defineCollection and defineConfig from '@dyrected/core'
|
|
756
|
+
- Use client.collection(slug) only \u2014 never client.collections
|
|
757
|
+
- Always use initialData in all data fetches
|
|
758
|
+
- Use a catch-all pages collection for marketing-managed pages
|
|
759
|
+
- Use blocks for flexible page layouts
|
|
760
|
+
- Use type: 'relationship', relationTo: 'collectionSlug' for relations
|
|
761
|
+
- Never throw during render \u2014 fall back to initialData on errors
|
|
762
|
+
- All relationship fields must handle null gracefully
|
|
763
|
+
|
|
764
|
+
CONTENT SETUP DELIVERABLES \u2014 in this order:
|
|
765
|
+
1. dyrected.config.ts \u2014 complete file based on their answers
|
|
766
|
+
2. Catch-all page route for CMS-managed pages
|
|
767
|
+
3. Block components list (names and fields only)
|
|
768
|
+
4. One example fetch showing how to load content on a page
|
|
769
|
+
|
|
770
|
+
After delivering the config, tell the user to sync their schema.
|
|
771
|
+
For TECHNICAL users show the command directly:
|
|
772
|
+
\`\`\`bash
|
|
773
|
+
npx @dyrected/cli sync:schema
|
|
774
|
+
\`\`\`
|
|
775
|
+
For SEMI-TECHNICAL or NON-TECHNICAL users explain it first:
|
|
776
|
+
"This next step tells Dyrected to read your content setup file
|
|
777
|
+
and prepare the database. Here is the command to run:" then show it.
|
|
778
|
+
|
|
779
|
+
Then ask: "Do you want me to help you connect this content to your
|
|
780
|
+
frontend pages now?"
|
|
781
|
+
|
|
782
|
+
\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501
|
|
783
|
+
DO NOT
|
|
784
|
+
\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501
|
|
785
|
+
- Do NOT show terminal commands before confirming the user's tech level
|
|
786
|
+
- Do NOT assume the user knows what a terminal, CLI, or package manager is
|
|
787
|
+
- Do NOT show all steps at once \u2014 one step at a time always
|
|
788
|
+
- Do NOT use client.collections \u2014 use client.collection(slug)
|
|
789
|
+
- Do NOT add custom auth middleware to the admin route
|
|
790
|
+
- Do NOT use renderAdminUI in a Nuxt.js project
|
|
791
|
+
- Do NOT skip the confirmation after each installation step
|
|
792
|
+
- Do NOT use jargon without explaining it in plain English first
|
|
793
|
+
- Do NOT assume the installation worked \u2014 ask the user to confirm
|
|
794
|
+
|
|
795
|
+
API Reference: https://docs.dyrected.com
|
|
796
|
+
If you are unsure about any syntax, refer to the official documentation above.`
|
|
797
|
+
].join("\n");
|
|
798
|
+
}
|
|
436
799
|
function generateAIPrompt(activeTab, config) {
|
|
437
|
-
const frameworkLabel = activeTab === "next" ? "Next.js" : activeTab === "nuxt" ? "Nuxt" : activeTab.charAt(0).toUpperCase() + activeTab.slice(1);
|
|
800
|
+
const frameworkLabel = activeTab === "next" ? "Next.js" : activeTab === "nuxt" ? "Nuxt.js" : activeTab ? activeTab.charAt(0).toUpperCase() + activeTab.slice(1) : "the project's detected framework";
|
|
438
801
|
const isSelfHosted = config.isSelfHosted === true || !config.apiKey && !config.siteId;
|
|
439
802
|
const existingSite = config.existingSite ?? false;
|
|
803
|
+
const missionText = existingSite ? `You are a Senior Content Architect. Your mission is to integrate Dyrected CMS into an EXISTING ${frameworkLabel} project. Your absolute priority is DATA PRESERVATION and MIGRATION of existing hardcoded content into a flexible, blocks-based schema that empowers marketing teams to move independently.` : `You are a Senior Content Architect. Your mission is to integrate Dyrected CMS into a NEW ${frameworkLabel} project. Your priority is DATA PRESERVATION and creating a CMS that empowers marketing teams to move independently without raising tickets to engineering.`;
|
|
440
804
|
const sections = [
|
|
441
|
-
|
|
805
|
+
missionText,
|
|
442
806
|
buildEnvironmentSection(frameworkLabel, isSelfHosted, config),
|
|
443
|
-
buildDiagnosticSection(
|
|
807
|
+
buildDiagnosticSection(),
|
|
444
808
|
buildConstraintsSection(),
|
|
445
809
|
buildSchemaRulesSection(),
|
|
446
810
|
buildDoNotSection(),
|
|
@@ -462,9 +826,11 @@ function defineConfig(config) {
|
|
|
462
826
|
return config;
|
|
463
827
|
}
|
|
464
828
|
export {
|
|
829
|
+
createDyrectedApp,
|
|
465
830
|
defineCollection,
|
|
466
831
|
defineConfig,
|
|
467
832
|
defineGlobal,
|
|
468
833
|
generateAIPrompt,
|
|
834
|
+
generateFreshSetupPrompt,
|
|
469
835
|
normalizeConfig
|
|
470
836
|
};
|