Setting Up a Custom Template with Connected Data

Build a reusable template in the Duda editor, connect widgets to the Content Library, and populate content for sites via API

Overview

A connected template is a Duda site template where widgets are linked to fields in the Content Library. When you create a new site from a connected template, those links come along with it. Updating the Content Library through the API then automatically propagates the right content to every connected widget on the site, with no editor access required.

This makes connected templates a foundational way for generating sites at scale. You design and configure the template once in the editor, and from that point on, new sites can be spun up and personalized entirely through API calls.

In this tutorial, you will:

  • Build a template site in the Duda editor and populate its Content Library with placeholder data
  • Connect widgets on the template to Content Library fields
  • Verify the setup end-to-end by creating a test site from the template and pushing content via the API

Prerequisites

  • A Duda partner account with API credentials
  • Access to the Duda editor to build and configure the template
  • Basic familiarity with the Partner REST API

Step 1: Build the Template in the Editor

Start by creating a new site in the Duda editor that will serve as your connected template. Design the layout, add the widgets you want, and style everything to match your intended look. Every decision you make here (layout, sections, widget placement) will be inherited by every site you create from this template, so design with your entire customer base in mind, not just one site.

💡 Tip: You can also start from an existing Duda template and modify it. The goal is a design that works as a starting point for any customer, with all the right sections in place to be connected and populated via API.


Step 2: Populate the Content Library with Placeholder Data

Before connecting desired connected widgets, fill in the Content Library with representative placeholder data. This gives you something visible to work with in the editor and lets you verify that each connection is pulling from the right field. The placeholder values will be replaced by real customer data via the API every time a new site is created from this template.

Open the Content Library from the Content Management (CMS) tab in the left panel of the editor. Fill in the relevant fields:

SectionWhat to addExample placeholder
Business InfoName, phone, address, emailAcme Web Co., 555-000-0000
Business TextOverview, About Us, custom blocksOverview: A great local business.
Business ImagesLogo, hero imageA generic placeholder logo URL
CollectionsAny repeating data setsSample gallery items or team members

Step 3: Connect Widgets to Content Library Fields

With placeholder data in place, connect each widget to its corresponding Content Library field. This is the step that makes the template scalable: every connection you set here means one less thing your provisioning code needs to handle per site.

For each widget you want to connect:

  1. Right-click the widget in the editor
  2. Select Connect to Data from the context menu
  3. Choose the matching field from the Content Library panel that appears

Connected widgets display a purple interlocking rings icon when hovered in the editor, confirming the link is active. A single Content Library field can be connected to multiple widgets, so a phone number in the footer and a click-to-call button in the header can both pull from the same source. Every widget you connect now is one that will populate automatically across every site created from this template, without any additional API calls.

💡 Which widgets can be connected? Text widgets, image widgets, button widgets, and many others support Connect to Data. The option only appears in the right-click menu if content exists in the Content Library for that widget type.


Collections & Dynamic Pages in a Connected Template

The Content Library handles scalar fields: business name, phone, overview text, logo. But some sections of a site need repeating content — a services grid, a photo gallery, a team roster, a testimonials section. That is where collections come in. A collection is a structured, multi-row data set that you define in the template and populate via the API once a site is created. Each row becomes one item in the connected widget.

The principle is exactly the same as with Content Library fields: configure the collection and its widget connections once in the template, and every site you create from it inherits that structure automatically. The only thing that changes per site is the row data you push via the API.

Setting Up a Collection in the Template

Create the collection on the template site in the editor before connecting any widgets. Give it a name that reflects the content it holds (Services, Gallery, Team, etc.) and define the fields that each row will carry. Field types must be uppercase and match the data you intend to push via the API.

If the collection will bind to a widget on a regular page (not a dynamic page), check the Allow use on static pages option when creating it. Because this structure lives on the template, you only need to make these decisions once regardless of how many sites you eventually provision from it.

💡 Define the collection structure on the template, not per site. The field names and types you set here are what the API expects when you push rows to a new site. Get the structure right in the template so every downstream site inherits it consistently.

Connecting Widgets to a Collection

Once the collection exists, connect widgets to it the same way you connect them to Content Library fields: right-click the widget, select Connect to Data, and choose the collection. For complex widgets like a media slider, gallery, or list widget, the widget binds to the collection as a whole and maps each field to a slot (image, caption, link, etc.). One row in the collection becomes one slide, card, or list item in the rendered widget.

This is where the scalability of the connected template pays off. Every site you create from this template inherits the widget-to-collection binding automatically. All you need to do at provisioning time is push the right rows via the API, and the widget populates itself. The template does the rest.

Populating a Collection When a Site is Created

After creating a new site from the template, push the customer's collection data via the API. The field names in each row must match exactly what was defined in the template.

POST https://api.duda.co/api/sites/multiscreen/{site_name}/collection/{current_collection_name}
Headers:
  Authorization: Basic {base64(username:password)}
  Content-Type: application/json
{
  "rows": [
    {
      "data": {
        "title": "Service One",
        "description": "Description for service one.",
        "image": "https://your-image-url.com/image1.jpg"
      }
    },
    {
      "data": {
        "title": "Service Two",
        "description": "Description for service two.",
        "image": "https://your-image-url.com/image2.jpg"
      }
    },
    {
      "data": {
        "title": "Service Three",
        "description": "Description for service three.",
        "image": "https://your-image-url.com/image3.jpg"
      }
    }
  ]
}

