cinqcinqdev-seo 0.1.27 → 0.1.29

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 CHANGED
@@ -23,7 +23,7 @@ A Nuxt 3 admin CMS module with a visual page editor, AI content generation, and
23
23
  - `@nuxtjs/supabase`
24
24
  - `@pinia/nuxt`
25
25
  - `@nuxt/icon`
26
- - An [OpenRouter](https://openrouter.ai) API key (for AI features)
26
+ - An [OpenRouter](https://openrouter.ai) API key (optional only needed if `features.ai: true`)
27
27
 
28
28
  ---
29
29
 
@@ -51,12 +51,6 @@ export default defineNuxtConfig({
51
51
  })
52
52
  ```
53
53
 
54
- Add the OpenRouter key to `.env`:
55
-
56
- ```env
57
- OPENROUTER_API_KEY=sk-or-...
58
- ```
59
-
60
54
  ---
61
55
 
62
56
  ## Database Setup
@@ -182,6 +176,7 @@ All options go under the `adminCms` key in `nuxt.config.js`.
182
176
  | `storageBucket` | `string` | `'site'` | Supabase storage bucket for image uploads |
183
177
  | `navSections` | `NavSectionItem[]` | `[]` | Extra sidebar links |
184
178
  | `extraSections` | `Record<string, SectionConfig>` | `{}` | Extra section types for the visual editor |
179
+ | `features.ai` | `boolean` | `false` | Enable AI content generation and SEO audit (requires `OPENROUTER_API_KEY`) |
185
180
 
186
181
  ### Default page types
187
182
 
@@ -398,7 +393,19 @@ Plain fields (colors, images, URLs, booleans) remain scalar values.
398
393
 
399
394
  ## AI Features
400
395
 
401
- Requires `OPENROUTER_API_KEY` in your environment. Uses `google/gemini-2.0-flash-lite-001` via OpenRouter.
396
+ AI features are **disabled by default**. To enable them, set `features.ai: true` in your config and add `OPENROUTER_API_KEY` to your `.env`:
397
+
398
+ ```js
399
+ adminCms: {
400
+ features: { ai: true },
401
+ }
402
+ ```
403
+
404
+ ```env
405
+ OPENROUTER_API_KEY=sk-or-...
406
+ ```
407
+
408
+ Uses `google/gemini-2.0-flash-lite-001` via OpenRouter.
402
409
 
403
410
  ### Content generation
404
411
 
package/dist/module.d.mts CHANGED
@@ -77,6 +77,19 @@ interface ModuleOptions {
77
77
  * e.g. '/cms' → routes become /cms, /cms/setup, /cms/editor/:id, etc.
78
78
  */
79
79
  basePath?: string;
80
+ /**
81
+ * Languages available in the editor's i18n switcher.
82
+ * Defaults to ['fr', 'ar', 'en']. Set to ['fr'] for French-only projects.
83
+ */
84
+ langs?: string[];
85
+ /**
86
+ * Feature flags to enable/disable optional functionality.
87
+ * All features are disabled by default.
88
+ */
89
+ features?: {
90
+ /** Enable AI content generation and SEO audit in the editor. Requires OPENROUTER_API_KEY. */
91
+ ai?: boolean;
92
+ };
80
93
  }
81
94
  declare const _default: _nuxt_schema.NuxtModule<ModuleOptions, ModuleOptions, false>;
82
95
 
package/dist/module.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "compatibility": {
5
5
  "nuxt": ">=3.0.0"
6
6
  },
7
- "version": "0.1.27",
7
+ "version": "0.1.29",
8
8
  "builder": {
9
9
  "@nuxt/module-builder": "1.0.2",
10
10
  "unbuild": "unknown"
package/dist/module.mjs CHANGED
@@ -26,7 +26,8 @@ const module$1 = defineNuxtModule({
26
26
  storageBucket: "site",
27
27
  navSections: [],
28
28
  extraSections: {},
29
- basePath: "/admin"
29
+ basePath: "/admin",
30
+ features: { ai: false }
30
31
  },
31
32
  setup(options, nuxt) {
32
33
  const { resolve } = createResolver(import.meta.url);
@@ -38,7 +39,8 @@ const module$1 = defineNuxtModule({
38
39
  tables: { pages: "pages", users: "users" },
39
40
  storageBucket: "site",
40
41
  navSections: [],
41
- extraSections: {}
42
+ extraSections: {},
43
+ features: { ai: false }
42
44
  }),
43
45
  pageTypes: options.pageTypes?.length ? options.pageTypes : defaultPageTypes,
44
46
  plans: options.plans?.length ? options.plans : [],
@@ -6,6 +6,7 @@ definePageMeta({ layout: false });
6
6
  const route = useRoute();
7
7
  const supabase = useSupabaseClient();
8
8
  const config = useRuntimeConfig().public.adminCms;
9
+ const aiEnabled = computed(() => config?.features?.ai === true);
9
10
  const table = config?.tables?.pages || "pages";
10
11
  const bucket = config?.storageBucket || "site";
11
12
  const pageId = route.params.id;
@@ -76,7 +77,7 @@ const blockDiffs = computed(() => {
76
77
  const dirtyBlocks = computed(() => new Set(blockDiffs.value.keys()));
77
78
  const showDiff = ref(false);
78
79
  const editingLang = ref("fr");
79
- const LANGS = ["fr", "ar", "en"];
80
+ const LANGS = config?.langs?.length ? config.langs : ["fr", "ar", "en"];
80
81
  const langLabel = (l) => l === "ar" ? "\u0639" : l.toUpperCase();
81
82
  const resolveI18nForPreview = (val) => {
82
83
  if (!val || typeof val !== "object" || Array.isArray(val)) return val ?? "";
@@ -575,7 +576,7 @@ const savePage = async () => {
575
576
  </div>
576
577
 
577
578
  <!-- AI Generate -->
578
- <div class="mb-5">
579
+ <div v-if="aiEnabled" class="mb-5">
579
580
  <div v-if="!showAiPrompt && !isGenerating">
580
581
  <button @click="showAiPrompt = true" class="w-full py-2.5 rounded-xl border-2 border-dashed border-[#3d35ff]/30 text-[#3d35ff] text-[8px] font-black uppercase tracking-widest hover:border-[#3d35ff] hover:bg-[#3d35ff]/5 transition-all">
581
582
  ✦ Générer avec l'IA
@@ -736,7 +737,7 @@ const savePage = async () => {
736
737
  <h3 class="text-[9px] font-black text-gray-300 uppercase mb-4 italic tracking-widest">Config SEO</h3>
737
738
 
738
739
  <!-- AI Audit -->
739
- <div class="mb-6">
740
+ <div v-if="aiEnabled" class="mb-6">
740
741
  <button @click="runSeoAudit" :disabled="isAuditing"
741
742
  class="w-full flex items-center justify-center gap-2 py-2.5 rounded-xl text-[10px] font-black uppercase tracking-widest bg-[#3d35ff]/10 text-[#3d35ff] hover:bg-[#3d35ff] hover:text-white transition-all disabled:opacity-50">
742
743
  <svg v-if="isAuditing" class="w-3.5 h-3.5 animate-spin" fill="none" viewBox="0 0 24 24"><circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"/><path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8v8z"/></svg>
@@ -746,7 +747,7 @@ const savePage = async () => {
746
747
  </div>
747
748
 
748
749
  <!-- Audit results -->
749
- <div v-if="seoAudit" class="mb-6 space-y-3">
750
+ <div v-if="aiEnabled && seoAudit" class="mb-6 space-y-3">
750
751
  <div class="flex items-center gap-3 p-3 bg-gray-50 rounded-xl">
751
752
  <div :class="[
752
753
  'w-11 h-11 rounded-xl flex items-center justify-center text-sm font-black shrink-0',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cinqcinqdev-seo",
3
- "version": "0.1.27",
3
+ "version": "0.1.29",
4
4
  "description": "A reusable Nuxt 3 admin CMS module with visual page editor powered by Supabase",
5
5
  "license": "MIT",
6
6
  "module": "./dist/module.mjs",