Novael
Bilingual (EN/AR) landing page for a technology services firm: a fixed scroll-spy navbar over a headline that sits on a photographic band, an overlapping intro card and count-up stats, a marquee of past employers, a teal service slab, a project grid whose captions expand on hover, and a contact section that doubles as the footer. Self-contained dark palette, Inter + Manrope with Cairo for Arabic, and RTL that follows the surrounding document.
Preview
Installation
npx shadcn@latest add https://hirael.com/r/novael.jsonCode
components/templates/novael/novael.tsx
'use client';
import * as React from 'react';
import { cn } from '@/lib/utils';
import { Contact } from './contact';
import { cairo, inter, manrope } from './fonts';
import { Hero } from './hero';
import { Navbar } from './navbar';
import { useDocumentRtl, type Lang } from './primitives';
import { Services } from './services';
import { NovaelStyles } from './styles';
import { Team } from './team';
import { Works } from './works';
const Novael = () => {
// The page opens in whatever direction the surrounding document reads, then
// follows the in-page switcher. The choice stays on this root — nothing is
// written to `<html>`, so the template is safe to drop into a page that
// already owns the document's direction.
const [langOverride, setLangOverride] = React.useState<Lang | null>(null);
const docIsRtl = useDocumentRtl();
const lang: Lang = langOverride ?? (docIsRtl ? 'ar' : 'en');
return (
<div
className={cn(
'novael',
inter.variable,
manrope.variable,
cairo.variable,
'flex min-h-svh flex-col bg-background text-foreground antialiased',
)}
dir={lang === 'ar' ? 'rtl' : 'ltr'}
lang={lang}
>
<NovaelStyles />
<Navbar lang={lang} setLang={setLangOverride} />
<main className="flex-1">
<Hero lang={lang} />
<Team lang={lang} />
<Services lang={lang} />
<Works lang={lang} />
<Contact lang={lang} />
</main>
</div>
);
};
export default Novael;
Dependencies
shadcn registry
buttonmarquee
npm
lucide-react
Shipped