The page_item_url value controls the URL slug for each dynamic page generated by this row. Omit it if the collection is bound to a static page widget only.

Dynamic Pages

When a collection powers a dynamic page, each row generates its own published page at a unique URL. You configure this in the editor by creating a dynamic page and pointing it at the collection. The layout is built once and Duda renders one instance per row.

From an API perspective, dynamic pages are transparent. Push rows and Duda generates the pages. Because the dynamic page layout lives in the template, every site you provision already has the page structure ready. The only thing your provisioning code needs to supply is the row data with clean, predictable page_item_url values.

💡 Dynamic pages vs. regular page widgets: A collection powers dynamic pages by default. If you also want to bind it to a widget on a regular page (such as a services grid on the homepage alongside a dynamic services detail page), create the collection with static_page_bindable set to true. Both can be active on the same collection simultaneously.


Complex Widgets

Most connected widgets map a single Content Library field to a single element. Complex widgets like media sliders, galleries, and list widgets work differently: they bind to an entire collection and render one item per row. In a connected template, these widgets follow the same scalability pattern. Set the binding up once in the template, and every site provisioned from it inherits a fully wired widget that only needs row data to come alive.

Media Slider

The media slider binds to a collection in the editor. Right-click the widget, select Connect to Data, choose the collection, then map each collection field (image, caption, link) to its corresponding slot. Set this up once on the template. Every site you create from it will have a fully wired slider: push the customer's image rows via the API and the slides populate automatically, with no editor involvement.

Gallery Widget

The gallery widget follows the same pattern as the media slider. Bind it to a collection in the editor and map the image and caption fields. Because that binding lives on the template, every downstream site gets a ready-to-populate gallery. Your provisioning code just pushes rows, and the gallery fills itself in.

List Widget

The list widget binds to a collection and renders each row as a line item, making it a good fit for simpler structured content like FAQs, feature lists, or menu items where a full card layout is not needed. Connect it to a collection in the editor and map the relevant fields (label, description, link) to the list item slots. Like the other collection-bound widgets, the binding lives on the template: every site provisioned from it gets a populated list simply by pushing rows to the collection via the API.


Custom Widgets

Custom Widgets via the Widget Builder with Collections

Custom widgets can connect to Content Library fields, collection fields, or both via the Connect to Data flow in the widget Settings panel. For widgets that need to process or filter data before rendering — such as an interactive map or a filterable list — use the Collections API inside the widget script to load collection data at runtime:

// Load a collection at runtime inside a custom widget script
const collection = await dmAPI.getCollection('Services');
collection.rows.forEach(row => {
  const card = document.createElement('div');
  card.classList.add('service-card');
  card.innerHTML = `
    <img src='${row.data.image}' alt='${row.data.title}' />
    <h3>${row.data.title}</h3>
    <p>${row.data.description}</p>
    <a href='${row.data.link}'>Learn more</a>
  `;
  document.querySelector('.services-grid').appendChild(card);
});

This gives you full control over rendering logic while keeping the underlying data entirely API-driven. Because the widget and its dmAPI calls live in the template, the logic is written once and inherited by every site you provision. Push the collection rows at site creation time and the widget picks them up on publish.

💡 dmAPI availability: dmAPI is available inside custom widget JavaScript contexts only. It is not available in arbitrary page scripts. Always check that the method exists before calling it if your widget may run outside of the Duda runtime.


Try It Out

With the template built and widgets connected, verify everything is working by spinning up a test site from the template and pushing content to it via the API.

Once the template is ready, retrieve its template alias. You will need this when creating new sites from the template.

GET https://api.duda.co/api/sites/multiscreen/templates
Headers:
  Authorization: Basic {base64(username:password)}
  Accept: application/json

Create a new site by passing the template_alias from Step 1. The new site will inherit the full design and all Content Library connections from the template.

POST https://api.duda.co/api/sites/multiscreen/create
Headers:
  Authorization: Basic {base64(username:password)}
  Content-Type: application/json
{
  "template_alias": "{template_alias}"
}

With the site created, push the real customer data to its Content Library. Because the widgets are already connected to Content Library fields, every connected element on the site will reflect the new content automatically.

POST https://api.duda.co/api/sites/multiscreen/{site_name}/content
Headers:
  Authorization: Basic {base64(username:password)}
  Content-Type: application/json
{
  "location_data": {
    "phones": [
      { "phoneNumber": "555-867-5309", "label": "Main" }
    ],
    "emails": [
      { "emailAddress": "[email protected]", "label": "General" }
    ],
    "address": {
      "streetAddress": "123 Main St",
      "city": "San Francisco",
      "region": "CA",
      "postalCode": "94105",
      "country": "US"
    }
  },
  "business_data": {
    "name": "Customer Business Name",
    "logo_url": "https://cdn.example.com/customer-logo.png"
  },
  "site_texts": {
    "overview": "Customer-specific overview text goes here.",
    "custom": [
      { "label": "tagline", "text": "Your tagline here" }
    ]
  }
}

Related Resources