Dyrected
GuidesNuxt

Let Editors Build Custom Pages in Nuxt with Dyrected

Set up Dyrected so your marketing and content team or clients can build new landing pages from approved reusable sections without waiting on a developer for every copy and layout change.

Use this page after Adding a Visual Editor in Nuxt. At this point, the important pieces should already exist:

  • the pages collection exists
  • the frontend can render Dyrected content
  • preview can open the real route and reflect edits

Now the goal changes. Instead of proving the integration works, you are deciding whether the setup is ready for editors to build real campaign and landing pages without developer help for every change.

By the end, you should know what a safe custom-page workflow looks like, which parts must stay controlled by code, and how the schema, rendering, and preview pieces fit together into one editor-ready system.

Start with the right mental model

For custom landing pages, the goal is usually not "let editors design anything." The goal is "let editors assemble approved page sections fast."

That means the safest setup is:

  • the frontend keeps the design system
  • the schema defines the approved section types
  • editors choose the order and content inside those sections

In Dyrected, that setup is usually:

  • a pages collection with a layout blocks field
  • a Nuxt renderer that maps each blockType to a real component
  • a preview setup that opens the real page while editors are working

Choose the sections editors should actually control

Before you write any code, list the section types the team needs most often.

A strong first set is usually small:

  • hero
  • feature grid
  • testimonial
  • call to action

If a section is not already designed in the frontend, do not add it yet. The fastest dashboard is the one that only offers sections the site already knows how to render well.

Add a layout blocks field to the pages collection

If you have not already done it during the earlier schema steps, this is the key schema change that turns a basic page model into a controlled landing-page builder.

import {
  defineBlock,
  defineBlocksField,
  defineCollection,
  defineRelationshipField,
  defineRichTextField,
  defineTextField,
  defineTextareaField,
  defineUrlField,
} from "@dyrected/core";

const HeroBlock = defineBlock({
  slug: "hero",
  labels: { singular: "Hero", plural: "Heroes" },
  fields: [
    defineTextField({ name: "heading", label: "Heading", required: true }),
    defineTextareaField({ name: "subheading", label: "Subheading" }),
    defineTextField({ name: "ctaLabel", label: "CTA label" }),
    defineUrlField({ name: "ctaUrl", label: "CTA URL" }),
    defineRelationshipField({
      name: "image",
      label: "Image",
      relationTo: "media",
    }),
  ],
});

const FeatureGridBlock = defineBlock({
  slug: "featureGrid",
  labels: { singular: "Feature grid", plural: "Feature grids" },
  fields: [
    defineTextField({ name: "heading", label: "Heading", required: true }),
    defineRichTextField({ name: "intro", label: "Intro" }),
  ],
});

const TestimonialBlock = defineBlock({
  slug: "testimonial",
  labels: { singular: "Testimonial", plural: "Testimonials" },
  fields: [
    defineTextField({ name: "quote", label: "Quote", required: true }),
    defineTextField({ name: "name", label: "Name", required: true }),
    defineTextField({ name: "role", label: "Role" }),
  ],
});

const CallToActionBlock = defineBlock({
  slug: "callToAction",
  labels: { singular: "Call to action", plural: "Calls to action" },
  fields: [
    defineTextField({ name: "heading", label: "Heading", required: true }),
    defineTextareaField({ name: "body", label: "Body" }),
    defineTextField({ name: "label", label: "Button label", required: true }),
    defineUrlField({ name: "url", label: "Button URL", required: true }),
  ],
});

export const Pages = defineCollection({
  slug: "pages",
  labels: { singular: "Page", plural: "Pages" },
  admin: {
    useAsTitle: "title",
    previewUrl: "slug == 'home' ? '/' : '/' + slug",
    urlPattern: "/{slug}",
  },
  fields: [
    defineTextField({ name: "title", label: "Title", required: true }),
    defineTextField({ name: "slug", label: "Slug", required: true }),
    defineBlocksField({
      name: "layout",
      label: "Page layout",
      blocks: [HeroBlock, FeatureGridBlock, TestimonialBlock, CallToActionBlock],
    }),
  ],
});

This keeps the page structure flexible, but only inside the set of blocks you approved.

Make sure the frontend can render every approved section

The dashboard is only half of the workflow. Every approved block also needs a matching Nuxt component in the frontend.

That means:

  • every blockType in the schema must map to a real component
  • the page route must render the layout field in order
  • preview must open the same route editors are trying to build

If one of those pieces is missing, this stops being a custom-page workflow and turns back into a schema exercise.

Keep the page builder controlled

This is where the setup either stays useful or becomes messy.

For a quick-start editorial workflow:

  • keep global site chrome like navigation and settings outside the page layout
  • keep one block focused on one visible section type
  • keep field names content-focused, not implementation-focused
  • avoid adding arbitrary JSON fields or open-ended style controls

A good page builder helps marketing move fast inside guardrails. It should not ask them to invent layout rules the frontend does not already understand.

Build one real landing page in the dashboard

Once schema, rendering, and preview all exist, create one real landing page in the admin and add a few sections in order:

  1. a hero
  2. a feature grid
  3. a testimonial
  4. a call to action

Then open that page in preview and make one real editorial change: update the hero copy, reorder a section, or replace a call to action.

That is the moment this guide is aiming for. It proves editors are no longer just editing fields. They are building a real page inside the system you prepared for them.

Know what this page depends on

This workflow only works because the earlier quick-start pages already handled the pieces below:

This page is where those pieces finally become one editor-ready landing-page workflow.

What this setup gives editors

Once this is in place, the dashboard can support the tasks marketing teams usually care about most:

  • create a new landing page
  • reorder approved page sections
  • update hero copy, proof, and calls to action
  • publish a campaign page without asking a developer for every text edit

What it does not do is allow arbitrary new section types or arbitrary design changes. That stays with the product or frontend team, which is usually the safer split.

Where to go deeper

Use this page for the quick-start version of the pattern. For the full background, continue to:

Success check

You are ready for the next step when:

  • the pages collection has a layout blocks field
  • the allowed block types match real designed page sections
  • the frontend renders those sections correctly
  • preview reflects changes on a real page
  • the dashboard can create at least one landing page from those approved sections

Once that is true, your Nuxt quick start is complete. When you are ready to give access to another person, continue to Handing Off to Editors.

On this page

Dyrected| Cloud

Get your backend ready in minutes

Use a managed database, storage, APIs, and admin dashboard without setting up the infrastructure yourself.

Set Up My Backend