PropertyWebBuilder Seed Packs System: Scenario-Based Site Setup Guide

PropertyWebBuilder's Seed Packs system enables developers to provision complete multi-tenant property websites from YAML scenario definitions using a single command or API call.

The Seed Packs system in PropertyWebBuilder (PWB) provides an extensible, scenario-driven approach to tenant provisioning. By bundling configuration, content, and assets into self-contained YAML definitions, developers can instantiate fully-featured real estate websites—complete with themes, properties, translations, and user accounts—without manual database seeding.

What Are Seed Packs?

A seed pack is a self-contained directory structure that describes every aspect of a property website. Stored under db/seeds/packs/, each pack contains a central pack.yml manifest alongside subdirectories for properties, pages, translations, and images. When applied, the pack creates or updates a Pwb::Website tenant with the specified theme, agency data, navigation links, and content translations.

Unlike traditional Rails database seeds, seed packs support scenario-based inheritance, allowing base configurations to be extended for specific markets (e.g., luxury Spanish properties vs. standard residential listings).

Core Architecture and Components

The seed packs architecture consists of four primary components that orchestrate the loading, validation, and application of scenario definitions.

Pwb::SeedPack Core Class

The Pwb::SeedPack class in lib/pwb/seed_pack.rb serves as the primary interface for pack operations. It handles:

  • Path resolution: Locates packs within PACKS_PATHS directories
  • Schema validation: Ensures required keys (display_name, website) exist
  • Inheritance resolution: Loads parent packs defined in inherits_from
  • Seeding orchestration: Executes the ten-step application flow

The class provides both destructive (apply!) and introspection (preview) methods for safe deployment workflows.

Rake Task Interface

CLI operations are exposed through lib/tasks/seed_packs.rake under the pwb:seed_packs namespace:

  • pwb:seed_packs:list – Enumerates available packs
  • pwb:seed_packs:preview[pack_name] – Generates a dry-run summary
  • pwb:seed_packs:apply[pack_name,subdomain] – Provisions a new tenant

These tasks instantiate the core SeedPack class and manage the target Pwb::Website lifecycle.

Pack Directory Structure

Each pack follows a standardized layout within db/seeds/packs/:

spain_luxury/
├── pack.yml              # Manifest and configuration

├── properties/           # YAML property definitions

├── pages/               # Page content files

├── field_keys.yml       # Custom attribute definitions

├── links.yml            # Navigation structure

├── translations/        # I18n locale files

└── images/              # Binary assets or URL manifests

The pack.yml file defines metadata, inheritance relationships, and configuration hashes for the website, agency, and user accounts.

Helper Seeder Integration

When a pack omits specific asset types, the system falls back to existing infrastructure:

  • Pwb::PagesSeeder – Supplies default page layouts when pages/ is empty
  • Pwb::ContentsSeeder – Populates translation keys when content/ is missing
  • Pwb::SeedImages – Generates external image URLs via attach_property_image to avoid storage bloat

Step-by-Step Seeding Execution Flow

When Pwb::SeedPack#apply! is invoked, the system executes a deterministic twelve-step process:

  1. Initialize – Loads pack.yml and validates required keys
  2. Inheritance – Recursively applies parent packs via apply_parent_pack! with skip_website and skip_agency flags to prevent overwrites
  3. Website Configuration – Executes seed_website to set theme, locales, palette, and search configuration
  4. Agency Provisioning – Creates or updates the agency record and address via seed_agency
  5. Field Keys – Loads field_keys.yml (supporting legacy list or nested hash formats)
  6. Navigation Links – Seeds navigation items from links.yml with slug-based deduplication
  7. Page Structure – Loads YAML files from pages/ directory
  8. Page Parts – Applies pack-specific page parts or falls back to PagesSeeder
  9. Property Import – Creates Pwb::RealtyAsset records and sale/rental listings from properties/
  10. Content Population – Seeds Website.contents and translations via seed_content
  11. User Creation – Generates admin and member accounts with UserMembership associations
  12. Materialized View Refresh – Calls Pwb::ListedProperty.refresh to update the search index

The method returns true on completion or raises a detailed error if validation fails.

