Skip to content

Content Architecture Guide

Audience: Developers building on the Progress Credit Union platform Stack: Umbraco 17, .NET 10, Bootstrap 5.3, Razor Views


1. Document Type Hierarchy

The platform organizes content into three tiers of document types: the site root, configuration nodes, and content pages.

Site Root

The content tree has a single Home node (homeGrid) as the public site root. Two configuration nodes sit at root level outside the Home tree:

Root Node Document Type Purpose
Home homeGrid Public site root, parent of all content pages
Website Configuration websiteConfiguration Global settings (logo, contact info, social URLs)
2FA Settings twoFASettings Two-factor authentication toggle

Configuration Nodes

Configuration nodes live under Home but have no public URL. They store site-wide settings that views read through SiteSettingsService:

Document Type What It Controls
menuConfiguration Navigation structure, mega-menu items
footerConfiguration Footer layout and links
siteStyleConfiguration Brand colors, fonts, CSS variables
seoConfiguration Default meta tags, Open Graph image
calculatorsConfiguration Loan/savings calculator rates and limits
loanBoxesConfiguration Loan product cards, APR rates
homepageSliderConfiguration Hero slider images and CTAs
googleMapConfiguration Map markers, API settings
googleTagManagerConfiguration GTM container ID
cookieConfiguration Cookiebot ID, consent text
privacyPolicyConfiguration DPO details, privacy statements

Content Pages

Content pages are the public-facing document types. Key page types:

Document Type Template Children Allowed
homeGrid Homepage Most page types
standardPage General content None
standardPageNew Modern full-width content None
article News/blog post None
articleList News archive newsCategoryItems
faqs FAQ page faqQuestionItem
gallery Photo gallery None
galleryList Gallery index gallery
contactus Contact page with map None
testimonialCategories Testimonial container testimonialCategoryItem
careers Job listings job

2. BlockGrid 4-Level Structure

The page builder uses a strict 4-level nesting hierarchy. Every piece of content on a BlockGrid page follows this chain:

┌─────────────────────────────────────────────────────┐
│  Row Config                                         │
│  Controls which layouts are available.              │
│  Only block type allowed at root level.             │
│                                                     │
│  ┌───────────────────────────────────────────────┐  │
│  │  Layout                                       │  │
│  │  Defines column structure (e.g., 6+6, 4+4+4)  │  │
│  │                                               │  │
│  │  ┌─────────────────┐  ┌─────────────────┐    │  │
│  │  │  Area Wrapper    │  │  Area Wrapper    │    │  │
│  │  │  Carries cell    │  │  (one per column)│    │  │
│  │  │  styles: bg,     │  │                  │    │  │
│  │  │  padding, AOS    │  │                  │    │  │
│  │  │                  │  │                  │    │  │
│  │  │  ┌────────────┐  │  │  ┌────────────┐  │    │  │
│  │  │  │  Content   │  │  │  │  Content   │  │    │  │
│  │  │  │  (RTE,     │  │  │  │  (Card,    │  │    │  │
│  │  │  │   Hero,    │  │  │  │   Form,    │  │    │  │
│  │  │  │   Card...) │  │  │  │   Chart...)│  │    │  │
│  │  │  └────────────┘  │  │  └────────────┘  │    │  │
│  │  └─────────────────┘  └─────────────────┘    │  │
│  └───────────────────────────────────────────────┘  │
└─────────────────────────────────────────────────────┘

Level Details

Level Element Type Pattern Properties allowAtRoot
Row Config grid_{dtId}_rowconfig_{name} None (structural only) true
Layout grid_{dtId}_layout_{name} None (structural only) false
Area Wrapper grid_{dtId}_areawrapper_{name}_{idx} Cell background, padding, animation, visibility false
Content grid_builtin_{alias} or grid_element_{alias} Component-specific false

Settings at Each Level

Level Available Settings
Row Config class, ID, data-aos-*, background-image, background-color, padding, margin, visible
Area Wrapper background-color
Content Varies per component (text, images, links, colors, etc.)

How Editors Build a Page

  1. Add a Row -- select a row configuration (e.g., "1 column layout", "Left Sidebar")
  2. Choose a Layout -- pick column structure (e.g., Half = 6+6, Thirds = 4+4+4)
  3. Drop Components -- drag content blocks into each column area
  4. Configure -- set properties on each component and row/cell settings

Example: Two-Column Page Section

Row Config "1 column layout"           ← root block
  └── Layout "Half"                    ← 2 areas: col-6 + col-6
      ├── Area Wrapper (half_0)        ← left column
      │   ├── Heading Element          ← content block
      │   └── Rich Text Editor         ← content block
      └── Area Wrapper (half_1)        ← right column
          └── Card Grid Controls       ← content block

Common Layout Patterns

Layout Columns Bootstrap Classes Typical Use
Full Width 1 col-12 Hero banners, full-width sections
Half 2 col-6 + col-6 Text + image, side-by-side
Thirds 3 col-4 + col-4 + col-4 Card grids, features
Fours 4 col-3 + col-3 + col-3 + col-3 Icon grids, stats
Left Nav 2 col-4 + col-8 Sidebar navigation + content
Right Sidebar 2 col-8 + col-4 Content + sidebar widgets
Five + Seven 2 col-5 + col-7 Asymmetric layout

