Vue d'ensemble : Site Société
README.md
NOVA is a one-page landing page for an AI product, built with Next.js 15, TypeScript and Tailwind CSS, in English and Arabic. It has a hero, a logo and stats row, how it works, a features tab view, integrations, testimonials, a blog preview, pricing with a monthly and yearly toggle, an FAQ and a closing call to action. It is a single page: the blog cards, the menu links and the buttons are placeholders for your own pages and actions.
Live Demo & More Info: aniq-ui.com NOVA Template
Getting Started
Requirements
- With Docker: Docker Desktop (or Docker Engine) and nothing else.
- Without Docker: Node.js 22 or newer, and Yarn 4. The repository pins Yarn 4 through
packageManager; if theyarncommand is missing, runcorepack enableonce.
Path A: Docker
From this folder:
docker build -t company-site .
docker run -p 3030:3030 company-siteOpen http://localhost:3030. English is at /en, Arabic at /ar.
Path B: without Docker
yarn install
yarn devOpen http://localhost:3030. The development server reloads as you edit.
For the production build:
yarn build
yarn startIt is served on http://localhost:3030 too.
A port is already in use?
Another program is using port 3030. Stop it, or use another port:
- Docker: change the left number, for example
docker run -p 3041:3030 company-site, then open http://localhost:3041. - Without Docker:
yarn dev -p 3041(oryarn start -p 3041), then open http://localhost:3041.
Environment variables
The site runs without a .env file. It reads one optional variable, listed in .env.example:
| Variable | Default | What it does |
|---|---|---|
NEXT_PUBLIC_SITE_URL | http://localhost:3030 | The address the site is served from. The canonical link, the language alternates and the social sharing image are built from it. |
Set it to your real domain before you deploy. It is read at build time, so build again after changing it:
- Without Docker:
cp .env.example .env, edit the value, thenyarn build. - Docker:
docker build -t company-site --build-arg NEXT_PUBLIC_SITE_URL=https://www.your-domain.com .
Scripts
| Command | What it does |
|---|---|
yarn dev | Development server on port 3030 |
yarn build | Production build |
yarn start | Serves the production build on port 3030 |
yarn lint | ESLint (Next.js rules) |
yarn typecheck | TypeScript check (tsc --noEmit) |
Customizing
| What | Where |
|---|---|
| Text, in every language | messages/en.json and messages/ar.json (same keys in both) |
| Brand name | brand.name in messages/en.json and messages/ar.json. Every text that names the brand says {brand} and takes this value, and so does the installed app's name (src/app/manifest.ts reads it from the default locale) |
| Page title and description | metadata in both message files |
| Images | public/images/ (hero, how it works steps, the first feature, the Slack and Salesforce logos), referenced from each section's constants/ folder |
| Remote images and logos | The blog preview, testimonial and feature photos come from Unsplash (images.unsplash.com), and most logos from Simple Icons (cdn.simpleicons.org). They are set in the constants/ folder of the BlogPreview, Testimonials, Features, Integrations and SocialProof sections. Replace them with your own files in public/images/ before you go live. An image from any other remote host must be added to images.remotePatterns in next.config.mjs |
| Logo mark | src/components/Logo.tsx |
| Favicon and app icons | public/favicon.svg, public/favicon.ico, public/apple-touch-icon.png, public/web-app-manifest-*.png; the manifest itself is src/app/manifest.ts |
| Social sharing image | public/image.png (1200 x 630) |
| Colours | The red to amber accent gradient is written as Tailwind classes (from-red-500, to-amber-500) in the components, starting with src/components/GradientButton.tsx; theme tokens are in src/app/globals.css and tailwind.config.ts |
| Fonts | src/app/[locale]/layout.tsx: Inter for English, Noto Sans Arabic for Arabic, both through next/font/google |
| Sections on the page and their order | src/app/[locale]/page.tsx |
Languages
The site is localized with next-intl and ships two locales:
| Locale | Language | Direction |
|---|---|---|
en | English (default) | LTR |
ar | Arabic | RTL |
- Routes are prefixed with the locale:
/en,/ar. src/middleware.tssends/to the browser's language when it isenorar, and to English otherwise.- `
is set from the locale, and layout uses logical Tailwind classes (ms-,pe-,start-*,text-start`...) so RTL mirrors automatically. - All copy lives in
messages/en.jsonandmessages/ar.json. Both files must keep the same keys. - Components read text with
useTranslations; constants only hold keys, ids, routes, icons, image paths and numbers. - A locale switcher sits in the header (
src/components/LocaleSwitcher.tsx), with one link for every other locale.
To add a locale, add its code to src/i18n/routing.ts, create messages/.json, and add the locale name under localeSwitcher.names in every messages file. If it is right-to-left, list it in src/i18n/direction.ts.
Project Structure
messages/ # en.json, ar.json
src/
├── app/
│ ├── globals.css
│ ├── manifest.ts # web app manifest, named after brand.name
│ └── [locale]/ # layout.tsx (html, providers, metadata) and page.tsx (home composition)
├── i18n/ # routing, request config, locale-aware navigation, text direction
├── middleware.ts # locale negotiation
├── components/ # Shared components (Logo, Reveal, SectionHeader, GlowFrame, LocaleSwitcher...)
│ └── ui/ # UI primitives (Button, Accordion, Tabs)
├── features/home/ # One folder per page section
│ └── <Section>/
│ ├── index.tsx # Composition only
│ ├── components/ # One component per file + index.ts barrel
│ ├── hooks/ # One hook per file + index.ts barrel
│ ├── constants/ # Keys, ids, images, numbers
│ └── types/
├── layouts/ # Header and Footer, same subfolder convention
├── hooks/ # Shared hooks (useTextDirection, useBrandName)
├── lib/ # cn() helper, site URL
└── providers/ # ThemeProviderBarrel index.ts files only re-export.
Adding a Section or Page
- Create the section folder under
src/features///using the layout above. - Add its copy to both
messages/en.jsonandmessages/ar.json, and read it withuseTranslations(""). - Compose it in
src/app/[locale]//page.tsx. CallsetRequestLocale(locale)at the top of a page so it stays statically rendered. - Use logical spacing classes and add
rtl:rotate-180to arrows and chevrons that point in a reading direction.
Styling
- Tailwind CSS with CSS variables for theme colors in
globals.css. - The page is designed dark.
next-themessets thedarkclass on ``. - Entrance animations go through the shared
Revealcomponent.
Tech Stack
| Technology | Purpose |
|---|---|
| Next.js 15 | React framework with App Router |
| next-intl | Localization (en, ar) |
| TypeScript | Type safety |
| Tailwind CSS | Utility-first styling |
| Framer Motion | Animations |
| Radix UI | Accordion, Tabs |
| Lucide React | Icons |
| next-themes | Theme management |
| Embla Carousel | Mobile carousels |
All dependencies are pinned to exact versions and yarn.lock is committed.
Support
For questions or support, contact the Aniq UI team.
License
This project is licensed under the MIT License. See the LICENSE file for details.
Created by Aniq UI, premium Next.js templates for modern web apps.