# 1. Overview & Architecture

## What this project is

The DCPH website is the public-facing marketing site for the **Data Center Operators of the Philippines**. It presents the alliance, its member operators, why the Philippines is a good location for data centers, news/announcements, and contact details.

It is a **static, content-driven marketing site**:

- There is **no backend, database, or content management system (CMS)**.
- All content — news articles, officer bios, facility listings, operator logos, contact details — is **hardcoded directly in the source code** as TypeScript arrays/objects.
- To change content, you **edit the code and redeploy**. The step-by-step instructions for every common change are in [Content Editing Recipes](05-content-editing-recipes.md).

This is the most important thing to understand about the project. "Adding a feature" or "updating the site" almost always means editing a data array in a `.tsx` file, not configuring an admin panel.

## Tech stack

| Layer            | Technology                          | Version (from `package.json`) | Notes                                                              |
| ---------------- | ----------------------------------- | ----------------------------- | ----------------------------------------------------------------- |
| Framework        | Next.js (App Router)                | `^16.2.1`                     | Handles routing, rendering, image optimization, fonts.            |
| UI library       | React                               | `19.2.3`                      | Component model + hooks (`useState`, `useEffect`, `useRef`).      |
| Language         | TypeScript                          | `^5`                          | Typed JavaScript. Files use `.tsx` (React) and `.ts`/`.mts`.      |
| Styling          | Tailwind CSS                        | `^4`                          | Utility-first CSS, configured CSS-first (no `tailwind.config.js`).|
| Maps             | Leaflet + react-leaflet             | `^1.9.4` / `^5.0.0`           | The interactive facility map on the Data Centers page.            |
| Carousel         | embla-carousel-react                | `^8.6.0`                      | The featured-news carousel on the News page.                      |
| Icons            | react-icons                         | `^5.6.0`                      | Icon set (Feather `Fi`, Font Awesome `Fa`, Bootstrap `Bs`, etc.). |
| Linting          | ESLint + `eslint-config-next`       | `^9` / `16.1.6`               | Code-quality checks via `npm run lint`.                           |

> ⚠️ `swiper` (`^12.1.3`) is listed as a dependency but is **not used anywhere** in the code. See [Known Issues](07-known-issues-and-maintenance.md).

## How Next.js App Router works here

This project uses Next.js's **App Router** (the `app/` directory). A few concepts you need:

### File-based routing

Each folder inside `app/` that contains a `page.tsx` becomes a URL route. The folder name is the URL path.

| Folder                | URL                       |
| --------------------- | ------------------------- |
| `app/page.tsx`        | `/` (home)                |
| `app/about/`          | `/about`                  |
| `app/whyph/`          | `/whyph`                  |
| `app/data-centers/`   | `/data-centers`           |
| `app/contact-us/`     | `/contact-us`             |
| `app/news/`           | `/news`                   |
| `app/news/[slug]/`    | `/news/<anything>`        |

