// app.jsx — root, tweaks, router. Loaded last.
const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
"theme": "dark",
"accent": "#7C3AED",
"fontPairing": "geist",
"heroVariant": "centered",
"density": "regular",
"animationIntensity": 60
}/*EDITMODE-END*/;
const FONT_PAIRS = {
geist: { sans: "'Geist', 'Inter', system-ui, sans-serif", mono: "'Geist Mono', ui-monospace, monospace", display: "'Geist', 'Inter', system-ui, sans-serif" },
editorial:{ sans: "'Inter Tight', system-ui, sans-serif", mono: "'JetBrains Mono', ui-monospace, monospace", display: "'Instrument Serif', Georgia, serif" },
techno: { sans: "'Space Grotesk', system-ui, sans-serif", mono: "'JetBrains Mono', ui-monospace, monospace", display: "'Space Grotesk', system-ui, sans-serif" },
};
const ACCENT_OPTIONS = ["#7C3AED", "#FF5B2E", "#0A66FF", "#16A34A", "#C8A24B", "#111111"];
function App() {
const [t, setTweak] = useTweaks(TWEAK_DEFAULTS);
const route = useRoute();
// Pause CSS animations when the tab is backgrounded — saves CPU + battery.
useEffect(() => {
const onVis = () => {
document.documentElement.dataset.visibility = document.hidden ? "hidden" : "visible";
};
document.addEventListener("visibilitychange", onVis);
onVis();
return () => document.removeEventListener("visibilitychange", onVis);
}, []);
// SEO: update document.title per route for crawler clarity + share previews
useEffect(() => {
const titles = {
home: "Digital Jaao — AI-Powered Growth Systems For Modern Brands | Jaipur",
services: "Services — AI Agents, Automation, Paid Media & AI SEO | Digital Jaao",
"case-studies":"Case Studies — Real systems. Real numbers. | Digital Jaao",
case: "Case Study | Digital Jaao",
portfolio: "Live Portfolio — Brands across 20 niches | Digital Jaao",
testimonials: "Client Feedback — Founders on the record | Digital Jaao",
blog: "Field Notes — AI marketing & automation writing | Digital Jaao",
about: "About — India's AI-first growth company | Digital Jaao",
book: "Book a 1-on-1 consult | Digital Jaao",
contact: "Contact — hello@digitaljaao.com | Digital Jaao",
};
document.title = titles[route.path] || titles.home;
}, [route.path, route.params[0]]);
// Apply theme variables to :root
useEffect(() => {
const root = document.documentElement;
root.dataset.theme = t.theme || "dark";
root.style.setProperty("--accent", t.accent);
const pair = FONT_PAIRS[t.fontPairing] || FONT_PAIRS.geist;
root.style.setProperty("--font-sans", pair.sans);
root.style.setProperty("--font-mono", pair.mono);
root.style.setProperty("--font-display", pair.display);
root.dataset.density = t.density;
root.style.setProperty("--motion", String(t.animationIntensity / 60));
}, [t.theme, t.accent, t.fontPairing, t.density, t.animationIntensity]);
// Render current page
const renderPage = () => {
switch (route.path) {
case "services": return ;
case "service": return ;
case "case-studies": return ;
case "case": return ;
case "portfolio": return ;
case "testimonials": return ;
case "blog": return ;
case "about": return ;
case "book": return ;
case "contact": return ;
case "home":
default: return ;
}
};
return (
{renderPage()}
setTweak("theme", v)} />
setTweak("accent", v)} />
setTweak("fontPairing", v)} />
setTweak("heroVariant", v)} />
setTweak("density", v)} />
setTweak("animationIntensity", v)} />
);
}
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render();