Skip to Content
📚 MyStoryFlow Docs — Your guide to preserving family stories
Technical DocumentationTemplate Component Architecture

Template Component Architecture

Overview

The MyStoryFlow Template Component Architecture implements a “Lego Pieces” system where content templates are built from reusable, modular components that can be composed into pages, chapters, and complete books.

Three-Tier Component System

Tier 1: Page Components (Atomic Level)

Page components are the smallest building blocks - individual content units that users fill out.

interface PageComponent { id: string name: string description: string category: 'text' | 'media' | 'interactive' | 'special' | 'design' version: string // Component definition schema: ComponentSchema prompts: string[] defaultContent: Record<string, unknown> // Publishing metadata formatOptions: { pdf: FormatConfig epub: FormatConfig kdp: FormatConfig } // Validation rules validation: ValidationRules dependencies?: string[] // Required components // Usage tracking usage_count: number is_public: boolean creator_id?: string created_at: string updated_at: string }

Example Page Components

PersonalInfoPage

{ id: 'personal-info-page', name: 'Personal Information', description: 'Basic personal details with photo', category: 'text', schema: { fields: [ { name: 'full_name', type: 'text', required: true }, { name: 'birth_date', type: 'date', required: false }, { name: 'birth_place', type: 'text', required: false }, { name: 'photo', type: 'image', required: false }, { name: 'bio_summary', type: 'rich_text', required: true } ] }, prompts: [ 'What would you like people to know about you?', 'What makes you unique?', 'What are you most proud of?' ], defaultContent: { full_name: '', bio_summary: '<p>Tell us about yourself...</p>' } }

TimelinePage

{ id: 'timeline-page', name: 'Timeline Events', description: 'Chronological list of important events', category: 'interactive', schema: { fields: [ { name: 'title', type: 'text', required: true }, { name: 'events', type: 'array', required: true, itemSchema: { date: { type: 'date', required: true }, event: { type: 'text', required: true }, description: { type: 'rich_text', required: false }, importance: { type: 'select', options: ['high', 'medium', 'low'] } }} ] }, prompts: [ 'What were the most important events in your life?', 'What moments changed your direction?', 'What achievements are you most proud of?' ] }

Tier 2: Chapter Components (Molecular Level)

Chapter components are logical groupings of page components with narrative flow.

interface ChapterComponent { id: string name: string description: string category: 'life-events' | 'relationships' | 'historical' | 'creative' | 'memorial' // Component composition page_components: PageComponentReference[] flow_config: ChapterFlowConfig // Narrative structure narrative_arc: 'chronological' | 'thematic' | 'problem-solution' | 'journey' estimated_length: { word_count: number page_count: number time_to_complete: number // minutes } // Chapter metadata chapter_settings: { include_in_toc: boolean page_break_before: boolean chapter_number_style: 'numeric' | 'roman' | 'none' header_footer_style: string } // Template metadata version: string usage_count: number is_public: boolean creator_id?: string created_at: string updated_at: string } interface PageComponentReference { component_id: string position: number is_required: boolean customizations?: Record<string, unknown> conditional_logic?: ConditionalRule[] } interface ChapterFlowConfig { introduction_prompt?: string transition_prompts: string[] conclusion_prompt?: string navigation_style: 'linear' | 'branching' | 'freeform' completion_criteria: CompletionRule[] }

Example Chapter Components

EarlyChildhoodChapter

{ id: 'early-childhood-chapter', name: 'Early Childhood (0-5 years)', description: 'Foundational years and first memories', category: 'life-events', page_components: [ { component_id: 'personal-info-page', position: 1, is_required: true, customizations: { focus_age_range: '0-5', prompts_override: [ 'What are your earliest memories?', 'What stories did your family tell about your early years?' ] } }, { component_id: 'timeline-page', position: 2, is_required: true, customizations: { title_default: 'Early Years Timeline', event_categories: ['first_words', 'first_steps', 'family_moments'] } }, { component_id: 'photo-gallery-page', position: 3, is_required: false, customizations: { suggested_photos: ['baby_photos', 'family_photos', 'home_photos'] } } ], flow_config: { introduction_prompt: 'Let\'s explore your earliest years and the foundation they laid for your life story.', transition_prompts: [ 'Now let\'s look at the important moments from this time period.', 'What photos capture these precious early memories?' ], conclusion_prompt: 'How did these early experiences shape who you became?', navigation_style: 'linear' }, narrative_arc: 'chronological', estimated_length: { word_count: 2500, page_count: 8, time_to_complete: 90 } }

Tier 3: Template Components (Organism Level)

Template components are complete book/campaign structures using chapter components.

interface TemplateComponent { id: string name: string description: string category: 'memoir' | 'family_history' | 'cookbook' | 'photo_book' | 'custom' // Template composition chapter_components: ChapterComponentReference[] special_sections: SpecialSectionReference[] // Book structure book_structure: { front_matter: FrontMatterSection[] main_content: MainContentSection[] back_matter: BackMatterSection[] } // Publishing configuration publishing_config: { target_length: { min_pages: number max_pages: number optimal_pages: number } pricing_tier: 'starter' | 'family' | 'premium' kdp_settings: KDPConfiguration export_formats: ('pdf' | 'epub' | 'print')[] } // User experience completion_flow: { estimated_duration_months: number prompt_schedule: 'daily' | 'weekly' | 'self_paced' milestone_celebrations: MilestoneConfig[] } // Template metadata version: string usage_count: number is_featured: boolean is_public: boolean creator_id?: string created_at: string updated_at: string } interface ChapterComponentReference { component_id: string position: number is_required: boolean customizations?: Record<string, unknown> conditional_logic?: ConditionalRule[] chapter_title_override?: string }

Example Template Component

CompleteLifeJourneyTemplate

{ id: 'complete-life-journey-template', name: 'Complete Life Journey', description: 'Comprehensive life story from birth to present day', category: 'memoir', chapter_components: [ { component_id: 'early-childhood-chapter', position: 1, is_required: true, chapter_title_override: 'The Beginning (0-5 years)' }, { component_id: 'school-years-chapter', position: 2, is_required: true, chapter_title_override: 'Learning and Growing (6-18 years)' }, { component_id: 'young-adulthood-chapter', position: 3, is_required: true, chapter_title_override: 'Finding My Way (18-25 years)' }, { component_id: 'career-beginnings-chapter', position: 4, is_required: true }, { component_id: 'family-formation-chapter', position: 5, is_required: false, conditional_logic: [ { condition: 'has_family', show_if: true } ] }, { component_id: 'career-peak-chapter', position: 6, is_required: true }, { component_id: 'parenting-adventures-chapter', position: 7, is_required: false, conditional_logic: [ { condition: 'has_children', show_if: true } ] }, { component_id: 'community-friendships-chapter', position: 8, is_required: true }, { component_id: 'challenges-triumphs-chapter', position: 9, is_required: true }, { component_id: 'retirement-years-chapter', position: 10, is_required: false, conditional_logic: [ { condition: 'age_over_60', show_if: true } ] }, { component_id: 'wisdom-reflections-chapter', position: 11, is_required: true }, { component_id: 'legacy-messages-chapter', position: 12, is_required: true } ], special_sections: [ { section_id: 'dedication-page', position: 'front_matter', is_required: false }, { section_id: 'family-tree-section', position: 'back_matter', is_required: false }, { section_id: 'photo-galleries', position: 'throughout', is_required: false }, { section_id: 'recipe-collection', position: 'back_matter', is_required: false } ], book_structure: { front_matter: [ { type: 'title_page', required: true }, { type: 'dedication', required: false }, { type: 'table_of_contents', required: true }, { type: 'foreword', required: false } ], main_content: [ { type: 'chapter_content', required: true }, { type: 'photo_inserts', required: false } ], back_matter: [ { type: 'acknowledgments', required: false }, { type: 'family_tree', required: false }, { type: 'recipe_collection', required: false }, { type: 'about_author', required: true } ] }, publishing_config: { target_length: { min_pages: 150, max_pages: 300, optimal_pages: 200 }, pricing_tier: 'premium', export_formats: ['pdf', 'epub', 'print'] }, completion_flow: { estimated_duration_months: 12, prompt_schedule: 'weekly', milestone_celebrations: [ { at_chapter: 3, type: 'progress_celebration' }, { at_chapter: 6, type: 'halfway_milestone' }, { at_chapter: 9, type: 'final_stretch' }, { at_completion: true, type: 'book_completion' } ] } }

Database Schema

Core Tables

-- Page component definitions CREATE TABLE page_components ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), name TEXT NOT NULL, description TEXT, category TEXT CHECK (category IN ('text', 'media', 'interactive', 'special', 'design')), version TEXT NOT NULL DEFAULT '1.0.0', -- Component definition schema JSONB NOT NULL, prompts JSONB NOT NULL DEFAULT '[]', default_content JSONB NOT NULL DEFAULT '{}', -- Publishing metadata format_options JSONB NOT NULL DEFAULT '{}', validation_rules JSONB NOT NULL DEFAULT '{}', dependencies JSONB DEFAULT '[]', -- Metadata usage_count INTEGER DEFAULT 0, is_public BOOLEAN DEFAULT false, creator_id UUID REFERENCES auth.users(id), created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() ); -- Chapter component definitions CREATE TABLE chapter_components ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), name TEXT NOT NULL, description TEXT, category TEXT CHECK (category IN ('life-events', 'relationships', 'historical', 'creative', 'memorial')), version TEXT NOT NULL DEFAULT '1.0.0', -- Component composition page_components JSONB NOT NULL DEFAULT '[]', flow_config JSONB NOT NULL DEFAULT '{}', -- Narrative structure narrative_arc TEXT CHECK (narrative_arc IN ('chronological', 'thematic', 'problem-solution', 'journey')), estimated_length JSONB NOT NULL DEFAULT '{}', chapter_settings JSONB NOT NULL DEFAULT '{}', -- Metadata usage_count INTEGER DEFAULT 0, is_public BOOLEAN DEFAULT false, creator_id UUID REFERENCES auth.users(id), created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() ); -- Template component definitions (enhanced book_templates) CREATE TABLE template_components ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), name TEXT NOT NULL, description TEXT, category TEXT CHECK (category IN ('memoir', 'family_history', 'cookbook', 'photo_book', 'custom')), version TEXT NOT NULL DEFAULT '1.0.0', -- Template composition chapter_components JSONB NOT NULL DEFAULT '[]', special_sections JSONB NOT NULL DEFAULT '[]', book_structure JSONB NOT NULL DEFAULT '{}', -- Publishing configuration publishing_config JSONB NOT NULL DEFAULT '{}', completion_flow JSONB NOT NULL DEFAULT '{}', -- Metadata usage_count INTEGER DEFAULT 0, is_featured BOOLEAN DEFAULT false, is_public BOOLEAN DEFAULT false, creator_id UUID REFERENCES auth.users(id), created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() ); -- User customizations CREATE TABLE user_customizations ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), user_id UUID REFERENCES auth.users(id) NOT NULL, component_type TEXT CHECK (component_type IN ('page', 'chapter', 'template')), component_id UUID NOT NULL, customizations JSONB NOT NULL DEFAULT '{}', created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), UNIQUE(user_id, component_type, component_id) );

