Skip to main content
Our docs redesign is live!

Understanding the Veda Content Model

12 min read

Once the app runs, the next thing to understand is the shape of the content itself. This is where Contentstack starts to feel different from a simple data fetch exercise. Veda works because the content model already encodes relationships, reusable structures, and route-friendly fields.

What you'll learn

  • Which content types Veda uses and what each one is responsible for

  • How modular blocks fit into page composition

  • How the content types relate to one another

  • Why the model supports both flexible pages and purpose-built product experiences

  • How editors and developers divide responsibilities inside this model

The main Veda content types

Before we go content type by content type, here is a compact developer-oriented view of the core Veda models.

Content type

Main purpose

Key props in the Veda types

Frontend use

page

Flexible marketing and editorial pages

titleurldescriptionimagecomponents$

Catch-all page routes render it through ComponentsRenderer

product

Individual catalog item pages

titleurlshort_descriptiondescriptionpricecategoryproduct_linemediataxonomies$

Product page, breadcrumbs, related lists, filtering context

product_line

Collection or line-level landing page

titleurldescriptionimageproductstaxonomies$

Collection pages and featured product groupings

category

Browsing-oriented grouping

titleurldescriptionmediaproductstaxonomies$

Category pages and product discovery

header

Shared global navigation content

titlelogolinks$

Mega menu and shared site chrome

What the most important props really mean

Prop

Meaning in practice

Why it matters

url

Canonical path stored in content

Lets the frontend resolve routes from content instead of hardcoded IDs

components

Array of modular blocks such as hero or rich_text

Powers flexible page composition

category / product_line

Reference arrays to related entries

Enables breadcrumbs, related products, and richer page context

media / image / logo

Asset references

Keeps images and media in Contentstack instead of the codebase

taxonomies

Structured classification terms

Supports filtering and grouping without custom hardcoded logic

$

Preview/edit metadata bindings

Lets Live Preview and Visual Builder map UI elements back to fields

page

Veda implementation: The page content type powers the more flexible, content-composed parts of the site.

This is usually where modular blocks do their most visible work. A page entry can describe a route such as / or another marketing-style URL and assemble its content from a series of reusable sections.

product

Products represent individual catalog items. They carry the sort of data you expect a product experience to need:

  • title

  • URL

  • media

  • short descriptive content

  • taxonomy-related data

  • product-specific display information

product_line

Product lines group products into larger branded collections. In Veda, this supports richer merchandising and collection storytelling instead of treating the catalog like one flat list.

category

Categories represent browsing-oriented groupings. These are useful for navigation and product discovery because users do not always browse by brand story alone.

header

The header content type supports shared navigation data and helps the frontend render consistent global navigation without hardcoding it into the app.

How these content types relate to each other

This is the simplest way to picture the Veda model:

DiagramMermaid

This is not trying to show every field. It is showing the relationships that matter most when you read the frontend code:

  • pages are block-driven

  • navigation is shared content

  • products sit inside broader browsing structures

  • assets and taxonomy data are part of the content model, not bolted on later

What the API data looks like in practice

Veda implementation: One of the nicest things about the Veda repo is that the TypeScript interfaces make the expected Contentstack response shape much easier to understand.

Here is a trimmed version of the current Page and Product types from lib/types.ts:

export interface Page extends SystemFields {
  title: string;
  url?: string;
  description?: string;
  image?: File | null;
  components?: Components[];
  $?: {
    title?: CSLPFieldMapping;
    url?: CSLPFieldMapping;
    description?: CSLPFieldMapping;
    image?: CSLPFieldMapping;
    components?: CSLPFieldMapping;
  };
}

export interface Product extends SystemFields {
  title: string;
  url?: string;
  short_description?: string;
  description?: string;
  price?: number | null;
  category?: Category[];
  product_line?: ProductLine[];
  media?: File[] | null;
  taxonomies?: Taxonomy[];
  $?: {
    title?: CSLPFieldMapping;
    url?: CSLPFieldMapping;
    short_description?: CSLPFieldMapping;
    description?: CSLPFieldMapping;
    price?: CSLPFieldMapping;
    category?: CSLPFieldMapping;
    product_line?: CSLPFieldMapping;
    media?: CSLPFieldMapping;
    taxonomies?: CSLPFieldMapping;
  };
}

That tells you a lot right away:

  • Page is built around flexible modular content in components

  • Product is a richer detail shape with relationships to category and product_line

  • both can carry a $ object for preview/edit bindings

How to read the Veda types as a developer

Veda implementation: The most useful habit here is to treat each interface as a contract between Contentstack and the React app.

For example:

  • required-looking fields such as title: string are fields the frontend expects to exist for a healthy render

  • optional fields such as description? or media? are fields the frontend can handle conditionally

  • arrays such as product_line?: ProductLine[] mean the content type is relational, not isolated

  • nested objects like image?: File | null tell you the frontend expects fully resolved asset objects, not just asset IDs

