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.
| Group | Collections | What lives here |
|---|---|---|
| Pages | pages, page_sections, seo_landing_pages, legal_pages, docs_pages | Marketing pages and page-like content |
| Blog | blog_posts, blog_categories, team_members | Articles + authors + taxonomy |
| Marketing | services, pricing_plans, testimonials, faqs, case_studies, portfolio_projects | Social proof and offer-related content |
| Navigation | navigation, footer_groups, footer_links | Header + footer links |
| System | form_submissions, languages | Contact-form inbox + supported locales |
| Top-level | site_settings (singleton) | Brand name, contact info, default SEO, social links |
Editing an item
- Sign into the admin at
http://localhost:8055(or your production URL). - Click the collection in the sidebar: e.g. Services under Marketing.
- Click any row to open the edit view.
- Scroll to the Translations section, click any language tab (English / Français / Español), and edit the translated fields (title, description, features).
- 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: thehomepage is special; itspage_sectionschild drives the homepage hero, features, testimonials, pricing, FAQ, CTA blocks. Each section has its owntype(hero, features, cta, etc.) andpayloadJSON for arbitrary structured data.blog_posts:status: publishedis 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.seofields: every page-like collection has anseoJSON field rendered by the@directus-labs/seo-pluginwith 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
- Open
languagescollection → create a row (e.g.{ code: "de", name: "Deutsch", direction: "ltr" }). - Open any content item → Translations tab will now show a new "Deutsch" tab alongside EN/FR/ES.
- Fill in translations.
- On the frontend, add
"de"tolocalesinfrontend/src/config/i18n.tsand createfrontend/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
- Hosting & Deployment: push the CMS + frontend to production.
- Implementation Status: what is live vs. roadmap.