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_PATHSdirectories - 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 packspwb:seed_packs:preview[pack_name]– Generates a dry-run summarypwb: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 whenpages/is emptyPwb::ContentsSeeder– Populates translation keys whencontent/is missingPwb::SeedImages– Generates external image URLs viaattach_property_imageto avoid storage bloat
Step-by-Step Seeding Execution Flow
When Pwb::SeedPack#apply! is invoked, the system executes a deterministic twelve-step process:
- Initialize – Loads
pack.ymland validates required keys - Inheritance – Recursively applies parent packs via
apply_parent_pack!withskip_websiteandskip_agencyflags to prevent overwrites - Website Configuration – Executes
seed_websiteto set theme, locales, palette, and search configuration - Agency Provisioning – Creates or updates the agency record and address via
seed_agency - Field Keys – Loads
field_keys.yml(supporting legacy list or nested hash formats) - Navigation Links – Seeds navigation items from
links.ymlwith slug-based deduplication - Page Structure – Loads YAML files from
pages/directory - Page Parts – Applies pack-specific page parts or falls back to
PagesSeeder - Property Import – Creates
Pwb::RealtyAssetrecords and sale/rental listings fromproperties/ - Content Population – Seeds
Website.contentsand translations viaseed_content - User Creation – Generates admin and member accounts with
UserMembershipassociations - Materialized View Refresh – Calls
Pwb::ListedProperty.refreshto 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:
- Locates or creates a
Pwb::Websitewith subdomaincosta-luxury - Assigns the theme specified in the pack configuration
- 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::SeedPackclass inlib/pwb/seed_pack.rborchestrates validation, inheritance, and the twelve-step seeding process. - CLI tools in
lib/tasks/seed_packs.rakeprovidelist,preview, andapplycommands for pack management. - Inheritance via
inherits_fromenables 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 viaPwb::SeedImagesto 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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →