Skip to main content

Content Architecture

What started as a single-page site has grown into 190+ statically generated routes covering research articles, teaching materials, bibliography entries, results dashboards, persona quick-starts, organizational resources, and project documentation. This page explains how we organize that content, keep it maintainable, and ensure it performs well at scale.

Static Export Architecture

TABS uses Next.js with output: 'export' - every page is pre-rendered to static HTML at build time. There is no server. The entire site is a collection of HTML, CSS, and JavaScript files hosted on GitHub Pages.

Why Static Export?

  • Performance - pages load instantly from a CDN with no server round-trip
  • Security - no server to compromise; the attack surface is minimal
  • Cost - GitHub Pages hosting is free for open source projects
  • Reliability - no database, no server processes, no downtime
  • Simplicity - deployment is copying files; rollback is redeploying a previous build

Trade-offs

Static export means we cannot use some Next.js features:

  • No API routes - external APIs (Qualtrics, Prolific) are called from GitHub Actions workflows instead
  • No server-side rendering - all data must be available at build time or fetched client-side
  • No Next.js Image optimization - we use standard <img> tags with the assetPath() helper

Site Organization

Content is organized into logical sections, each with a distinct purpose:

SectionPagesPurpose
Research Articles16Two branches of original research (8 articles each, including branch introductions)
Bibliography44Auto-generated citation pages: 22 individual-adoption + 21 organizational-adoption + 1 comprehensive index
Making of TABS51Architecture, integrations, AI-assisted development, mind maps, SEO, validity checks, and operational playbooks
Results & Data27Live and CRP-2026 dashboards: descriptive, reliability, factor analysis, sensitivity, findings, top barriers, glossary, and reproducibility
Technology Adoption Series13Teaching workshop pages: presentation viewer, handouts, slide tracks
Persona Quick-Starts12Index plus 11 role-specific landing pages dynamically generated under /start/[role] (CEO, CFO, CIO, CTO, CISO, COO, CMO, CSO, CHRO, CRO, Other)
Organizational Resources5Role-grouped guidance under /for-organizations
Concept Mapping & Lit Review5/concept-mapping (3) plus /lit-review-complex and /lit-review-mind-map
Policy Pages6Privacy, cookies, terms, security acknowledgements, vulnerability disclosure, contribution policy
Core Pages12+Homepage, barriers (3), about, FAQ, media, survey, survey-complete, get-involved, technology-adoption-models, tabs-presentation

Data-Driven Content

Repetitive content is stored as structured data in src/data/ and rendered by reusable components. This prevents duplication and makes bulk updates straightforward:

  • Team members - JSON files in src/data/team/, aggregated by team.ts
  • FAQs - JSON files in src/data/faqs/, aggregated by faqs.ts
  • Testimonials - JSON files in src/data/testimonials/
  • Impact metrics - live data in src/data/impact.json, updated by the daily Google Analytics workflow
  • Survey response funnel - Qualtrics response counts in src/data/qualtrics-metrics.json and the Prolific submission funnel in src/data/disposition-summary.json, both surfaced on /results/survey-stats
  • Article series - navigation ordering and metadata in technology-adoption-models-series.ts

SEO Strategy

Every page is optimized for search engines through several mechanisms:

  • Kebab-case URLs - all route folders use hyphens (/privacy-policy, not /PrivacyPolicy), following Google's recommendation
  • Metadata on every page - title, description, and canonical URL via Next.js Metadata API
  • Dynamic sitemap - generated at build time with all 190+ routes (including parameterized routes such as the 11 /start/[role] persona pages and the teaching-series slide pages under /technology-adoption-series/[slide]), correct change frequencies, and priorities
  • Robots.txt - programmatically generated to allow search engine crawling
  • Semantic HTML - proper heading hierarchy (h1 → h2 → h3), landmark regions, and structured content
  • Canonical URLs - prevent duplicate content between custom domain and GitHub Pages deployment

Responsive Design

The site uses a mobile-first responsive design approach with Tailwind CSS:

  • Mobile-first - base styles target mobile; breakpoints add desktop enhancements
  • Breakpoints - sm (640px), md (768px), lg (1024px), xl (1280px)
  • Mobile navigation - slide-out panel with overlay, replacing the desktop dropdown menu
  • Flexible grids - content reflows from single column (mobile) to multi-column (desktop)
  • Touch targets - buttons and links have minimum 44×44px touch areas on mobile

Shared Style System

With 16 research articles and 44 bibliography pages, visual consistency is essential. The src/lib/articleStyles.ts module exports shared Tailwind class constants used across all article-style pages:

import { ARTICLE_CLASSES, H1_CLASSES, H2_CLASSES }
  from '@/lib/articleStyles'

// Every article page uses the same base classes:
<article className={ARTICLE_CLASSES}>
  <h1 className={H1_CLASSES}>Page Title</h1>
  <h2 className={H2_CLASSES}>Section Heading</h2>
</article>

This means a single change to articleStyles.ts updates the typography, spacing, and layout of every article and bibliography page simultaneously.

Dual Deployment

The site is deployed to two locations simultaneously:

Custom Domain

technologyadoptionbarriers.org

No basePath - assets at root

GitHub Pages

<username>.github.io/<repo>/

Requires basePath via NEXT_PUBLIC_BASE_PATH

The assetPath() helper in src/lib/assetPath.ts automatically prepends the correct basePath to all asset URLs, making images and other static resources work in both environments.

Dynamic Routes (still static, but parameterized)

One source file can produce many statically-generated pages by pairing a Next.js dynamic segment with generateStaticParams(). We currently use this in two places:

  • /start is a single hub page; /start/[role] is one source file that emits 11 persona-specific landing pages at build time (CEO, CFO, CIO, CTO, CISO, COO, CMO, CSO, CHRO, CRO, plus a generic Otherfallback). Each persona's recommended next steps, framing, and example barriers come from src/lib/personas.ts, not from individual hand-written pages.
  • /technology-adoption-series/[slide] is one source file that emits a route for every slide in the teaching series (plus legacy URL aliases) at build time. The slide list is derived from technologyAdoptionTeachingSeries.parts[].slides in src/data/technology-adoption-teaching-series.ts.

Together these two parameterized routes are why the route count (190+) exceeds the source-file count (180+). Everything else on the site is a 1-to-1 source file to route mapping. We could templatize more (e.g., bibliography entries) but currently keep them as individual files so each entry can carry custom annotations alongside the auto-generated citation block.

190+ routes from 180+ source files, zero servers, one build step.