That means the TypeScript file is doing two jobs at once:

  • documenting the content model

  • documenting the data shape the components are built around

A mental model for the response payload

Contentstack concept: The Delivery SDK eventually gives you normal JavaScript objects. The TypeScript interfaces are not the payload themselves, but they are a strong guide to the payload shape.

A page entry fetched for a route like / will look roughly like this:

{
  "uid": "blt-page-home",
  "title": "The Revival Collection",
  "url": "/",
  "description": "Luxury jewelry with modular content sections.",
  "image": {
    "uid": "blt-asset-hero",
    "title": "Homepage hero",
    "url": "https://images.contentstack.io/v3/assets/..."
  },
  "components": [{
    "hero": {
      "title": "The Revival Collection",
      "description": "An upscale unisex jewelry line",
      "image": {
        "url": "https://images.contentstack.io/v3/assets/..."
      }
    }
  },
  {
    "list": {
      "title": "Explore the collections",
      "reference": [{
        "title": "Digital Dawn",
        "url": "/products/digital-dawn"
       }]
      }
    }]
  }

This is not a copy-pasted live response. It is an inferred shape based on the Veda types and query behavior. The important part is the structure:

  • system fields such as uid

  • content fields such as titleurl, and description

  • nested asset objects

  • modular blocks represented as keyed objects inside the components array

Why the modular block array looks a little unusual

Veda implementation: The components field is not just an array of identical objects. Each item is a one-key object whose key identifies the block type:

[{ "hero": { "...": "..." } },{ "rich_text": { "...": "..." } },{ "media": { "...": "..." } }]

That design is the reason Veda needs a central renderer. The renderer inspects the key, then decides which React component to use.

What the $ field is for

Contentstack concept: The $ object is preview-oriented metadata added by the frontend utility layer so rendered elements can be linked back to content fields during editing.

Readers often see $ in the Veda code and assume it is normal published content. It is better to think of it as editor-facing metadata attached to the content object for Live Preview and Visual Builder behavior.

That means:

  • title is content

  • $?.title is field-binding metadata about that content

Both matter, but they serve different audiences.

Why this model is stronger than a single "page" schema

Contentstack concept: A common beginner mistake is to overuse one generic content type for everything.

That can work for small demos, but it breaks down fast. Product detail pages, collection pages, and generic editorial pages often have different rendering needs, different data relationships, and different editorial expectations.

Veda avoids that trap by modeling content domains separately while still allowing flexible composition where it makes sense.

Modular blocks in Veda

Veda implementation: The current Veda materials describe these core modular blocks:

  • hero

  • list

  • two column

  • media

  • rich text

Here is the developer-facing summary of those block props:

Block type

Key props

What the block is good for

hero

titledescriptionctasimagevideodesign

Top-of-page storytelling and visual entry points

list

titledescriptionreferencecardsload_first_image_eager

Featured collections, related products, grouped content

two_column

side_aside_b

Structured paired layouts without hardcoding a one-off page

media

imagewidthheightcropwidths

Image-led sections with delivery and layout hints

rich_text

titlecontentalternative_contentctas

Editorial copy blocks with optional call-to-action support

This is one of the most important ideas in the guide.

The content model does not say, "Editors can build anything." It says, "Editors can build anything from this approved set of structured building blocks."

That is the right kind of flexibility. It creates freedom without turning the frontend into an unbounded renderer.

Full component inventory from the Veda types

Veda implementation: The Veda repo has both top-level page-builder blocks and smaller supporting component shapes nested inside those blocks. This table helps you read lib/types.ts without having to guess which pieces are page sections and which pieces are sub-objects.

Type or component

Kind

Key props

Why it exists

Hero

Top-level modular block

titletitle_tagdescriptionctasimagevideodesign

Hero section with copy, CTA, and media support

List

Top-level modular block

titletitle_tagdescriptionload_first_image_eagerreferencecards

Reusable listing block for product references, cards, and grouped content

TwoColumn

Top-level modular block

side_aside_b

Two-column layout that can hold other nested content objects

Media

Top-level modular block and nested media object

imagewidthheightcropwidths

Structured image block with rendering hints

RichText

Top-level modular block and nested editorial object

titletitle_tagcontentalternative_contentctas

Rich editorial content with optional CTA support

Card

Supporting nested component

titledescriptionimagelink

Small repeatable promo or summary unit inside a list

Cards

Supporting wrapper object

card

Gives the list a repeatable array of card objects in the Contentstack schema

Cta

Supporting nested component

textlink

Reusable call-to-action shape

Ctas

Supporting wrapper object

cta

Lets a hero carry one or more CTA items in a structured way

SideA

Supporting nested layout item

listmediarich_text

Defines the allowed content shapes inside each column

Components

Top-level modular block union object

herolisttwo_columnmediarich_text

The union-like content structure the renderer inspects block by block

Links

Supporting navigation component

labelitemreferencefeatured_productshow_product_linesshow_all_products_links

Structured nav link definition used by the mega menu

PageHeader

Supporting reference wrapper

