// Broadway Interiors — main app, navigation, home, footer const { useState: useS, useEffect: useE, useRef: useR, useMemo: useM } = React; // ────────────────────────────────────────────────────────────────────── // Tweaks defaults — wired through useTweaks() in the panel // ────────────────────────────────────────────────────────────────────── const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{ "accent": "#A98B53", "type": "instrument", "heroTreatment": "still", "darkChrome": false }/*EDITMODE-END*/; // ────────────────────────────────────────────────────────────────────── // Tiny hash router // ────────────────────────────────────────────────────────────────────── function useRoute() { const [route, setRoute] = useS(() => parseHash(location.hash)); useE(() => { const onHash = () => setRoute(parseHash(location.hash)); window.addEventListener('hashchange', onHash); return () => window.removeEventListener('hashchange', onHash); }, []); const go = (path) => { location.hash = '#' + path; window.scrollTo(0, 0); }; return [route, go]; } function parseHash(hash) { const path = (hash || '#/').replace(/^#/, '') || '/'; const parts = path.split('/').filter(Boolean); if (parts.length === 0) return { page: 'home', path: '/' }; if (parts[0] === 'projects' && parts.length === 1) return { page: 'projects', path }; if (parts[0] === 'projects' && parts[1]) return { page: 'case', slug: parts[1], path }; if (parts[0] === 'sectors' && parts.length === 1) return { page: 'sectors', path }; if (parts[0] === 'sectors' && parts[1]) return { page: 'sector', id: parts[1], path }; if (parts[0] === 'about') return { page: 'about', path }; if (parts[0] === 'awards') return { page: 'awards', path }; if (parts[0] === 'contact') return { page: 'contact', path }; return { page: '404', path }; } // ────────────────────────────────────────────────────────────────────── // Navbar // ────────────────────────────────────────────────────────────────────── function Navbar({ route, go, scrolled, darkChrome }) { const [open, setOpen] = useS(false); const items = [ { id: 'projects', label: 'Projects' }, { id: 'sectors', label: 'Sectors' }, { id: 'about', label: 'Studio' }, { id: 'awards', label: 'Awards' }, { id: 'contact', label: 'Contact' }, ]; // Dark chrome when explicitly forced, or on home (scrolled toggles) const isHome = route.page === 'home'; const isCase = route.page === 'case'; const transparent = (isHome || isCase) && !scrolled; return ( ); } // ────────────────────────────────────────────────────────────────────── // Home // ────────────────────────────────────────────────────────────────────── function Home({ go, heroTreatment }) { const featured = PROJECTS.filter(p => p.featured); const [marqueeIdx, setMarqueeIdx] = useS(0); useE(() => { const i = setInterval(() => setMarqueeIdx(x => (x + 1) % featured.length), 4500); return () => clearInterval(i); }, [featured.length]); return (
{/* Manifesto strip */}
An award-winning, design-and-build consultancy in Dubai. Established 1999.

We design it  to be built.
And then we build it.

One studio. One project manager. One quantity surveyor. The drawings and the workshop sit four metres apart — which is why the rooms we deliver still look the way we drew them.
{/* Sectors */}
Five sectors · 70+ projects

Rooms we draw and build.

{SECTORS.map((s, i) => { const proj = PROJECTS.filter(p => p.sector === s.id); const cover = proj[0]; return ( { e.preventDefault(); go(`/sectors/${s.id}`); }} style={{ '--idx': i }}>
{cover && }
0{i + 1}
{s.label}
{proj.length} projects →
); })}
{/* Featured work — big editorial spreads */}
Selected case studies

Designed & built.

{ e.preventDefault(); go('/projects'); }}> All 30 projects →
{featured.slice(0, 4).map((p, i) => ( ))}
{/* Design-and-build differentiator strip */}
The difference
01.

One studio for design and delivery.

Most fit-out projects involve at least three companies. Ours involve one. The programme tightens and the change orders disappear.

02.

In-house QS, on day one.

Our Managing QS sits in design reviews. The concept already knows what it costs — and how it will be procured — before you see it.

03.

A 70-project rolodex of trades.

Twenty-five years of vetted joiners, MEP partners and finish suppliers — picked per project, not assigned by default.

