# 5. Content Editing Recipes ⭐

This is the practical "how do I change X?" guide. Because the site has **no CMS**, every change here is a code edit followed by a redeploy.

**Before you start any recipe:**
1. `npm run dev` and keep <http://localhost:3000> open so you see changes live.
2. Make your edit.
3. Check it in the browser.
4. When done, `npm run build` to confirm no errors, then commit/push to deploy ([Getting Started → Deployment](02-getting-started.md#deployment)).

> **General tips**
> - In these data arrays, items are separated by commas. Keep the commas and the `{ }` braces matched.
> - Text containing an apostrophe inside double quotes is fine (`"DCPH's mission"`). If you write a string in single quotes, escape inner apostrophes or just use double quotes.
> - After editing, if the page is blank or the terminal shows a red error, re-read the error — it usually names the file and line.

---

## Recipe: Add or edit a news article

⚠️ **Read this first.** News content is duplicated in **up to three places**. To fully add an article it must exist in all the relevant spots, or links will 404 and the article won't show in every list.

| # | File | Array / location | Controls |
| - | ---- | ---------------- | -------- |
| 1 | `app/news/[slug]/page.tsx` | `articles` object | **The actual article page and its text.** Required. |
| 2 | `app/news/page.tsx` | `newsArticles` array | The card in the `/news` grid. |
| 3 | `app/news/page.tsx` | `newsItems` array | The featured carousel at the top of `/news` (optional — only for highlighted stories). |
| 4 | `components/Landing.tsx` | "Latest News & Updates" section | The 3 cards on the **home page** (optional — only the latest few). |

### Step 1 — Create the article body (required)

In `app/news/[slug]/page.tsx`, add a new entry to the `articles` object. The **key** is the URL slug (lowercase, hyphenated, no spaces):

```ts
const articles: Record<string, Article> = {
  // …existing articles…

  "my-new-article-slug": {
    slug: "my-new-article-slug",
    title: "Your Headline Goes Here",
    date: "March 2026",
    author: "DCPH Communications Team",
    image: "/images/Article 5_1.jpg",   // see "Add the images" below
    content: [
      { type: "paragraph", text: "Opening paragraph (this one renders emphasized)." },
      { type: "heading", text: "A Section Heading" },
      { type: "paragraph", text: "More body text." },
      { type: "image-grid", images: ["/images/Article 5_2.jpg", "/images/Article 5_3.jpg"] },
      { type: "paragraph", text: "Closing paragraph." },
      { type: "image", images: ["/images/Article 5_4.jpg"] },
    ],
  },
};
```

Block `type` options: `paragraph`, `heading`, `subheading`, `image` (single, uses `images[0]`), `image-grid` (two columns, uses `images`). See [Pages & Components](04-pages-and-components.md#news-article--appnewsslugpagetsx).

### Step 2 — Add the images

Put the image files in `public/images/`. They're referenced by URL string (e.g., `"/images/Article 5_1.jpg"`). The existing articles follow the `Article N_x.jpg` naming convention — match it for tidiness, but any filename works as long as the string matches.

### Step 3 — Add it to the listing grid

In `app/news/page.tsx`, add to `newsArticles` (give it a new `id`):

```ts
{
  id: 5,
  category: "News",
  title: "Your Headline Goes Here",
  description: "One- or two-sentence summary for the card.",
  date: "March 2026",
  image: "/images/Article 5_1.jpg",
  slug: "my-new-article-slug",   // MUST match the key from Step 1
},
```

### Step 4 (optional) — Feature it / show it on the home page

- To feature it in the `/news` carousel: add a matching entry to `newsItems` in `app/news/page.tsx`.
- To show it on the home page: edit the "Latest News & Updates" block in `components/Landing.tsx`. These cards are written out individually (not from an array), so copy an existing `<Link href="/news/...">…</Link>` card and update its `href`, image `src`, date, title, and summary. You'll typically replace the oldest of the three.

### Editing or removing an article

- **Edit:** change the fields in whichever array(s) hold it. Update the title/description everywhere it appears.
- **Remove:** delete its entry from `articles` (Step 1) and from `newsArticles`/`newsItems` and the home-page cards. If you remove it from `articles` but leave a link elsewhere, that link will 404.

> ✅ **Sanity check:** the `slug` in the listing must equal the **key** in `articles`. Mismatched slugs are the #1 cause of broken news links.

---

## Recipe: Add, edit, or remove a data center facility

Two files must agree on the facility **name**.

### Step 1 — Add the facility card

In `app/data-centers/page.tsx`, add to the `facilities` array:

```ts
{
  name: "New Operator Data Center",
  location: "City, Province",          // e.g. "Biñan, Laguna"
  tags: ["COLOCATION", "HYPERSCALE"],  // any of these strings
  linkedin: "https://www.linkedin.com/company/their-page/",
},
```

`tags` drive the card icons: `"HYPERSCALE"` shows a server icon, anything else shows a data icon.

### Step 2 — Add the map pin

In `app/data-centers/FacilityMap.tsx`, add to `facilityCoordinates`. **The key must exactly match the `name` from Step 1:**

```ts
const facilityCoordinates = {
  // …existing…
  "New Operator Data Center": {
    coords: [14.2345, 121.0678],   // [latitude, longitude]
    color: "#333333",
  },
};
```

To get coordinates: open [Google Maps](https://maps.google.com), right-click the location, and click the lat/long pair to copy it — it's already in `latitude, longitude` order.

### Step 3 — (only if it's in a new province) update the filter

The location filter buttons are the `locations` array in `app/data-centers/page.tsx`:

```ts
const locations = ["ALL LOCATIONS", "QUEZON CITY", "LAGUNA", "BATANGAS", "RIZAL"];
```

If the new facility is in a province not listed, add the province name (UPPERCASE) here **and** add a matching condition in the `matchesLocation` logic just below the array (copy one of the existing `(selectedLocation === "LAGUNA" && …)` lines).

> ✅ **If a facility appears in the list but has no map pin**, the name in `facilityCoordinates` doesn't match the name in `facilities`. They must be byte-for-byte identical.

**Edit/remove:** change or delete the entry in both `facilities` and `facilityCoordinates`.

---

## Recipe: Add or edit an officer / board member

In `app/about/page.tsx`, edit the `officers` array:

```ts
import NewPerson from "../../assets/NewPerson.png";   // add at top with the other imports

const officers = [
  // …existing…
  {
    imagePath: NewPerson,
    name: "Full Name",
    position: "Trustee",
    linkedIn: "https://www.linkedin.com/in/their-profile/",
  },
];
```

Steps:
1. Add the portrait image to the **`assets/`** folder (officers use imported images, not `public/`).
2. Add an `import` for it at the top of `app/about/page.tsx`.
3. Add the object to `officers`.

> ⚠️ Officer **names also appear** as `subheading` blocks in the `dcph-officers-trustees` article inside `app/news/[slug]/page.tsx`. If the board changes, update that article too.

---

## Recipe: Edit the member operators

Operators show up in three places, all in two files:

| Where | File | What to edit |
| ----- | ---- | ------------ |
| Home hero rotating background | `components/Landing_bg.tsx` | `backgroundImages` array (imported photos) |
| Home logo marquee | `components/Landing.tsx` | the `<li><Image .../></li>` logo list (appears **twice** — it's duplicated for the seamless scroll loop) |
| Home "Meet our Operators" panels | `components/Landing.tsx` | `operators` array (`{ src, alt, name, linkedin }`) |
| Facility listing | `app/data-centers/page.tsx` | `facilities` array (see facility recipe) |

For a new operator you'd typically: add its logo + photo to `assets/`, import them, then add entries to `operators` (and the marquee, and `backgroundImages`) in the home-page components, plus a `facilities` entry on the Data Centers page.

---

## Recipe: Update contact info (phone / email)

⚠️ Contact details live in **two** files. Update both:

1. `app/contact-us/page.tsx` — the EMAIL and PHONE blocks, and the `mailto:` link in the "Email Us" button.
2. `components/Landing.tsx` — the "CONNECT WITH US" section near the bottom (phone, both emails).

Current values: phone `+63 908 399 4599`; emails `info@dcph.org` and `secretariat@datacenterph.org`; LinkedIn `https://www.linkedin.com/company/datacenterph/`.

---

## Recipe: Swap the "Why Philippines" video

1. Put your new video file in `public/` (e.g., `public/WHY_PHILIPPINES.mp4`).
2. If you keep the same filename, no code change is needed — it's referenced in `app/whyph/page.tsx` as `<source src="/WHY_PHILIPPINES.mp4" type="video/mp4" />`.
3. If you use a different filename or format, update that `src` (and `type`) string.

---

## Recipe: Edit the "Why Philippines" advantages

All six advantage sections and their statistics are in the `accordionItems` array at the top of `app/whyph/page.tsx`. Each section:

```ts
{
  id: 0,
  icon: location,            // imported icon image (from assets/)
  iconAlt: "location",
  label: "STRATEGIC DIGITAL GATEWAY",
  content: [
    { icon: globe, iconAlt: "globe", title: "Geography Access", description: "…the stat/claim text…" },
    // 3 sub-items per section
  ],
},
```

To change a statistic (e.g., "473 MW", "~10,100 MW total clean energy"), edit the relevant `description` string. To change an icon, import a new image into `assets/` and swap the `icon` reference.

> Note: the **"473 MW"** combined-capacity figure on the *About* page is separate — it's hardcoded in the "Who We Are" paragraph of `app/about/page.tsx`, not here.

---

## Recipe: Edit Purpose / Mission / Vision

In `app/about/page.tsx`, edit the `cards` array. Each card: `{ id, title, icon, color, content }`. `icon` is a `react-icons` component (e.g., `FaHandshake`); `color` is the accent hex used for the border and title.

---

## Recipe: Change the navigation menu

Edit `navLinks` in `components/Header.tsx`:

```ts
const navLinks = [
  { label: "Home", href: "/" },
  { label: "About Us", href: "/about" },
  // add / reorder / rename here
];
```

> ⚠️ The footer has its **own hardcoded copy** of these links in `components/Footer.tsx` (written as individual `<Link>` elements, not from `navLinks`). If you add or rename a page, update the footer too.

---

## Recipe: Add a brand-new page

Say you want `/resources`:

1. Create `app/resources/page.tsx`.
2. Start it like an existing page. If it needs interactivity (state, clicks), make the first line `"use client";`.
3. Import and render the shared chrome yourself — pages add `Header`/`Footer` individually:
   ```tsx
   import Header from "../../components/Header";
   import Footer from "../../components/Footer";

   export default function Resources() {
     return (
       <div className="flex flex-col min-h-screen bg-white">
         <Header />
         {/* your content */}
         <Footer />
       </div>
     );
   }
   ```
4. Add it to the nav: `navLinks` in `components/Header.tsx` (and the footer links).

---

## Recipe: Replace the logo or favicon

- **Logo:** replace `assets/dcph_logo.png` (keep the filename) — it's imported by both `Header.tsx` and `Footer.tsx`. If you change the filename, update both imports.
- **Browser tab icon (favicon):** replace `app/favicon.ico` and/or `app/icon.png`. Next.js serves these automatically from the `app/` folder.
  > Note: `app/layout.tsx` also has an `icons: { icon: "/favicon.png" }` metadata entry that points to a file that **doesn't exist**. It's harmless (the `app/icon.png` convention wins), but you can remove that line or create a real `public/favicon.png`. See [Known Issues](07-known-issues-and-maintenance.md).

---

## Recipe: Update the site title / SEO metadata

- **Site-wide title & description:** `app/layout.tsx` → the `metadata` object.
- **Per-article SEO (Open Graph / Twitter):** generated automatically in `app/news/[slug]/page.tsx` by `generateMetadata`. The canonical domain is the `BASE_URL = "https://dcph.ph"` constant — change it if the production domain changes.

---

## Recipe: Add a new image (which folder?)

- Will you use it inside a Next.js `<Image src={...}>` (logos, photos, icons)? → put it in **`assets/`** and `import` it.
- Will you reference it by a URL string (`<img src="/...">`, a CSS `url(...)`, news article images, video)? → put it in **`public/`**.

See [Project Structure → assets vs public](03-project-structure.md#assets-vs-public).

Next: [Styling & Design System →](06-styling-and-design-system.md)