Relationship Tables

-- Campaign to template mapping CREATE TABLE campaign_templates ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), campaign_template_id TEXT NOT NULL, -- from existing templates.ts template_component_id UUID REFERENCES template_components(id), mapping_config JSONB NOT NULL DEFAULT '{}', created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() ); -- Book to template component usage CREATE TABLE book_template_usage ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), book_id UUID REFERENCES books(id) ON DELETE CASCADE, template_component_id UUID REFERENCES template_components(id), customizations JSONB NOT NULL DEFAULT '{}', completion_status JSONB NOT NULL DEFAULT '{}', created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() );

Component Registry System

Centralized Component Registry

class ComponentRegistry { private static instance: ComponentRegistry private pageComponents: Map<string, PageComponent> = new Map() private chapterComponents: Map<string, ChapterComponent> = new Map() private templateComponents: Map<string, TemplateComponent> = new Map() static getInstance(): ComponentRegistry { if (!ComponentRegistry.instance) { ComponentRegistry.instance = new ComponentRegistry() } return ComponentRegistry.instance } // Page component methods registerPageComponent(component: PageComponent): void { this.pageComponents.set(component.id, component) } getPageComponent(id: string): PageComponent | undefined { return this.pageComponents.get(id) } getPageComponentsByCategory(category: string): PageComponent[] { return Array.from(this.pageComponents.values()) .filter(comp => comp.category === category) } // Chapter component methods registerChapterComponent(component: ChapterComponent): void { this.chapterComponents.set(component.id, component) } getChapterComponent(id: string): ChapterComponent | undefined { return this.chapterComponents.get(id) } // Template component methods registerTemplateComponent(component: TemplateComponent): void { this.templateComponents.set(component.id, component) } getTemplateComponent(id: string): TemplateComponent | undefined { return this.templateComponents.get(id) } // Component validation validateComponent(component: any, type: 'page' | 'chapter' | 'template'): ValidationResult { const schema = this.getValidationSchema(type) return validateAgainstSchema(component, schema) } // Component dependency resolution resolveDependencies(componentId: string, type: 'page' | 'chapter' | 'template'): string[] { const component = this.getComponent(componentId, type) if (!component) return [] return this.getDependencyTree(component) } }

Component Builder Interface

interface ComponentBuilder { // Page component builder createPageComponent(config: PageComponentConfig): PageComponent clonePageComponent(sourceId: string, modifications: Partial<PageComponent>): PageComponent // Chapter component builder createChapterComponent(config: ChapterComponentConfig): ChapterComponent addPageToChapter(chapterId: string, pageId: string, position: number): void reorderChapterPages(chapterId: string, newOrder: string[]): void // Template component builder createTemplateComponent(config: TemplateComponentConfig): TemplateComponent addChapterToTemplate(templateId: string, chapterId: string, position: number): void customizeTemplateForUser(templateId: string, userId: string, customizations: any): TemplateComponent }

Template Inheritance System

Component Versioning

interface ComponentVersion { component_id: string version: string parent_version?: string changes: ComponentChange[] backward_compatible: boolean migration_script?: string created_at: string created_by: string } interface ComponentChange { type: 'field_added' | 'field_removed' | 'field_modified' | 'prompt_changed' | 'schema_updated' field_path: string old_value?: any new_value?: any breaking_change: boolean }

Template Customization

interface TemplateCustomization { user_id: string base_template_id: string customization_name: string modifications: { chapters_added: ChapterModification[] chapters_removed: string[] chapters_reordered: string[] chapter_customizations: Record<string, any> page_customizations: Record<string, any> global_settings: Record<string, any> } is_public: boolean created_at: string updated_at: string }

Component Marketplace

Public Component Sharing

interface ComponentMarketplace { // Browse components browsePageComponents(filter: ComponentFilter): PageComponent[] browseChapterComponents(filter: ComponentFilter): ChapterComponent[] browseTemplateComponents(filter: ComponentFilter): TemplateComponent[] // Component ratings and reviews rateComponent(componentId: string, rating: number, review?: string): void getComponentRating(componentId: string): ComponentRating // Usage analytics trackComponentUsage(componentId: string, userId: string, context: string): void getPopularComponents(category?: string, timeframe?: string): Component[] // Component sharing publishComponent(component: Component, visibility: 'public' | 'community' | 'private'): void forkComponent(componentId: string, modifications: any): Component }

Integration with Existing Systems

Bridge to Current Templates

// Migration utility to convert existing templates const migrateExistingTemplates = async () => { const existingTemplates = await loadExistingTemplates() for (const template of existingTemplates) { const templateComponent = await convertToTemplateComponent(template) await ComponentRegistry.getInstance().registerTemplateComponent(templateComponent) } } // Convert campaign template to template component const convertCampaignTemplate = (campaignTemplate: any): TemplateComponent => { return { id: `campaign-${campaignTemplate.id}`, name: campaignTemplate.displayName, description: campaignTemplate.description, category: 'memoir', // default mapping chapter_components: convertPromptsToChapters(campaignTemplate.samplePrompts), // ... rest of conversion logic } }

Content Migration Strategy

// Migrate existing content to component system const migrateExistingContent = async (contentId: string, contentType: 'story' | 'chapter' | 'book') => { const existingContent = await loadContent(contentId, contentType) const componentStructure = await analyzeContentStructure(existingContent) // Create component mapping const componentMapping = await mapContentToComponents(componentStructure) // Preserve original content await preserveOriginalContent(contentId, existingContent) // Apply component structure await applyComponentStructure(contentId, componentMapping) return componentMapping }

This modular component architecture provides the foundation for the “Lego Pieces” template system, enabling users to build custom books from reusable, standardized components while maintaining consistency and professional quality across all content types.