`[slug]` is a **dynamic route**: the part of the URL in brackets is a variable. `/news/dcph-mou-signing` and `/news/ptc-2026-global-mission` both render `app/news/[slug]/page.tsx`, with `slug` set to the matching value. See [Pages & Components](04-pages-and-components.md#newsslug--app-newsslugpagetsx).

### The root layout

`app/layout.tsx` wraps **every** page. It defines the `<html>`/`<body>` tags, loads the two Google Fonts (Montserrat + Orbitron), and sets the default site `<title>` and metadata. Anything that should appear on every page (or global setup) goes here.

### Server vs. Client Components

This is the one Next.js concept that trips people up most. Every component is a **Server Component by default**. A file becomes a **Client Component** only if its first line is `"use client";`.

- **Server Components** render on the server. They cannot use browser-only features: no `useState`, `useEffect`, `onClick`, etc. They're great for static content and SEO.
- **Client Components** run in the browser. You need `"use client";` at the top whenever the file uses React hooks or event handlers (clicks, hovers, typing, timers).

Quick reference for this project:

| File                         | `"use client"`? | Why                                                       |
| ---------------------------- | --------------- | --------------------------------------------------------- |
| `app/layout.tsx`             | No              | Static shell.                                             |
| `app/page.tsx`               | No              | Just composes other components.                           |
| `app/about/page.tsx`         | **Yes**         | Flip-card carousel uses state + timers.                   |
| `app/whyph/page.tsx`         | **Yes**         | Accordion + video modal use state.                        |
| `app/data-centers/page.tsx`  | **Yes**         | Search box + location filter use state.                   |
| `app/contact-us/page.tsx`    | No              | Fully static.                                             |
| `app/news/page.tsx`          | **Yes**         | Carousel + search use state.                              |
| `app/news/[slug]/page.tsx`   | No              | Renders article data; also exports `generateMetadata`.    |
| `components/Header.tsx`       | **Yes**         | Mobile menu toggle + active-link highlighting.            |
| `components/Footer.tsx`       | No              | Static.                                                   |
| `components/Landing.tsx`      | **Yes**         | Hover panels + scroll tracking.                           |
| `components/Landing_bg.tsx`   | **Yes**         | Auto-rotating background timer.                           |
| `components/Officers.tsx`     | No              | Static presentation.                                      |
| `components/News.tsx`         | No              | Static (and currently unused).                            |

> **Rule of thumb:** if you add an `onClick`, `useState`, `useEffect`, or any interactivity to a file, make sure `"use client";` is the very first line — otherwise the build will fail with an error about hooks in a Server Component.

## How a page is assembled

Most pages follow the same shape: a `<Header />` at the top, page-specific content in the middle, and a `<Footer />` at the bottom. The home page is the clearest example:

```
app/page.tsx
 ├── <Header />        components/Header.tsx     (nav bar, same on every page)
 ├── <Landing_bg />    components/Landing_bg.tsx (hero with rotating background)
 ├── <Landing />       components/Landing.tsx    (operators, "why PH", news, contact)
 └── <Footer />        components/Footer.tsx     (links + copyright, same on every page)
```

`Header` and `Footer` are imported into nearly every page individually (the project does **not** put them in the root layout). If you ever add a new page, remember to import and render `<Header />` and `<Footer />` yourself — see [Recipe: Add a brand-new page](05-content-editing-recipes.md#recipe-add-a-brand-new-page).

## Where content lives (the mental model)

Because there's no CMS, here's where each kind of content is defined:

| Content                          | File(s)                                                                                          |
| -------------------------------- | ------------------------------------------------------------------------------------------------ |
| News articles (full text)        | `app/news/[slug]/page.tsx` → `articles` object                                                   |
| News listing cards               | `app/news/page.tsx` → `newsItems` (featured) + `newsArticles` (grid)                             |
| News cards on the home page      | `components/Landing.tsx` (hardcoded, 3 cards)                                                     |
| Data center facilities           | `app/data-centers/page.tsx` → `facilities` array                                                 |
| Facility map pins                | `app/data-centers/FacilityMap.tsx` → `facilityCoordinates`                                       |
| Officers / Board of Trustees     | `app/about/page.tsx` → `officers` array                                                          |
| Member operators (logos/cards)   | `components/Landing.tsx` → `operators` array + marquee logos; `components/Landing_bg.tsx`        |
| "Why Philippines" advantages     | `app/whyph/page.tsx` → `accordionItems` array                                                    |
| Purpose / Mission / Vision       | `app/about/page.tsx` → `cards` array                                                              |
| Contact details (phone/email)    | `app/contact-us/page.tsx` **and** `components/Landing.tsx`                                        |
| Navigation links                 | `components/Header.tsx` → `navLinks` array (and a duplicated set in `components/Footer.tsx`)      |

> ⚠️ Several pieces of content are **duplicated** across files (news appears in 3 places, contact info in 2, officer names in 2). When you change one, check the others. The recipes call out every location.

## Rendering & data flow summary

- There are no API calls and no data fetching from external services at runtime. Everything is bundled at build time.
- Images are either **imported** (from `assets/`, processed by Next's `<Image>` for optimization) or **referenced by URL** (from `public/`, served as-is). See [Project Structure](03-project-structure.md#assets-vs-public).
- The map (`FacilityMap`) is loaded **client-side only** (`dynamic(..., { ssr: false })`) because Leaflet needs the browser's `window` object.

Next: [Getting Started →](02-getting-started.md)