reference

Reference container for header content when header data is modeled as referenced content

Link

Shared value object

titlehref

Generic link shape reused across the content model

File

Shared asset object

titleurldescriptiondimensionpublish_details

Standard Contentstack asset payload used throughout the app

How to interpret this table

  • The top-level page-builder blocks are HeroListTwoColumnMedia, and RichText

  • Wrapper types like Cards and Ctas exist because Contentstack schemas often model repeatable nested items through small wrapper objects

  • Shared objects like Link and File are not page sections by themselves, but they appear all over the content model and are essential to understanding the payload shape

  • Components is especially important because it is the type that lets page.components hold different block kinds in one array

If you are trying to understand what the renderer is doing, focus first on Components, then on the five top-level blocks, then on the nested helper types those blocks use.

How the content types relate to each other

The real power of Veda is not the list of content types. It is the fact that those types work together.

Veda implementation: From the repository and guide materials, you can see patterns like these:

  • pages use modular composition

  • header data is fetched alongside page-level content

  • product lines and categories support dedicated route experiences

  • product filtering uses taxonomy-aware logic

  • richer queries often include related content instead of treating entries as isolated records

This is why the Veda repo uses deeper include behavior in its fetch layer. The app is not merely asking for a title and body. It is asking for connected content that can support a full page experience.

A concrete relationship example from product data

Veda implementation: The Product type tells you that a product payload is not flat. It can include related categories, product lines, media arrays, and taxonomy data:

export interface Product extends SystemFields {
  title: string;
  url?: string;
  price?: number | null;
  category?: Category[];
  product_line?: ProductLine[];
  media?: File[] | null;
  taxonomies?: Taxonomy[];
}

So a product response can look conceptually like this:

{"title": "Silver Orbit Ring","url": "/products/digital-dawn/silver-orbit-ring","price": 240,"category": [
    { "title": "Rings", "url": "/category/rings" }],"product_line": [
    { "title": "Digital Dawn", "url": "/products/digital-dawn" }],"media": [
    { "url": "https://images.contentstack.io/v3/assets/..." }],"taxonomies": [
    { "taxonomy_uid": "materials", "term_uid": "silver" },
    { "taxonomy_uid": "product_type", "term_uid": "ring" }]}

That is why catalog features like breadcrumbs, related listings, and filters can work without hardcoded lookup tables in the frontend.

What editors control versus what developers control

Contentstack concept: Good Contentstack architecture makes the editor/developer boundary obvious.

Editors control:

  • entry values

  • page composition using allowed blocks

  • ordering of sections

  • text, media, and content relationships within the defined schema

Developers control:

  • the content type schema itself

  • which blocks exist

  • how each block renders

  • how URLs map to routes

  • how queries fetch and normalize data

That is a healthy collaboration model. Editors gain flexibility without silently changing the application's architecture.

Why Veda is a good teaching model

Veda implementation: Veda demonstrates that a project can mix:

  • flexible content-composed pages

  • dedicated page templates for important content types

  • shared navigation content

  • catalog-oriented data behavior

That blend is exactly what many production sites need. Not everything should be one generic block page. Not everything should be one rigid template either.

Questions to ask when adapting this model

As you study the Veda model, keep these questions in mind:

  • Which content types in my project deserve dedicated page templates?

  • Which content should stay modular and editor-composed?

  • Which fields need stable URLs?

  • Which relationships are editorially meaningful enough to model as references?

  • Which repeated page patterns should become modular blocks instead of duplicated fields?

Those questions matter more than copying Veda field-for-field.

Key takeaways

  • Veda uses multiple content types because multiple page behaviors exist in the site

  • page handles flexible composition, while product-oriented types support more purpose-built experiences

  • Modular blocks provide the right balance between editorial flexibility and frontend control

  • References and richer queries turn the model into a connected system instead of disconnected entries

  • The useful lesson is not to clone the exact schema blindly, but to understand why each content type exists

Frequently asked questions

  • What are the main Veda content types and what do they do?

    Veda centers on page (modular marketing/editorial pages), product (catalog detail), product_line (collection landing), category (browsing group), and header (global navigation). Each type encodes both fields and relationships used by the frontend.

  • How do modular blocks work in Veda pages?

    The page.components field is an array of one-key objects, where the key identifies the block type (for example hero or rich_text). A central renderer inspects the key and selects the matching React component.

  • Why does Veda store a url field in content?

    The url field acts as the canonical path so the frontend can resolve routes from content rather than hardcoded IDs. It supports predictable routing for pages, products, and collection-like entries.

  • What is the $ field in the Veda types?

    The $ object carries preview/edit field-binding metadata used by Live Preview and Visual Builder. It is not normal published content, but it is attached to content objects to map rendered UI back to fields.

  • How should developers read lib/types.ts in the Veda repo?

    Treat each TypeScript interface as a contract for the expected Delivery API response shape. Required fields indicate render expectations, optional fields are handled conditionally, and arrays/references signal relational content.