for in-page actions like form submits.
// Premium calm: lime CTA stays the loudest element on the page, but the
// glow halo is dialed down (was 0.55 / 0.7) so it reads "solid premium"
// instead of "neon button". Min-h-[44px] guarantees a thumb-sized target
// even when we override padding for compact contexts (e.g. mobile sticky).
const ButtonPrimary = ({ children, className = "", href, ...rest }) => {
const Tag = href ? "a" : "button";
const tagProps = href ? { href } : rest;
return (
{children}
);
};
const ButtonGhost = ({ children, className = "", href, ...rest }) => {
const Tag = href ? "a" : "button";
const tagProps = href ? { href } : rest;
return (
{children}
);
};
// Tag / pill
const Pill = ({ children, className = "", dot = false, tone = "default" }) => {
const tones = {
default: "border-white/10 bg-white/[0.03] text-ink-200",
lime: "border-lime/30 bg-lime/[0.08] text-lime",
soft: "border-white/8 bg-black/20 text-ink-300",
};
return (
{dot && }
{children}
);
};
// Card – core glass surface
const Card = ({ children, className = "", ...rest }) => (
{children}
);
// Scroll-reveal fade-up wrapper using IntersectionObserver
const Reveal = ({ children, delay = 0, className = "", as: As = "div" }) => {
const ref = React.useRef(null);
const [shown, setShown] = React.useState(false);
React.useEffect(() => {
const el = ref.current;
if (!el) return;
const io = new IntersectionObserver(
(entries) => {
entries.forEach((e) => {
if (e.isIntersecting) {
setShown(true);
io.disconnect();
}
});
},
{ threshold: 0.12, rootMargin: "0px 0px -60px 0px" }
);
io.observe(el);
return () => io.disconnect();
}, []);
return (
{children}
);
};
// Dashed divider
const Divider = ({ className = "" }) => (
);
// Subtle "system" badge — used to brand the product as an OS
const SystemBadge = ({ children, className = "" }) => (
{children}
);
// Stat counter that animates from 0 -> value when visible
function useCountUp(target, duration = 1400) {
const ref = React.useRef(null);
const [v, setV] = React.useState(0);
React.useEffect(() => {
const el = ref.current;
if (!el) return;
let started = false;
const io = new IntersectionObserver(
(entries) => {
entries.forEach((e) => {
if (e.isIntersecting && !started) {
started = true;
const start = performance.now();
const animate = (now) => {
const t = Math.min(1, (now - start) / duration);
const eased = 1 - Math.pow(1 - t, 3);
setV(target * eased);
if (t < 1) requestAnimationFrame(animate);
};
requestAnimationFrame(animate);
io.disconnect();
}
});
},
{ threshold: 0.4 }
);
io.observe(el);
return () => io.disconnect();
}, [target]);
return [ref, v];
}
const CountUp = ({ to, format = (v) => Math.round(v).toLocaleString("mk-MK"), className = "" }) => {
const [ref, v] = useCountUp(to);
return (
{format(v)}
);
};
Object.assign(window, {
cn,
Container,
Section,
Eyebrow,
SectionTitle,
SectionLead,
ButtonPrimary,
ButtonGhost,
Pill,
Card,
Reveal,
Divider,
SystemBadge,
CountUp,
});
// ================== hero.jsx ==================
// HERO — left: editorial headline; right: looping product narrative
// (Vehicle → 4 platforms → Published → Lead notification)
const { motion: M, AnimatePresence: AP } = window.framerMotion;
// ---------- Animated product panel ----------
const PLATFORMS = [
{ key: "fb", label: "Facebook Marketplace", Logo: PlatformFB, time: 0.9 },
{ key: "ig", label: "Instagram", Logo: PlatformIG, time: 1.4 },
{ key: "r5", label: "Реклама5", Logo: PlatformR5, time: 1.9 },
{ key: "p3", label: "Pazar3", Logo: PlatformP3, time: 2.4 },
];
function useHeroCycle() {
// step: 0=idle, 1=car-in, 2=channels-shown, 3=published, 4=lead-in
const [step, setStep] = React.useState(0);
const [cycle, setCycle] = React.useState(0); // forces re-mount on each loop
React.useEffect(() => {
let timers = [];
const run = () => {
setStep(0);
timers.push(setTimeout(() => setStep(1), 250));
timers.push(setTimeout(() => setStep(2), 1400));
timers.push(setTimeout(() => setStep(3), 2600));
timers.push(setTimeout(() => setStep(4), 4400));
timers.push(
setTimeout(() => {
setCycle((c) => c + 1);
}, 7200)
);
};
run();
return () => timers.forEach(clearTimeout);
}, [cycle]);
return { step, cycle };
}
const CarPhotoPlaceholder = () => (
{/* Real Audi A6 photo (Higgsfield GPT Image 2) */}
{/* Subtle vignette so the card stays brand-dark */}
{/* Photo counter label */}
Audi A6 · 2021 · Photo 01/12
{/* Scan sweep — keeps the "scanning a fresh upload" feel */}
);
const SpecRow = ({ k, v }) => (
{k}
{v}
);
const PlatformRow = ({ p, step, idx }) => {
// status by step:
const published = step >= 3;
const queued = step >= 2 && step < 3;
return (
{p.label}
{published ? "Огласот објавен" : queued ? "Се подготвува огласот…" : "Spreman"}
{/* Status indicator */}
{published ? "Објавено" : "Чекање"}
);
};
const HeroProductPanel = () => {
const { step, cycle } = useHeroCycle();
return (
{/* Ambient lime glow */}
{/* Outer card */}
{/* Window chrome */}
dealerhub · inventory · add-vehicle
Live
{/* Two-column body */}
{/* Vehicle card */}
= 1 ? 1 : 0,
transform: step >= 1 ? "translateY(0) scale(1)" : "translateY(-10px) scale(0.985)",
transition: "opacity 700ms cubic-bezier(0.22,1,0.36,1), transform 700ms cubic-bezier(0.22,1,0.36,1)",
}}
>
Audi A6 45 TFSI
2021 · Sedan · S-line
{/* Channels column */}
Канали за објава
{step >= 3 ? "4/4" : step >= 2 ? "0/4" : "—"}
{PLATFORMS.map((p, i) =>
step >= 2 ? (
) : (
)
)}
{/* Footer action */}
Објави на 4 канали
+ сајт на салонот
= 2 ? "bg-lime text-ink-950" : "bg-white/5 text-ink-300"
)}
>
{step >= 3 ? "Готово" : "⌘ + ↵ Објави"}
{/* Lead notification — slides in over panel */}
{step >= 4 && (
Нов lead
сега
Стефан М. — заинтересиран за Audi A6
Од: Facebook · одговор за < 2 мин
)}
);
};
// ---------- Mobile-specific compact mockup ----------
const MobileHeroMockup = () => {
const { step, cycle } = useHeroCycle();
return (
{/* Phone-style frame */}
{/* App chrome */}
{/* Body */}
{/* Vehicle card */}
= 1 ? 1 : 0,
transform: step >= 1 ? "translateY(0)" : "translateY(-8px)",
transition: "opacity 600ms cubic-bezier(0.22,1,0.36,1), transform 600ms cubic-bezier(0.22,1,0.36,1)",
}}
className="rounded-xl border border-white/[0.06] bg-black/30 p-3"
>
{/* Real Audi A6 photo */}
Audi A6 2.0 TDI
2021 · Дизел · 48.210 km
€ 18.900
{/* Channels */}
Објавува на
{step >= 3 ? "4/4" : step >= 2 ? "0/4" : "—"}
{PLATFORMS.map((p, i) => {
const published = step >= 3;
return (
= 2 ? 1 : 0,
transform: step >= 2 ? "translateY(0)" : "translateY(6px)",
transition: "opacity 500ms cubic-bezier(0.22,1,0.36,1) " + (i * 80) + "ms, transform 500ms cubic-bezier(0.22,1,0.36,1) " + (i * 80) + "ms",
}}
className="flex items-center gap-2 rounded-lg border border-white/[0.06] bg-white/[0.02] p-2"
>
{p.label.replace(" Marketplace", "")}
{published ? "Објавено" : "Чекање"}
);
})}
{/* Lead toast */}
{step >= 4 && (
Нов lead
Александар — заинтересиран за Audi A6
)}
);
};
// ---------- Demo video modal ----------
const DemoModal = ({ open, onClose }) => {
React.useEffect(() => {
if (!open) return;
const onKey = (e) => { if (e.key === "Escape") onClose(); };
document.addEventListener("keydown", onKey);
document.body.style.overflow = "hidden";
return () => {
document.removeEventListener("keydown", onKey);
document.body.style.overflow = "";
};
}, [open, onClose]);
if (!open) return null;
return (
e.stopPropagation()}
className="relative w-full max-w-[1100px] overflow-hidden rounded-2xl border border-white/[0.08] bg-ink-900 shadow-[0_40px_120px_-20px_rgba(0,0,0,0.9)]"
>
);
};
// ---------- Hero section ----------
const Hero = () => {
const [demoOpen, setDemoOpen] = React.useState(false);
return (
{/* Faint blueprint backdrop */}
{/* Eyebrow / mobile badge — tighter mobile spacing so the headline
sits higher above the fold on 360–430px screens. */}
v3.0 · 2026 release
Оперативен систем за авто салони
Сајт · CRM · 4 канали
{/* Headline column */}
{/* 5-second value prop. Three short clauses that read as a
single linear flow — внеси → објавува → следиш — so the
dealer reads one sentence, not three. */}
Внеси возило{" "}
еднаш .
Објави го{" "}
секаде .
Следи ги купците .
Сајт за салонот, автоматско објавување на Facebook,
Instagram, Реклама5, Pazar3 — и CRM каде ги следиш сите
купци на едно место.
Започни сега
setDemoOpen(true)}
>
Види како работи
setDemoOpen(false)} />
{/* Trust badges — calmer treatment: white check icons (not
lime) so the only loud lime in the hero is the primary CTA. */}
{[
"Без картичка",
"Готов сајт за 15 мин.",
"Поддршка на МК",
"За авто салони",
].map((t) => (
{t}
))}
{/* Product panel column */}
{/* Logo / platform strip */}
Објавува автоматски на →
Facebook
Instagram
Реклама5
Pazar3
Сопствен сајт
);
};
Object.assign(window, { Hero });
// ================== sections.jsx ==================
// Sections: Problem (before/after), How it works (3 steps), Bento grid
const { motion: M2 } = window.framerMotion;
// ---------- 03. PROBLEM — Before / After ----------
const BeforeList = [
"Рачно објавување на Facebook",
"Рачно објавување на Instagram",
"Рачно внесување на Реклама5",
"Рачно внесување на Pazar3",
"Купци расфрлани во пораки",
"Нема јасна аналитика",
];
const AfterList = [
"Внесуваш возило еднаш",
"Избираш каде да се објави",
"DealerHub го синхронизира огласот",
"Купците автоматски влегуваат во CRM",
"Гледаш која платформа носи купци",
];
const BeforeAfter = () => (
Проблем
Авто салоните губат премногу време на{" "}
рачни објави .
Една кола = четири огласи, четири пати фотки, четири пати опис. DealerHub
го прави тоа еднаш и за сите канали.
{/* Before card */}
Без DealerHub
≈ 45 мин / возило
Шест прозори, шест copy-paste, и пораки секаде.
{BeforeList.map((t) => (
{t}
))}
{/* Faux chaos: stacked browser tabs */}
{["facebook", "instagram", "reklama5", "pazar3", "viber"].map(
(t, i) => (
{t}
)
)}
{/* After card */}
{/* Lime ambient */}
Со DealerHub
≈ 90 секунди / возило
Еден екран. Еден клик. Сè останато е автоматизирано.
{AfterList.map((t, i) => (
{t}
))}
{/* Visual: hub with rays to platforms */}
{/* hub */}
HUB
{/* rays */}
{[20, 45, 70, 95].map((y, i) => (
))}
{/* targets */}
{["Facebook", "Instagram", "Реклама5", "Pazar3"].map((t, i) => (
{t}
))}
);
// ---------- 04. HOW IT WORKS ----------
const Steps = [
{
n: "01",
title: "Додај возило",
desc: "Внеси слики, цена, опис, километража и детали за возилото — само еднаш.",
Icon: ICar,
art: () => (
{/* Faux form rows for "марка / модел / цена" so the mock reads as a
real input form, not three empty boxes. */}
{[
{ l: "Марка / Модел", v: "BMW · X5 xDrive40d" },
{ l: "Цена", v: "€ 41.500" },
{ l: "Километража", v: "62 000 км · 2022" },
].map((r) => (
{r.l}
{r.v}
))}
{/* Photo grid — first slot has a tiny accent-tinted car silhouette;
other two stay as upload placeholders so it's clear you can add
more. */}
{[2, 3].map((n) => (
{n}
))}
),
},
{
n: "02",
title: "Избери канали",
desc: "Одбери дали возилото да оди на сајт, Facebook, Instagram, Реклама5 и Pazar3.",
Icon: ILayers,
art: () => (
{[
{ l: "Facebook", a: true },
{ l: "Instagram", a: true },
{ l: "Реклама5", a: true },
{ l: "Pazar3", a: false },
{ l: "Сопствен сајт", a: true },
].map((c) => (
{c.l}
))}
),
},
{
n: "03",
title: "Објави со еден клик",
desc: "DealerHub го подготвува огласот и го објавува во правилен формат за секоја платформа.",
Icon: IBolt,
art: () => (
{[
{ l: "Огласот подготвен", t: "00:03" },
{ l: "Текст оптимизиран", t: "00:05" },
{ l: "Слики подготвени", t: "00:09" },
{ l: "Објавено на 4 канали", t: "00:12" },
].map((s, i) => (
{s.l}
{s.t}
))}
),
},
];
const HowItWorks = () => (
Како работи
Од внес до објавено за{" "}
помалку од минута .
Три чекори. Останатото го прави платформата — фотки, описи, формати и
објави по канал.
{/* Mobile vertical timeline */}
{Steps.map((s, i) => (
))}
{/* Desktop 3-col with connecting line */}
{Steps.map((s, i) => (
Чекор / {s.n}
{s.title}
{s.desc}
))}
);
// ---------- 05. BENTO ----------
const BentoCell = ({ className = "", eyebrow, title, desc, children }) => (
{eyebrow}
{title}
{desc}
{children}
);
const Bento = () => (
Систем
Сè што му треба на еден{" "}
модерен авто салон.
Сајт, инвентар, CRM, аналитика и објавување — едно место, една логика.
{/* LARGE — Automatic publishing */}
{/* hub diagram */}
Audi A6 · 2021
внесен еднаш
{[
{ l: "Facebook", Logo: PlatformFB },
{ l: "Instagram", Logo: PlatformIG },
{ l: "Реклама5", Logo: PlatformR5 },
{ l: "Pazar3", Logo: PlatformP3 },
].map((p) => (
))}
{/* MEDIUM — Pro site */}
salon.mk
{["audi-a6", "bmw-x5", "merc-e", "vw-golf", "range-rover", "porsche"].map((slug) => (
))}
{/* MEDIUM — CRM */}
{[
{ n: "Стефан М.", v: "Audi A6", s: "Нов" },
{ n: "Ана Т.", v: "BMW X5", s: "Тест" },
{ n: "Дамјан П.", v: "VW Tiguan", s: "Договор" },
].map((l) => (
))}
{/* SMALL — AI desc */}
AI · Опис
Audi A6 во одлична состојба, прв сопственик, редовно сервисиран…
Тон · Премиум
МК
{/* SMALL — Analytics */}
{/* SMALL — Marker for sold cars */}
{["Facebook", "Instagram", "Реклама5", "Pazar3"].map((p, i) => (
{p}
Активно
))}
→ Продадено
{/* WIDE — Local */}
{[
"🇲🇰 Македонски интерфејс",
"Реклама5 · Pazar3 интеграции",
"MKD / EUR цени",
"Локални формат за фотки",
"Поддршка за салони со 5–500 возила",
].map((t) => (
{t}
))}
);
Object.assign(window, { BeforeAfter, HowItWorks, Bento });
// ================== product.jsx ==================
// Product sections: Templates gallery, Platform automation, CRM mockup, Analytics
const { motion: M3, AnimatePresence: AP3 } = window.framerMotion;
// CSS-based progress bar that animates in when scrolled into view
const InViewBar = ({ pct, delay = 0, className = "" }) => {
const ref = React.useRef(null);
const [shown, setShown] = React.useState(false);
React.useEffect(() => {
const el = ref.current;
if (!el) return;
const io = new IntersectionObserver(
(entries) => {
entries.forEach((e) => {
if (e.isIntersecting) {
setShown(true);
io.disconnect();
}
});
},
{ threshold: 0.3 }
);
io.observe(el);
return () => io.disconnect();
}, []);
return (
);
};
// ---------- 06. TEMPLATES ----------
const Templates = [
{
key: "premia",
name: "Premia",
desc: "За премиум салони",
accent: "#C9A66B",
tone: "warm",
},
{
key: "apex",
name: "Apex",
desc: "Спортски и динамичен стил",
accent: "#FF5C42",
tone: "sport",
},
{
key: "voltek",
name: "Voltek",
desc: "Модерен electric / future изглед",
accent: "#CFF255",
tone: "future",
},
{
key: "familia",
name: "Familia",
desc: "Пристапен и доверлив стил",
accent: "#7AA8FF",
tone: "family",
},
{
key: "classic",
name: "Classic",
desc: "Чист, професионален изглед",
accent: "#E8E8E6",
tone: "classic",
},
];
const TemplatePreview = ({ t }) => {
// tiny stylized website mock per tone
return (
{/* Browser bar */}
{t.key}.salon.mk
{/* Header */}
{t.name === "Premia" ? "Premia" : t.name === "Familia" ? "Familia" : t.name === "Voltek" ? "VOLTEK" : t.name}
{t.tone === "sport" && • }
Возила
Финансирање
Контакт
{/* Hero strip */}
{t.tone === "future"
? "Иднината на возила."
: t.tone === "sport"
? "Вози. Победувај."
: t.tone === "warm"
? "Класа, без компромис."
: t.tone === "family"
? "Возило за фамилијата."
: "Возила со доверба."}
{/* Featured car silhouette */}
{/* Cards row */}
{[0, 1, 2].map((i) => (
))}
{/* Live preview badge */}
Во живо
);
};
const TemplatesSection = () => {
const scrollerRef = React.useRef(null);
const [active, setActive] = React.useState(0);
const total = Templates.length + 1; // +1 for the "all templates" card
const onScroll = () => {
const el = scrollerRef.current;
if (!el) return;
const cardW = el.firstChild ? el.firstChild.offsetWidth + 16 : 0;
if (!cardW) return;
const idx = Math.round(el.scrollLeft / cardW);
setActive(Math.min(total - 1, Math.max(0, idx)));
};
return (
Дизајни
Секој салон може да изгледа{" "}
премиум .
Готови шаблони што се прилагодуваат на твојот бренд. Менуваш бои, фотки
и копирајт — без дизајнер.
{/* Mobile: horizontal snap carousel */}
{Templates.map((t) => (
))}
{/* All templates card */}
+ Уште шаблони
12+ шаблони. Сите со сопствен домен.
Сите се responsive, SEO-структурирани и оптимизирани за возила.
Види ги сите дизајни
{/* Dots */}
{Array.from({ length: total }).map((_, i) => (
))}
{/* Desktop: grid */}
{Templates.map((t, i) => (
))}
{/* Sixth card: "All templates" */}
+ Уште шаблони
12+ шаблони. Сите со сопствен домен.
Сите се responsive, SEO-структурирани и оптимизирани за возила.
Види ги сите дизајни
);
};
// ---------- 08. PLATFORM AUTOMATION ----------
const PlatformCard = ({ name, Logo, sub, idx, animate }) => {
// animation: cycle through "Ready" -> "Publishing" -> "Published"
const published = animate >= 2;
const publishing = animate === 1;
return (
{published ? "Published" : publishing ? "Publishing…" : "Ready"}
{/* progress */}
Audi A6
{published ? "00:12" : publishing ? "00:08" : "00:00"}
);
};
const PlatformsSection = () => {
// animation cycle for all 4 cards
const [phase, setPhase] = React.useState(0); // 0,1,2 -> loop
React.useEffect(() => {
const id = setInterval(() => setPhase((p) => (p + 1) % 3), 2200);
return () => clearInterval(id);
}, []);
return (
);
};
// ---------- 09. CRM ----------
const Leads = [
{ n: "Стефан М.", c: "Audi A6 · 2021", s: "New", src: "Facebook", v: "€ 38.900", color: "#CFF255" },
{ n: "Ана Т.", c: "BMW X5 · 2020", s: "Contacted", src: "Instagram", v: "€ 41.500", color: "#E8E8E6" },
{ n: "Дамјан П.", c: "VW Tiguan · 2022", s: "Test Drive", src: "Реклама5", v: "€ 26.400", color: "#7AA8FF" },
{ n: "Маја С.", c: "Mercedes C-Class", s: "Closed", src: "Pazar3", v: "€ 32.000", color: "#CFF255" },
{ n: "Бојан Р.", c: "Škoda Octavia", s: "Contacted", src: "Website", v: "€ 18.900", color: "#E8E8E6" },
];
const statusTone = {
New: "border-lime/30 bg-lime/[0.08] text-lime",
Contacted: "border-white/[0.12] bg-white/[0.04] text-ink-100",
"Test Drive": "border-blue-300/30 bg-blue-300/[0.06] text-[#9EC0FF]",
Closed: "border-lime/40 bg-lime/[0.14] text-lime",
};
const CRMSection = () => (
CRM
Не губи клиенти{" "}
низ пораки .
DealerHub ги собира купците од сите канали и ти помага да следиш кој
клиент за кое возило е заинтересиран.
{/* Left: stats */}
{[
{ l: "Активни возила", v: 38, sub: "+4 оваа недела" },
{ l: "Купци / месец", v: 127, sub: "+18% од минатиот месец" },
{ l: "Посети на сајтот", v: 4287, sub: "82% mobile", wide: true },
].map((s, i) => (
{s.l}
{s.sub}
))}
* Демо податоци за приказ.
{/* Right: CRM table */}
Pipeline · оваа недела
Live
5 нови
2 test drives
1 closed
{/* Pipeline chips (mobile only) */}
{[
{ l: "Нов", n: 2, tone: "lime" },
{ l: "Контактиран", n: 2, tone: "soft" },
{ l: "Тест возење", n: 1, tone: "soft" },
{ l: "Продадено", n: 1, tone: "lime" },
].map((c) => (
{c.l} {c.n}
))}
Клиент
Возило
Канал
Статус
Вредност
{Leads.map((l, i) => (
{/* Mobile layout */}
{l.n.split(" ").map((p) => p[0]).join("")}
{l.s}
Од: {l.src}
{l.v}
{/* Desktop layout */}
{l.n.split(" ").map((p) => p[0]).join("")}
{l.c}
{l.s}
{l.v}
))}
{/* Footer summary */}
Pipeline вредност
€ 157.700
);
// ---------- 10. ANALYTICS ----------
const AnalyticsSection = () => (
Аналитика
Знај што навистина продава.
Која платформа носи најмногу клиенти. Кои возила бараат најмногу
внимание. Едно место за сите одговори.
{/* Top viewed vehicle */}
Најгледано возило
Audi A6 45 TFSI
2021 · S-line · 48.210 km
{/* Best channel */}
Најдобар канал
{[
{ l: "Facebook", v: 48, Logo: PlatformFB },
{ l: "Instagram", v: 27, Logo: PlatformIG },
{ l: "Реклама5", v: 18, Logo: PlatformR5 },
{ l: "Pazar3", v: 7, Logo: PlatformP3 },
].map((c, i) => (
))}
{/* Conversion */}
Conversion rate
Lead → продажба, последни 30 дена
{/* sparkline */}
{/* Bottom row */}
Најмногу побарувани
{[
{ v: "BMW X5", n: 41 },
{ v: "Audi A6", n: 37 },
{ v: "VW Tiguan", n: 28 },
{ v: "Mercedes C", n: 22 },
].map((r) => (
{r.v}
{r.n}
))}
Продадени возила
Q4 2025 · +3 vs. Q3
{/* monthly bars */}
{[3, 5, 4, 6, 4, 7].map((h, i) => (
{["Јул", "Авг", "Сеп", "Окт", "Ное", "Дек"][i]}
))}
Mobile traffic
{/* ring */}
Mobile-first посетители
Сите шаблони се mobile-optimized
);
Object.assign(window, { TemplatesSection, PlatformsSection, CRMSection, AnalyticsSection });
// ================== pricing.jsx ==================
// Pricing, Trust, FAQ, Final CTA, Footer
const { motion: M4 } = window.framerMotion;
// ---------- 11. PRICING ----------
// Plans MUST match src/lib/plan-features.ts (PLAN_FEATURES) — that's the
// source of truth used by /admin/billing, feature gates and signup checkout.
// Prices below mirror monthlyPriceEur for each tier:
// PRESENCE €29 — сакам само сајт
// STARTER €69 — solo dealer
// PRO €129 — активен тим (NAJPOPULARNO)
// BUSINESS €229 — голем салон
// ENTERPRISE — контактирај продажби
const Plans = [
{
key: "presence",
name: "Презенс",
price: 29,
forWho: "Сакам само вебсајт за моите возила — без социјални и CRM.",
features: [
"Сопствен сајт со домен",
"До 20 возила",
"1 администратор",
"Основна аналитика",
"Поддршка на македонски",
],
cta: "Започни сега",
},
{
key: "starter",
name: "Стартер",
price: 69,
forWho: "За самостоен дилер што почнува со автоматско објавување.",
features: [
"Сè од Презенс",
"До 50 возила · 2 корисници",
"Instagram + Reels објавување",
"AI описи на возила",
"Преводи на пораки од купувачи",
"Неделен дигест извештај",
],
cta: "Започни сега",
},
{
key: "pro",
name: "Про",
price: 129,
badge: "Најпопуларен",
forWho: "За активен дилерски тим што објавува секоја недела.",
features: [
"Сè од Стартер",
"До 200 возила · 5 корисници",
"Facebook + Реклама5 + Pazar3",
"Reels масовно објавување (50/мес.)",
"AI текст за реклами",
"Сопствен домен + паметно пребарување",
"Замена на возило + пазарна аналитика",
],
cta: "Започни сега",
highlighted: true,
},
{
key: "business",
name: "Бизнис",
price: 229,
forWho: "За поголем салон со повеќе корисници и напредна поддршка.",
features: [
"Сè од Про",
"Неограничено возила и корисници",
"Сопствен бренд (white-label)",
"API пристап за интеграции",
"Приоритет на купци + автоматизации",
"Reels без лимит",
],
cta: "Започни сега",
},
];
// Enterprise lives in its own strip below the 4-card grid — contact sales
// only, no monthly price to show.
const EnterprisePlan = {
name: "Ентерпрајс",
forWho:
"За мрежи салони, повеќе локации или индивидуален SLA. Договараме поединечно.",
features: [
"Сè од Бизнис",
"Повеќе локации под еден акаунт",
"Посветен account manager",
"SLA за uptime и поддршка",
],
cta: "Контактирај нè",
};
const PriceCard = ({ p }) => (
{p.highlighted && (
)}
{p.badge && (
{p.badge}
)}
€{p.price}
/ мес.
без ДДВ · отказ во секое време
{p.features.map((f) => (
{f}
))}
{p.highlighted ? (
{p.cta}
) : (
{p.cta}
)}
);
const PricingSection = () => (
Цени
Пакети за секој тип авто салон.
Без поставување, без скриени трошоци. 14 дена бесплатно за сите пакети
— плаќаш дури кога ќе одлучиш дека е вистинско.
{/* Plans — 4 self-serve tiers as a responsive grid (1 col mobile,
2 cols tablet, 4 cols desktop). Pro card is visually highlighted
and lifted to first position on mobile so the most-popular plan
gets the lead position regardless of viewport. */}
{Plans.map((p, i) => (
))}
{/* Enterprise — separate full-width strip below the 4 self-serve
cards. Contact-sales only, so it gets a calmer treatment without
a price. */}
{EnterprisePlan.name}
Контактирај продажби
{EnterprisePlan.forWho}
{EnterprisePlan.features.map((f) => (
{f}
))}
{EnterprisePlan.cta}
{/* Conversion strip */}
{[
{ l: "Готов сајт за 15 мин.", d: "Дизајн, инвентар и објави во еден чекор." },
{ l: "Без обврзувачки договор", d: "Месечно. Откажуваш во секое време." },
{ l: "Поддршка на македонски", d: "Реални луѓе, не chatbot." },
].map((b) => (
))}
Цените може да се приспособат според потребите на салонот.
);
// ---------- CONTACT / DEMO ----------
const ContactSection = () => {
const [submitted, setSubmitted] = React.useState(false);
const onSubmit = (e) => {
e.preventDefault();
setSubmitted(true);
};
return (
);
};
const Field = ({ label, name, type = "text", ...rest }) => (
{label}
);
const FieldArea = ({ label, name, rows = 3, ...rest }) => (
{label}
);
// ---------- 12. TRUST ----------
const TrustSection = () => {
const trusts = [
{ t: "Поддршка на македонски", Icon: IUsers },
{ t: "Локални платформи", Icon: ILayers },
{ t: "Без комплициран setup", Icon: IBolt },
{ t: "Готово за кратко време", Icon: ITag },
{ t: "Mobile-first сајтови", Icon: IPhone },
{ t: "SEO структура за возила", Icon: IGlobe },
];
return (
Доверба
Направено за реалниот начин на работа на авто салоните.
Не уште една западна SaaS алатка. DealerHub го разбира локалниот
пазар, локалните канали и реалниот процес на продажба.
);
};
// ---------- 13. FAQ ----------
const FAQs = [
{
q: "Дали ми треба постоечки сајт?",
a: "Не. DealerHub може да ти креира комплетен нов сајт за салонот — со сопствен домен, мобилна верзија и SEO структура за возила.",
},
{
q: "Дали автоматски објавува на Facebook и Instagram?",
a: "Да, DealerHub е направен за автоматско објавување на возила на социјални мрежи и локални канали, со оптимизирани слики и текст за секоја платформа.",
},
{
q: "Дали работи со Реклама5 и Pazar3?",
a: "Платформата е дизајнирана да поддржи локални огласници како Реклама5 и Pazar3 — без потреба за рачно внесување.",
},
{
q: "Дали можам да имам сопствен домен?",
a: "Да, секој салон може да користи сопствен домен — пример: tvoj-salon.mk или voziladealer.mk.",
},
{
q: "Дали можам сам да го креирам сајтот?",
a: "Да. Преку /signup за околу 15 минути сам го избираш дизајнот, го пишуваш името на салонот, го прикачуваш логото и поврзуваш канали. Без картичка, без обврзувачки договор.",
},
{
q: "Колку трае пробниот период?",
a: "14 дена потполно бесплатно — без картичка. Ако ти одговара, продолжуваш со некој од 4-те самостојни пакети. Ако не — едноставно прекинуваш.",
},
];
// Premium calm: open state used a solid lime fill for the +/- pill, which
// pulled the eye when several FAQs were stacked. The lime is now a quiet
// hairline ring + tinted text so the accent reads as "active state", not
// "alert". Touch target stays ≥ 44px (h-9 = 36 + padding around button is
// from the wrapping py-4).
const FAQItem = ({ q, a, isOpen, onClick }) => (
);
const FAQSection = () => {
const [open, setOpen] = React.useState(0);
return (
FAQ
Често поставувани прашања .
Не го гледаш одговорот? Пишувај ни — одговараме во рок од еден работен ден.
Контактирај нè
{FAQs.map((f, i) => (
setOpen(open === i ? -1 : i)}
/>
))}
);
};
// ---------- 14. FINAL CTA ----------
const FinalCTA = () => (
{/* Ambient */}
{/* Blueprint grid */}
DealerHub · 2026
Подготвен си да го{" "}
модернизираш твојот авто салон?
Започни со DealerHub и претвори го твојот инвентар во професионален
продажен систем — сајт, објави и CRM на едно место.
Започни сега
Види пример сајт
Без картичка
Готов сајт за 15 мин.
Откажуваш во секое време
);
// ---------- FOOTER ----------
const Footer = () => (
Оперативен систем за авто салони — сајт, инвентар, објавување, CRM и
аналитика на едно место.
© 2026 DealerHub · Скопје, MK
{[
{
t: "Продукт",
links: ["Како работи", "Функции", "Дизајни", "Цени", "Интеграции"],
},
{
t: "Платформи",
links: ["Facebook", "Instagram", "Реклама5", "Pazar3", "Сопствен сајт"],
},
{
t: "Компанија",
links: ["FAQ", "Контакт", "Поддршка", "Правила", "Приватност"],
},
].map((col) => (
{col.t}
{col.links.map((l) => (
{l}
))}
))}
{/* Big wordmark */}
);
Object.assign(window, { PricingSection, ContactSection, TrustSection, FAQSection, FinalCTA, Footer });
// ================== app.jsx ==================
// App shell: sticky header, page composition, mobile sticky CTA
const { useState, useEffect } = React;
// ---------- HEADER ----------
const NavLinks = [
{ href: "#how", l: "Како работи" },
{ href: "#features", l: "Функции" },
{ href: "#designs", l: "Дизајни" },
{ href: "#pricing", l: "Цени" },
{ href: "#faq", l: "FAQ" },
];
const Logo = ({ className = "" }) => (
DealerHub
);
const Header = () => {
const [scrolled, setScrolled] = useState(false);
const [mobileOpen, setMobileOpen] = useState(false);
useEffect(() => {
const onScroll = () => setScrolled(window.scrollY > 12);
onScroll();
window.addEventListener("scroll", onScroll, { passive: true });
return () => window.removeEventListener("scroll", onScroll);
}, []);
return (
<>
{NavLinks.map((n) => (
{n.l}
))}
Пријави се
Започни сега
setMobileOpen(true)}
aria-label="Open menu"
>
{/* Mobile menu */}
{mobileOpen && (
)}
>
);
};
// ---------- MOBILE STICKY CTA ----------
// Premium calm: dark-glass dock with reduced lime ring, safe-area padding,
// and a wider hide-zone (contact + faq + footer). The dock is intentionally
// quiet — it's a recurring affordance, not a banner — so the lime is
// confined to the button, with only a faint warm hairline on the dock.
const MobileStickyCTA = () => {
const [show, setShow] = useState(false);
const [hideZone, setHideZone] = useState(false);
useEffect(() => {
const onScroll = () => {
setShow(window.scrollY > 480);
// Hide whenever any "destination" section near the page bottom is in
// view — contact form, FAQ accordion or footer — so the dock never
// sits on top of the actual conversion area.
const ids = ["contact", "faq", "cta"];
let near = false;
for (const id of ids) {
const el = document.getElementById(id);
if (!el) continue;
const r = el.getBoundingClientRect();
if (r.top < window.innerHeight - 120) { near = true; break; }
}
// Also hide once the footer is in view
const footer = document.querySelector("footer");
if (footer) {
const r = footer.getBoundingClientRect();
if (r.top < window.innerHeight - 60) near = true;
}
setHideZone(near);
};
onScroll();
window.addEventListener("scroll", onScroll, { passive: true });
window.addEventListener("resize", onScroll);
return () => {
window.removeEventListener("scroll", onScroll);
window.removeEventListener("resize", onScroll);
};
}, []);
const visible = show && !hideZone;
return (
Спремен за демо?
15 мин · без картичка
Побарај демо
);
};
// ---------- APP ----------
function App() {
return (
);
}
ReactDOM.createRoot(document.getElementById("root")).render( );