Services Controller — The /services/ Listing Page

Configure the /services/ listing page in Dax Pro: pagination, ordering, and card layout. The services controller generates the listing automatically from content/services/*.md. Edit via Decap CMS or directly in content/services.md.

What a Controller Is

Every collection in Dax Pro — posts, services, tags — has a controller file. A controller is a Markdown file in content/ that is not itself a piece of content, but a configuration for a generated listing page.

The controller for services is:

content/services.md

When Dax Pro builds the site, it reads this file and generates:

  • /services/ — the listing page (page 1)
  • /services/page/2/ — page 2, if there are more than pagination items
  • /services/page/3/ — page 3, and so on
  • Without the controller, individual service pages in content/services/*.md would still be built (each at its own URL like /services/dotnet-architecture/), but there would be no /services/ index page to list them. Visitors would have no way to browse the services.

    The controller is the entry point to the collection. It is required.

    This chapter covers:

    1. The controller file structure — what each field means

    2. How the listing renders — what visitors see

    3. Changing pagination — how many services per page

    4. Changing ordering — which services appear first

    5. Changing the page title and description — the SEO of the listing page

    6. Editing via Decap CMS and directly — both methods


    The Controller File Structure

    The default content/services.md looks like this:

    ---
    

    layout: "services-list.dax"

    title: "Specialized .NET SSG Architecture Services"

    breadcrumb: "Enterprise Services"

    description: "End-to-end consulting, migration roadmaps, and custom theme engineering to modernize enterprise publishing pipelines."

    collection: "services"

    pagination: 6


    Every field explained:

    Field Purpose
    layout The template used to render the listing page. Must be services-list.dax. Do not change.
    title The page's H1 and browser title.
    breadcrumb Short label for the breadcrumb bar.
    description Meta description for SEO.
    collection The folder whose items are listed. Must be services. Do not change.
    pagination Number of services per page.

    The two fields that matter most are collection and pagination. The first tells Dax Pro what to list; the second tells it how many per page.

    Do not add a body to this file. The controller's body is not rendered. All rendering comes from the template, which reads from the collection.

    Do not change collection: "services". If you set it to "posts", the file becomes a posts controller, and you would have two controllers for the same collection — an error. The value must match the folder name.

    Do not change layout: "services-list.dax". This is the dedicated listing template. Changing it to page.dax or home.dax breaks the layout.

    The only fields you should edit as a site owner are title, breadcrumb, description, and pagination.


    How the Listing Renders

    When a visitor opens https://yoursite.com/services/, Dax Pro renders the services-list.dax layout with:

    1. Page header — breadcrumb and title from the frontmatter

    2. Service grid — one card per service, styled as a "trust card" (numbered badge, title, description, read-more link)

    3. Pagination — Previous / current page / Next, shown only if there are multiple pages

    Each service card in the grid contains:

  • Index badge — the index field from the service's frontmatter (e.g., "01. COMPILATION")
  • Title — the title field
  • Description — the description field
  • Read-more link — labeled by read_more field (default: "Explore Solution Architecture")
  • The cards are clickable. Clicking a card goes to /services/{slug}/, the individual service page.

    The grid layout is three columns on desktop, two on tablet, one on mobile. This is defined in style.css and not configurable from the controller.

    Ordering is by date in descending order. The most recently dated service appears first. If two services share a date, they are ordered alphabetically by URL.


    Changing Pagination

    pagination: 6 means six services per page. With 15 services and pagination: 6:

  • /services/ shows services 1–6
  • /services/page/2/ shows services 7–12
  • /services/page/3/ shows services 13–15
  • With pagination: 12 and 15 services:

  • /services/ shows services 1–12
  • /services/page/2/ shows services 13–15
  • With pagination: 20 and 15 services:

  • /services/ shows all 15
  • No pagination links appear
  • Choosing a value:

    Number of services Recommended pagination
    1–6 10 (no pagination appears)
    7–12 12 (no pagination appears)
    13–24 12 (paginated, 2 pages)
    25+ 9 or 12 (paginated, 3+ pages)

    Rule of thumb: pick a value that shows all your services on one page unless you have more than a dozen. Pagination on a small services list looks odd — it implies you have more content than you do.

    To change pagination via Decap CMS:

    1. Open https://yoursite.com/admin/

    2. Click 🛠 Services in the left sidebar

    3. You cannot directly edit the controller file from the admin panel — the "Services" collection is the content/services/ folder, not content/services.md

    4. To edit the controller, you must edit content/services.md directly (see below)

    Why is the controller not in Decap CMS? The Dax Pro configuration currently exposes the services folder collection (individual service files) but not the controller file. This is intentional — controllers are configuration, not content, and changing them from a CMS risks breaking the listing. If you need to change pagination, edit the file directly.

    To change pagination directly:

    1. Open content/services.md in VS Code

    2. Change pagination: 6 to your preferred value

    3. Save

    4. Rebuild

    dotnet run -- build
    

    For deployed sites:

    git add content/services.md
    

    git commit -m "Change services pagination to 12"

    git push


    Changing Ordering

    The listing orders services by date in descending order. The date field is on each individual service file (content/services/*.md), not on the controller.

    To reorder services:

    1. Open each content/services/*.md file

    2. Change the date field to control the order

    3. Rebuild

    Example: you have three services and want them in this order:

    1. "Architecture" (should be first)

    2. "Migration" (should be second)

    3. "Audit" (should be third)

    Set their dates accordingly:

    content/services/architecture.md:

    date: 2026-03-01
    

    content/services/migration.md:

    date: 2026-02-01
    

    content/services/audit.md:

    date: 2026-01-01
    

    The most recent date appears first. "Architecture" (March 1) appears first, "Migration" (February 1) appears second, "Audit" (January 1) appears third.

    The dates do not need to reflect real publication dates. They are used purely for ordering. You can set them to arbitrary values to control the order. The convention is to use real dates, but for services, the ordering intention is what matters.

    Alternative ordering via index field: the index field ("01. COMPILATION", "02. HEADLESS CMS") provides a visible badge but does not affect ordering. If you want the badge and the position to match, set both index and date consistently.

    Changing ordering via Decap CMS:

    1. Open https://yoursite.com/admin/

    2. Click 🛠 Services

    3. Click an individual service

    4. Scroll to Date

    5. Change the date

    6. Click Publish

    7. Repeat for other services to control their order

    Each publish triggers a rebuild (30–60 seconds). If you are reordering many services, it is faster to edit the files directly and push once.


    Changing the Page Title and Description

    The listing page's title, breadcrumb, and description are configured on the controller, not on individual services.

    To change the title via direct edit:

    1. Open content/services.md

    2. Update title, breadcrumb, description

    3. Rebuild

    ---
    

    layout: "services-list.dax"

    title: "Enterprise Services"

    breadcrumb: "Services"

    description: "Consulting, migration, and custom .NET static site architecture for enterprise teams."

    collection: "services"

    pagination: 9


    These values appear in:

  • Title — the

    of the listing page, the browser tab, the OpenGraph title

  • Breadcrumb — the crumb "Home / Services" (or whatever you set)
  • Description — the and OpenGraph description
  • Optimizing for SEO:

  • Title: keep under 60 characters. Include your main keyword. Example: "Enterprise .NET Static Site Services"
  • Description: keep under 160 characters. Include your primary value proposition. Example: "Consulting, migration, and custom .NET static site architecture for enterprise teams. Six services, one expert team."
  • Breadcrumb: one to three words. "Services" or "Enterprise Services".

  • What About the Individual Services?

    The controller lists the services, but each individual service lives in its own file:

    content/services/dotnet-architecture.md
    

    content/services/decap-cms-workflow.md

    content/services/azure-devops-pipelines.md

    content/services/legacy-cms-migration.md

    content/services/corporate-brand-theme.md

    content/services/performance-wcag-audits.md

    These files are covered in the next chapter (Services Post Collections). This chapter is only about the controller — the listing page itself.

    If you want to add a new service, you:

    1. Create content/services/new-service.md

    2. Fill in the frontmatter (title, description, date, etc.)

    3. Write the Markdown body

    4. Rebuild

    The new service appears in the listing automatically. No changes to the controller are needed.

    If you want to remove a service:

    1. Delete content/services/removed-service.md

    2. Rebuild

    The service disappears from the listing automatically.

    The controller is a dynamic listing — it always shows whatever is currently in content/services/. You do not update it when services change.


    The Full Frontmatter Reference

    For completeness, here is every field that can appear in content/services.md:

    ---
    

    layout: "services-list.dax"

    title: "Specialized .NET SSG Architecture Services"

    breadcrumb: "Enterprise Services"

    description: "End-to-end consulting, migration roadmaps, and custom theme engineering to modernize enterprise publishing pipelines."

    collection: "services"

    pagination: 6


    Field-by-field:

    Field Type Required Change?
    layout string Yes No — always services-list.dax
    title string Yes Yes — your page title
    breadcrumb string No Yes — short nav label
    description string Yes Yes — meta description
    collection string Yes No — always services
    pagination number Yes Yes — services per page

    Total configurable: 4 fields. Everything else is fixed.


    Method 1 — Editing the Controller

    There is no way to edit the services controller via Decap CMS in the current configuration. The "Services" collection in Decap CMS exposes individual service files (content/services/*.md), not the controller file (content/services.md).

    To change the controller, you must edit it directly.

    Why? The controller is configuration, not content. Exposing it in the CMS risks accidental edits (like changing collection: "services" to collection: "posts") that break the listing. Keeping it out of the CMS is a safety measure.

    If you want the controller in the CMS, you can add it to config.yml as a file collection:

      - name: "services_controller"
    

    label: "🛠 Services Listing"

    files:

    - name: "services_listing"

    label: "Services Listing"

    file: "content/services.md"

    fields:

    - { label: "Layout", name: "layout", widget: "hidden", default: "services-list.dax" }

    - { label: "Title", name: "title", widget: "string" }

    - { label: "Breadcrumb", name: "breadcrumb", widget: "string" }

    - { label: "Description", name: "description", widget: "text" }

    - { label: "Collection", name: "collection", widget: "hidden", default: "services" }

    - { label: "Pagination", name: "pagination", widget: "number", default: 6 }

    This is a developer task — see the Developer Guide. For most users, editing the controller directly is fine because it changes rarely.


    Method 2 — Editing the Controller Directly

    Open content/services.md in VS Code. Edit the fields. Save. Rebuild.

    Example — change pagination from 6 to 9:

    ---
    

    layout: "services-list.dax"

    title: "Specialized .NET SSG Architecture Services"

    breadcrumb: "Enterprise Services"

    description: "End-to-end consulting, migration roadmaps, and custom theme engineering to modernize enterprise publishing pipelines."

    collection: "services"

    pagination: 9


    Example — change the title and description for a broader offering:

    ---
    

    layout: "services-list.dax"

    title: "Enterprise .NET Services"

    breadcrumb: "Services"

    description: "Architecture, migration, CI/CD, brand customization, and accessibility audits. Six specialized services for enterprise .NET teams."

    collection: "services"

    pagination: 9


    Rebuild:

    dotnet run -- build
    

    Or push to Git for the cloud build:

    git add content/services.md
    

    git commit -m "Update services listing title and pagination"

    git push


    Verifying the Listing

    After editing the controller, verify:

    1. URL works — navigate to /services/. The page loads.

    2. Title — the browser tab shows the new title, and the page H1 matches.

    3. Breadcrumb — the crumb shows "Home / {breadcrumb}". If you set breadcrumb: "Services", the crumb says "Services".

    4. Description — view source (Ctrl + U), confirm matches.

    5. Grid — service cards appear in a 3-column grid (desktop).

    6. Card content — each card has an index badge, title, description, and read-more link.

    7. Ordering — the most recently dated service appears first.

    8. Pagination — if you have more services than pagination, pagination links appear at the bottom.

    If a service does not appear in the listing, check:

  • The service file exists in content/services/
  • The file has a valid frontmatter
  • The file has layout: "service.dax"
  • The build completed without errors
  • If the ordering is wrong:

  • Check the date field in each service file
  • The most recent date appears first
  • Ties are broken alphabetically

  • Common Services Controller Mistakes

    Mistake 1: Changing collection: "services" to another value.

    The value must match the folder name (services). Changing it breaks the listing.

    Mistake 2: Adding a body to the controller.

    Anything after the closing --- is not rendered. The controller renders through the template. A body is ignored.

    Mistake 3: Using a date in the controller.

    The controller has no date. If you add one, it has no effect. Ordering is determined by the date of individual services.

    Mistake 4: Setting pagination: 0.

    Zero means zero items per page. The listing is empty. Set a positive number.

    Mistake 5: Setting a pagination larger than the number of services.

    If you have 6 services and set pagination: 100, all 6 appear on one page. No pagination links. Fine.

    Mistake 6: Editing the wrong file.

    If you want to change a service's title, edit content/services/{name}.md, not content/services.md. The controller only controls the listing.

    Mistake 7: Forgetting to rebuild.

    Any change requires a rebuild. If you edit and see no change, you forgot to build.

    Mistake 8: Removing layout.

    The controller needs a layout. Without it, Dax Pro cannot render the listing. Do not remove the layout field.


    What You Have Now

    After this chapter, you can:

  • ✅ Understand what a controller is and what it generates
  • ✅ Change the listing page's title, breadcrumb, and description
  • ✅ Change pagination (how many services per page)
  • ✅ Understand ordering (by date, descending)
  • ✅ Edit the controller directly in content/services.md
  • ✅ Know when to modify individual services vs. the controller
  • ✅ Verify the listing renders correctly
  • ✅ Avoid the eight most common controller mistakes
The services controller is configured. The next chapter covers Services Post Collections — the individual service detail pages in content/services/*.md, including their frontmatter, their CTA block, and the ordering that determines their position in the listing.

→ Continue to Services Post Collections