Foundation Categories

Every Uniweb foundation is a Vite library project that builds to entry.js. But foundations vary in how much they know about the site they serve. A foundation that hardcodes an API endpoint and a color palette works fine — for one site. A foundation that delegates those decisions to the site works everywhere.

This isn't a quality distinction. It's a trade-off between simplicity and reusability, and the right answer depends on what you're building.


The Spectrum

Foundation portability isn't binary. It's a sliding scale with two clear endpoints and a lot of reasonable middle ground.

Bundled — The foundation and site are effectively one unit. Components fetch their own data, hardcode their colors, and assume a specific deployment. Standard React patterns. Nothing new to learn.

Portable — The foundation doesn't know which site it serves. Data sources come from page.yml. Colors come from theme.yml. The same foundation can serve multiple sites with different content, branding, and APIs.

Most foundations land somewhere in between. A foundation might use CCA's semantic theming (portable colors) but fetch data directly from a known API (bundled data). That's fine — you pick up each convention when the trade-off makes sense for you.


What Changes Along the Scale

Data

BundledPortable
Component calls fetch() in a useEffectSite declares data sources in page.yml
Component manages loading state, errors, cachingRuntime handles fetch, cache, loading state
Component knows the API endpointComponent reads content.data, doesn't know where it came from
Works with one backendWorks with any backend the site configures

The portable approach is genuinely less code per component — no useEffect, no useState for loading, no cache logic. The runtime handles all of that. The trade-off is learning how fetch configs, auto-wiring, and data.entity work. See Working with Data for the full picture.

Theming

BundledPortable
Component uses Tailwind color classes directly (bg-blue-600)Component uses semantic CSS tokens (var(--bg), var(--heading))
Theme changes mean editing component codeSite changes theme.yml, components adapt
One look per foundationSame foundation, different look per site

Semantic theming removes code — no theme maps, no conditional class names, no themes.light.title objects. Each component just uses tokens, and the site controls what those tokens resolve to. See Thinking in Contexts.

Configuration

BundledPortable
Component reads env vars or imported configComponent reads params from meta.js
Options are code-level (developer changes a constant)Options are content-level (author picks from a dropdown)
Changing behavior requires a code deployChanging behavior requires editing frontmatter

Params force a cleaner interface — you ask "what actually varies?" and expose only that. The constraint produces tighter components, the same way writing testable code produces more modular code. The author-facing dropdown is a consequence, not the goal.


When Each Makes Sense

Bundled is the right choice when:

  • You're building a personal site or a single-purpose project
  • The foundation and site will always be the same team, same repo, same deploy
  • You already have React components you want to use as-is
  • You're prototyping and don't want to learn new conventions yet

A portfolio site, a startup landing page, a weekend project — bundled is fine. You get Uniweb's file-based routing, content parsing, and static generation without adopting the full CCA data/theming layer.

Portable is the right choice when:

  • The foundation might serve more than one site
  • You want content authors to change data sources or theming without code changes
  • You're building a component library that others will use
  • You want the runtime to handle data fetching and caching for you

A design system, a multi-brand marketing site, an agency template — portable pays for itself quickly. The upfront learning (fetch configs, semantic tokens, meta.js) removes ongoing work (loading states, theme maps, cache invalidation).

The middle is the right choice most of the time:

  • Use semantic theming (it's less code even for one site)
  • Use CCA data fetching for external APIs (the caching alone is worth it)
  • Hardcode things that genuinely won't change (a company logo path, a fixed navigation structure)
  • Move things to the site layer when you find yourself editing the foundation for content reasons

You don't have to commit upfront. Start bundled, move things to the site layer when the repetition bothers you. The architecture supports gradual migration.


What You Give Up, What You Get

Moving toward portableWhat you give upWhat you get
Semantic themingHardcoded palette classes (bg-blue-600)Components that adapt to any brand and context. No theme maps. Less code.
CCA data layeruseEffect + fetch() in componentsAutomatic caching, deduplication, loading states. No data-fetching code.
Params via meta.jsHardcoded config or env varsConstrained, tested interface. Content authors can configure without code.
Content from markdownText in JSXContent changes without deploys. i18n support for free.

Every row is optional. You can use semantic theming without the data layer, or the data layer without params. They compose independently.

A note on "give up": Semantic theming doesn't mean giving up visual richness. Tokens handle context adaptation — the hard problem of making one component work in light, dark, and medium contexts. But your foundation's styles.css can (and should) add design classes that build on those tokens: shadow hierarchies, border variants, gradient effects, accent treatments. A foundation can be fully portable and visually rich. The priority is always: design quality first, portability second, configurability third.


A Note About the Guides

The developer guides in this series focus primarily on portable patterns — semantic theming, CCA data fetching, meta.js params — because those are the conventions that need explaining. Standard React patterns don't need a Uniweb guide.

To see these patterns in practice, the Template Tour maps each official template to its position on the spectrum — what conventions it adopts, what it keeps bundled, and why.

When a guide describes a CCA convention (like declaring data sources in page.yml instead of calling fetch() directly), it's describing the portable approach. If your foundation is bundled or partially bundled, the standard React way still works. The runtime doesn't enforce portability — it enables it.


See Also