Skip to content

mollyclare/scaffold

 
 

Repository files navigation

Draftlab Scaffold

A modern, content-focused web template built with Astro v5, Tailwind CSS v4, and React v19. This scaffold provides a flexible page-building system with reusable components, type-safe content collections, and an integrated headless CMS.

Netlify Status

Installation

Create a new project using this template:

npx create-astro --template draftlab-org/scaffold
cd your-project-name
npm install
npm run dev

Or clone and install manually:

git clone https://github.com/draftlab-org/scaffold.git
cd scaffold
npm install
npm run dev

Stack

The template combines Astro v5 for static site generation with Tailwind CSS v4 for styling and React v19 for interactive components. Content is managed through Astro's type-safe content collections with Pages CMS providing a visual editing interface. The build includes automatic image optimization and is preconfigured for Netlify deployment.

Screenshots

Homepage

The homepage showcases the component architecture with a clean hero section and visual representation of atomic design principles.

Homepage

Articles

The articles page displays blog posts in a card grid layout with hero images, tags, author information, and publication dates.

Articles Page

People Directory

The people page features team members in a responsive grid with avatars, names, and titles.

People Page

Rich Search

The rich search module provides fuzzy search across all content types with keyboard shortcuts and category filters.

Rich Search

Architecture

Component System

