nca-ai-cms-astro-plugin 1.0.7 → 1.0.8
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 +52 -0
- package/package.json +1 -1
- package/src/services/ContentGenerator.ts +15 -14
- package/src/services/PromptService.ts +20 -6
- package/update.md +17 -0
package/README.md
CHANGED
|
@@ -88,6 +88,58 @@ ncaAiCms({
|
|
|
88
88
|
|
|
89
89
|
All `/api/*` and `/editor` routes are protected by cookie-based authentication.
|
|
90
90
|
|
|
91
|
+
## Settings Best Practice
|
|
92
|
+
|
|
93
|
+
The editor has a **Settings** tab with two groups of fields (Homepage and Website) that control how AI generates content. It also has three prompt categories (Content-KI, Analyse-KI, Bild-KI) where you create reusable prompts. Filling these in with values tailored to your business dramatically improves output quality.
|
|
94
|
+
|
|
95
|
+
### Settings fields
|
|
96
|
+
|
|
97
|
+
| Tab | Field | Key | Description |
|
|
98
|
+
|---|---|---|---|
|
|
99
|
+
| Homepage | Hero Ueberschrift | `hero_headline` | Main headline shown on your homepage |
|
|
100
|
+
| Homepage | Hero Text | `hero_text` | Supporting text below the hero headline |
|
|
101
|
+
| Homepage | Zielgruppe | `target_audience` | Who your content is for (e.g. "CTOs at mid-size SaaS companies") |
|
|
102
|
+
| Homepage | Tonalitaet | `tone` | Voice and tone for generated content (e.g. "professional but approachable") |
|
|
103
|
+
| Homepage | Kernbotschaft | `core_message` | The one key message your site should communicate |
|
|
104
|
+
| Website | CTA Link | `cta_url` | Default call-to-action URL (e.g. "/contact" or "/demo") |
|
|
105
|
+
| Website | CTA Stil | `cta_style` | Style or label for the CTA button (e.g. "Jetzt starten") |
|
|
106
|
+
| Website | CTA Prompt | `cta_prompt` | Prompt text used to generate CTA copy |
|
|
107
|
+
| Website | Core Tags | `core_tags` | Comma-separated keywords for your site (e.g. "AI, CMS, Astro, Open Source") |
|
|
108
|
+
| Website | Markenrichtlinien | `brand_guidelines` | Brand rules the AI should follow (colors, dos/don'ts, terminology) |
|
|
109
|
+
|
|
110
|
+
### Get values for your business with one AI prompt
|
|
111
|
+
|
|
112
|
+
Copy the prompt below into any AI chat (ChatGPT, Claude, Gemini) and replace the placeholder with a description of your business. You will get ready-to-paste values for every field.
|
|
113
|
+
|
|
114
|
+
```text
|
|
115
|
+
I run the following business/website:
|
|
116
|
+
[Describe your business in 1-2 sentences, e.g. "An open-source community that organizes charity coding events for nonprofits in Germany."]
|
|
117
|
+
|
|
118
|
+
Please generate values for each of the following content management settings.
|
|
119
|
+
Return them as a simple list so I can copy-paste each value into the corresponding field.
|
|
120
|
+
|
|
121
|
+
1. hero_headline — A compelling hero headline (max ~10 words)
|
|
122
|
+
2. hero_text — Supporting hero text (2-3 sentences)
|
|
123
|
+
3. target_audience — Target audience description (one sentence)
|
|
124
|
+
4. tone — Tone of voice for all generated content (2-4 descriptive words)
|
|
125
|
+
5. core_message — Core message / value proposition (1-2 sentences)
|
|
126
|
+
6. cta_url — Suggested CTA link path (e.g. /contact)
|
|
127
|
+
7. cta_style — CTA button label text (2-4 words)
|
|
128
|
+
8. cta_prompt — Short prompt the AI uses to generate CTA copy (one sentence)
|
|
129
|
+
9. core_tags — 5-8 comma-separated keywords/tags for the site
|
|
130
|
+
10. brand_guidelines — Brand guidelines for AI-generated content (3-5 bullet points covering tone, terminology, and things to avoid)
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
### Prompt categories
|
|
134
|
+
|
|
135
|
+
The three prompt tabs let you create reusable prompts that the AI uses when generating or analysing content.
|
|
136
|
+
|
|
137
|
+
| Category | Purpose | Tips for good prompts |
|
|
138
|
+
|---|---|---|
|
|
139
|
+
| **Content-KI** | Controls how the AI writes blog articles and text | Define word count, structure (intro/sections/CTA), target keywords, and writing style. The more specific, the better. |
|
|
140
|
+
| **Analyse-KI** | Controls how the AI analyses existing text | Specify what to check — SEO, readability, accessibility, keyword density — and ask for concrete improvement suggestions. |
|
|
141
|
+
| **Bild-KI** | Controls how the AI generates images | Describe the visual style, color palette, composition, and aspect ratio. Mention what should *not* appear in the image. |
|
|
142
|
+
|
|
91
143
|
## Development
|
|
92
144
|
|
|
93
145
|
```bash
|
package/package.json
CHANGED
|
@@ -32,21 +32,21 @@ interface SourceAnalysis {
|
|
|
32
32
|
|
|
33
33
|
// Fallback values when database is not available
|
|
34
34
|
const DEFAULT_CONTACT_URL =
|
|
35
|
-
'https://nevercodealone.de/de/
|
|
35
|
+
'https://nevercodealone.de/de/kontakt';
|
|
36
36
|
|
|
37
|
-
const DEFAULT_CORE_TAGS = ['
|
|
37
|
+
const DEFAULT_CORE_TAGS = ['Web-Entwicklung', 'Best Practices'];
|
|
38
38
|
|
|
39
39
|
const DEFAULT_SYSTEM_PROMPT = `Du bist ein erfahrener technischer Content-Writer für Web-Entwicklung.
|
|
40
40
|
Deine Aufgabe ist es, hochwertige deutsche Fachartikel zu erstellen.
|
|
41
41
|
|
|
42
|
-
Zielgruppe: Content-Marketing-Professionals und
|
|
42
|
+
Zielgruppe: Content-Marketing-Professionals und Entwickler
|
|
43
43
|
Tonalität: Professionell, aber zugänglich. Technisch korrekt, nicht übermäßig akademisch.
|
|
44
44
|
|
|
45
45
|
KRITISCH - 100% Originalität:
|
|
46
46
|
- Schreibe einen KOMPLETT EIGENSTÄNDIGEN Artikel
|
|
47
47
|
- KEINE Sätze, Formulierungen oder Strukturen aus externen Quellen übernehmen
|
|
48
48
|
- KEINE Hinweise auf Quellen, Referenzen oder Inspiration im Text
|
|
49
|
-
- Nutze ausschließlich DEIN Expertenwissen
|
|
49
|
+
- Nutze ausschließlich DEIN Expertenwissen zum jeweiligen Thema
|
|
50
50
|
- Jeder Satz muss NEU formuliert sein - wie von einem Experten geschrieben
|
|
51
51
|
- Der Artikel muss wirken als käme er aus eigener Fachkenntnis
|
|
52
52
|
|
|
@@ -57,7 +57,6 @@ Regeln:
|
|
|
57
57
|
- WICHTIG: Content MUSS mit einer H1-Überschrift (# Titel) beginnen
|
|
58
58
|
- Danach H2 (##) und H3 (###) Hierarchie ohne Sprünge
|
|
59
59
|
- WICHTIG: Nur Markdown, KEINE HTML-Tags wie <p>, <div>, <span> etc.
|
|
60
|
-
- WICHTIG: Integriere die Keywords "Semantik", "HTML" und "Barrierefrei" natürlich in den Text
|
|
61
60
|
|
|
62
61
|
Titel-Regeln:
|
|
63
62
|
- Das Hauptthema/Keyword MUSS im Titel vorkommen
|
|
@@ -148,8 +147,10 @@ export class ContentGenerator {
|
|
|
148
147
|
private async analyzeSource(
|
|
149
148
|
fetched: FetchedContent
|
|
150
149
|
): Promise<SourceAnalysis> {
|
|
150
|
+
const systemPrompt = await this.buildSystemPrompt();
|
|
151
151
|
const model = this.client.getGenerativeModel({
|
|
152
152
|
model: this.model,
|
|
153
|
+
systemInstruction: systemPrompt,
|
|
153
154
|
generationConfig: {
|
|
154
155
|
responseMimeType: 'application/json',
|
|
155
156
|
responseSchema: buildSourceAnalysisSchema(),
|
|
@@ -165,7 +166,7 @@ Inhalt:
|
|
|
165
166
|
${fetched.content.slice(0, 12000)}
|
|
166
167
|
|
|
167
168
|
Identifiziere:
|
|
168
|
-
1. Das Hauptthema
|
|
169
|
+
1. Das Hauptthema
|
|
169
170
|
2. Die wichtigsten Kernaussagen
|
|
170
171
|
3. Besondere Erkenntnisse oder einzigartige Tipps
|
|
171
172
|
4. Relevante Code-Beispiele oder Patterns`;
|
|
@@ -180,23 +181,23 @@ Identifiziere:
|
|
|
180
181
|
}
|
|
181
182
|
|
|
182
183
|
private async researchKeywords(keywords: string): Promise<SourceAnalysis> {
|
|
184
|
+
const systemPrompt = await this.buildSystemPrompt();
|
|
183
185
|
const model = this.client.getGenerativeModel({
|
|
184
186
|
model: this.model,
|
|
187
|
+
systemInstruction: systemPrompt,
|
|
185
188
|
generationConfig: {
|
|
186
189
|
responseMimeType: 'application/json',
|
|
187
190
|
responseSchema: buildSourceAnalysisSchema(),
|
|
188
191
|
},
|
|
189
192
|
});
|
|
190
193
|
|
|
191
|
-
const prompt = `
|
|
192
|
-
|
|
193
|
-
Recherchiere zum Thema: "${keywords}"
|
|
194
|
+
const prompt = `Recherchiere zum Thema: "${keywords}"
|
|
194
195
|
|
|
195
196
|
Nutze dein Fachwissen um:
|
|
196
|
-
1. Das Hauptthema klar zu definieren
|
|
197
|
-
2. Die wichtigsten Fakten, Best Practices und
|
|
197
|
+
1. Das Hauptthema klar zu definieren
|
|
198
|
+
2. Die wichtigsten Fakten, Best Practices und Standards zusammenzufassen
|
|
198
199
|
3. Weniger bekannte aber wichtige Tipps und Erkenntnisse zu identifizieren
|
|
199
|
-
4. Praktische
|
|
200
|
+
4. Praktische Beispiele oder Patterns vorzuschlagen
|
|
200
201
|
|
|
201
202
|
Fokussiere auf aktuelle Standards und praktische Anwendbarkeit.`;
|
|
202
203
|
|
|
@@ -296,13 +297,13 @@ Fokussiere auf aktuelle Standards und praktische Anwendbarkeit.`;
|
|
|
296
297
|
}
|
|
297
298
|
|
|
298
299
|
private buildUserPrompt(analysis: SourceAnalysis): string {
|
|
299
|
-
return `Schreibe
|
|
300
|
+
return `Schreibe einen deutschen Fachartikel zum Thema: ${analysis.topic}
|
|
300
301
|
|
|
301
302
|
Behandle diese Aspekte aus deinem Fachwissen:
|
|
302
303
|
${analysis.keyPoints.map((p) => `- ${p}`).join('\n')}
|
|
303
304
|
${analysis.uniqueInsights.map((p) => `- ${p}`).join('\n')}
|
|
304
305
|
|
|
305
|
-
${analysis.codeExamples.length > 0 ? `Zeige praktische
|
|
306
|
+
${analysis.codeExamples.length > 0 ? `Zeige praktische Beispiele für:\n${analysis.codeExamples.map((c) => `- ${c}`).join('\n')}` : ''}
|
|
306
307
|
|
|
307
308
|
Wichtig: Schreibe komplett eigenständig aus deiner Expertise heraus.`;
|
|
308
309
|
}
|
|
@@ -58,10 +58,24 @@ export class PromptService {
|
|
|
58
58
|
}
|
|
59
59
|
|
|
60
60
|
async updateSetting(key: string, value: string): Promise<void> {
|
|
61
|
-
await db
|
|
62
|
-
.
|
|
63
|
-
.
|
|
64
|
-
.where(eq(SiteSettings.key, key))
|
|
61
|
+
const existing = await db
|
|
62
|
+
.select()
|
|
63
|
+
.from(SiteSettings)
|
|
64
|
+
.where(eq(SiteSettings.key, key))
|
|
65
|
+
.get();
|
|
66
|
+
|
|
67
|
+
if (existing) {
|
|
68
|
+
await db
|
|
69
|
+
.update(SiteSettings)
|
|
70
|
+
.set({ value, updatedAt: new Date() })
|
|
71
|
+
.where(eq(SiteSettings.key, key));
|
|
72
|
+
} else {
|
|
73
|
+
await db.insert(SiteSettings).values({
|
|
74
|
+
key,
|
|
75
|
+
value,
|
|
76
|
+
updatedAt: new Date(),
|
|
77
|
+
});
|
|
78
|
+
}
|
|
65
79
|
}
|
|
66
80
|
|
|
67
81
|
async getAllSettings(): Promise<Array<{ key: string; value: string }>> {
|
|
@@ -88,11 +102,11 @@ export class PromptService {
|
|
|
88
102
|
|
|
89
103
|
async getCoreTags(): Promise<string[]> {
|
|
90
104
|
const tags = await this.getSetting('core_tags');
|
|
91
|
-
if (!tags) return ['
|
|
105
|
+
if (!tags) return ['Web-Entwicklung', 'Best Practices'];
|
|
92
106
|
try {
|
|
93
107
|
return JSON.parse(tags);
|
|
94
108
|
} catch {
|
|
95
|
-
return ['
|
|
109
|
+
return ['Web-Entwicklung', 'Best Practices'];
|
|
96
110
|
}
|
|
97
111
|
}
|
|
98
112
|
}
|
package/update.md
CHANGED
|
@@ -1,3 +1,20 @@
|
|
|
1
|
+
# v1.0.8
|
|
2
|
+
|
|
3
|
+
## Generalize content generator for any topic
|
|
4
|
+
- Removed hardcoded accessibility/Barrierefreiheit references from all prompts
|
|
5
|
+
- `analyzeSource` now uses `systemInstruction` consistently with `researchKeywords` and `generateContent`
|
|
6
|
+
- Default system prompt uses topic-agnostic language ("zum jeweiligen Thema" instead of "zur Barrierefreiheit")
|
|
7
|
+
- Removed hardcoded keyword integration rule from default system prompt
|
|
8
|
+
- Default core tags changed from accessibility-specific to general (`Web-Entwicklung`, `Best Practices`)
|
|
9
|
+
- Default contact URL updated to generic contact page
|
|
10
|
+
- Domain specialization now lives entirely in configurable database prompts
|
|
11
|
+
|
|
12
|
+
## Fix: updateSetting upsert
|
|
13
|
+
- `PromptService.updateSetting()` now inserts if key doesn't exist instead of silently doing nothing
|
|
14
|
+
- Enables creating new settings through the settings UI without pre-seeding the database
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
1
18
|
# v1.0.6
|
|
2
19
|
|
|
3
20
|
## Separate settings from prompts in SettingsTab
|