Content Management

Every page on the Agency site reads from Directus. Non-developers can edit copy in all three supported locales (EN, FR, ES) without touching the repo.

Content collections

The sidebar in the Directus admin groups collections by concern. Every collection has an icon, color, and display template so list views are readable at a glance instead of showing UUIDs.

GroupCollectionsWhat lives here
Pagespages, page_sections, seo_landing_pages, legal_pages, docs_pagesMarketing pages and page-like content
Blogblog_posts, blog_categories, team_membersArticles + authors + taxonomy
Marketingservices, pricing_plans, testimonials, faqs, case_studies, portfolio_projectsSocial proof and offer-related content
Navigationnavigation, footer_groups, footer_linksHeader + footer links
Systemform_submissions, languagesContact-form inbox + supported locales
Top-levelsite_settings (singleton)Brand name, contact info, default SEO, social links

Editing an item

  1. Sign into the admin at http://localhost:8055 (or your production URL).
  2. Click the collection in the sidebar: e.g. Services under Marketing.
  3. Click any row to open the edit view.
  4. Scroll to the Translations section, click any language tab (English / Français / Español), and edit the translated fields (title, description, features).
  5. Click the checkmark (top right) to save.

Frontend picks up the change within ~60 seconds via Next.js incremental cache revalidation: no rebuild needed.

Per-collection tips

  • pages: the home page is special; its page_sections child drives the homepage hero, features, testimonials, pricing, FAQ, CTA blocks. Each section has its own type (hero, features, cta, etc.) and payload JSON for arbitrary structured data.
  • blog_posts: status: published is required for public visibility. Drafts stay invisible on the frontend.
  • site_settings: singleton: there's exactly one row. Drives footer text, contact info, default SEO, Organization + LocalBusiness JSON-LD.
  • seo fields: every page-like collection has an seo JSON field rendered by the @directus-labs/seo-plugin with a live Search Preview and character-count hints.
  • form_submissions: read-only for the Public role (writes only). Every contact-form submission lands here.

Adding a new language

  1. Open languages collection → create a row (e.g. { code: "de", name: "Deutsch", direction: "ltr" }).
  2. Open any content item → Translations tab will now show a new "Deutsch" tab alongside EN/FR/ES.
  3. Fill in translations.
  4. On the frontend, add "de" to locales in frontend/src/config/i18n.ts and create frontend/src/messages/de.json.

The Directus side needs no code change: new languages are data, not schema.

Where content translation is NOT done

Do not use the /admin/settings/translations page. That system (directus_translations) handles UI string keys via $t: references: unrelated to per-row content translations. Leave it empty; content translations happen inside each item's Translations tab.

Previewing changes

The frontend is rendered with Next.js App Router. Preview is available by default: edits save immediately in Directus, and the frontend serves the new content within one revalidation cycle. For draft-aware previews before publish, wire up DIRECTUS_PREVIEW_TOKEN and Directus preview URLs pointing at /api/preview.

Next steps