Files
timeline-svg/TEMPLATE_V2_GUIDE.md
tegwick c22a47f1ea refactor: complete migration to template-v2 architecture
- Remove legacy template.svg files from example/ and my-project/
- Simplify generator.js by removing generateHardcoded method (326→210 lines, -36%)
- Add strict template validation with clear error messages
- Remove all fallback mechanisms - template-v2.svg format now required
- Clean up tests: remove hardcoded generation tests, keep template-based tests
- Add comprehensive e2e tests (large datasets, edge cases, error handling)
- Update documentation: mark REFACTORING_PLAN.md complete, add TEMPLATE_V2_GUIDE.md
- All 56 tests passing (16 engine + 25 generator + 15 integration)

BREAKING CHANGE: Old template.svg format no longer supported. Must use template-v2.svg with <g id="*-template"> elements in defs section.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-27 15:29:58 +01:00

11 KiB

Template-v2.svg Guide

Overview

Template-v2.svg is the required format for creating custom timeline visualizations. Templates are standard SVG files that can be edited in any SVG editor (Inkscape, Adobe Illustrator, Figma, etc.) and contain special template elements that define how months, lanes, and tasks are rendered.

Template Structure

A valid template-v2.svg file must contain:

  1. Standard SVG wrapper with xmlns declaration
  2. <defs> section containing three required template elements:
    • <g id="month-template"> - Defines how each month column is rendered
    • <g id="lane-template"> - Defines how each lane (epic/swimlane) is rendered
    • <g id="task-template"> - Defines how each task item is rendered
  3. Main content area with {{MONTHS}} and {{LANES}} placeholders
  4. Optional styling (gradients, filters, patterns, etc.)

Minimal Template Example

<svg xmlns="http://www.w3.org/2000/svg">
  <defs>
    <!-- Month template -->
    <g id="month-template" style="display:none">
      <line x1="{{MONTH_X}}" y1="{{GRID_TOP}}" x2="{{MONTH_X}}" y2="{{GRID_BOTTOM}}"
            stroke="#E0E0E0" stroke-width="1"/>
      <text x="{{MONTH_TEXT_X}}" y="{{MONTH_LABEL_Y}}"
            font-family="Arial" font-size="12" fill="#424242">{{MONTH_LABEL}}</text>
    </g>

    <!-- Lane template -->
    <g id="lane-template" style="display:none">
      <rect x="{{LANE_X}}" y="{{LANE_Y}}" width="{{LANE_WIDTH}}" height="{{LANE_HEIGHT}}"
            fill="#FAFAFA" stroke="#E0E0E0" rx="8"/>
      <text x="{{LABEL_X}}" y="{{LABEL_Y}}"
            font-family="Arial" font-size="14" font-weight="bold" fill="#212121">{{LANE_NAME}}</text>
    </g>

    <!-- Task template -->
    <g id="task-template" style="display:none">
      <circle cx="{{TASK_X}}" cy="{{TASK_Y}}" r="6" fill="#1976D2"/>
      <text x="{{TEXT_X}}" y="{{TEXT_Y}}"
            font-family="Arial" font-size="11" fill="#424242">{{TASK_ID}} {{TASK_TITLE}}</text>
    </g>
  </defs>

  <rect width="100%" height="100%" fill="#FFFFFF"/>
  {{MONTHS}}
  {{LANES}}
</svg>

Available Placeholders

Month Template Placeholders

Placeholder Description Example Value
{{MONTH_X}} X position of month column 340
{{GRID_TOP}} Y position of grid start 120
{{GRID_BOTTOM}} Y position of grid end 560
{{MONTH_X_OFFSET}} X position offset for backgrounds 310
{{MONTH_LABEL_Y_OFFSET}} Y position offset for label background 70
{{MONTH_TEXT_X}} X position for month text 344
{{MONTH_LABEL_Y}} Y position for month text 90
{{MONTH_LABEL}} Month label text "Jan 25"
{{MONTH_SEP_X}} X position for separator line 339
{{GRID_HEIGHT}} Height of the grid 440

Lane Template Placeholders

Placeholder Description Example Value
{{LANE_X}} X position of lane 40
{{LANE_Y}} Y position of lane 116
{{LANE_WIDTH}} Width of lane 2460
{{LANE_HEIGHT}} Height of lane 80
{{LABEL_X}} X position for lane label 56
{{LABEL_Y}} Y position for lane label 140
{{LANE_NAME}} Lane name text (XML-escaped) "Development"

Task Template Placeholders

Placeholder Description Example Value
{{TASK_X}} X position of task marker 400
{{TASK_Y}} Y position of task marker 150
{{TEXT_X}} X position for task text 412
{{TEXT_Y}} Y position for task text 154
{{TASK_ID}} Task ID (XML-escaped) "T-123"
{{TASK_TITLE}} Task title (XML-escaped) "Implement feature"

Global Placeholders

These appear in the main template body (not in template elements):

Placeholder Description
{{MONTHS}} Replaced with all rendered month elements
{{LANES}} Replaced with all rendered lane and task elements

Editing Templates in SVG Tools

Inkscape

  1. Open template-v2.svg in Inkscape
  2. Locate template elements in the Layers panel (inside <defs>)
  3. Edit shapes, colors, fonts, etc. as needed
  4. Important: Keep id="month-template", id="lane-template", id="task-template" unchanged
  5. Important: Keep {{PLACEHOLDER}} text exactly as is - these are replaced at runtime
  6. Save file (keep SVG format, avoid Inkscape-specific extensions)

Adobe Illustrator

  1. Open template-v2.svg in Illustrator
  2. Use Layers panel to find template groups
  3. Edit visual properties (stroke, fill, fonts)
  4. Do not change group IDs or placeholder text
  5. Export as SVG (use "SVG 1.1" profile)

