6.0 KiB
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_idon GeneratedContent - If
site_deployment_idis 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
TemplateServiceclass insrc/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_idexists:- Query SiteDeployment table and return
site.template_name - Template is tracked at site/domain level in database
- Query SiteDeployment table and return
- If
site_deployment_idis null: randomly select template (don't persist) - 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
template_namefield toSiteDeploymentmodel (String(50), default='basic', not null) - Add
formatted_htmlfield toGeneratedContentmodel (Text type, nullable) - Add
template_usedfield toGeneratedContentmodel (String(50), nullable) - Add
site_deployment_idfield toGeneratedContentmodel (FK to site_deployments, nullable, indexed) - Create database migration script (
scripts/migrate_add_template_to_sites.py) - 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.pyto call template service after content generation - Template service reads
site_deployment_idfrom 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.jsonalready has templates section with mappings (lines 52-59)src/templating/service.pyexists but is empty (only 2 lines)src/templating/templates/directory exists but only contains__init__.pyGeneratedContentmodel 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
- Template format: Simple string replacement with {{ placeholders }}
- CSS approach: Embedded
<style>tags in HTML template - Storage: Store both raw content AND formatted HTML
- Template selection:
- Has site_deployment_id → use site.template_name from database
- No site_deployment_id → pick random, don't persist
- Template tracking: Stored at site level in
site_deployments.template_namefield - 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