We are following atomic design principles described by Brad Frost (https://atomicdesign.bradfrost.com/chapter-2/) to make it easier to manage our components:

Components are organized from simple to complex in src/components/. Atoms like Button and Image are basic building blocks. Molecules combine atoms into simple patterns like Card. Organisms such as Hero and Navigation are complex, standalone components. Sections are full-width page blocks that combine organisms and molecules into complete interface sections.

Development Utilities

The DevOnly component and devClass utility help manage development-only UI elements. Wrap any content in <DevOnly> to remove it from production builds. Use devClass('classes') to apply Tailwind classes only in development.

import DevOnly from '@components/atoms/DevOnly.astro'; import {devClass} from '@utils/dev';

<DevOnly><span>Debug info</span></DevOnly>
<div class={`base ${devClass('border-2 border-red-500')}`}></div>

Content Collections

Content lives in src/content/ with schemas defined in config.ts. The scaffold includes nine content collections:

Site Configuration (src/content/site/config.json) - Global site settings including title, description, default SEO images, social media links, favicon, cookie consent configuration, and archived banner settings. This serves as the single source of truth for site-wide metadata and is fully editable through Pages CMS.

Pages (src/content/pages/) - YAML files where each file becomes a route. Pages contain a sections array that you can populate with any combination of Hero, RichText, Card, People, Partners, FeaturedPartners, ArticlesRoll, ResourcesRoll, FlexiSection, Button, or CallToAction sections.

Navigation (src/content/navigation/) - JSON files defining menu structures. Includes main navigation and footer menus. Add new menus by creating additional JSON files.

People (src/content/people/) - Team member information as individual JSON files with headshots, titles, and department tags.

Partners (src/content/partners/) - Partner organizations as individual JSON files with name, logo, URL, category, display order, and featured flag. Partners have individual detail pages at /partners/[id].

Articles (src/content/articles/) - Markdown blog posts with frontmatter including permalink, authors, tags, status, and hero images.

Docs (src/content/docs/) - Markdown documentation pages organized into chapters. Each doc has a permalink, title, chapter label, chapterOrder, and order — used to build a structured, multi-chapter documentation section with navigation at /docs/[slug].

Resources (src/content/resources/) - Data collection for publications like reports, whitepapers, case studies, and guides. Each resource has a title, category, year, optional contributors (linked to people), external links, and tags. Resources have individual detail pages at /resources/[id] with cross-links to contributor profiles.

Categories (src/content/categories/) - Category definitions for articles, people, partners, and resources. Used by filter components across the site.

All collections support a unified status field (draft, published, archived). Drafts are only visible in development and preview modes. Published and archived items are always visible.

Images use absolute paths from the project root (/src/assets/...) for consistency. The image() helper in content collections automatically resolves and optimizes these at build time.

Page Building

The dynamic route at src/pages/[...slug].astro renders pages from the Pages collection. Each page is assembled from sections in the order they appear in the YAML file. To create a new page, add a YAML file to src/content/pages/ and the route appears automatically.

Section types are defined as a discriminated union in the content schema. Each section has its own structure and corresponding component in src/components/sections/. Available section types include Hero, RichText, Card, People, Partners, FeaturedPartners, ArticlesRoll, ResourcesRoll, FlexiSection (nested sections), Button, and CallToAction.

API Endpoints

Dynamic API endpoints automatically expose all content collections as JSON:

  • /api/pages.json - All page data
  • /api/people.json - All team members
  • /api/partners.json - All partner organizations
  • /api/articles.json - All articles with metadata and content
  • /api/docs.json - All documentation pages with metadata and content
  • /api/navigation.json - All navigation menus
  • /api/resources.json - All resources
  • /api/categories.json - All category definitions
  • /api/site.json - Site configuration

The endpoint implementation at src/pages/api/[collection].json.ts automatically generates these routes from your content collections. Add a new collection to config.ts and it becomes available as an API endpoint with no additional configuration.

Navigation & SEO

Navigation menus are managed through the Navigation collection and automatically populate the header and footer. The PageLayout component fetches menu data at build time, so changes to navigation files immediately reflect across all pages.

SEO defaults are defined in the Site Configuration collection. The Head component uses these as fallbacks when pages don't specify their own metadata. This includes default Open Graph images, site description, favicon, and social media links.

Content Management

Pages CMS

The template includes a complete configuration for Pages CMS in .pages.yml. This provides a visual interface for editing content without code.

Access the CMS by logging into https://app.pagescms.org with your Github profile (the project repository must be hosted on Github).

Available in Pages CMS:

  • Site Settings - Global configuration, SEO defaults, social links, cookie consent, and archived banners
  • Pages - Page builder with drag-and-drop sections
  • Navigation Menus - Header and footer menu management
  • Articles - Blog post editor with markdown support
  • Docs - Multi-chapter documentation editor with markdown support
  • People - Team member profiles
  • Partners - Partner organizations with logos, categories, and display order
  • Resources - Publications, reports, whitepapers, and guides

The interface lets you add, edit, and reorder page sections with a drag-and-drop builder. All components include validation and helpful descriptions.

Automatic Permalink Synchronization

The repository includes GitHub Actions automation that keeps page filenames and permalinks synchronized. When changes are pushed or submitted via pull request:

  • Renaming a page file automatically updates its permalink field to match the new filename
  • Changing a permalink field automatically renames the file to match the new permalink value

This bidirectional sync runs via .github/workflows/auto-fix-permalinks.yml using the Python script at .github/scripts/auto_fix_permalinks.py. The automation commits any changes back to the repository, ensuring filenames and permalinks always stay in sync without manual intervention.

Content Status Workflow

All collections use a unified status field with three values:

  • draft - Only visible in development (npm run dev) and preview environments (PUBLIC_PREVIEW=true)
  • published - Visible everywhere
  • archived - Visible everywhere (useful for marking outdated content while keeping it accessible)

Use the isVisible() utility from @utils/content to filter collections by status. The collection-specific utilities (getPages(), getResources(), etc.) already handle this.

Cookie Consent

Configure cookie consent and Google Analytics in src/content/site/config.json:

{
  "cookieConsent": {
    "message": "We use cookies to improve your experience.",
    "googleAnalyticsId": "G-XXXXXXXXXX"
  }
}

The CookieBanner component renders automatically when configured. It stores consent in localStorage and conditionally loads the GA script. Works with Astro View Transitions.

Extending

To add new section types, update the schema in src/content/config.ts, create a component in src/components/sections/, and add the configuration to .pages.yml. The dynamic page route supports new sections automatically.

Commands

npm run dev          # Development server
npm run build        # Production build
npm run preview      # Preview production build

Project Structure

src/
├── assets/          # Images and media
├── components/
│   ├── atoms/       # Basic elements (Button, Image, Link, DevOnly, Banner)
│   ├── molecules/   # Simple combinations (Card, NavItem, FormField)
│   ├── organisms/   # Complex components (Hero, Person, Head, CookieBanner, PageSection)
│   │   └── Resource/  # Resource card components (ResourceItem, ResourceItems)
│   ├── sections/    # Page sections (Hero, Card, RichText, ArticlesRoll, ResourcesRoll, etc.)
│   └── landing/     # Landing page components (ArticlesLanding, PeopleLanding, ResourcesLanding)
├── content/
│   ├── articles/    # Blog posts (Markdown)
│   ├── categories/  # Category definitions (JSON)
│   ├── docs/        # Documentation pages (Markdown)
│   ├── navigation/  # Menu definitions (JSON)
│   ├── pages/       # Page definitions (YAML)
│   ├── partners/    # Partner organizations (JSON)
│   ├── people/      # Team members (JSON)
│   ├── resources/   # Publications and guides (JSON)
│   ├── site/        # Global configuration (JSON)
│   └── config.ts    # Content schemas with Zod validation
├── layouts/
│   ├── BaseLayout.astro     # Document wrapper
│   ├── PageLayout.astro     # Page structure with header/footer
│   └── SectionLayout.astro  # Section wrapper with dev labels
├── lib/
│   └── config.ts          # Site configuration helper
├── pages/
│   ├── api/
│   │   └── [collection].json.ts  # Dynamic API endpoints
│   ├── articles/
│   │   ├── index.astro    # Articles list with filtering
│   │   └── [id].astro     # Individual articles
│   ├── people/
│   │   ├── index.astro    # People directory
│   │   └── [id].astro     # Individual profiles
│   ├── resources/
│   │   ├── index.astro    # Resources list with filtering
│   │   └── [id].astro     # Individual resource pages
│   ├── [...slug].astro    # Dynamic page renderer
│   └── index.astro
├── utils/
│   ├── dev.ts             # Development & preview utilities
│   ├── content.ts         # Content visibility (status filtering)
│   ├── slugify.ts         # URL slug generation
│   ├── renderMarkdown.ts  # Markdown rendering pipeline
│   ├── og.ts              # Open Graph image generation
│   ├── navigation.ts      # Navigation menu utilities
│   ├── pages.ts           # Pages collection utilities
│   ├── articles.ts        # Articles collection utilities
│   ├── docs.ts            # Docs collection utilities
│   ├── people.ts          # People collection utilities
│   ├── partners.ts        # Partners collection utilities
│   └── resources.ts       # Resources collection utilities
└── styles/
    ├── global.css         # Base imports
    ├── typography.css     # Text utilities
    ├── colors.css         # Color definitions
    └── breakpoints.css    # Responsive breakpoints

Icons

The scaffold uses unplugin-icons with @iconify/json for access to thousands of icons. Icons work in both Astro and React/TSX components.

Usage in React/TSX Components

import IconGithub from '~icons/simple-icons/github';
import MagnifyingGlassIcon from '~icons/heroicons/magnifying-glass-20-solid';

export default function MyComponent() {
  return (
    <div>
      <IconGithub class="w-6 h-6" />
      <MagnifyingGlassIcon class="w-5 h-5 text-gray-500" />
    </div>
  );
}

Note: Icons use class (not className) in both Astro and React components.

Usage in Astro Components

---
import IconGithub from '~icons/simple-icons/github';
import MagnifyingGlassIcon from '~icons/heroicons/magnifying-glass-20-solid';
---

<div>
  <IconGithub class="w-6 h-6" />
  <MagnifyingGlassIcon class="w-5 h-5 text-gray-500" />
</div>

Finding Icons

Browse available icons at Icônes or Iconify.

Popular icon sets:

  • Heroicons: ~icons/heroicons/[icon-name]
  • Simple Icons (brands): ~icons/simple-icons/[brand-name]
  • Material Design Icons: ~icons/mdi/[icon-name]
  • Lucide: ~icons/lucide/[icon-name]
  • Tabler Icons: ~icons/tabler/[icon-name]

Import pattern: ~icons/[collection]/[icon-name]

Icons inherit text color and can be styled with Tailwind classes or standard CSS.

Customization

Tailwind CSS v4 uses @theme definitions in the style files. Update src/styles/colors.css for color schemes and src/styles/typography.css for text sizing. Components follow atomic design hierarchy, so start with atoms and compose upward when building new features.

BaseLayout handles document-level concerns while PageLayout adds header, footer, and content structure. Create specialized layouts by extending these base layouts.

Learn More

About

Scaffolding template made with Astro, Tailwind, and React, for SSG sites. PagesCMS-ready.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages

  • TypeScript 48.5%
  • Astro 46.1%
  • CSS 4.5%
  • JavaScript 0.9%