Figma

  1. Import template-v2.svg into Figma
  2. Edit styling and layout
  3. Keep placeholder text intact (wrapped in {{ and }})
  4. Export as SVG
  5. Manually verify id attributes are preserved

Common Customizations

Changing Colors

Edit the fill and stroke attributes:

<!-- Original -->
<rect fill="#FAFAFA" stroke="#E0E0E0"/>

<!-- Dark theme -->
<rect fill="#2C2C2C" stroke="#404040"/>

Changing Fonts

Edit font-family, font-size, and font-weight attributes:

<!-- Original -->
<text font-family="Arial" font-size="12" fill="#424242">{{MONTH_LABEL}}</text>

<!-- Custom font -->
<text font-family="'Roboto', sans-serif" font-size="14" fill="#1A1A1A">{{MONTH_LABEL}}</text>

Adding Gradients

  1. Define gradient in <defs>:
<defs>
  <linearGradient id="laneGradient" x1="0%" y1="0%" x2="0%" y2="100%">
    <stop offset="0%" style="stop-color:#E3F2FD;stop-opacity:1" />
    <stop offset="100%" style="stop-color:#BBDEFB;stop-opacity:1" />
  </linearGradient>

  <g id="lane-template" style="display:none">
    <rect x="{{LANE_X}}" y="{{LANE_Y}}" width="{{LANE_WIDTH}}" height="{{LANE_HEIGHT}}"
          fill="url(#laneGradient)" stroke="#90CAF9" rx="8"/>
    ...
  </g>
</defs>

Adding Drop Shadows

Use SVG filters:

<defs>
  <filter id="dropShadow" x="-50%" y="-50%" width="200%" height="200%">
    <feGaussianBlur in="SourceAlpha" stdDeviation="2"/>
    <feOffset dx="0" dy="2" result="offsetblur"/>
    <feComponentTransfer>
      <feFuncA type="linear" slope="0.2"/>
    </feComponentTransfer>
    <feMerge>
      <feMergeNode/>
      <feMergeNode in="SourceGraphic"/>
    </feMerge>
  </filter>

  <g id="task-template" style="display:none">
    <circle cx="{{TASK_X}}" cy="{{TASK_Y}}" r="6" fill="#1976D2" filter="url(#dropShadow)"/>
    ...
  </g>
</defs>

Layout Constants

The generator uses these constants for positioning (defined in generator.js):

const left = 220;      // Left margin
const top = 140;       // Top margin
const monthWidth = 120; // Width of each month column
const laneHeight = 80;  // Height of each lane
const laneGap = 16;     // Vertical gap between lanes

To change the overall layout, you would need to modify generator.js. Templates control the visual appearance within these constraints.

Troubleshooting

Error: "Template is required"

Cause: No template was provided or template file couldn't be loaded.

Fix:

  • Verify svgTemplate field in project.json points to a valid template-v2.svg file
  • Check that the template file exists in the project folder

Error: "Template is missing required elements: month-template"

Cause: The template is missing one or more required <g id="*-template"> elements.

Fix:

  • Ensure template has all three required elements in <defs>:
    • <g id="month-template">
    • <g id="lane-template">
    • <g id="task-template">
  • Check that IDs are exactly as shown (case-sensitive)
  • Verify elements are inside <defs> section

Error: "Failed to extract template element: month-template"

Cause: Template element was found during validation but couldn't be extracted (malformed structure).

Fix:

  • Ensure each template element is properly closed: <g id="month-template">...</g>
  • Check for invalid nested structures or unclosed tags
  • Validate SVG syntax using an online SVG validator

Placeholders Not Being Replaced

Symptoms: Generated SVG contains literal {{MONTH_X}} text instead of numbers.

Fix:

  • Verify placeholder syntax: must be exactly {{PLACEHOLDER}} (case-sensitive)
  • Check for typos in placeholder names (see tables above for correct names)
  • Ensure placeholders are in text content, not in comments

Template Elements Visible in Output

Symptoms: Template elements appear in the final SVG with display:none style.

Fix:

  • Verify that template elements have style="display:none" attribute
  • The generator removes this attribute when cloning, but if elements are leaking through, check template structure
  • Ensure template elements are only in <defs>, not in main content area

SVG Dimensions Too Small/Large

Cause: Generator calculates dimensions based on number of months, lanes, and layout constants.

Symptoms: Content is cut off or timeline has excessive white space.

Fix:

  • Adjust timelineMonths setting in project.json to show more/fewer months
  • Modify layout constants in generator.js:151 for more control over spacing
  • Template styling doesn't affect dimensions - that's controlled by the generator

Best Practices

  1. Keep template elements hidden: Always include style="display:none" on template groups
  2. Use semantic IDs: Don't change the required id attributes
  3. Test frequently: Generate a timeline after each template edit to verify changes
  4. Version control: Keep template files in version control to track changes
  5. Start simple: Begin with the minimal template example and add complexity gradually
  6. Preserve placeholders: Never modify the placeholder text - they're replaced at runtime
  7. Use relative units carefully: Absolute pixel values work best for positioning placeholders
  8. Add comments: Document custom styles and modifications for future reference

Example Templates

See the example/ and my-project/ folders for working template-v2.svg files that demonstrate:

  • Professional styling with gradients and shadows
  • Custom color schemes
  • Different font choices
  • Grid patterns and backgrounds

Further Resources

Support

If you encounter issues not covered in this guide:

  1. Check that your template validates as proper SVG
  2. Compare with the example templates
  3. Review error messages carefully - they indicate what's missing or malformed
  4. File an issue at the project repository with your template attached