{/* Awards strip — marquee */}
25+ design awards · 2010 — 2025

Including a few we’re especially proud of.

{AWARDS.filter(a => a.flagship).concat(AWARDS.filter(a => !a.flagship).slice(0, 4)).map((a, i) => (
{a.year}
{a.flagship && '★ '}{a.title}
{a.issuer}{a.project ? ` · ${a.project}` : ''}
{a.flagship &&
Flagship
}
))}
{ e.preventDefault(); go('/awards'); }}> The full list →
{/* Trusted by */}
Public, private & operator clients · selected
{['DEWA', 'KHDA', 'DIFC', 'MBRSC', 'Asia Asia', 'STK', 'Black Tap', 'Lock, Stock & Barrel', 'Viacom', 'Anantara', 'Make Up For Ever', 'Rixos', 'Grand Millennium', 'twofour54', 'DAFZA', 'HIPA'].map(c => (
{c}
))}
Some government and operator names withheld pending publication clearance.
); } function HeroBlock({ treatment, go }) { const hero = PROJECTS.find(p => p.hero) || PROJECTS[0]; if (treatment === 'split') return ; if (treatment === 'noir') return ; return ; } function HeroStill({ project, go }) { return (
{project.name}
Award-winning interior design + build · Dubai · since 1999

Intelligent,
innovative
design.

A boutique design and build consultancy — drawing and delivering F&B, office, government, leisure and residential interiors from a single studio in Barsha Heights.

№ 01 / Asia Asia
Pier 7, Dubai Marina · 2013 · World’s Best Leisure Interior, 2021
Scroll
); } function HeroSplit({ project, go }) { return (
Dubai · since 1999

Intelligent,
innovative
design.

Award-winning interior design + build consultancy. One studio. Five sectors. Seventy delivered projects.

{project.name}
№ 01 · Asia Asia
Pier 7, Dubai Marina · 2013
); } function HeroNoir({ project, go }) { return (
{project.name}
Broadway Interiors · est. 1999 · Dubai

Intelligent,
innovative
design.

); } function FeatureSpread({ project, index, go }) { const sector = SECTORS.find(s => s.id === project.sector); return ( { e.preventDefault(); go(`/projects/${project.slug}`); }}>
{project.name}
№ {String(index + 1).padStart(2, '0')}
{sector ? sector.label : project.sector} · {project.location}

{project.name}.

{project.tagline &&
{project.tagline}
}

{project.summary}

{project.scope}·{project.year}
Read the case study →
); } // ────────────────────────────────────────────────────────────────────── // Footer // ────────────────────────────────────────────────────────────────────── function Footer({ go }) { return ( ); } // ────────────────────────────────────────────────────────────────────── // Tweaks // ────────────────────────────────────────────────────────────────────── function TweaksUI() { const [t, setTweak] = useTweaks(TWEAK_DEFAULTS); useE(() => { const root = document.documentElement; root.style.setProperty('--accent', t.accent); root.dataset.type = t.type; root.dataset.darkChrome = t.darkChrome ? '1' : '0'; }, [t.accent, t.type, t.darkChrome]); return ( setTweak('accent', v)} /> setTweak('type', v)} /> setTweak('heroTreatment', v)} /> setTweak('darkChrome', v)} /> ); } // ────────────────────────────────────────────────────────────────────── // Root // ────────────────────────────────────────────────────────────────────── function App() { const [route, go] = useRoute(); const [scrolled, setScrolled] = useS(false); const [projFilter, setProjFilter] = useS('all'); const [t] = useTweaks(TWEAK_DEFAULTS); useE(() => { const onScroll = () => setScrolled(window.scrollY > 24); window.addEventListener('scroll', onScroll, { passive: true }); onScroll(); return () => window.removeEventListener('scroll', onScroll); }, []); let body = null; if (route.page === 'home') body = ; else if (route.page === 'projects') body = ; else if (route.page === 'case') body = ; else if (route.page === 'sectors') body = ; else if (route.page === 'sector') body = ; else if (route.page === 'about') body = ; else if (route.page === 'awards') body = ; else if (route.page === 'contact') body = ; else body = ; return (
{body}
); } ReactDOM.createRoot(document.getElementById('root')).render();