The definitive visual-first UI component library, theme engine, and visual editing platform for modern Next.js storefronts on Fivora.
Docs Portal · Setup Fivora · Component Catalog · AI Master Guide · npm Packages
- About DENEB UI
- Core Packages
- Installation & Setup
- Core Architecture & Mandatory Files
- Visual Editing Engine (
data-preview-*) - Master Component Catalog (All 43 Components)
- Complete Storefront Implementation Examples
- CLI Tooling & Validation Workflow
- Local Development
- Authors & License
DENEB UI is an enterprise-grade, visual-first component ecosystem designed specifically for the Fivora commerce platform. It enables frontend developers and agencies to build stunning, lightning-fast static Next.js storefronts that seamlessly embed inside the Fivora Merchant Studio.
When a merchant views your storefront inside Fivora:
- They can click directly on headlines, paragraphs, banners, and product cards to edit copy and photos in real time.
- Fivora communicates bidirectional updates via a secure
postMessageprotocol. - The storefront renders instantly without server restarts using the
@deneb-ui/uistate engine. - Templates compile into 100% pure static HTML/JS/CSS bundles (
output: "export") deployable to any Jamstack CDN.
| Package | Purpose | Version |
|---|---|---|
@deneb-ui/ui |
43 production commerce components, state providers, and hooks | latest |
@deneb-ui/core |
CSS token injection, variable resolver, theme presets, schemas | latest |
@deneb-ui/cli |
Local visual preview simulator (lab), preflight validator (validate), zip packaging |
latest |
Install the core packages and peer dependencies in your Next.js App Router project:
npm install @deneb-ui/ui @deneb-ui/core lucide-react
npm install -D @deneb-ui/cli tailwindcss postcss autoprefixer typescriptOr using Yarn / PNPM / Bun:
# Yarn
yarn add @deneb-ui/ui @deneb-ui/core lucide-react
yarn add -D @deneb-ui/cli tailwindcss postcss autoprefixer typescript
# PNPM
pnpm add @deneb-ui/ui @deneb-ui/core lucide-react
pnpm add -D @deneb-ui/cli tailwindcss postcss autoprefixer typescript
# Bun
bun add @deneb-ui/ui @deneb-ui/core lucide-react
bun add -d @deneb-ui/cli tailwindcss postcss autoprefixer typescriptEnsure Tailwind scans both your application files and the @deneb-ui/ui package node_modules:
import type { Config } from "tailwindcss";
const config: Config = {
content: [
"./src/pages/**/*.{js,ts,jsx,tsx,mdx}",
"./src/components/**/*.{js,ts,jsx,tsx,mdx}",
"./src/app/**/*.{js,ts,jsx,tsx,mdx}",
"./node_modules/@deneb-ui/ui/**/*.{js,ts,jsx,tsx}",
],
theme: {
extend: {
colors: {
primary: "var(--color-primary, #6366F1)",
background: "var(--color-background, #090D1A)",
},
},
},
plugins: [],
};
export default config;Every Fivora storefront template requires four core configuration files in addition to standard Next.js files:
{
"name": "fivora-storefront-template",
"version": "2.0.0",
"private": true,
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"lab": "deneb lab .",
"validate": "deneb validate .",
"validate-and-zip": "deneb validate-and-zip .",
"zip": "deneb zip ."
},
"dependencies": {
"@deneb-ui/ui": "latest",
"@deneb-ui/core": "latest",
"lucide-react": "^1.0.0",
"next": "^14.2.0",
"react": "^18.3.0",
"react-dom": "^18.3.0"
},
"devDependencies": {
"@deneb-ui/cli": "latest",
"tailwindcss": "^3.4.0",
"typescript": "^5.0.0"
}
}Fivora requires pure static export (output: "export") with unoptimized images and trailing slashes:
import type { NextConfig } from "next";
const nextConfig: NextConfig = {
output: "export",
trailingSlash: true,
images: {
unoptimized: true,
},
basePath: process.env.NEXT_PUBLIC_BASE_PATH || "",
assetPrefix: process.env.NEXT_PUBLIC_BASE_PATH || "",
};
export default nextConfig;The manifest defines the template metadata, visual editing mode, and customizable theme tokens:
{
"manifestVersion": 2,
"id": "template-artisan-boutique",
"name": "Artisan Boutique Storefront",
"version": "2.0.0",
"category": "retail",
"listingTier": "premium",
"author": "Your Studio Name",
"visualEditing": {
"contractVersion": 1,
"mode": "strict"
},
"themeSchema": {
"tokens": [
{ "key": "primaryColor", "type": "color", "label": "Primary Accent", "default": "#6366F1" },
{ "key": "backgroundColor", "type": "color", "label": "Background", "default": "#090D1A" },
{ "key": "fontFamily", "type": "font", "label": "Heading Font", "default": "Inter" }
],
"defaults": {
"primaryColor": "#6366F1",
"backgroundColor": "#090D1A"
}
},
"pages": [
{ "key": "home", "title": "Storefront", "route": "/" },
{ "key": "catalog", "title": "Products", "route": "/#products" }
]
}All dynamic business details, hero text, products, and contact info must be stored in src/data/site-data.json:
{
"project": { "id": "demo-store", "slug": "demo-store", "title": "Artisan Footwear" },
"shop": {
"name": "Artisan Footwear",
"tagline": "Handcrafted Daily Distinction",
"whatsapp": "+15550192834",
"phone": "+15550192834",
"email": "concierge@artisanfootwear.com",
"address": "452 Broadway Avenue, New York, NY"
},
"content": {
"hero": {
"badge": "Spring 2026",
"title": "Bespoke Footwear Engineered for Distinction",
"subtitle": "Handcrafted micro-batch leather shoes with active cushioning.",
"primaryCta": "Shop Collection",
"image": "https://images.unsplash.com/photo-1542291026-7eec264c27ff"
},
"products": [
{
"id": "vanta-runner",
"title": "Vanta Velocity Sneaker",
"price": 149.99,
"compareAtPrice": 189.99,
"currency": "$",
"category": "Running",
"image": "https://images.unsplash.com/photo-1542291026-7eec264c27ff",
"rating": 4.9,
"reviewsCount": 38,
"inStock": true,
"description": "Featherweight engineered mesh with adaptive dual-density foam."
}
],
"businessHours": [
{ "day": "Monday - Friday", "hours": "9:00 AM - 7:00 PM", "isOpen": true },
{ "day": "Saturday", "hours": "10:00 AM - 5:00 PM", "isOpen": true },
{ "day": "Sunday", "hours": "Closed", "isOpen": false }
]
},
"theme": {
"primary": "#6366F1",
"primaryGlow": "rgba(99, 102, 241, 0.4)",
"background": "#090D1A",
"cardBackground": "#0E1220",
"border": "#1E2438",
"text": "#F8FAFC",
"textMuted": "#94A3B8"
}
}Wrap the entire storefront inside <SiteDataProvider> and <CartProvider>:
import "./globals.css";
import { SiteDataProvider, ThemeStyles, ResponsiveBaseStyles, CartProvider } from "@deneb-ui/ui";
import initialSiteData from "@/data/site-data.json";
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="en" className="scroll-smooth">
<head>
<ThemeStyles theme={initialSiteData.theme} />
<ResponsiveBaseStyles />
</head>
<body className="bg-[#090D1A] text-slate-100 antialiased min-h-screen">
<SiteDataProvider initialSiteData={initialSiteData}>
<CartProvider>
{children}
</CartProvider>
</SiteDataProvider>
</body>
</html>
);
}The Fivora Merchant Studio automatically enables inline visual editing by inspecting elements tagged with data-preview-* attributes:
- Leaf Elements Only:
data-preview-field-pathanddata-preview-image-pathMUST only be attached to leaf visual tags:<h1>-<h6>,<p>,<span>,<a>,<button>,<img>.- NEVER place field markers on
<div>,<section>,<article>,<main>, or<ul>.
- Never Beneath Static Ancestors:
- Elements marked with
data-preview-staticdeclare their entire subtree non-editable. - NEVER place
data-preview-field-pathinside a container marked withdata-preview-static.
- Elements marked with
- Repeated Lists & Loops:
- List wrapper:
data-preview-list-path="home.products" - Iterated item container:
data-preview-item-path={home.products.${index}} - Leaf value inside item:
data-preview-field-path={home.products.${index}.title}
- List wrapper:
- Defensive Defaults:
- Always use nullish coalescing (
??) rather than||for text values:content?.hero?.title ?? "Fallback" - Always default arrays:
const products = content?.products ?? [];so testing probes never triggerCannot read properties of undefined (reading 'map').
- Always use nullish coalescing (
Every single component below is imported directly from @deneb-ui/ui:
Import: import { Button } from "@deneb-ui/ui";
Category: Core Primitives
Description: An interactive button primitive with celestial glows, glassmorphic variants, loading states, and visual editing support.
| Prop | Type | Default | Description |
|---|---|---|---|
variant |
`'default' | 'glow' | 'secondary' |
size |
`'sm' | 'md' | 'lg'` |
disabled |
boolean |
false |
Whether the button is interactable. |
onClick |
() => void |
- |
Click event handler. |
className |
string |
'' |
Additional Tailwind or CSS class names. |
import { Button } from "@deneb-ui/ui";
import { ArrowRight, ShoppingBag } from "lucide-react";
export function ActionButtons() {
return (
<div className="flex flex-wrap gap-4 items-center">
<Button variant="glow" size="lg" onClick={() => console.log('Order initiated')}>
<ShoppingBag className="w-5 h-5 mr-2" />
Order Now
</Button>
<Button variant="outline" size="lg">
Explore Catalog
<ArrowRight className="w-5 h-5 ml-2" />
</Button>
</div>
);
}Import: import { Card } from "@deneb-ui/ui";
Category: Core Primitives
Description: A versatile container card with obsidian glass styling, luminous borders, and structured content slots.
| Prop | Type | Default | Description |
|---|---|---|---|
variant |
`'default' | 'glass' | 'glow' |
padding |
`'sm' | 'md' | 'lg' |
hoverEffect |
boolean |
true |
Enable celestial border illumination on hover. |
className |
string |
'' |
Additional Tailwind utility classes. |
import { Card } from "@deneb-ui/ui";
import { Sparkles } from "lucide-react";
export function FeatureCard() {
return (
<Card variant="glass" padding="lg" hoverEffect className="space-y-4">
<div className="w-12 h-12 rounded-xl bg-indigo-500/10 border border-indigo-500/20 flex items-center justify-center text-indigo-400">
<Sparkles className="w-6 h-6" />
</div>
<h3 className="text-xl font-bold text-white">Mastercrafted Durability</h3>
<p className="text-sm text-slate-400 leading-relaxed">
Full-grain Italian calfskin with Goodyear-welted construction engineered for decades of wear.
</p>
</Card>
);
}Import: import { Badge } from "@deneb-ui/ui";
Category: Core Primitives
Description: Status indicator tags with celestial starlight glows, pulsing dots, and color tiers.
| Prop | Type | Default | Description |
|---|---|---|---|
variant |
`'default' | 'glow' | 'outline' |
size |
`'sm' | 'md'` | 'md' |
pulse |
boolean |
false |
Renders an animated glowing pulse dot. |
children |
React.ReactNode |
required |
Tag text or element content. |
import { Badge } from "@deneb-ui/ui";
export function ProductBadges() {
return (
<div className="flex items-center gap-2">
<Badge variant="glow" pulse>In Stock</Badge>
<Badge variant="warning">-25% OFF</Badge>
<Badge variant="outline">Handmade</Badge>
</div>
);
}Import: import { Typography } from "@deneb-ui/ui";
Category: Core Primitives
Description: Semantic text primitives (Heading, Paragraph, Text) connected directly to Fivora theme font tokens and visual click-to-edit markers.
| Prop | Type | Default | Description |
|---|---|---|---|
level |
`1 | 2 | 3 |
data-preview-field-path |
string |
- |
Click-to-edit path binding (e.g. 'home.title'). |
className |
string |
'' |
Tailwind styling classes. |
import { Heading, Paragraph, Text } from "@deneb-ui/ui";
export function SectionHeader({ title, subtitle }: { title?: string; subtitle?: string }) {
return (
<div className="text-center space-y-3">
<Text className="text-xs uppercase font-bold tracking-widest text-indigo-400">
Artisanal Heritage
</Text>
<Heading level={2} data-preview-field-path="home.catalogTitle" className="text-3xl font-extrabold text-white">
{title ?? "Bespoke Collection"}
</Heading>
<Paragraph data-preview-field-path="home.catalogSubtitle" className="text-sm text-slate-400 max-w-xl mx-auto">
{subtitle ?? "Each pair is individually numbered and conditioned before leaving our workshop."}
</Paragraph>
</div>
);
}Import: import { Dialog } from "@deneb-ui/ui";
Category: Core Primitives
Description: Accessible modal dialog with backdrop blur, keyboard ESC dismissal, sizing tiers, and live visual editing.
| Prop | Type | Default | Description |
|---|---|---|---|
isOpen |
boolean |
false |
Controls dialog visibility. |
onClose |
() => void |
required |
Callback when user closes dialog or clicks backdrop. |
title |
string |
'' |
Dialog header title. |
size |
`'sm' | 'md' | 'lg' |
import { Dialog, Button } from "@deneb-ui/ui";
import { useState } from "react";
export function SizeGuideModal() {
const [open, setOpen] = useState(false);
return (
<>
<Button variant="outline" size="sm" onClick={() => setOpen(true)}>
View Size Chart
</Button>
<Dialog isOpen={open} onClose={() => setOpen(false)} title="Footwear Sizing Guide" size="md">
<div className="space-y-4 text-sm text-slate-300">
<p>Our shoes fit true to European standards. If between sizes, choose the smaller size.</p>
<table className="w-full text-left text-xs border border-slate-800">
<thead><tr className="bg-slate-900"><th className="p-2">EU</th><th className="p-2">US</th><th className="p-2">CM</th></tr></thead>
<tbody>
<tr className="border-t border-slate-800"><td className="p-2">41</td><td className="p-2">8.0</td><td className="p-2">26.5</td></tr>
<tr className="border-t border-slate-800"><td className="p-2">42</td><td className="p-2">9.0</td><td className="p-2">27.0</td></tr>
<tr className="border-t border-slate-800"><td className="p-2">43</td><td className="p-2">10.0</td><td className="p-2">28.0</td></tr>
</tbody>
</table>
</div>
</Dialog>
</>
);
}Import: import { Grid } from "@deneb-ui/ui";
Category: Core Primitives
Description: Layout containers featuring auto-balancing columns, responsive device breakpoints, and flex alignment.
| Prop | Type | Default | Description |
|---|---|---|---|
cols |
`1 | 2 | 3 |
gap |
`'sm' | 'md' | 'lg'` |
children |
React.ReactNode |
required |
Grid child elements. |
import { Grid, Card } from "@deneb-ui/ui";
export function FeaturesSection() {
return (
<Grid cols={3} gap="lg" className="max-w-7xl mx-auto px-4 py-12">
<Card variant="glass" padding="md"><h4>Italian Leather</h4></Card>
<Card variant="glass" padding="md"><h4>Goodyear Welt</h4></Card>
<Card variant="glass" padding="md"><h4>Free Returns</h4></Card>
</Grid>
);
}Import: import { Image } from "@deneb-ui/ui";
Category: Core Primitives
Description: Responsive storefront image component supporting preset aspect ratios, border radii, zoom hover, and visual editing upload triggers.
| Prop | Type | Default | Description |
|---|---|---|---|
src |
string |
required |
Image source URL. |
alt |
string |
'' |
Accessibility alternative text. |
aspectRatio |
`'square' | '16/9' | '4/3' |
radius |
`'sm' | 'md' | 'lg' |
fieldPath |
string |
'' |
Visual click-to-edit path for image replacement. |
import { Image } from "@deneb-ui/ui";
export function ShowcaseImage({ url, path }: { url: string; path?: string }) {
return (
<Image
src={url ?? "https://images.unsplash.com/photo-1542291026-7eec264c27ff"}
alt="Hero Sneaker"
aspectRatio="16/9"
radius="xl"
fieldPath={path ?? "home.hero.image"}
className="shadow-2xl border border-slate-800"
/>
);
}Import: import { ContactActions } from "@deneb-ui/ui";
Category: Smart Commerce Actions
Description: Multi-channel instant commerce action bar providing 1-tap WhatsApp, phone call, email, and Google Maps routing.
| Prop | Type | Default | Description |
|---|---|---|---|
whatsapp |
string |
'' |
Target international WhatsApp number (digits only). |
phone |
string |
'' |
Telephone number for direct dialing. |
email |
string |
'' |
Inquiry recipient email address. |
address |
string |
'' |
Physical street address for map routing. |
variant |
`'compact' | 'expanded' | 'minimal'` |
orientation |
`'horizontal' | 'vertical'` | 'horizontal' |
import { ContactActions, useSiteData } from "@deneb-ui/ui";
export function StoreContactBar() {
const siteData = useSiteData();
const shop = siteData?.shop;
return (
<div className="p-6 rounded-2xl bg-[#0E1220] border border-slate-800 space-y-3">
<h3 className="text-lg font-bold text-white">Instant Concierge Support</h3>
<ContactActions
whatsapp={shop?.whatsapp}
phone={shop?.phone}
email={shop?.email}
address={shop?.address?.street}
variant="expanded"
orientation="horizontal"
/>
</div>
);
}Import: import { WhatsAppButton } from "@deneb-ui/ui";
Category: Smart Commerce Actions
Description: High-converting WhatsApp conversion launcher with pre-filled order or inquiry message templates.
| Prop | Type | Default | Description |
|---|---|---|---|
phoneNumber |
string |
required |
E.164 formatted telephone number without plus. |
message |
string |
'' |
Pre-filled WhatsApp message text. |
variant |
`'solid' | 'outline' | 'floating'` |
size |
`'sm' | 'md' | 'lg'` |
label |
string |
'Chat on WhatsApp' |
Action text. |
import { WhatsAppButton, useSiteData } from "@deneb-ui/ui";
export function InstantProductOrder({ title, price }: { title: string; price: number }) {
const siteData = useSiteData();
return (
<WhatsAppButton
phoneNumber={siteData?.shop?.whatsapp ?? "94771234567"}
message={`Hi! I would like to order the ${title} (Rs. ${price}). Is it currently available?`}
variant="solid"
size="lg"
label="Order via WhatsApp"
/>
);
}Import: import { PhoneButton } from "@deneb-ui/ui";
Category: Smart Commerce Actions
Description: One-tap telephone dialer with international number formatting.
| Prop | Type | Default | Description |
|---|---|---|---|
phoneNumber |
string |
required |
Telephone number to dial. |
label |
string |
'Call Now' |
Button label text. |
variant |
`'solid' | 'outline' | 'minimal'` |
import { PhoneButton } from "@deneb-ui/ui";
export function TelephoneSupport({ phone }: { phone: string }) {
return <PhoneButton phoneNumber={phone} label="Call Atelier: +94 11 234 5678" variant="outline" size="md" />;
}Import: import { EmailButton } from "@deneb-ui/ui";
Category: Smart Commerce Actions
Description: Pre-filled mailto trigger with automatic subject and body encoding.
| Prop | Type | Default | Description |
|---|---|---|---|
email |
string |
required |
Inquiry recipient email address. |
subject |
string |
'' |
Pre-filled email subject line. |
label |
string |
'Email Us' |
Button label text. |
import { EmailButton } from "@deneb-ui/ui";
export function EmailConcierge({ email }: { email: string }) {
return (
<EmailButton
email={email}
subject="Bespoke Order Inquiry - Artisan Store"
label="Send Email Inquiry"
variant="outline"
/>
);
}Import: import { FloatingContactWidget } from "@deneb-ui/ui";
Category: Smart Commerce Actions
Description: Corner-docked interactive drawer presenting WhatsApp, Call, and Email triggers with zero layout shift.
| Prop | Type | Default | Description |
|---|---|---|---|
whatsapp |
string |
'' |
WhatsApp contact number. |
phone |
string |
'' |
Direct phone number. |
email |
string |
'' |
Support email address. |
position |
`'bottom-right' | 'bottom-left'` | 'bottom-right' |
storeName |
string |
'Store Concierge' |
Title displayed on the widget popover. |
import { FloatingContactWidget, useSiteData } from "@deneb-ui/ui";
export function GlobalSupportWidget() {
const siteData = useSiteData();
return (
<FloatingContactWidget
whatsapp={siteData?.shop?.whatsapp}
phone={siteData?.shop?.phone}
email={siteData?.shop?.email}
position="bottom-right"
storeName={siteData?.shop?.name ?? "Artisan Footwear"}
/>
);
}Import: import { LocationCard } from "@deneb-ui/ui";
Category: Location & Navigation
Description: Flagship store address, city, hours, and direct directions button.
| Prop | Type | Default | Description |
|---|---|---|---|
title |
string |
'Flagship Store' |
Location name. |
address |
string |
required |
Street address. |
city |
string |
'' |
City or province name. |
googleMapsUrl |
string |
'' |
Direct Google Maps URL. |
hours |
string |
'' |
Operating hours summary. |
import { LocationCard } from "@deneb-ui/ui";
export function StoreAddressCard() {
return (
<LocationCard
title="Colombo Flagship Store"
address="42 Heritage Boulevard, Ward Place"
city="Colombo 07, Sri Lanka"
hours="Mon - Sat: 9:00 AM - 7:00 PM"
googleMapsUrl="https://maps.google.com/?q=Colombo"
/>
);
}Import: import { LocationLink } from "@deneb-ui/ui";
Category: Location & Navigation
Description: Smart directions link opening Google Maps or Apple Maps.
| Prop | Type | Default | Description |
|---|---|---|---|
address |
string |
required |
Target destination address. |
provider |
`'google' | 'apple'` | 'google' |
label |
string |
'Get Directions' |
Link text. |
import { LocationLink } from "@deneb-ui/ui";
export function MapDirectionsButton({ address }: { address: string }) {
return <LocationLink address={address} provider="google" label="Open Google Maps ↗" />;
}Import: import { MapEmbed } from "@deneb-ui/ui";
Category: Location & Navigation
Description: Responsive map iframe embed with rounded corners and zero layout shift.
| Prop | Type | Default | Description |
|---|---|---|---|
address |
string |
required |
Address string to center map. |
height |
`string | number` | '350px' |
zoom |
number |
15 |
Default map zoom level. |
aspectRatio |
string |
'16/9' |
Aspect ratio. |
import { MapEmbed } from "@deneb-ui/ui";
export function EmbeddedMapSection({ address }: { address: string }) {
return <MapEmbed address={address} height={350} zoom={15} aspectRatio="16/9" />;
}Import: import { Address } from "@deneb-ui/ui";
Category: Location & Navigation
Description: Local SEO Schema.org microdata address formatter.
| Prop | Type | Default | Description |
|---|---|---|---|
street |
string |
required |
Street name and number. |
city |
string |
required |
City or town. |
region |
string |
'' |
State or province. |
postalCode |
string |
'' |
Postal code. |
country |
string |
'' |
Country name. |
import { Address, useSiteData } from "@deneb-ui/ui";
export function StructuredAddress() {
const siteData = useSiteData();
const a = siteData?.shop?.address;
return (
<Address
street={a?.street ?? "42 Heritage Blvd"}
city={a?.city ?? "Colombo"}
region={a?.region ?? "Western Province"}
postalCode={a?.postalCode ?? "00700"}
country={a?.country ?? "Sri Lanka"}
/>
);
}Import: import { BusinessHours } from "@deneb-ui/ui";
Category: Social & Business
Description: Live open/closed timetable with real-time open status indicators.
| Prop | Type | Default | Description |
|---|---|---|---|
schedule |
Array<{ day: string; open: string; close: string }> |
[] |
Weekly operating schedule. |
showStatus |
boolean |
true |
Show live 'Open Now' or 'Closed' tag. |
variant |
`'card' | 'list' | 'compact'` |
import { BusinessHours, useSiteData } from "@deneb-ui/ui";
export function StoreHoursDisplay() {
const siteData = useSiteData();
return (
<BusinessHours
schedule={siteData?.content?.businessHours ?? [
{ day: "Monday - Friday", open: "09:00 AM", close: "07:00 PM" },
{ day: "Saturday", open: "10:00 AM", close: "05:00 PM" },
{ day: "Sunday", open: "Closed", close: "" }
]}
showStatus={true}
variant="card"
/>
);
}Import: import { SocialLinks } from "@deneb-ui/ui";
Category: Social & Business
Description: Branded social media network icons with customizable layouts.
| Prop | Type | Default | Description |
|---|---|---|---|
links |
Record<string, string> |
{} |
Object with platform URLs (instagram, facebook, etc.). |
variant |
`'icon' | 'pill' | 'colored'` |
size |
`'sm' | 'md' | 'lg'` |
import { SocialLinks } from "@deneb-ui/ui";
export function SocialRow() {
return (
<SocialLinks
links={{
instagram: "https://instagram.com/artisan",
facebook: "https://facebook.com/artisan",
tiktok: "https://tiktok.com/@artisan"
}}
variant="pill"
size="md"
/>
);
}Import: import { SocialButton } from "@deneb-ui/ui";
Category: Social & Business
Description: Single branded social channel follower trigger.
| Prop | Type | Default | Description |
|---|---|---|---|
platform |
`'instagram' | 'facebook' | 'tiktok' |
url |
string |
required |
Profile destination URL. |
label |
string |
'' |
Optional custom label. |
import { SocialButton } from "@deneb-ui/ui";
export function InstagramFollow() {
return <SocialButton platform="instagram" url="https://instagram.com/artisan" label="Follow on Instagram" />;
}Import: import { Hero } from "@deneb-ui/ui";
Category: Storefront Sections
Description: High-conversion storefront hero showcase supporting Split, Centered, and Minimal layouts.
| Prop | Type | Default | Description |
|---|---|---|---|
layout |
`'split' | 'centered' | 'minimal'` |
title |
string |
required |
Main headline text. |
description |
string |
'' |
Sub-headline description text. |
image |
string |
'' |
Featured image asset URL. |
badge |
string |
'' |
Top announcement pill kicker. |
primaryCta |
{ label: string; href: string } |
- |
Primary action button. |
secondaryCta |
{ label: string; href: string } |
- |
Secondary action button. |
import { Hero, useSiteData } from "@deneb-ui/ui";
export function MainHero() {
const siteData = useSiteData();
const hero = siteData?.content?.hero;
return (
<Hero
layout="split"
title={hero?.title ?? "Bespoke Footwear Engineered for Distinction"}
description={hero?.subtitle ?? "Micro-batch leather shoes crafted by fourth-generation artisans."}
badge={hero?.badge ?? "New Season 2026"}
image={hero?.image ?? "https://images.unsplash.com/photo-1542291026-7eec264c27ff"}
primaryCta={{ label: hero?.primaryCta ?? "Shop Collection", href: "#products" }}
secondaryCta={{ label: "Our Heritage", href: "#about" }}
/>
);
}Import: import { ProductCard } from "@deneb-ui/ui";
Category: Storefront Sections
Description: The primary commerce catalog card with pricing, compare-at discounts, star reviews, stock badges, and WhatsApp checkout.
| Prop | Type | Default | Description |
|---|---|---|---|
title |
string |
required |
Product name. |
price |
number |
required |
Current retail price. |
compareAtPrice |
number |
undefined |
Original price for strike-through discount. |
currency |
string |
'$' |
Currency symbol prefix. |
image |
string |
required |
Product photo URL. |
category |
string |
'' |
Category badge tag. |
whatsappNumber |
string |
'' |
WhatsApp merchant number for direct order. |
itemPath |
string |
'' |
Fivora visual editing marker (e.g. 'home.products.0'). |
import { ProductCard, useSiteData } from "@deneb-ui/ui";
export function ProductItemView({ product, index }: { product: any; index: number }) {
const siteData = useSiteData();
return (
<ProductCard
itemPath={`home.products.${index}`}
title={product.title}
price={product.price}
compareAtPrice={product.compareAtPrice}
currency={product.currency ?? "Rs."}
image={product.image}
category={product.category}
badge={product.badge}
whatsappNumber={siteData?.shop?.whatsapp}
/>
);
}Import: import { ProductDetail } from "@deneb-ui/ui";
Category: Storefront Sections
Description: Elite single product showcase with multi-angle gallery, live size & color selectors, direct WhatsApp order CTA, and Fivora visual editing synchronization.
| Prop | Type | Default | Description |
|---|---|---|---|
product |
ProductItem |
required |
Comprehensive product record. |
whatsappNumber |
string |
'' |
WhatsApp target number. |
showReviews |
boolean |
true |
Render customer review summary. |
import { ProductDetail, useSiteData } from "@deneb-ui/ui";
export function SingleProductDetail({ product }: { product: any }) {
const siteData = useSiteData();
return (
<main className="max-w-6xl mx-auto px-4 py-12">
<ProductDetail
product={product}
whatsappNumber={siteData?.shop?.whatsapp}
showReviews={true}
/>
</main>
);
}Import: import { ProductQuickView } from "@deneb-ui/ui";
Category: Storefront Sections
Description: Instant lightbox inspection modal for products with thumbnail switcher, quantity counter, and 1-click purchase.
| Prop | Type | Default | Description |
|---|---|---|---|
product |
ProductItem |
required |
Product data object. |
isOpen |
boolean |
false |
Modal open state. |
onClose |
() => void |
required |
Close callback. |
whatsappNumber |
string |
'' |
WhatsApp order number. |
import { ProductQuickView, useSiteData } from "@deneb-ui/ui";
import { useState } from "react";
export function QuickViewInspection({ product }: { product: any }) {
const [open, setOpen] = useState(false);
const siteData = useSiteData();
return (
<>
<button onClick={() => setOpen(true)} className="text-xs text-indigo-400 underline">
Quick View
</button>
<ProductQuickView
product={product}
isOpen={open}
onClose={() => setOpen(false)}
whatsappNumber={siteData?.shop?.whatsapp}
/>
</>
);
}Import: import { ProductGrid } from "@deneb-ui/ui";
Category: Storefront Sections
Description: Responsive commerce catalog grid with category filter tabs and configurable columns per device.
| Prop | Type | Default | Description |
|---|---|---|---|
cols |
`1 | 2 | 3 |
gap |
`'sm' | 'md' | 'lg'` |
children |
React.ReactNode |
required |
List of ProductCard components. |
import { ProductGrid, ProductCard, useProducts, useSiteData } from "@deneb-ui/ui";
export function StoreCatalog() {
const products = useProducts();
const siteData = useSiteData();
return (
<section id="products" data-preview-list-path="home.products">
<ProductGrid cols={3} gap="lg">
{products.map((p, idx) => (
<ProductCard
key={p.id || idx}
itemPath={`home.products.${idx}`}
title={p.title}
price={p.price}
compareAtPrice={p.compareAtPrice}
currency={p.currency ?? "$"}
image={p.image}
whatsappNumber={siteData?.shop?.whatsapp}
/>
))}
</ProductGrid>
</section>
);
}Import: import { CartDrawer } from "@deneb-ui/ui";
Category: Storefront Sections
Description: High-converting slide-over shopping cart drawer with quantity steppers, free shipping progress bar, and 1-click WhatsApp order dispatch.
| Prop | Type | Default | Description |
|---|---|---|---|
whatsappNumber |
string |
required |
WhatsApp number to send completed order to. |
storeName |
string |
'Store' |
Store title included in order message. |
freeShippingThreshold |
number |
0 |
Free shipping threshold amount. |
import { CartDrawer, useSiteData } from "@deneb-ui/ui";
export function StoreCartDrawer() {
const siteData = useSiteData();
return (
<CartDrawer
whatsappNumber={siteData?.shop?.whatsapp ?? "94771234567"}
storeName={siteData?.shop?.name ?? "Artisan Boutique"}
freeShippingThreshold={15000}
/>
);
}Import: import { FilterSidebar } from "@deneb-ui/ui";
Category: Storefront Sections
Description: Faceted catalog filtering sidebar with category chips, price range slider, and size swatches.
| Prop | Type | Default | Description |
|---|---|---|---|
categories |
string[] |
[] |
Available category options. |
priceRange |
[number, number] |
[0, 1000] |
Min and max price boundaries. |
onFilterChange |
(filters: any) => void |
required |
Filter change event callback. |
import { FilterSidebar } from "@deneb-ui/ui";
import { useState } from "react";
export function CatalogFilters({ onUpdate }: { onUpdate: (f: any) => void }) {
return (
<FilterSidebar
categories={["All", "Formal", "Lifestyle", "Sneakers", "Boots"]}
priceRange={[0, 50000]}
onFilterChange={onUpdate}
/>
);
}Import: import { CustomerReviews } from "@deneb-ui/ui";
Category: Storefront Sections
Description: Social proof review showcase with aggregate star score, verified buyer tags, and rating filters.
| Prop | Type | Default | Description |
|---|---|---|---|
averageRating |
number |
5.0 |
Overall star rating. |
totalReviews |
number |
0 |
Total customer count. |
reviews |
Array<ReviewItem> |
[] |
List of review testimonials. |
import { CustomerReviews } from "@deneb-ui/ui";
export function ReviewsSection() {
return (
<CustomerReviews
averageRating={4.9}
totalReviews={84}
reviews={[
{ id: "1", author: "Kamal D.", rating: 5, date: "3 days ago", comment: "The leather quality and packaging were incredible.", verified: true },
{ id: "2", author: "Nirosha F.", rating: 5, date: "1 week ago", comment: "Fast WhatsApp communication and perfect fit.", verified: true }
]}
/>
);
}Import: import { TrustBadges } from "@deneb-ui/ui";
Category: Storefront Sections
Description: Conversion-boosting security strip featuring Free Shipping, SSL Checkout, Warranty, and 30-Day Returns badges.
| Prop | Type | Default | Description |
|---|---|---|---|
layout |
`'row' | 'grid'` | 'row' |
badges |
Array<TrustBadgeItem> |
defaultBadges |
Custom badge definitions. |
import { TrustBadges } from "@deneb-ui/ui";
export function TrustSection() {
return (
<div className="max-w-7xl mx-auto px-4 py-8">
<TrustBadges layout="row" />
</div>
);
}Import: import { StickyMobileBar } from "@deneb-ui/ui";
Category: Storefront Sections
Description: Sticky bottom checkout and WhatsApp action bar for mobile devices, boosting mobile conversion rates.
| Prop | Type | Default | Description |
|---|---|---|---|
whatsappNumber |
string |
required |
WhatsApp order telephone. |
phone |
string |
'' |
Direct phone call option. |
primaryCtaText |
string |
'Order via WhatsApp' |
Action button label. |
import { StickyMobileBar, useSiteData } from "@deneb-ui/ui";
export function MobileActionBar() {
const siteData = useSiteData();
return (
<StickyMobileBar
whatsappNumber={siteData?.shop?.whatsapp}
phone={siteData?.shop?.phone}
primaryCtaText="Order on WhatsApp"
/>
);
}Import: import { ServiceCard } from "@deneb-ui/ui";
Category: Storefront Sections
Description: Service offering card with duration, pricing, and direct booking triggers.
| Prop | Type | Default | Description |
|---|---|---|---|
title |
string |
required |
Service title. |
price |
number |
required |
Starting price. |
duration |
string |
'' |
Service time duration. |
description |
string |
'' |
Service description. |
import { ServiceCard } from "@deneb-ui/ui";
export function RestorationService() {
return (
<ServiceCard
title="Leather Conditioning & Resole"
price={6500}
duration="48 Hours"
description="Deep hydration with Saphir Medaille d'Or creams and Goodyear heel replacement."
/>
);
}Import: import { PricingCard } from "@deneb-ui/ui";
Category: Storefront Sections
Description: Tier comparison card with feature checklists and popular glow styling.
| Prop | Type | Default | Description |
|---|---|---|---|
tier |
string |
required |
Package name. |
price |
`number | string` | required |
features |
string[] |
[] |
Checklist items. |
isPopular |
boolean |
false |
Highlight card. |
ctaText |
string |
'Choose Plan' |
Button text. |
import { PricingCard } from "@deneb-ui/ui";
export function VipClubCard() {
return (
<PricingCard
tier="Atelier Patron"
price="Rs. 20,000 / yr"
features={[
"Unlimited annual leather re-polishing",
"Priority access to bespoke releases",
"Free cedar shoe trees with every order"
]}
isPopular={true}
ctaText="Join Atelier Club"
/>
);
}Import: import { TestimonialCard } from "@deneb-ui/ui";
Category: Storefront Sections
Description: Customer review card with star ratings, quote body, and avatar.
| Prop | Type | Default | Description |
|---|---|---|---|
name |
string |
required |
Client name. |
role |
string |
'' |
Job title or city. |
content |
string |
required |
Testimonial text. |
rating |
number |
5 |
Star score. |
avatar |
string |
'' |
Profile picture URL. |
import { TestimonialCard } from "@deneb-ui/ui";
export function ClientQuote() {
return (
<TestimonialCard
name="Malik Perera"
role="Architect, Colombo"
content="The craftsmanship on these Oxfords rivals anything from Northampton at a fraction of the cost."
rating={5}
avatar="https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d"
/>
);
}Import: import { FAQAccordion } from "@deneb-ui/ui";
Category: Storefront Sections
Description: Expandable FAQ accordion with smooth animations and accessibility.
| Prop | Type | Default | Description |
|---|---|---|---|
items |
Array<{ question: string; answer: string }> |
[] |
Questions and answers. |
allowMultiple |
boolean |
false |
Allow multiple open items. |
import { FAQAccordion } from "@deneb-ui/ui";
export function StoreFAQ() {
return (
<FAQAccordion
items={[
{ question: "How do I care for full-grain leather?", answer: "Apply wax-based shoe cream monthly and store with cedar shoe trees." },
{ question: "What is your delivery timeframe?", answer: "Colombo orders deliver next business day; islandwide delivers in 2-3 days." }
]}
/>
);
}Import: import { AnnouncementBar } from "@deneb-ui/ui";
Category: Storefront Sections
Description: Dismissible header announcement ticker with CTA links.
| Prop | Type | Default | Description |
|---|---|---|---|
message |
string |
required |
Announcement text. |
linkText |
string |
'' |
CTA link label. |
href |
string |
'' |
CTA destination URL. |
dismissible |
boolean |
true |
Show close button. |
import { AnnouncementBar } from "@deneb-ui/ui";
export function HeaderAnnouncement() {
return (
<AnnouncementBar
message="Free islandwide express delivery on orders over Rs. 15,000"
linkText="Shop Collection"
href="#products"
dismissible={true}
/>
);
}Import: import { CategoryPills } from "@deneb-ui/ui";
Category: Storefront Sections
Description: Horizontal catalog filter pills for instant category switching.
| Prop | Type | Default | Description |
|---|---|---|---|
categories |
string[] |
[] |
Category names. |
activeCategory |
string |
'All' |
Selected category. |
onSelect |
(category: string) => void |
required |
Selection callback. |
import { CategoryPills } from "@deneb-ui/ui";
import { useState } from "react";
export function CategoryBar() {
const [active, setActive] = useState("All");
return (
<CategoryPills
categories={["All", "Formal", "Loafers", "Boots", "Sneakers"]}
activeCategory={active}
onSelect={setActive}
/>
);
}Import: import { ContactForm } from "@deneb-ui/ui";
Category: Storefront Sections
Description: Direct customer inquiry form with input validation and zero SMTP config.
| Prop | Type | Default | Description |
|---|---|---|---|
recipientEmail |
string |
'' |
Destination email. |
whatsappFallback |
string |
'' |
WhatsApp fallback number. |
submitLabel |
string |
'Send Message' |
Submit button text. |
import { ContactForm, useSiteData } from "@deneb-ui/ui";
export function SupportForm() {
const siteData = useSiteData();
return (
<ContactForm
recipientEmail={siteData?.shop?.email}
whatsappFallback={siteData?.shop?.whatsapp}
submitLabel="Send Message to Artisan"
/>
);
}Import: import { Navbar } from "@deneb-ui/ui";
Category: Storefront Sections
Description: Top header navigation bar with brand name, navigation links, and mobile drawer menu.
| Prop | Type | Default | Description |
|---|---|---|---|
brandName |
string |
required |
Brand or store title. |
links |
Array<{ label: string; href: string }> |
[] |
Navigation menu items. |
logoUrl |
string |
'' |
Brand logo asset URL. |
import { Navbar, useSiteData } from "@deneb-ui/ui";
export function HeaderNav() {
const siteData = useSiteData();
return (
<Navbar
brandName={siteData?.shop?.name ?? "Artisan Boutique"}
links={[
{ label: "Home", href: "/" },
{ label: "Collection", href: "#products" },
{ label: "Reviews", href: "#reviews" },
{ label: "Contact", href: "#contact" }
]}
/>
);
}Import: import { Footer } from "@deneb-ui/ui";
Category: Storefront Sections
Description: Multi-column footer with quick navigation links, store summary, and copyright notice.
| Prop | Type | Default | Description |
|---|---|---|---|
brandName |
string |
required |
Brand name. |
copyright |
string |
'' |
Copyright notice text. |
import { Footer, useSiteData } from "@deneb-ui/ui";
export function SiteFooter() {
const siteData = useSiteData();
return (
<Footer
brandName={siteData?.shop?.name ?? "Artisan Boutique"}
copyright={`(c) ${new Date().getFullYear()} ${siteData?.shop?.name ?? "Artisan Boutique"}. All rights reserved.`}
/>
);
}Import: import { SiteDataProvider } from "@deneb-ui/ui";
Category: Data & Theme Engine
Description: Central headless state provider managing siteData, products, cart, and postMessage visual click-to-edit synchronization.
| Prop | Type | Default | Description |
|---|---|---|---|
initialSiteData |
SiteData |
required |
Initial JSON seed data loaded from src/data/site-data.json. |
children |
React.ReactNode |
required |
App component tree. |
import { SiteDataProvider, CartProvider } from "@deneb-ui/ui";
import initialSiteData from "@/data/site-data.json";
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="en">
<body>
<SiteDataProvider initialSiteData={initialSiteData}>
<CartProvider>
{children}
</CartProvider>
</SiteDataProvider>
</body>
</html>
);
}Import: import { ThemeStyles } from "@deneb-ui/ui";
Category: Data & Theme Engine
Description: Dynamic CSS variable injector resolving primary accents, backgrounds, glows, and typography tokens.
| Prop | Type | Default | Description |
|---|---|---|---|
theme |
ThemeTokens |
required |
Theme configuration object. |
import { ThemeStyles } from "@deneb-ui/ui";
import initialSiteData from "@/data/site-data.json";
export function ThemeInjector() {
return <ThemeStyles theme={initialSiteData.theme} />;
}DENEB UI provides headless reactive data hooks to cleanly access live storefront data, products, services, and backend endpoints without manual fetch() boilerplates.
Import: import { useProducts } from "@deneb-ui/ui";
Category: Data & Commerce Hooks
Description: React hook to retrieve products cleanly from siteData. Automatically resolves top-level content.products, nested home.products, live backend rehydration updates from api.catalogUrl, and instant parent editor postMessage updates.
function useProducts(fallback?: ProductItem[]): ProductItem[]import { useProducts, ProductGrid } from "@deneb-ui/ui";
export function StoreCatalog() {
const products = useProducts();
return (
<ProductGrid
title="Featured Collection"
subtitle="Handpicked Styles"
products={products}
categories={["All", "Shoes", "Apparel"]}
cardVariant="modern-glass"
columns={{ mobile: 1, tablet: 2, desktop: 3 }}
/>
);
}Import: import { useSiteApi } from "@deneb-ui/ui";
Category: Data & Commerce Hooks
Description: Hook to access official Fivora backend API endpoints configured in site-data.json (baseUrl, catalogUrl, contactUrl, analyticsUrl).
function useSiteApi(): SiteDataApiConfig | nullimport { useSiteApi } from "@deneb-ui/ui";
export function ApiDemo() {
const api = useSiteApi();
// api?.baseUrl -> "https://api.fivora.site"
// api?.catalogUrl -> "https://api.fivora.site/site-catalog/:slug/live-data"
// api?.contactUrl -> "https://api.fivora.site/site-contact"
// api?.analyticsUrl -> "https://api.fivora.site/site-analytics/page-view"
return null;
}Import: import { useSiteCatalog } from "@deneb-ui/ui";
Category: Data & Commerce Hooks
Description: Comprehensive hook returning { products, services, project, siteInstance, api } in a single call with live rehydration.
function useSiteCatalog(): {
products: ProductItem[];
services: ServiceItem[];
project: SiteDataProject | null;
siteInstance: SiteInstanceData | null;
api: SiteDataApiConfig | null;
}import { useSiteCatalog } from "@deneb-ui/ui";
export function StoreOverview() {
const { products, services, project, siteInstance, api } = useSiteCatalog();
return (
<div>
<h3>{project?.title}</h3>
<p>Total Products: {products.length}</p>
<p>Total Services: {services.length}</p>
</div>
);
}Import: import { useServices } from "@deneb-ui/ui";
Category: Data & Commerce Hooks
Description: React hook to retrieve services from content.services or content.home.services with live rehydration support.
function useServices(fallback?: ServiceItem[]): ServiceItem[]import { useServices, ServiceCard } from "@deneb-ui/ui";
export function ServicesList() {
const services = useServices();
return (
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
{services.map((service, index) => (
<ServiceCard
key={service.id || index}
itemPath={`services[${index}]`}
service={service}
/>
))}
</div>
);
}Import: import { useSiteData } from "@deneb-ui/ui";
Category: Data & Commerce Hooks
Description: Access the entire live siteData tree (content, common navigation, shop info, requirements, and media).
function useSiteData(): SiteDataImport: import { GoogleFeedback } from "@deneb-ui/ui";
Category: Storefront Sections
Description: Official Google Customer Review card section with verified platform badge, aggregate rating pill, live 1–5 star DOM synchronization, and responsive review cards.
| Prop | Type | Default | Description |
|---|---|---|---|
basePath |
string |
'feedback' |
JSON schema root key in site-data.json for Fivora visual editing. |
badgeIcon |
string |
Google "G" SVG |
URL or SVG data URI for the review platform badge. |
badgeTitle |
string |
'Google' |
Review platform name shown alongside the badge icon. |
badgeRating |
`string | number` | '4.9' |
badgeReviewsCount |
`string | number` | '128 reviews' |
heading |
string |
required |
Section primary headline. |
subheading |
string |
'' |
Section introductory description paragraph. |
feedbacks |
FeedbackItem[] |
[] |
Array of customer review items with name, avatar, rating (1-5), and comment. |
maxStars |
number |
5 |
Maximum rating star count. |
className |
string |
'' |
Custom CSS / Tailwind classes for section container. |
cardClassName |
string |
'' |
Custom CSS / Tailwind classes for individual review cards. |
import { GoogleFeedback, useSiteData } from "@deneb-ui/ui";
export function ReviewsSection() {
const siteData = useSiteData();
const feedback = siteData?.feedback ?? {};
return (
<GoogleFeedback
basePath="feedback"
badgeIcon={feedback.badgeIcon}
badgeTitle={feedback.badgeTitle}
badgeRating={feedback.badgeRating}
badgeReviewsCount={feedback.badgeReviewsCount}
heading={feedback.heading ?? "Loved by Coffee Lovers Worldwide"}
subheading={feedback.subheading ?? "Real reviews verified on Google."}
feedbacks={feedback.feedbacks ?? []}
/>
);
}Import: import { TestimonialSection } from "@deneb-ui/ui";
Category: Storefront Sections
Description: Editorial critic and connoisseur review showcase featuring large quotation typography, author credentials, accreditation tags, and synchronized star ratings.
| Prop | Type | Default | Description |
|---|---|---|---|
basePath |
string |
'testimonials' |
Root key in site-data.json for Fivora visual editing. |
badge |
string |
'Critic Acclaim' |
Uppercase pill badge text displayed above heading. |
heading |
string |
required |
Main section title. |
subheading |
string |
'' |
Subheading description text. |
testimonials |
TestimonialSectionItem[] |
[] |
Array of critic reviews containing quote, author, role, avatar, tag, and rating. |
maxStars |
number |
5 |
Maximum star rating per testimonial. |
className |
string |
'' |
CSS / Tailwind classes for section wrapper. |
cardClassName |
string |
'' |
CSS / Tailwind classes for testimonial cards. |
import { TestimonialSection, useSiteData } from "@deneb-ui/ui";
export function ConnoisseurReviews() {
const siteData = useSiteData();
const testimonials = siteData?.testimonials ?? {};
return (
<TestimonialSection
basePath="testimonials"
badge={testimonials.badge ?? "Critic Acclaim"}
heading={testimonials.heading ?? "What Connoisseurs Say"}
subheading={testimonials.subheading ?? "Unfiltered sensory impressions and reviews."}
testimonials={testimonials.testimonials ?? []}
/>
);
}Import: import { Map } from "@deneb-ui/ui";
Category: Location & Navigation
Description: Universal Google Maps responsive iframe embed with intelligent URL parsing for full iframe snippets, @lat,lng coordinates, place URLs, short links, and search queries.
| Prop | Type | Default | Description |
|---|---|---|---|
mapUrl |
string |
'' |
Google Maps URL, share link, coordinate URL (@lat,lng), place URL, or full <iframe> embed tag. |
address |
string |
'Sri Lanka' |
Physical address fallback query string when mapUrl is empty or unparseable. |
defaultLocation |
string |
'' |
Secondary location fallback query string. |
data-preview-field-path |
string |
'' |
Fivora visual editing binding annotation. |
className |
string |
'w-full h-full border-0' |
CSS / Tailwind styling for iframe. |
title |
string |
'Google Map Location' |
Accessibility title attribute for the iframe. |
import { Map, useSiteData } from "@deneb-ui/ui";
export function StoreMap() {
const siteData = useSiteData();
return (
<div className="w-full h-[400px] rounded-2xl overflow-hidden shadow-xl">
<Map
data-preview-field-path="contact.mapUrl"
mapUrl={siteData?.contact?.mapUrl}
address={siteData?.shop?.address}
/>
</div>
);
}Here is a complete, production-ready storefront combining all essential DENEB UI commerce modules:
"use client";
import {
useSiteData,
useProducts,
Navbar,
Footer,
Hero,
ProductGrid,
ProductCard,
CartDrawer,
FilterSidebar,
CustomerReviews,
TrustBadges,
StickyMobileBar,
BusinessHours,
ContactActions,
AnnouncementBar
} from "@deneb-ui/ui";
import { useState } from "react";
export default function HomePage() {
const siteData = useSiteData();
const products = useProducts();
const content = siteData?.content ?? {};
const [activeCategory, setActiveCategory] = useState("All");
const filteredProducts = activeCategory === "All"
? products
: products.filter(p => p.category === activeCategory);
return (
<div className="flex flex-col min-h-screen">
{/* Top Announcement */}
<AnnouncementBar
message="Free express delivery on all orders over $100"
linkText="Shop Now"
href="#products"
/>
{/* Header Navigation */}
<Navbar
brandName={siteData?.shop?.name ?? "Artisan Store"}
links={[
{ label: "Home", href: "/" },
{ label: "Products", href: "#products" },
{ label: "Reviews", href: "#reviews" },
{ label: "Contact", href: "#contact" }
]}
/>
{/* Hero Showcase */}
<Hero
layout="split"
title={content?.hero?.title ?? "Bespoke Footwear Engineered for Distinction"}
description={content?.hero?.subtitle ?? "Handcrafted micro-batch leather shoes."}
image={content?.hero?.image ?? "https://images.unsplash.com/photo-1542291026-7eec264c27ff"}
/>
{/* Trust & Guarantee Strip */}
<div className="max-w-7xl mx-auto px-4 py-8 w-full">
<TrustBadges />
</div>
{/* Commerce Catalog with Filter Sidebar */}
<section id="products" className="max-w-7xl mx-auto px-4 py-16 w-full space-y-8">
<div className="text-center space-y-3">
<h2 className="text-3xl font-bold text-white tracking-tight">Curated Collection</h2>
<p className="text-sm text-slate-400">Discover handpicked styles designed to last.</p>
</div>
<div className="grid grid-cols-1 lg:grid-cols-4 gap-8 items-start">
<FilterSidebar
categories={["All", "Running", "Lifestyle", "Formal"]}
onFilterChange={(f) => setActiveCategory(f.selectedCategories[0] || "All")}
/>
<div className="lg:col-span-3">
<ProductGrid cols={3} gap="lg">
{filteredProducts.map((product, idx) => (
<ProductCard
key={product.id || idx}
title={product.title}
price={product.price}
compareAtPrice={product.compareAtPrice}
currency={product.currency ?? "$"}
image={product.image}
whatsappNumber={siteData?.shop?.whatsapp}
/>
))}
</ProductGrid>
</div>
</div>
</section>
{/* Reviews & Social Proof */}
<section id="reviews" className="bg-[#0C0F1A] py-16 border-y border-slate-800/60">
<div className="max-w-7xl mx-auto px-4">
<CustomerReviews />
</div>
</section>
{/* Business Hours & Support */}
<section id="contact" className="max-w-7xl mx-auto px-4 py-16 w-full grid grid-cols-1 md:grid-cols-2 gap-8">
<BusinessHours schedule={content?.businessHours} />
<div className="p-8 rounded-2xl border border-slate-800 bg-[#0E1220] flex flex-col justify-center space-y-4">
<h3 className="text-xl font-bold text-white">Instant Concierge Support</h3>
<p className="text-sm text-slate-400">Order directly with our personal shoppers via WhatsApp or phone.</p>
<ContactActions
whatsapp={siteData?.shop?.whatsapp}
phone={siteData?.shop?.phone}
email={siteData?.shop?.email}
/>
</div>
</section>
{/* Cart Drawer */}
<CartDrawer
whatsappNumber={siteData?.shop?.whatsapp ?? "15550192834"}
storeName={siteData?.shop?.name ?? "Artisan Store"}
/>
{/* Sticky Mobile Bar */}
<StickyMobileBar
whatsappNumber={siteData?.shop?.whatsapp}
phone={siteData?.shop?.phone}
/>
{/* Footer */}
<Footer
brandName={siteData?.shop?.name ?? "Artisan Store"}
copyright="(c) 2026 Artisan Store. All rights reserved."
/>
</div>
);
}import initialSiteData from "@/data/site-data.json";
import { ProductDetail } from "@deneb-ui/ui";
// REQUIRED FOR NEXT.JS STATIC EXPORT:
export function generateStaticParams() {
const products = initialSiteData.content?.products || [];
return products.map((p) => ({ id: p.id }));
}
export default async function ProductPage({
params,
}: {
params: Promise<{ id: string }>;
}) {
const { id } = await params;
const products = initialSiteData.content?.products || [];
const product = products.find((p) => p.id === id) || products[0];
return (
<main className="max-w-6xl mx-auto px-4 py-12">
<ProductDetail product={product} />
</main>
);
}The @deneb-ui/cli binary provides local testing and strict preflight certification:
Simulate the Fivora Merchant Studio iframe canvas in your browser on port 4300:
npx @deneb-ui/cli lab .Validates your template against the strict Fivora static and visual editing schema:
npx @deneb-ui/cli validate .Checks performed:
fivora-template.jsonstructure, tokens, and page routes.next.config.tsstatic export configuration (output: "export").data-preview-*annotations (no block-level placements, no markers under static ancestors).- Zero prohibited server-only APIs (
cookies(),headers(), dynamic API routes).
Runs preflight validation and compiles a clean fivora-template.zip archive ready for upload:
npx @deneb-ui/cli validate-and-zip .To run the DENEB UI documentation site locally:
npm install
npm run dev # Starts local docs portal on http://localhost:3000
npm run sync:core # Sync components from ../core/packages/deneb-ui
npm run build # Production standalone buildMIT License © DENEB UI & Fivora. Built for modern commerce.