@deneb-ui/create-template 2.0.70 → 2.0.71

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/bin/index.js CHANGED
@@ -54,11 +54,121 @@ function copyFolderSync(src, dest) {
54
54
  }
55
55
  }
56
56
 
57
- function runScaffolding(targetInput) {
57
+ const THEME_PRESETS = {
58
+ dual: {
59
+ key: 'dual',
60
+ name: 'Dual-Mode (Light + Dark Switcher) [Recommended]',
61
+ theme: {
62
+ primaryColor: '#016a7e',
63
+ secondaryColor: '#0a1931',
64
+ accentColor: '#00adb5',
65
+ backgroundColor: '#ffffff',
66
+ textColor: '#0f172a',
67
+ headingFont: 'Inter',
68
+ bodyFont: 'Inter',
69
+ baseSize: '16px',
70
+ heroMinHeight: '72vh',
71
+ sectionPadding: '5rem',
72
+ dark: {
73
+ backgroundColor: '#090d16',
74
+ cardBackgroundColor: '#131b2e',
75
+ textColor: '#f8fafc',
76
+ borderColor: 'rgba(255, 255, 255, 0.12)',
77
+ primaryColor: '#00adb5',
78
+ },
79
+ },
80
+ },
81
+ light: {
82
+ key: 'light',
83
+ name: 'Modern Clean (Pure Light Commerce)',
84
+ theme: {
85
+ primaryColor: '#2563eb',
86
+ secondaryColor: '#1e293b',
87
+ accentColor: '#3b82f6',
88
+ backgroundColor: '#ffffff',
89
+ cardBackgroundColor: '#ffffff',
90
+ textColor: '#0f172a',
91
+ borderColor: '#e2e8f0',
92
+ headingFont: 'Inter',
93
+ bodyFont: 'Inter',
94
+ baseSize: '16px',
95
+ heroMinHeight: '72vh',
96
+ sectionPadding: '5rem',
97
+ },
98
+ },
99
+ dark: {
100
+ key: 'dark',
101
+ name: 'Luxury Obsidian (Pure Dark Theme)',
102
+ theme: {
103
+ primaryColor: '#6366f1',
104
+ secondaryColor: '#0f172a',
105
+ accentColor: '#818cf8',
106
+ backgroundColor: '#090d16',
107
+ cardBackgroundColor: '#131b2e',
108
+ textColor: '#f8fafc',
109
+ borderColor: 'rgba(255, 255, 255, 0.12)',
110
+ headingFont: 'Inter',
111
+ bodyFont: 'Inter',
112
+ baseSize: '16px',
113
+ heroMinHeight: '72vh',
114
+ sectionPadding: '5rem',
115
+ },
116
+ },
117
+ emerald: {
118
+ key: 'emerald',
119
+ name: 'Emerald Luxury (Deep Green & Gold)',
120
+ theme: {
121
+ primaryColor: '#10b981',
122
+ secondaryColor: '#064e3b',
123
+ accentColor: '#d97706',
124
+ backgroundColor: '#061a14',
125
+ cardBackgroundColor: '#0c2e24',
126
+ textColor: '#f0fdf4',
127
+ borderColor: 'rgba(16, 185, 129, 0.2)',
128
+ headingFont: 'Inter',
129
+ bodyFont: 'Inter',
130
+ baseSize: '16px',
131
+ heroMinHeight: '72vh',
132
+ sectionPadding: '5rem',
133
+ },
134
+ },
135
+ cyberpunk: {
136
+ key: 'cyberpunk',
137
+ name: 'Cyberpunk Neon (Futuristic Dark)',
138
+ theme: {
139
+ primaryColor: '#ec4899',
140
+ secondaryColor: '#18181b',
141
+ accentColor: '#06b6d4',
142
+ backgroundColor: '#09090b',
143
+ cardBackgroundColor: '#18181b',
144
+ textColor: '#fafafa',
145
+ borderColor: 'rgba(236, 72, 153, 0.3)',
146
+ headingFont: 'Inter',
147
+ bodyFont: 'Inter',
148
+ baseSize: '16px',
149
+ heroMinHeight: '72vh',
150
+ sectionPadding: '5rem',
151
+ },
152
+ },
153
+ };
154
+
155
+ function resolveThemePreset(input) {
156
+ if (!input) return THEME_PRESETS.dual;
157
+ const clean = input.trim().toLowerCase();
158
+ if (clean === '1' || clean === 'dual') return THEME_PRESETS.dual;
159
+ if (clean === '2' || clean === 'light') return THEME_PRESETS.light;
160
+ if (clean === '3' || clean === 'dark') return THEME_PRESETS.dark;
161
+ if (clean === '4' || clean === 'emerald') return THEME_PRESETS.emerald;
162
+ if (clean === '5' || clean === 'cyberpunk') return THEME_PRESETS.cyberpunk;
163
+ return THEME_PRESETS[clean] || THEME_PRESETS.dual;
164
+ }
165
+
166
+ function runScaffolding(targetInput, chosenThemeKey = 'dual') {
58
167
  const targetPath = path.resolve(process.cwd(), targetInput.trim());
59
168
  const folderName = path.basename(targetPath);
60
169
  const sanitizedPkgName = folderName.toLowerCase().replace(/[^a-z0-9_-]/g, '-');
61
170
  const templateDir = path.resolve(__dirname, '..', 'template');
171
+ const selectedPreset = resolveThemePreset(chosenThemeKey);
62
172
 
63
173
  if (!fs.existsSync(templateDir)) {
64
174
  console.error(`\n\x1b[31mError:\x1b[0m Template directory not found at ${templateDir}`);
@@ -71,6 +181,7 @@ function runScaffolding(targetInput) {
71
181
  }
72
182
 
73
183
  console.log(`\n\x1b[32mCreating DENEB template in:\x1b[0m ${targetPath}...\n`);
184
+ console.log(` \x1b[36m🎨 Starter Theme Style:\x1b[0m ${selectedPreset.name}`);
74
185
  copyFolderSync(templateDir, targetPath);
75
186
 
76
187
  // Restore .gitignore if preserved as _gitignore
@@ -91,8 +202,29 @@ function runScaffolding(targetInput) {
91
202
  }
92
203
  }
93
204
 
205
+ // Inject selected theme into site-data.json
206
+ const siteDataPath = path.join(targetPath, 'src', 'data', 'site-data.json');
207
+ if (fs.existsSync(siteDataPath)) {
208
+ try {
209
+ const siteData = JSON.parse(fs.readFileSync(siteDataPath, 'utf8'));
210
+ if (siteData.template && siteData.template.structure) {
211
+ siteData.template.structure.theme = {
212
+ ...(siteData.template.structure.theme || {}),
213
+ ...selectedPreset.theme,
214
+ };
215
+ }
216
+ siteData.theme = {
217
+ ...(siteData.theme || {}),
218
+ ...selectedPreset.theme,
219
+ };
220
+ fs.writeFileSync(siteDataPath, JSON.stringify(siteData, null, 2) + '\n');
221
+ } catch {
222
+ // ignore
223
+ }
224
+ }
225
+
94
226
  console.log(`\x1b[32m✔ Template structure created!\x1b[0m`);
95
- console.log(` \x1b[90m- Pre-configured @deneb-ui/ui (Visual editing & smart template components)\x1b[0m`);
227
+ console.log(` \x1b[90m- Pre-configured @deneb-ui/ui (ThemeStyles, ThemeToggle & 28+ Editable Components)\x1b[0m`);
96
228
  console.log(` \x1b[90m- Pre-configured @deneb-ui/cli (lab, validate, zip tools)\x1b[0m\n`);
97
229
 
98
230
  const skipInstall = process.argv.includes('--skip-install');
@@ -135,7 +267,7 @@ function runScaffolding(targetInput) {
135
267
  console.log(`\x1b[32m══════════════════════════════════════════════════════════════════════════════\x1b[0m\n`);
136
268
  console.log(`Your storefront template is pre-configured with:`);
137
269
  console.log(` \x1b[36m⚡ Next.js 15 App Router\x1b[0m (React 19 + Static Export support)`);
138
- console.log(` \x1b[36m🎨 Tailwind CSS\x1b[0m (Pre-configured tailwind.config.ts & tokens)`);
270
+ console.log(` \x1b[36m🎨 Dynamic Theming Engine\x1b[0m (ThemeStyles + ThemeToggle + Zero-FOUC)`);
139
271
  console.log(` \x1b[36m💎 @deneb-ui/ui\x1b[0m (28+ Visual-First Editable Components)`);
140
272
  console.log(` \x1b[36m🛠️ @deneb-ui/cli\x1b[0m (Visual Lab, Preflight Validator & Packager)`);
141
273
  console.log(` \x1b[36m📋 Fivora Manifest\x1b[0m (Version 2 Contract Compliant)\n`);
@@ -163,8 +295,44 @@ function runScaffolding(targetInput) {
163
295
 
164
296
  printBanner();
165
297
 
166
- if (targetDirInput && targetDirInput.trim() && !targetDirInput.startsWith('-')) {
167
- runScaffolding(targetDirInput);
298
+ // Extract CLI flags like --theme=dark or --theme=dual
299
+ let cliTheme = null;
300
+ const themeArg = args.find((a) => a.startsWith('--theme='));
301
+ if (themeArg) {
302
+ cliTheme = themeArg.split('=')[1];
303
+ }
304
+
305
+ const positionalTarget = args.find((a) => !a.startsWith('-'));
306
+ const isNonInteractive =
307
+ !process.stdin.isTTY ||
308
+ Boolean(process.env.CI) ||
309
+ args.includes('--yes') ||
310
+ args.includes('-y') ||
311
+ args.includes('--non-interactive') ||
312
+ args.includes('--skip-install');
313
+
314
+ if (positionalTarget && positionalTarget.trim()) {
315
+ if (cliTheme || isNonInteractive) {
316
+ runScaffolding(positionalTarget, cliTheme || 'dual');
317
+ } else {
318
+ const rl = readline.createInterface({
319
+ input: process.stdin,
320
+ output: process.stdout,
321
+ });
322
+ console.log('⚡ Template Theme Selection:\n');
323
+ console.log(' \x1b[36m1)\x1b[0m Dual-Mode \x1b[90m(Light + Dark Switcher pre-installed)\x1b[0m \x1b[32m[Recommended]\x1b[0m');
324
+ console.log(' \x1b[36m2)\x1b[0m Modern Clean \x1b[90m(Pure Light commerce)\x1b[0m');
325
+ console.log(' \x1b[36m3)\x1b[0m Luxury Obsidian \x1b[90m(Pure Dark theme)\x1b[0m');
326
+ console.log(' \x1b[36m4)\x1b[0m Emerald Luxury \x1b[90m(Deep Green & Gold)\x1b[0m');
327
+ console.log(' \x1b[36m5)\x1b[0m Cyberpunk Neon \x1b[90m(Futuristic Dark)\x1b[0m\n');
328
+
329
+ rl.question(' \x1b[36m?\x1b[0m \x1b[1mSelect starter theme (1-5, default 1):\x1b[0m ', (themeAns) => {
330
+ rl.close();
331
+ runScaffolding(positionalTarget, themeAns.trim() || 'dual');
332
+ });
333
+ }
334
+ } else if (isNonInteractive) {
335
+ runScaffolding('my-deneb-store', cliTheme || 'dual');
168
336
  } else {
169
337
  const rl = readline.createInterface({
170
338
  input: process.stdin,
@@ -173,8 +341,24 @@ if (targetDirInput && targetDirInput.trim() && !targetDirInput.startsWith('-'))
173
341
 
174
342
  console.log('⚡ Welcome to DENEB UI Template Creator!\n');
175
343
  rl.question(' \x1b[36m?\x1b[0m \x1b[1mWhat is your template name?\x1b[0m \x1b[90m(e.g. my-store)\x1b[0m: ', (answer) => {
176
- rl.close();
177
344
  const name = answer.trim() || 'my-deneb-store';
178
- runScaffolding(name);
345
+
346
+ if (cliTheme) {
347
+ rl.close();
348
+ runScaffolding(name, cliTheme);
349
+ return;
350
+ }
351
+
352
+ console.log('\n \x1b[36m?\x1b[0m \x1b[1mSelect starter theme style:\x1b[0m');
353
+ console.log(' \x1b[36m1)\x1b[0m Dual-Mode \x1b[90m(Light + Dark Switcher pre-installed)\x1b[0m \x1b[32m[Recommended]\x1b[0m');
354
+ console.log(' \x1b[36m2)\x1b[0m Modern Clean \x1b[90m(Pure Light commerce)\x1b[0m');
355
+ console.log(' \x1b[36m3)\x1b[0m Luxury Obsidian \x1b[90m(Pure Dark theme)\x1b[0m');
356
+ console.log(' \x1b[36m4)\x1b[0m Emerald Luxury \x1b[90m(Deep Green & Gold)\x1b[0m');
357
+ console.log(' \x1b[36m5)\x1b[0m Cyberpunk Neon \x1b[90m(Futuristic Dark)\x1b[0m\n');
358
+
359
+ rl.question(' \x1b[1mEnter choice (1-5, default 1):\x1b[0m ', (themeAns) => {
360
+ rl.close();
361
+ runScaffolding(name, themeAns.trim() || 'dual');
362
+ });
179
363
  });
180
364
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@deneb-ui/create-template",
3
- "version": "2.0.70",
3
+ "version": "2.0.71",
4
4
  "description": "Scaffold production-ready DENEB UI storefront templates for Next.js in seconds.",
5
5
  "bin": {
6
6
  "create-deneb-template": "bin/index.js",
@@ -424,6 +424,11 @@
424
424
  "key": "submitLabel",
425
425
  "type": "text",
426
426
  "label": "Submit button"
427
+ },
428
+ {
429
+ "key": "directMessageText",
430
+ "type": "text",
431
+ "label": "Direct message label"
427
432
  }
428
433
  ]
429
434
  },
@@ -18,7 +18,7 @@
18
18
  "next": "15.5.23",
19
19
  "react": "19.2.8",
20
20
  "react-dom": "19.2.8",
21
- "@deneb-ui/ui": "^2.0.70"
21
+ "@deneb-ui/ui": "^2.0.71"
22
22
  },
23
23
  "devDependencies": {
24
24
  "@eslint/eslintrc": "3.3.6",
@@ -28,7 +28,7 @@
28
28
  "eslint": "9.39.5",
29
29
  "eslint-config-next": "15.5.23",
30
30
  "typescript": "5.8.3",
31
- "@deneb-ui/cli": "^2.0.70",
31
+ "@deneb-ui/cli": "^2.0.71",
32
32
  "tailwindcss": "^3.4.17",
33
33
  "postcss": "8.5.26",
34
34
  "autoprefixer": "^10.4.20"
@@ -1,8 +1,7 @@
1
1
  'use client';
2
2
 
3
- import { HeritageCollage } from '@deneb-ui/ui';
3
+ import { HeritageCollage, EditableText, EditableImage } from '@deneb-ui/ui';
4
4
  import { contentObject, contentText, contentList, useSiteData } from '@/lib/siteDataContext';
5
- import { withBasePath } from '@/lib/utils';
6
5
 
7
6
  export default function AboutPage() {
8
7
  const siteData = useSiteData();
@@ -13,14 +12,29 @@ export default function AboutPage() {
13
12
  <div data-preview-page-key="about_us">
14
13
  <section className="page-section split" data-design-section="about">
15
14
  <div className="split-copy">
16
- <h1 className="section-title" data-preview-field-path="about.heading">{contentText(about.heading)}</h1>
17
- <p data-preview-field-path="about.body">{contentText(about.body)}</p>
15
+ <EditableText
16
+ variant="h1"
17
+ size="4xl"
18
+ weight="bold"
19
+ color="heading"
20
+ className="section-title"
21
+ data-preview-field-path="about.heading"
22
+ defaultValue={contentText(about.heading)}
23
+ />
24
+ <EditableText
25
+ variant="lead"
26
+ color="muted"
27
+ data-preview-field-path="about.body"
28
+ defaultValue={contentText(about.body)}
29
+ />
18
30
  </div>
19
- <img
31
+ <EditableImage
20
32
  className="split-image"
21
- src={withBasePath(contentText(about.imageUrl) || '/placeholder.svg')}
22
- alt=""
33
+ src={contentText(about.imageUrl) || '/placeholder.svg'}
34
+ alt="About DENEB-UI"
23
35
  data-preview-field-path="about.imageUrl"
36
+ radius="xl"
37
+ fit="cover"
24
38
  />
25
39
  </section>
26
40
 
@@ -1,7 +1,7 @@
1
1
  'use client';
2
2
 
3
3
  import { useState, type FormEvent } from 'react';
4
- import { MapLink } from '@deneb-ui/ui';
4
+ import { MapLink, EditableText, EditableBox } from '@deneb-ui/ui';
5
5
  import { contentObject, contentText, useSiteData } from '@/lib/siteDataContext';
6
6
 
7
7
  export default function ContactPage() {
@@ -15,6 +15,10 @@ export default function ContactPage() {
15
15
  contentText(contact.mapUrl) ||
16
16
  contentText(contact.addressUrl);
17
17
  const address = contentText(contact.address);
18
+ const phone = contentText(contact.phone);
19
+ const email = contentText(contact.email);
20
+ const whatsapp = contentText(contact.whatsapp);
21
+ const directMessageText = contentText(contact.directMessageText) || 'Chat on WhatsApp';
18
22
 
19
23
  async function handleSubmit(event: FormEvent<HTMLFormElement>) {
20
24
  event.preventDefault();
@@ -49,47 +53,114 @@ export default function ContactPage() {
49
53
  return (
50
54
  <div data-preview-page-key="contact">
51
55
  <section className="page-section page-heading" data-design-section="contact-heading">
52
- <h1 data-preview-field-path="contact.heading">{contentText(contact.heading)}</h1>
53
- <p data-preview-field-path="contact.intro">{contentText(contact.intro)}</p>
56
+ <EditableText
57
+ variant="h1"
58
+ size="4xl"
59
+ weight="bold"
60
+ color="heading"
61
+ data-preview-field-path="contact.heading"
62
+ defaultValue={contentText(contact.heading)}
63
+ />
64
+ <EditableText
65
+ variant="lead"
66
+ color="muted"
67
+ data-preview-field-path="contact.intro"
68
+ defaultValue={contentText(contact.intro)}
69
+ />
54
70
  </section>
71
+
55
72
  <section className="page-section contact-grid" data-design-section="contact-details">
56
- <div className="contact-details">
57
- <a href={`tel:${contentText(contact.phone)}`} data-preview-field-path="contact.phone">{contentText(contact.phone)}</a>
58
- <a href={`mailto:${contentText(contact.email)}`} data-preview-field-path="contact.email">{contentText(contact.email)}</a>
59
- <p data-preview-field-path="contact.address">{address}</p>
60
- <MapLink
61
- mapUrl={directionsUrl}
62
- address={address}
63
- label={directionsLabel}
64
- labelFieldPath="contact.directionsLabel"
65
- urlFieldPath="contact.directionsUrl"
66
- variant="outline"
67
- size="md"
73
+ <EditableBox className="card contact-details" balance radius="xl">
74
+ <EditableText
75
+ variant="h3"
76
+ size="xl"
77
+ weight="bold"
78
+ color="heading"
79
+ defaultValue="Direct Information"
68
80
  />
69
- </div>
70
- <form
71
- className="contact-form"
72
- onSubmit={handleSubmit}
73
- data-fivora-contact-disabled
74
- >
75
- <h2 data-preview-field-path="contact.formTitle">{contentText(contact.formTitle)}</h2>
76
- <label data-preview-static>
77
- Name
78
- <input type="text" name="name" autoComplete="name" />
79
- </label>
80
- <label data-preview-static>
81
- Email
82
- <input type="email" name="email" autoComplete="email" />
83
- </label>
84
- <label data-preview-static>
85
- Message
86
- <textarea name="message" rows={5} />
87
- </label>
88
- <button type="submit" className="button-primary">
89
- <span data-preview-field-path="contact.submitLabel">{contentText(contact.submitLabel)}</span>
90
- </button>
91
- <p role="status" aria-live="polite">{status}</p>
92
- </form>
81
+ <div style={{ display: 'flex', flexDirection: 'column', gap: '0.75rem', marginTop: '0.5rem' }}>
82
+ {phone && (
83
+ <a href={`tel:${phone}`} data-preview-field-path="contact.phone">
84
+ {phone}
85
+ </a>
86
+ )}
87
+ {email && (
88
+ <a href={`mailto:${email}`} data-preview-field-path="contact.email">
89
+ {email}
90
+ </a>
91
+ )}
92
+ {address && (
93
+ <EditableText
94
+ variant="p"
95
+ color="muted"
96
+ data-preview-field-path="contact.address"
97
+ defaultValue={address}
98
+ />
99
+ )}
100
+ </div>
101
+ <div style={{ marginTop: '1.5rem', display: 'flex', flexWrap: 'wrap', gap: '0.75rem' }}>
102
+ <MapLink
103
+ mapUrl={directionsUrl}
104
+ address={address}
105
+ label={directionsLabel}
106
+ labelFieldPath="contact.directionsLabel"
107
+ urlFieldPath="contact.directionsUrl"
108
+ variant="outline"
109
+ size="md"
110
+ />
111
+ {whatsapp && (
112
+ <a
113
+ href={`https://wa.me/${whatsapp.replace(/[^0-9]/g, '')}`}
114
+ target="_blank"
115
+ rel="noopener noreferrer"
116
+ className="button-secondary"
117
+ >
118
+ <span data-preview-field-path="contact.directMessageText">
119
+ {directMessageText}
120
+ </span>
121
+ </a>
122
+ )}
123
+ </div>
124
+ </EditableBox>
125
+
126
+ <EditableBox className="card" balance radius="xl">
127
+ <form
128
+ className="contact-form"
129
+ onSubmit={handleSubmit}
130
+ data-fivora-contact-disabled
131
+ >
132
+ <EditableText
133
+ variant="h2"
134
+ size="2xl"
135
+ weight="bold"
136
+ color="heading"
137
+ data-preview-field-path="contact.formTitle"
138
+ defaultValue={contentText(contact.formTitle)}
139
+ />
140
+ <label data-preview-static>
141
+ Name
142
+ <input type="text" name="name" autoComplete="name" required />
143
+ </label>
144
+ <label data-preview-static>
145
+ Email
146
+ <input type="email" name="email" autoComplete="email" required />
147
+ </label>
148
+ <label data-preview-static>
149
+ Message
150
+ <textarea name="message" rows={4} required />
151
+ </label>
152
+ <button type="submit" className="button-primary" style={{ marginTop: '0.5rem' }}>
153
+ <span data-preview-field-path="contact.submitLabel">
154
+ {contentText(contact.submitLabel)}
155
+ </span>
156
+ </button>
157
+ {status && (
158
+ <p role="status" aria-live="polite" style={{ marginTop: '0.75rem', fontSize: '0.9rem' }}>
159
+ {status}
160
+ </p>
161
+ )}
162
+ </form>
163
+ </EditableBox>
93
164
  </section>
94
165
  </div>
95
166
  );
@@ -6,6 +6,11 @@
6
6
  color-scheme: light;
7
7
  }
8
8
 
9
+ html.dark,
10
+ .dark {
11
+ color-scheme: dark;
12
+ }
13
+
9
14
  * {
10
15
  box-sizing: border-box;
11
16
  }
@@ -18,6 +23,7 @@ body {
18
23
  margin: 0;
19
24
  background: var(--page-background, #ffffff);
20
25
  color: var(--page-text, #0f172a);
26
+ transition: background-color 0.25s ease, color 0.25s ease;
21
27
  }
22
28
 
23
29
  button,
@@ -252,10 +258,11 @@ h3 {
252
258
 
253
259
  .card {
254
260
  padding: 1.4rem;
255
- border: 1px solid color-mix(in srgb, var(--page-text) 12%, transparent);
261
+ border: 1px solid var(--card-border, color-mix(in srgb, var(--page-text) 12%, transparent));
256
262
  border-radius: 1.35rem;
257
- background: var(--page-background);
263
+ background: var(--card-bg, var(--page-background));
258
264
  box-shadow: 0 1rem 2.5rem color-mix(in srgb, var(--brand-secondary) 8%, transparent);
265
+ transition: transform 0.2s ease, box-shadow 0.2s ease, background-color 0.25s ease, border-color 0.25s ease;
259
266
  }
260
267
 
261
268
  .card h3 {
@@ -347,10 +354,11 @@ h3 {
347
354
  .contact-form textarea {
348
355
  width: 100%;
349
356
  padding: 0.85rem 1rem;
350
- border: 1px solid color-mix(in srgb, var(--page-text) 20%, transparent);
357
+ border: 1px solid var(--input-border, color-mix(in srgb, var(--page-text) 20%, transparent));
351
358
  border-radius: 0.8rem;
352
- background: var(--page-background);
353
- color: var(--page-text);
359
+ background: var(--input-bg, var(--page-background));
360
+ color: var(--input-color, var(--page-text));
361
+ transition: border-color 0.2s ease, box-shadow 0.2s ease;
354
362
  }
355
363
 
356
364
  .site-footer {
@@ -442,81 +450,3 @@ h3 {
442
450
  transform: scale(1.06) translateY(-4px);
443
451
  }
444
452
 
445
- /* Developer Quickstart Guide Section */
446
- .dev-guide-section {
447
- border-top: 1px solid color-mix(in srgb, var(--page-text) 10%, transparent);
448
- border-bottom: 1px solid color-mix(in srgb, var(--page-text) 10%, transparent);
449
- background: color-mix(in srgb, var(--brand-color) 4%, var(--page-background));
450
- }
451
-
452
- .dev-guide-header {
453
- text-align: center;
454
- max-width: 44rem;
455
- margin: 0 auto 2.5rem;
456
- }
457
-
458
- .dev-badge {
459
- display: inline-block;
460
- padding: 0.35rem 0.9rem;
461
- border-radius: 999px;
462
- font-size: 0.8rem;
463
- font-weight: 700;
464
- letter-spacing: 0.05em;
465
- background: color-mix(in srgb, var(--brand-color) 15%, transparent);
466
- color: var(--brand-color);
467
- margin-bottom: 0.85rem;
468
- }
469
-
470
- .dev-command-grid {
471
- display: grid;
472
- grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
473
- gap: 1.5rem;
474
- }
475
-
476
- .dev-cmd-card {
477
- padding: 1.5rem;
478
- border-radius: 1rem;
479
- background: var(--page-background);
480
- border: 1px solid color-mix(in srgb, var(--page-text) 12%, transparent);
481
- box-shadow: 0 4px 12px rgba(0, 0, 0, 0.04);
482
- transition: transform 0.2s ease, box-shadow 0.2s ease, border-color 0.2s ease;
483
- }
484
-
485
- .dev-cmd-card:hover {
486
- transform: translateY(-3px);
487
- border-color: var(--brand-accent);
488
- box-shadow: 0 8px 24px color-mix(in srgb, var(--brand-color) 15%, transparent);
489
- }
490
-
491
- .dev-cmd-card .cmd-header {
492
- display: flex;
493
- align-items: center;
494
- justify-content: space-between;
495
- margin-bottom: 0.75rem;
496
- gap: 0.5rem;
497
- }
498
-
499
- .dev-cmd-card .cmd-tag {
500
- font-size: 0.75rem;
501
- font-weight: 700;
502
- text-transform: uppercase;
503
- letter-spacing: 0.08em;
504
- color: var(--brand-color);
505
- }
506
-
507
- .dev-cmd-card code {
508
- font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
509
- font-size: 0.85rem;
510
- font-weight: 700;
511
- padding: 0.2rem 0.5rem;
512
- border-radius: 0.35rem;
513
- background: color-mix(in srgb, var(--page-text) 8%, transparent);
514
- color: var(--page-text);
515
- }
516
-
517
- .dev-cmd-card p {
518
- margin: 0;
519
- font-size: 0.9rem;
520
- line-height: 1.5;
521
- color: color-mix(in srgb, var(--page-text) 70%, transparent);
522
- }
@@ -1,7 +1,7 @@
1
1
  import type { Metadata } from 'next';
2
2
  import type { ReactNode } from 'react';
3
3
  import siteData from '@/data/site-data.json';
4
- import { SiteDataProvider } from '@/lib/siteDataContext';
4
+ import { SiteDataProvider, ThemeStyles } from '@/lib/siteDataContext';
5
5
  import SiteChrome from '@/components/SiteChrome';
6
6
  import './globals.css';
7
7
  import '../fonts/deneb-fonts.css';
@@ -15,8 +15,14 @@ export const metadata: Metadata = {
15
15
  };
16
16
 
17
17
  export default function RootLayout({ children }: { children: ReactNode }) {
18
+ const initialTheme =
19
+ (siteData as any)?.template?.structure?.theme || (siteData as any)?.theme;
20
+
18
21
  return (
19
22
  <html lang="en" suppressHydrationWarning>
23
+ <head>
24
+ <ThemeStyles theme={initialTheme} enableDualMode />
25
+ </head>
20
26
  <body suppressHydrationWarning>
21
27
  <SiteDataProvider initialSiteData={siteData}>
22
28
  <SiteChrome>{children}</SiteChrome>
@@ -4,6 +4,7 @@ import type { ReactNode } from 'react';
4
4
  import { usePathname } from 'next/navigation';
5
5
  import { useSiteData } from '@/lib/siteDataContext';
6
6
  import { Navbar, Footer, AnnouncementBar, FloatingContactWidget, getThemeCssProperties } from '@deneb-ui/ui';
7
+ import { ThemeToggle } from './ThemeToggle';
7
8
 
8
9
  export default function SiteChrome({ children }: { children: ReactNode }) {
9
10
  const siteData = useSiteData();
@@ -19,6 +20,9 @@ export default function SiteChrome({ children }: { children: ReactNode }) {
19
20
  <main>{children}</main>
20
21
  <Footer />
21
22
  <FloatingContactWidget />
23
+ <div className="fixed bottom-6 left-6 z-40">
24
+ <ThemeToggle showLabel className="shadow-lg backdrop-blur-md" />
25
+ </div>
22
26
  </div>
23
27
  );
24
28
  }
@@ -0,0 +1,87 @@
1
+ 'use client';
2
+
3
+ import { useEffect, useState } from 'react';
4
+
5
+ export interface ThemeToggleProps {
6
+ className?: string;
7
+ showLabel?: boolean;
8
+ }
9
+
10
+ /**
11
+ * Built-in ThemeToggle Component for DENEB Storefront Templates.
12
+ * Toggles the `.dark` class on the root <html> element and persists preference to localStorage.
13
+ */
14
+ export function ThemeToggle({ className = '', showLabel = false }: ThemeToggleProps) {
15
+ const [isDark, setIsDark] = useState(false);
16
+ const [mounted, setMounted] = useState(false);
17
+
18
+ useEffect(() => {
19
+ setMounted(true);
20
+ const hasDarkClass = document.documentElement.classList.contains('dark');
21
+ const storedTheme = typeof window !== 'undefined' ? localStorage.getItem('deneb-theme') : null;
22
+ const prefersDark = typeof window !== 'undefined' ? window.matchMedia('(prefers-color-scheme: dark)').matches : false;
23
+
24
+ const activeDark = storedTheme ? storedTheme === 'dark' : hasDarkClass || prefersDark;
25
+ setIsDark(activeDark);
26
+ if (activeDark) {
27
+ document.documentElement.classList.add('dark');
28
+ } else {
29
+ document.documentElement.classList.remove('dark');
30
+ }
31
+ }, []);
32
+
33
+ const toggleTheme = () => {
34
+ const nextDark = !isDark;
35
+ setIsDark(nextDark);
36
+ if (nextDark) {
37
+ document.documentElement.classList.add('dark');
38
+ localStorage.setItem('deneb-theme', 'dark');
39
+ } else {
40
+ document.documentElement.classList.remove('dark');
41
+ localStorage.setItem('deneb-theme', 'light');
42
+ }
43
+ };
44
+
45
+ if (!mounted) {
46
+ return (
47
+ <button
48
+ type="button"
49
+ aria-label="Toggle theme"
50
+ className={`w-9 h-9 rounded-lg border border-[var(--border-color,#e2e8f0)] bg-[var(--card-bg,#ffffff)] opacity-0 transition-opacity ${className}`}
51
+ />
52
+ );
53
+ }
54
+
55
+ return (
56
+ <button
57
+ type="button"
58
+ onClick={toggleTheme}
59
+ aria-label={isDark ? 'Switch to light mode' : 'Switch to dark mode'}
60
+ title={isDark ? 'Switch to light mode' : 'Switch to dark mode'}
61
+ className={`inline-flex items-center justify-center gap-2 h-9 px-2.5 rounded-lg border border-[var(--border-color,rgba(0,0,0,0.1))] bg-[var(--card-bg,#ffffff)] text-[var(--text-color,#0f172a)] hover:border-[var(--color-primary,#016a7e)] hover:text-[var(--color-primary,#016a7e)] shadow-sm transition-all duration-200 cursor-pointer ${className}`}
62
+ >
63
+ {isDark ? (
64
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" className="w-4 h-4 text-amber-400">
65
+ <path d="M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z" />
66
+ </svg>
67
+ ) : (
68
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" className="w-4 h-4 text-amber-500">
69
+ <circle cx="12" cy="12" r="4" />
70
+ <path d="M12 2v2" />
71
+ <path d="M12 20v2" />
72
+ <path d="m4.93 4.93 1.41 1.41" />
73
+ <path d="m17.66 17.66 1.41 1.41" />
74
+ <path d="M2 12h2" />
75
+ <path d="M20 12h2" />
76
+ <path d="m6.34 17.66-1.41 1.41" />
77
+ <path d="m19.07 4.93-1.41 1.41" />
78
+ </svg>
79
+ )}
80
+ {showLabel && (
81
+ <span className="text-xs font-medium">{isDark ? 'Dark' : 'Light'}</span>
82
+ )}
83
+ </button>
84
+ );
85
+ }
86
+
87
+ export default ThemeToggle;
@@ -1,17 +1,17 @@
1
1
  {
2
2
  "project": {
3
- "id": "starter-demo",
4
- "slug": "starter-demo",
5
- "title": "Fivora Starter Demo",
3
+ "id": "deneb-portfolio-showcase",
4
+ "slug": "deneb-portfolio-showcase",
5
+ "title": "DENEB UI — Showcase & Portfolio",
6
6
  "status": "APPROVED"
7
7
  },
8
8
  "merchant": {
9
- "businessName": "Fivora Store",
10
- "description": "A modern high-converting digital storefront built on the Fivora platform."
9
+ "businessName": "DENEB UI Showcase",
10
+ "description": "The visual-first React framework for high-converting storefronts and modern digital portfolios. Powered by DENEB-UI in collaboration with FIVORA."
11
11
  },
12
12
  "template": {
13
- "id": "starter-template",
14
- "name": "Fivora Starter",
13
+ "id": "deneb-portfolio-template",
14
+ "name": "DENEB UI Portfolio Showcase",
15
15
  "engine": "NEXT_STATIC_EXPORT",
16
16
  "structure": {
17
17
  "pages": [
@@ -30,7 +30,17 @@
30
30
  "bodyFont": "Inter",
31
31
  "baseSize": "16px",
32
32
  "heroMinHeight": "72vh",
33
- "sectionPadding": "5rem"
33
+ "sectionPadding": "5rem",
34
+ "borderRadius": "12px",
35
+ "dark": {
36
+ "backgroundColor": "#090d16",
37
+ "cardBackgroundColor": "#131b2e",
38
+ "textColor": "#f8fafc",
39
+ "borderColor": "rgba(255, 255, 255, 0.12)",
40
+ "primaryColor": "#00adb5",
41
+ "secondaryColor": "#1e293b",
42
+ "accentColor": "#38bdf8"
43
+ }
34
44
  }
35
45
  }
36
46
  },
@@ -45,8 +55,8 @@
45
55
  },
46
56
  "content": {
47
57
  "common": {
48
- "websiteTitle": "Fivora Store",
49
- "shortDescription": "Next-generation commerce templates built for the Fivora with reusable components and strict visual editing.",
58
+ "websiteTitle": "DENEB UI — Showcase & Portfolio",
59
+ "shortDescription": "The visual-first React framework for modern storefronts and digital portfolios. Powered by DENEB-UI in collaboration with FIVORA.",
50
60
  "logoUrl": "/fivora-logo.png",
51
61
  "headerCtaLabel": "Contact Us",
52
62
  "navLabels": {
@@ -55,111 +65,126 @@
55
65
  "services": "Services",
56
66
  "contact": "Contact"
57
67
  },
58
- "footerHeading": "Build something extraordinary with Fivora.",
59
- "copyright": "Fivora. All rights reserved.",
68
+ "footerHeading": "Build something extraordinary with DENEB-UI & FIVORA.",
69
+ "copyright": "DENEB-UI. All rights reserved. Collaborate with FIVORA.",
60
70
  "socialMedia": {
61
- "twitter": "https://twitter.com",
62
- "github": "https://github.com",
71
+ "twitter": "https://twitter.com/denebui",
72
+ "github": "https://github.com/deneb-ui",
63
73
  "linkedin": "https://linkedin.com",
64
74
  "instagram": "https://instagram.com"
65
75
  }
66
76
  },
67
77
  "home": {
68
- "heroEyebrow": "⚡ Fivora Template Starter",
69
- "heroTitle": "Design Stores That Captivate",
70
- "heroSummary": "Built with @deneb-ui/ui. Hot-reload locally, simulate merchant visual editing in the Lab, validate preflight contracts, and package with 1-click.",
78
+ "heroEyebrow": "⚡ DENEB UI FRAMEWORK",
79
+ "heroTitle": "The Visual-First React Framework for High-Converting Experiences",
80
+ "heroSummary": "Design, build, and ship web storefronts and portfolios with 100% atomic editable components, auto-balancing layouts, and instant dual-mode aesthetics. Built in collaboration with FIVORA Cloud.",
71
81
  "bannerImageUrl": "/fivora-icon.svg",
72
- "primaryCtaLabel": "Explore Services",
73
- "secondaryCtaLabel": "About This Starter",
74
- "introTitle": "Engineered for high conversion and effortless editing",
75
- "introBody": "Every editable value comes directly from Fivora site data with auto-balancing layouts, responsive typography, and strict contract validation out of the box.",
76
- "featuresHeading": "Why build with the Fivora Authoring Kit?",
82
+ "primaryCtaLabel": "Explore Showcase",
83
+ "secondaryCtaLabel": "About DENEB-UI",
84
+ "introTitle": "Engineered for visual perfection and effortless editing",
85
+ "introBody": "Every editable value comes directly from structured site data with auto-balancing layouts, responsive typography, and strict contract validation out of the box.",
86
+ "featuresHeading": "Why build with the DENEB-UI Authoring Kit?",
77
87
  "features": [
78
88
  {
79
- "title": "Auto-Balancing Layouts",
80
- "body": "Cards, grids, and containers automatically balance and fill space seamlessly across all screen sizes."
89
+ "title": "100% Atomic DENEB Components",
90
+ "body": "Pre-built, accessible, high-converting components with responsive design token integration and zero runtime overhead."
81
91
  },
82
92
  {
83
93
  "title": "Strict Visual Editing",
84
- "body": "Direct bindings enable merchants to click, edit, and preview changes without breaking template styles."
94
+ "body": "Direct bidirectional field bindings enable instant visual customization in the Lab and on the FIVORA platform without breaking styles."
95
+ },
96
+ {
97
+ "title": "Instant Dual-Mode Aesthetics",
98
+ "body": "Seamless light and dark mode out-of-the-box with intelligent token contrast calculations for typography and surfaces."
85
99
  },
86
100
  {
87
- "title": "1-Click Clean Packaging",
88
- "body": "Built-in zip command strips heavy caches, node_modules, and git files so uploads pass instantly."
101
+ "title": "FIVORA Cloud Collaboration",
102
+ "body": "Built-in integration for collaborative editing, marketplace publishing, and automated zero-dependency clean packaging."
89
103
  }
90
104
  ],
91
105
  "demoPreOrderCta": [
92
106
  {
93
- "buttonLabel": "Book a Demo",
107
+ "buttonLabel": "Book a Consultation",
94
108
  "buttonUrl": "https://wa.me/94771234567"
95
109
  }
96
110
  ],
97
- "productsHeading": "Featured Store Products",
98
- "productsSummary": "Live inventory and pricing updated in real time from your Fivora Shop Owner panel."
111
+ "productsHeading": "Featured Portfolio & Templates",
112
+ "productsSummary": "Explore high-converting storefronts, portals, and templates engineered with DENEB-UI and verified for production."
99
113
  },
100
114
  "about": {
101
- "heading": "Built for the next generation of online storefronts",
102
- "body": "The Fivora connects businesses with high-converting, beautifully crafted templates. This starter template demonstrates clean monorepo architecture, responsive typography, and auto-balancing components.",
115
+ "heading": "Empowering Developers to Build Visually Editable Web Experiences",
116
+ "body": "DENEB UI was created by Chamika Gayashan & Induranga Kawishwara to bridge the gap between developer-grade React code and effortless visual editing. In collaboration with the FIVORA platform, we empower creators to ship ultra-fast static web applications while giving non-technical teams an intuitive live visual editor.",
103
117
  "imageUrl": "/placeholder.svg",
104
- "collageHeading": "Our story in pictures",
105
- "collageDescription": "A quick visual tour of how we design, build, and ship merchant-ready storefronts.",
106
- "historyHeading": "Where we started",
107
- "history": "We began as a small team helping local businesses move online. Today our templates power visual editing labs, strict Fivora contracts, and one-click packaging for developers worldwide.",
118
+ "collageHeading": "The DENEB-UI Journey",
119
+ "collageDescription": "A visual tour of our architecture, design system engineering, and cloud deployment pipeline.",
120
+ "historyHeading": "Our Engineering Philosophy",
121
+ "history": "We believe modern web developers shouldn't have to choose between code elegance and visual customization. DENEB-UI provides atomic, contract-bound components that compile to lean Next.js static exports, backed by FIVORA Cloud for instant real-time publishing.",
108
122
  "collageImages": [
109
123
  {
110
- "id": "studio",
124
+ "id": "design-system",
111
125
  "image": "/placeholder.svg",
112
- "caption": "Design studio"
126
+ "caption": "Atomic Design System"
113
127
  },
114
128
  {
115
- "id": "build",
129
+ "id": "visual-engine",
116
130
  "image": "/placeholder.svg",
117
- "caption": "Build & test"
131
+ "caption": "Live Visual Engine"
118
132
  },
119
133
  {
120
- "id": "ship",
134
+ "id": "cloud-publish",
121
135
  "image": "/placeholder.svg",
122
- "caption": "Ship to Fivora"
136
+ "caption": "FIVORA Cloud Publishing"
123
137
  }
124
138
  ]
125
139
  },
126
140
  "servicesPage": {
127
- "heading": "Template Services & Capabilities",
128
- "intro": "Each service card is an atomic component featuring an image, heading, description, and repeatable checklist."
141
+ "heading": "Framework Solutions & Capabilities",
142
+ "intro": "Every capability is backed by atomic DENEB components, automated packaging, and preflight verification."
129
143
  },
130
144
  "services": [
131
145
  {
132
146
  "id": "visual-editing",
133
147
  "name": "Visual Editing Lab",
134
- "description": "Simulate how merchants customize your template in real time with the built-in local development lab.",
148
+ "description": "Simulate how merchants customize your template in real time with the built-in local development lab and field focus bridge.",
135
149
  "imageUrl": "/placeholder.svg",
136
150
  "features": [
137
151
  "Zero-server static preview",
138
152
  "Field focus bridge",
139
- "Instant feedback"
153
+ "Instant visual feedback"
140
154
  ]
141
155
  },
142
156
  {
143
157
  "id": "clean-packaging",
144
158
  "name": "Automated Packager",
145
- "description": "Automatically produce clean, upload-ready ZIP archives excluding junk and cache files.",
159
+ "description": "Automatically produce clean, upload-ready ZIP archives excluding junk, build caches, and sensitive files.",
146
160
  "imageUrl": "/placeholder.svg",
147
161
  "features": [
148
162
  "Excludes node_modules",
149
163
  "Excludes .next and .git",
150
164
  "100% preflight compliant"
151
165
  ]
166
+ },
167
+ {
168
+ "id": "dual-mode-system",
169
+ "name": "Dual-Mode Theme Engine",
170
+ "description": "Harmonic light and dark themes generated automatically with smart contrast adjustments for high visual appeal.",
171
+ "imageUrl": "/placeholder.svg",
172
+ "features": [
173
+ "Auto contrast calculations",
174
+ "ThemeToggle component",
175
+ "Persistent theme storage"
176
+ ]
152
177
  }
153
178
  ],
154
179
  "contact": {
155
- "heading": "Get in touch with our team",
156
- "intro": "Have questions about building or customizing Fivora templates? Contact us today.",
180
+ "heading": "Connect with the DENEB-UI Team",
181
+ "intro": "Have questions about DENEB-UI components or building custom storefronts with the FIVORA platform? Contact us today.",
157
182
  "phone": "+94 11 234 5678",
158
- "email": "developer@fivora.lk",
183
+ "email": "hello@deneb-ui.dev",
159
184
  "address": "Colombo, Sri Lanka",
160
185
  "directionsLabel": "Get Directions",
161
186
  "directionsUrl": "https://maps.app.goo.gl/example",
162
- "formTitle": "Send an enquiry",
187
+ "formTitle": "Send an Inquiry",
163
188
  "submitLabel": "Send Message",
164
189
  "directMessageText": "Send us a direct message",
165
190
  "whatsapp": "+94 77 123 4567"
@@ -167,38 +192,38 @@
167
192
  "products": [
168
193
  {
169
194
  "id": "prod-1",
170
- "name": "Minimalist Ceramic Cup",
171
- "description": "Handcrafted matte ceramic cup for your daily espresso or pour-over brew.",
172
- "price": 3200,
173
- "compareAtPrice": 4000,
195
+ "name": "Aura Luxury Storefront",
196
+ "description": "High-converting boutique and jewelry storefront template with dark aesthetics, before/after sliders, and quick checkout.",
197
+ "price": 4900,
198
+ "compareAtPrice": 6500,
174
199
  "currency": "LKR",
175
200
  "imageUrl": "/placeholder.svg",
176
- "category": "Ceramics",
177
- "badge": "Bestseller",
201
+ "category": "E-Commerce",
202
+ "badge": "Popular",
178
203
  "isAvailable": true
179
204
  },
180
205
  {
181
206
  "id": "prod-2",
182
- "name": "Artisan Linen Apron",
183
- "description": "Durable pure washed linen apron with deep front utility pockets.",
184
- "price": 5400,
185
- "compareAtPrice": 6200,
207
+ "name": "Apex SaaS & Analytics",
208
+ "description": "Clean, high-performance web template tailored for developer tools, SaaS metrics, and responsive pricing grids.",
209
+ "price": 6200,
210
+ "compareAtPrice": 7500,
186
211
  "currency": "LKR",
187
212
  "imageUrl": "/placeholder.svg",
188
- "category": "Kitchen",
189
- "badge": "New",
213
+ "category": "Technology",
214
+ "badge": "Featured",
190
215
  "isAvailable": true
191
216
  },
192
217
  {
193
218
  "id": "prod-3",
194
- "name": "Botanical Room Spray",
195
- "description": "Natural essential oil room mist infused with wild lavender and cedarwood.",
196
- "price": 2800,
219
+ "name": "Zenith Artisan Portfolio",
220
+ "description": "Minimalist digital portfolio template featuring auto-balancing photo galleries, quote cards, and WhatsApp contact integration.",
221
+ "price": 3800,
197
222
  "compareAtPrice": null,
198
223
  "currency": "LKR",
199
224
  "imageUrl": "/placeholder.svg",
200
- "category": "Aromatherapy",
201
- "badge": null,
225
+ "category": "Portfolio",
226
+ "badge": "New",
202
227
  "isAvailable": true
203
228
  }
204
229
  ]
@@ -206,16 +231,16 @@
206
231
  "media": {},
207
232
  "seo": null,
208
233
  "siteInstance": {
209
- "id": "starter-demo-instance",
210
- "slug": "starter-demo",
211
- "domain": "starter-demo.fivora.site",
212
- "subdomain": "starter-demo",
234
+ "id": "deneb-portfolio-showcase-instance",
235
+ "slug": "deneb-portfolio-showcase",
236
+ "domain": "deneb-showcase.fivora.site",
237
+ "subdomain": "deneb-showcase",
213
238
  "customDomain": null,
214
- "liveUrl": "https://starter-demo.fivora.site"
239
+ "liveUrl": "https://deneb-showcase.fivora.site"
215
240
  },
216
241
  "api": {
217
242
  "baseUrl": "https://api.fivora.site",
218
- "catalogUrl": "https://api.fivora.site/site-catalog/starter-demo/live-data",
243
+ "catalogUrl": "https://api.fivora.site/site-catalog/deneb-portfolio-showcase/live-data",
219
244
  "contactUrl": "https://api.fivora.site/site-contact",
220
245
  "analyticsUrl": "https://api.fivora.site/site-analytics/page-view"
221
246
  }
@@ -2,6 +2,7 @@
2
2
 
3
3
  export {
4
4
  SiteDataProvider,
5
+ ThemeStyles,
5
6
  useSiteData,
6
7
  useProducts,
7
8
  useServices,
@@ -28,4 +29,5 @@ export type {
28
29
  SiteInstanceData,
29
30
  ProductItem,
30
31
  ServiceItem,
32
+ TemplateTheme,
31
33
  } from '@deneb-ui/ui';