Rendering Views

The BlockGrid renders through a chain of partial views:

View Responsibility
BootstrapGrid.cshtml Entry point, renders row configs with <div class="container"> wrapper
_MultiSectionGrid.cshtml Handles multi-area layouts
area.cshtml / areas.cshtml Renders individual grid areas
items.cshtml Iterates content blocks within an area
Components/*.cshtml Individual component rendering (120+ views)

3. Page Templates vs BlockGrid Components

Page Templates

Templates define the overall page structure: header, footer, navigation, and where the BlockGrid sits. There are 46 templates organized by function:

Category Examples Count
Main content standardPage, homeGrid, article 10
Special purpose contactus, cookies, Faq, search 14
Authentication Login1, CustomerOnlyPage1 4
Framework master, masterNoHeaderNoFooter, SPALoader 5
Configuration Non-public, backoffice-only 13

Templates inherit from master.cshtml, which provides:

  • Service injection (SiteSettingsService, IDictionaryService)
  • Header and footer partials
  • SEO meta tags from seoConfiguration
  • Google Tag Manager script from googleTagManagerConfiguration
  • CSS and JavaScript asset loading

BlockGrid Components

Components are the drag-and-drop building blocks editors place inside BlockGrid areas. There are 120+ components across 25 categories:

Category Count Examples
Hero & Banner 6 Hero Element, Header, CTA Curves
Text & Content 10 Rich Text Editor, Heading, Quote
Call to Action 6 CTA Element, Button Widget, Loan Input CTA
Media & Video 12 Fancy Video, Video Full Width, Parallax Image
Cards 8 Card Grid, Flip Card, Spotlight
Lists 10 Numbered List, Image List, Link List
Accordion 7 Accordion Controls, FAQ Controls
Calculators 5 Main Calculator, Loan Input CTA
Charts 6 Bar Chart, Donut Chart, Comparison Table
Social 7 Facebook, Instagram, Twitter, Trustpilot
Maps 4 Google Map, Leaflet Map

Each component is a Razor partial in Views/Partials/blockgrid/Components/. The view receives a BlockGridItem model:

@inherits Umbraco.Cms.Web.Common.Views.UmbracoViewPage<BlockGridItem>
@{
    var content = Model.Content;
    var title = content.Value<string>("title") ?? string.Empty;
}

4. Media Management

MediaWithCrops Pattern

All media properties use the MediaWithCrops type from Umbraco's MediaPicker3. The critical rule for single-pick media:

// CORRECT: Single-pick (multiple: false)
var image = content.Value<MediaWithCrops>("image");
var url = image?.MediaUrl() ?? string.Empty;

// WRONG: These return null silently
var image = content.Value<IPublishedContent>("image");        // null
var images = content.Value<IEnumerable<MediaWithCrops>>("image"); // null

For multi-pick media:

// Multi-pick (multiple: true)
var images = content.Value<IEnumerable<MediaWithCrops>>("images")
    ?? Enumerable.Empty<MediaWithCrops>();

foreach (var img in images)
{
    var url = img.MediaUrl();
    var alt = img.Value<string>("altText") ?? string.Empty;
}

Image URL Generation

// Basic URL
var url = image?.MediaUrl();

// With crop
var url = image?.GetCropUrl("thumbnail");

// With width/height
var url = image?.GetCropUrl(width: 800, height: 600);

5. Dictionary Items for Multi-Language Labels

The platform uses Umbraco Dictionary items for translatable UI labels. There are 169 dictionary keys covering calculators, widgets, forms, and navigation.

Accessing Dictionary Values in Views

// In Razor views (Umbraco helper available)
var label = Umbraco.GetDictionaryValue("widget.Address");
var faxLabel = Umbraco.GetDictionaryValue("widget.Fax");
var telLabel = Umbraco.GetDictionaryValue("widget.Tel");

Common Dictionary Key Patterns

Prefix Purpose Example Keys
widget.* Component labels widget.Address, widget.Tel, widget.Fax, Widget.Email
Calculator.* Calculator UI Calculator.Amount, Calculator.Term, Calculator.Rate
TCMobile.* Terms/mobile TCMobile.CreditUnionWebsite
Search.* Search UI Search.NoResults, Search.Placeholder

Case Sensitivity

Dictionary keys are case-sensitive. Some keys use widget. (lowercase) while others use Widget. (capitalized). Always match the exact key as stored in Umbraco.


6. Content Tree Organization

The content tree follows a logical hierarchy that maps to the site's URL structure:

Root
├── Home                              /
│   ├── Membership                    /membership/
│   │   ├── How to Join               /membership/how-to-join/
│   │   └── Switch Account            /membership/switch-account/
│   ├── Loans                         /loans/
│   │   ├── Motor Loan                /loans/motor-loan/
│   │   ├── Holiday Loan              /loans/holiday-loan/
│   │   ├── Home Improvement          /loans/home-improvement/
│   │   └── Apply Now                 /loans/apply-now/
│   ├── Savings                       /savings/
│   ├── Services                      /services/
│   ├── About                         /about/
│   ├── Contact                       /contact/
│   ├── News & Events                 /news/
│   │   └── News Categories           (category folders)
│   ├── FAQ                           /faq/
│   │   ├── Loans FAQ                 /faq/loans/
│   │   ├── Savings FAQ               /faq/savings/
│   │   └── (more categories)
│   ├── Help                          /help/
│   ├── Search                        /search/
│   ├── Testimonials                  /testimonials/
│   │   └── Categories                (Loans, General, etc.)
│   ├── Privacy Policy                /privacy-policy/
│   ├── Terms and Conditions          /terms-and-conditions/
│   ├── Cookie Notice                 /cookie-notice/
│   │
│   └── [Configuration Nodes]         (no public URL)
│       ├── Calculators Config
│       ├── Loan Boxes Config
│       ├── Menu Config
│       ├── Footer Config
│       ├── Homepage Slider Config
│       ├── SEO Config
│       ├── Site Styles Config
│       ├── Google Maps Config
│       ├── GTM Config
│       ├── Cookie Config
│       └── Privacy Config
├── Website Configuration             (root level, no URL)
└── 2FA Settings                      (root level, no URL)

Total content nodes: ~116

Access Control

  • Credit Union Administrators -- see all content including Website Configuration
  • Credit Union Editors -- see only content under Home (cannot access root-level config nodes)

7. Website Configuration Node

The websiteConfiguration document type is the central settings hub. It stores global values that every page needs. Views access it through SiteSettingsService, which caches all configuration nodes in a single snapshot.

How SiteSettingsService Works

The service scans the content tree at startup, finds each configuration node by document type alias, and wraps them in typed adapter interfaces:

// Injection in views
@inject ISiteSettingsService SiteSettings

// Access typed settings
var logo = SiteSettings.Website?.Logo;
var phone = SiteSettings.Website?.PhoneNumber;
var brandColor = SiteSettings.Styles?.PrimaryColor;
var gtmId = SiteSettings.GoogleTagManager?.ContainerId;

Available Settings Properties

Property Source Type
SiteSettings.Website websiteConfiguration IWebsiteSettings -- logo, contact info, social URLs
SiteSettings.Styles siteStyleConfiguration ISiteStyleSettings -- brand colors, fonts
SiteSettings.Menu menuConfiguration IMenuSettings -- navigation items
SiteSettings.Footer footerConfiguration IFooterSettings -- footer content
SiteSettings.Seo seoConfiguration ISeoSettings -- default meta tags, OG image
SiteSettings.GoogleTagManager googleTagManagerConfiguration IGoogleTagManagerSettings -- GTM ID
SiteSettings.HomepageSlider homepageSliderConfiguration IHomepageSliderSettings -- hero slides
SiteSettings.Cookie cookieConfiguration ICookieSettings -- Cookiebot settings
SiteSettings.LoanBoxesConfiguration loanBoxesConfiguration IPublishedContent -- raw content node
SiteSettings.GoogleMapConfiguration googleMapConfiguration IPublishedContent -- raw content node
SiteSettings.CalculatorsConfiguration calculatorsConfiguration IPublishedContent -- raw content node
SiteSettings.SearchPage search IPublishedContent -- search page node

Caching

The SiteSettingsService uses Umbraco's RuntimeCache with key Progress_SiteSettings_v3. The entire settings snapshot is built once and cached until the application pool recycles or cache is explicitly cleared. This means all 12 configuration node lookups happen in a single cache miss, not per-request.

Adding New Configuration

To add a new site-wide setting:

  1. Create a new document type (e.g., newFeatureConfiguration) in the backoffice
  2. Add a content node of that type under Home
  3. Add a property to SiteSettingsSnapshot and a lookup in SiteSettingsService.GetSettings()
  4. Create an adapter implementing a new interface (e.g., INewFeatureSettings)
  5. Expose it as a property on ISiteSettingsService

Appendix: Grid Types Reference

The platform has 14 BlockGrid datatypes, each scoped to specific page types:

Grid Type Layouts Components Used By
Standard Page Grid 20 108 standardPage, gallery
Std Page Full Width 11 41 standardPageNew
Homepage Grid 5 61 homeGrid
Animated Grid 6 50 standardPageWow
Footer Grid 7 31 Footer partial
Article Grid 4 35 article, articleType2
Contact Us Grid 5 14 contactus
Cookie Grid 5 8 cookies
Services Grid 4 16 Services pages
Nav Left Grid 4 12 Left-sidebar pages
Full Width Grid 4 8 Simple full-width pages
Full Width Bottom 4 1 Bottom-of-page sections

Each grid type controls which layouts and components are available to editors, preventing inappropriate component usage (e.g., hero banners in the footer).

Migration documentation by Double for Progress Credit Union