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 |
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 |
To scaffold a production-ready, fully compliant DENEB storefront template in seconds with interactive theme selection (Dual-Mode, Pure Light, Obsidian Dark, etc.):
# Interactive template creation
npx create-deneb my-store
# Or using the scoped package
npx @deneb-ui/create-template my-store
# Or specify theme flag directly
npx create-deneb my-store --theme=dualThis automatically configures:
- Next.js 15 App Router + Static Export (
output: "export") - Dynamic Theming Engine (
<ThemeStyles />+ Zero-FOUC) - Dual-Mode Ready (
<ThemeToggle />pre-installed with Sun/Moon switch) - Strict Fivora Manifest v2 contract
- 28+ Visual-First editable components pre-configured
If adding DENEB UI to an existing 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, CartProvider, THEME_PRESETS } from "@deneb-ui/ui";
import initialSiteData from "@/data/site-data.json";
export default function RootLayout({ children }: { children: React.ReactNode }) {
const activeTheme = initialSiteData.theme || THEME_PRESETS.luxury;
return (
<html lang="en" className="scroll-smooth">
<head>
{/* Injects CSS variables and responsive base rules before page paint */}
<ThemeStyles theme={activeTheme} />
</head>
<body className="bg-[var(--page-background)] text-[var(--page-text)] antialiased min-h-screen">
<SiteDataProvider initialData={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 (
Storefronts built with DENEB UI synchronize automatically in real-time with changes made in the Fivora Merchant Portal. When a store owner changes their store name, WhatsApp number, phone number, email address, physical location, Google Maps directions link, operating schedule, or reviews, the live storefront updates instantly without requiring manual site re-exports or code rebuilds!
Contact and location components automatically self-hydrate from the live merchant profile when props are omitted:
<WhatsAppButton />automatically connects to the merchant's live registered WhatsApp number with international click-to-chat routing.<PhoneButton />automatically triggers 1-tap phone dialing (tel:) to the merchant's live primary business phone.<EmailButton />automatically opens an inquiry mailto directed to the live registered business email.<ContactActions />dynamically displays buttons for whichever channels (WhatsApp, Phone, Email, Maps) the merchant has active.<LocationCard />automatically renders the store's physical street address, city, district, postal code, and clickable Google Maps directions link.<MapLink />/<MapEmbed />automatically center and link to the store's live Google Maps location.<BusinessHours />automatically calculates weekly hours with an active Open Now / Closed live status indicator based on visitor local time.<CustomerReviews />/<GoogleFeedback />/<TestimonialSection />automatically display verified customer reviews and Google feedback.
Direct programmatic access to live store details:
import { useShop } from "@deneb-ui/ui";
export function HeaderStoreInfo() {
const shop = useShop();
// shop.name, shop.whatsapp, shop.phone, shop.email, shop.address, shop.city, shop.mapLocation, shop.openingHours
return (
<div className="flex items-center gap-4 text-sm text-slate-300">
<span>{shop?.name}</span>
{shop?.whatsapp && <a href={`https://wa.me/${shop.whatsapp}`}>WhatsApp Us</a>}
{shop?.address && <span>{shop.address}, {shop.city}</span>}
</div>
);
}Direct access to verified customer reviews and Google feedback:
import { useReviews } from "@deneb-ui/ui";
export function SocialProofCounter() {
const reviews = useReviews();
return <span>Rated by {reviews.length} verified customers</span>;
}DENEB UI organizes storefronts into modular semantic sections. In the Fivora Merchant Studio and Website Agent portal, store owners can visually reorder, center, and delete sections without touching code:
- 1-Click Section Reordering (Move Up / Move Down): Move any section higher or lower on the page (e.g. moving the Contact section below Products and Services, or elevating Services above Featured Products).
- 1-Click Centering: Align headings, body copy, and CTA buttons to center or left.
- 1-Click Hiding / Deletion: Toggle off sections (e.g. hiding Testimonials or FAQ).
To enable non-destructive reordering, the parent page wrapper MUST declare:
body > main, main, [data-preview-page-key] {
display: flex;
flex-direction: column;
}Sections are positioned via CSS order: <number> and --deneb-section-order. This ensures zero DOM mutations, eliminating React hydration mismatches and preserving Next.js static exports.
import { EditableSection } from "@deneb-ui/ui";
// Option A: Using <EditableSection>
export function ServicesSection() {
return (
<EditableSection sectionId="services" title="Our Services" className="py-16">
<div className="max-w-7xl mx-auto px-4">{/* Content */}</div>
</EditableSection>
);
}
// Option B: Semantic HTML5 <section>
export function ContactSection() {
return (
<section id="contact" data-design-section="contact" data-section-id="contact" className="py-16">
<div className="max-w-7xl mx-auto px-4">{/* Content */}</div>
</section>
);
}Fivora storefronts support both Single Fixed Price products and Dynamic Price Range products (for apparel with size/color options, customizable goods, and tiered products).
{
"products": [
{
"id": "prod-1",
"name": "Classic Leather Shoes",
"price": 3850,
"currency": "LKR"
},
{
"id": "prod-2",
"name": "Linen Resort Shirt",
"isPriceRange": true,
"minPrice": 2800,
"maxPrice": 4800,
"priceRange": "LKR 2,800 – LKR 4,800",
"currency": "LKR",
"colors": [
{ "name": "Navy", "hex": "#0f2942", "imageUrl": "/images/shirt-navy.jpg" },
{ "name": "Olive", "hex": "#4d6840", "imageUrl": "/images/shirt-olive.jpg" }
],
"sizes": ["S", "M", "L", "XL"]
}
]
}<ProductCard
itemPath={`content.products.${idx}`}
title={product.name ?? product.title}
price={product.price}
isPriceRange={product.isPriceRange}
minPrice={product.minPrice}
maxPrice={product.maxPrice}
priceRange={product.priceRange}
currency={product.currency ?? "LKR"}
image={product.imageUrl ?? product.image}
colors={product.colors}
sizes={product.sizes}
/>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. Automatically self-hydrates from live registered store WhatsApp number when phoneNumber or value is omitted.
| Prop | Type | Default | Description |
|---|---|---|---|
phoneNumber |
string |
auto-synced |
Optional. E.164 formatted telephone number. If omitted, automatically self-hydrates from useShop()?.whatsapp and live site data. |
value |
string |
auto-synced |
Alias for phoneNumber. |
message |
string |
'' |
Pre-filled WhatsApp message text. |
variant |
`'solid' | 'outline' | 'floating' |
size |
`'sm' | 'md' | 'lg'` |
label |
string |
'Chat on WhatsApp' |
Action text. |
import { WhatsAppButton } from "@deneb-ui/ui";
// Option A: Zero-config auto-hydration (uses live registered merchant WhatsApp)
export function QuickChat() {
return <WhatsAppButton label="Order via WhatsApp" />;
}
// Option B: Contextual product inquiry message
export function InstantProductOrder({ title, price }: { title: string; price: number }) {
return (
<WhatsAppButton
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. Automatically self-hydrates from live registered store phone when phoneNumber or value is omitted.
| Prop | Type | Default | Description |
|---|---|---|---|
phoneNumber |
string |
auto-synced |
Optional. Telephone number to dial. If omitted, automatically self-hydrates from useShop()?.phone and live site data. |
value |
string |
auto-synced |
Alias for phoneNumber. |
label |
string |
'Call Now' |
Button label text. |
variant |
`'solid' | 'outline' | 'minimal'` |
import { PhoneButton } from "@deneb-ui/ui";
// Zero-config: dials the live registered store telephone
export function SupportCall() {
return <PhoneButton label="Call Us Directly" 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. |
sectionPath |
string |
'product' |
Visual editing path prefix. |
sizes |
string[] |
footwear defaults | Fallback options when the product has no sizes/options. |
colors |
Array<{ name: string; hex: string }> |
default swatches | Color choices shown by the detail UI. |
onAddToSelection |
(product, size, color) => void |
undefined |
Primary action callback. |
whatsappUrl |
string |
generated from product data | Optional custom WhatsApp order URL. |
import { ProductDetail } from "@deneb-ui/ui";
export function SingleProductDetail({ product }: { product: any }) {
return (
<main className="max-w-6xl mx-auto px-4 py-12">
<ProductDetail
product={product}
sectionPath="product"
onAddToSelection={(item, size, color) =>
console.log("Selected", item, size, color)
}
/>
</main>
);
}ProductDetail is the visual component. PlatformProductDetail is the route
controller: it reads the product ID, resolves current live data, retries the
catalog API, and handles loading, errors, and missing products.
// src/app/products/detail/page.tsx
import { PlatformProductDetail } from "@deneb-ui/ui";
export default function ProductDetailPage() {
return <PlatformProductDetail />;
}For a custom template design, pass
renderProduct={(product, context) => <MyDetail product={product} index={context.productIndex} />}
or use the usePlatformProductDetail() hook directly. Build card links with
platformProductDetailHref(product.id).
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 { ProductShowcase, EditableProductShowcase } from "@deneb-ui/ui";
Category: Storefront Sections
Description: Complete flagship product showcase section with live-editable category filter pills, glassmorphism cards, interactive color swatches (data-preview-field-type="color"), compare-at strikethrough pricing, quick-view detail modal linking (/products/detail/?id=...), and direct WhatsApp order button.
- Backend Endpoints: Fully compatible with
ShopOwnerController&ShopOwnerServiceendpoints (GET /shop-owner/shops/:shopId/products,POST,PUT,PATCH .../availability,POST .../reorder). - Generated Site Routing: Follows
backend/src/common/generated-site-product-route.tsmapping (/products/detail/?id=...and/products/:id).
| Prop | Type | Default | Description |
|---|---|---|---|
sectionPath |
string |
'home' |
Field path prefix for Fivora visual editing synchronization. |
listPath |
string |
'featuredPhones' |
List property key within section (e.g., 'products'). |
badge |
string |
'' |
Section pill kicker / badge text. |
heading |
string |
'' |
Section main heading text. |
description |
string |
'' |
Section description copy. |
products |
ProductShowcaseItem[] |
undefined |
Array of products (falls back to siteData.content[sectionPath][listPath]). |
currency |
string |
'Rs' |
Currency prefix. |
shippingLabel |
string |
'Free Insured Courier' |
Free delivery or courier subtext badge. |
whatsappOrderLabel |
string |
'Order via WhatsApp' |
WhatsApp action button label. |
categories |
string[] |
['All', ...] |
Category filter options. |
onQuickView |
(product, index) => void |
undefined |
Callback invoked when user clicks quick view eye icon. |
productDetailRoutePrefix |
string |
'/products/detail' |
Product detail route prefix. |
import { ProductShowcase, useSiteData } from "@deneb-ui/ui";
export function FeaturedShowcase() {
const siteData = useSiteData();
const home = siteData?.content?.home;
return (
<ProductShowcase
sectionPath="home"
listPath="featuredPhones"
badge={home?.badge ?? "Direct Showroom & Verified Refurbished"}
heading={home?.heading ?? "Upgrade Your Everyday."}
description={home?.description ?? "Brand new flagships and laboratory-certified refurbished devices."}
currency="Rs"
shippingLabel="Free Insured Courier"
whatsappOrderLabel="Order via WhatsApp"
/>
);
}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, THEME_PRESETS, getCategoryTheme } from "@deneb-ui/ui";
Category: Data & Theme Engine
Description: Runtime CSS Custom Properties injector connecting Fivora Studio's Visual Editor and theme presets to storefronts. Generates semantic design tokens (--color-primary, --button-bg, --card-bg, --page-text), resolves WCAG-compliant high-contrast button typography, and automatically propagates real-time postMessage theme updates across components without page reloads.
| Prop | Type | Default | Description |
|---|---|---|---|
theme |
TemplateTheme | null |
required |
Theme configuration object containing brand colors, typography, dimensions, buttons, and custom camelCase tokens. |
defaultPrimary |
string |
"#2563eb" |
Fallback primary brand color if undefined in theme. |
defaultSecondary |
string |
"#0f172a" |
Fallback secondary brand color if undefined in theme. |
defaultAccent |
string |
"#14b8a6" |
Fallback highlight color if undefined in theme. |
defaultBg |
string |
"#ffffff" |
Fallback page background color if undefined in theme. |
defaultText |
string |
"#0f172a" |
Fallback body text color if undefined in theme. |
- Colors:
primaryColor,secondaryColor,accentColor,backgroundColor,textColor,headingColor,mutedTextColor,linkColor - Buttons:
buttonBackgroundColor,buttonTextColor(automatically WCAG AA/AAA contrast tuned if omitted) - Typography:
headingFont,bodyFont,baseSize - Dimensions:
borderRadius(e.g."8px"),heroMinHeight,sectionPadding,align - Custom Tokens: Any custom
camelCaseproperty (e.g.cardBg: "#111",badgeRadius: "9999px") is automatically converted to a CSS variable (--card-bg,--badge-radius).
DENEB UI ships with 10 built-in industry palettes:
"luxury" | "emeraldGold" | "tech" | "retail" | "restaurant" | "cyberpunk" | "minimalDark" | "nordicPastel" | "medical" | "corporate"
Extend any preset using getCategoryTheme(presetName, overrides):
import { getCategoryTheme } from "@deneb-ui/ui";
const customTheme = getCategoryTheme("restaurant", {
primaryColor: "#d97706",
borderRadius: "16px",
});// app/layout.tsx
import { ThemeStyles, SiteDataProvider, THEME_PRESETS } from "@deneb-ui/ui";
import initialSiteData from "@/data/site-data.json";
export default function RootLayout({ children }: { children: React.ReactNode }) {
const activeTheme = initialSiteData.theme || THEME_PRESETS.luxury;
return (
<html lang="en">
<head>
{/* Injects CSS variables into :root before page paint */}
<ThemeStyles theme={activeTheme} />
</head>
<body className="bg-[var(--page-background)] text-[var(--page-text)] antialiased">
{/* Listens to live Fivora Visual Editor updates without page reloads */}
<SiteDataProvider initialData={initialSiteData}>
{children}
</SiteDataProvider>
</body>
</html>
);
}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 { PlatformProductDetail } from "@deneb-ui/ui";
export default function ProductDetailPage() {
return <PlatformProductDetail />;
}Link products with platformProductDetailHref(product.id). Never use
/products/${product.id} in a static export because merchant-created products
do not have build-time HTML directories.
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.