CLI Operations for Pack Management

Listing Available Packs

Enumerate all valid seed packs in the load path:

rails pwb:seed_packs:list

Internally, this invokes Pwb::SeedPack.available, which scans PACKS_PATHS directories for valid pack.yml files.

Previewing Pack Contents

Generate a JSON summary of what would be created without modifying the database:

rails pwb:seed_packs:preview[spain_luxury]

Output includes pack metadata, inheritance chain, entity counts, and supported locales:

{
  "pack_name": "spain_luxury",
  "display_name": "Spanish Luxury Real Estate",
  "inherits_from": "base",
  "website": { "theme_name": "bristol" },
  "properties": 7,
  "locales": ["es", "en", "de"],
  "users": 1
}

Applying a Pack to a Tenant

Provision a new website using a specific pack:

rails pwb:seed_packs:apply[spain_luxury,costa-luxury]

This command:

  1. Locates or creates a Pwb::Website with subdomain costa-luxury
  2. Assigns the theme specified in the pack configuration
  3. Executes the full seeding flow via Pwb::SeedPack.find('spain_luxury').apply!(website: website)

Programmatic API Usage

For automated provisioning workflows, interact with seed packs directly in Ruby:


# Load a pack definition

pack = Pwb::SeedPack.find('spain_luxury')

# Create a tenant website

website = Pwb::Website.create!(
  subdomain: 'costa-demo',
  theme_name: 'bristol'
)

# Apply the pack with options

pack.apply!(website: website, options: { dry_run: false })

The apply! method accepts a website instance and optional configuration hashes, enabling integration with background job processors like Sidekiq for automated tenant onboarding.

Creating Custom Packs with Inheritance

Extend existing packs using the inherits_from directive to avoid duplication of common data (field keys, base pages, standard translations).

Define a premium variant of an existing pack:


# db/seeds/packs/spain_luxury_premium/pack.yml

name: spain_luxury_premium
display_name: "Spanish Luxury – Premium"
inherits_from: spain_luxury

website:
  theme_name: bristol
  default_client_locale: es
  supported_locales: [es, en, de, fr]

When applied, the system first executes the parent spain_luxury pack (skipping website and agency creation if already present), then overlays the premium-specific configuration. Add supplementary property files under properties/ or override specific content keys to customize the scenario.

Summary

  • Seed packs are self-contained YAML bundles in db/seeds/packs/ that define complete website scenarios including themes, properties, and translations.
  • The Pwb::SeedPack class in lib/pwb/seed_pack.rb orchestrates validation, inheritance, and the twelve-step seeding process.
  • CLI tools in lib/tasks/seed_packs.rake provide list, preview, and apply commands for pack management.
  • Inheritance via inherits_from enables pack specialization without duplication, applying parent configurations first with selective skipping of website and agency data.
  • The system integrates with existing seeders (PagesSeeder, ContentsSeeder) and supports external image URLs via Pwb::SeedImages to minimize storage overhead.

Frequently Asked Questions

How do I create a new seed pack from scratch?

Create a directory under db/seeds/packs/ containing a pack.yml file with required keys (name, display_name, website). Add subdirectories for properties/, pages/, or translations/ as needed. Validate your structure by running rails pwb:seed_packs:list to ensure the pack appears in the registry.

What happens if a pack references missing images?

When Pwb::SeedImages.enabled? returns true, the attach_property_image method generates external URLs on-the-fly rather than storing binary data. If image files are missing from the pack's images/ directory, the seeder logs a warning but continues processing the property record, ensuring partial seeding does not fail.

Can I apply multiple packs to the same website?

Yes. Invoke apply! sequentially with different pack instances. The system updates existing records (e.g., agency data) or creates missing entities (e.g., new properties) based on unique identifiers like slugs. Use inheritance instead of sequential application if packs represent logical extensions of the same scenario.

How do I override specific pages without copying the entire pack?

Create a child pack using inherits_from pointing to the base pack. Place only the modified YAML files in the child pack's pages/ or content/ directories. The seeding process prioritizes pack-specific files over parent definitions and default seeders, applying your overrides while retaining base configuration.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →