Big-Link-Man/docs/stories/story-2.4-html-formatting-t...

6.0 KiB

Story 2.4: HTML Formatting with Multiple Templates

Status

Completed

Story

As a developer, I want a module that takes the generated text content and formats it into a standard HTML file using one of a few predefined CSS templates, assigning one template per bucket/subdomain, so that all deployed content has a consistent look and feel per site.

Acceptance Criteria

  • A directory of multiple, predefined HTML/CSS templates exists.
  • The master JSON configuration file maps a specific template to each deployment target (e.g., S3 bucket, subdomain).
  • A function accepts the generated content and a target identifier (e.g., bucket name).
  • The function correctly selects and applies the appropriate template based on the configuration mapping.
  • The content is structured into a valid HTML document with the selected CSS.
  • The final HTML content is stored and associated with the project in the database.

Dependencies

  • Story 2.5: Deployment Target Assignment must run before this story to set site_deployment_id on GeneratedContent
  • If site_deployment_id is null, a random template will be selected

Tasks / Subtasks

1. Create Template Infrastructure

Effort: 3 story points

  • Create template file structure under src/templating/templates/
    • Basic template (default)
    • Modern template
    • Classic template
    • Minimal template
  • Each template should include:
    • HTML structure with placeholders for title, meta, content
    • Embedded or inline CSS for styling
    • Responsive design (mobile-friendly)
    • SEO-friendly structure (proper heading hierarchy, meta tags)

2. Implement Template Loading Service

Effort: 3 story points

  • Implement TemplateService class in src/templating/service.py
  • Add load_template(template_name: str) method that reads template file
  • Add get_available_templates() method that lists all templates
  • Handle template file not found errors gracefully with fallback to default
  • Cache loaded templates in memory for performance

3. Implement Template Selection Logic

Effort: 2 story points

  • Add select_template_for_content(site_deployment_id: Optional[int]) method
  • If site_deployment_id exists:
    • Query SiteDeployment table for custom_hostname
    • Check master.config.json templates.mappings for hostname
    • If mapping exists, use it
    • If no mapping, randomly select template and save to config
  • If site_deployment_id is null: randomly select template
  • Return template name

4. Implement Content Formatting

Effort: 5 story points

  • Create format_content(content: str, title: str, meta_description: str, template_name: str) method
  • Parse HTML content and extract components
  • Replace template placeholders with actual content
  • Ensure proper escaping of HTML entities where needed
  • Validate output is well-formed HTML
  • Return formatted HTML string

5. Database Integration

Effort: 2 story points

  • Add formatted_html field to GeneratedContent model (Text type, nullable)
  • Add template_used field to GeneratedContent model (String(50), nullable)
  • Add site_deployment_id field to GeneratedContent model (FK to site_deployments, nullable, indexed)
  • Create database migration script
  • Update repository to save formatted HTML and template_used alongside raw content

6. Integration with Content Generation Flow

Effort: 2 story points

  • Update src/generation/service.py to call template service after content generation
  • Template service reads site_deployment_id from GeneratedContent
  • Store formatted HTML and template_used in database
  • Handle template formatting errors without breaking content generation

7. Unit Tests

Effort: 3 story points

  • Test template loading with valid and invalid names
  • Test template selection with site_deployment_id present
  • Test template selection with site_deployment_id null (random)
  • Test content formatting with different templates
  • Test fallback behavior when template not found
  • Test error handling for malformed templates
  • Achieve >80% code coverage for templating module

8. Integration Tests

Effort: 2 story points

  • Test end-to-end flow: content generation → template application → database storage
  • Test with site_deployment_id assigned (consistent template per site)
  • Test with site_deployment_id null (random template)
  • Verify formatted HTML is valid and renders correctly
  • Test new site gets random template assigned and persisted to config

Dev Notes

Current State

  • master.config.json already has templates section with mappings (lines 52-59)
  • src/templating/service.py exists but is empty (only 2 lines)
  • src/templating/templates/ directory exists but only contains __init__.py
  • GeneratedContent model stores raw content in Text field but no formatted HTML field yet

Dependencies

  • Story 2.2/2.3: Content must be generated before it can be formatted
  • Story 2.5: Deployment target assignment (optional - defaults to random if not assigned)
  • Configuration system: Uses existing master.config.json structure

Technical Decisions

  1. Template format: Jinja2 or simple string replacement (to be decided during implementation)
  2. CSS approach: Embedded <style> tags in HTML template
  3. Storage: Store both raw content AND formatted HTML
  4. Template selection:
    • Has site_deployment_id + config mapping → use mapped template
    • Has site_deployment_id + no mapping → pick random, save to config
    • No site_deployment_id → pick random, don't persist
  5. Story 2.4 owns ALL template selection logic

Suggested Template Structure

src/templating/templates/
  ├── basic.html
  ├── modern.html
  ├── classic.html
  └── minimal.html

Testing Approach

  • Unit tests: Test each service method in isolation
  • Integration tests: Test full content → template → storage flow
  • Manual QA: Visual inspection of rendered HTML in browser