Skip to content

v1.21 — Goal Template Library — Curated Seed

Eliminate the blank-slate problem by shipping 12 curated goal templates with pre-built milestones, letting new users tap "Start from a template" to prefill the goal form and get moving immediately.

Summary

Goal Template Library is a four-phase implementation of a read-only, curator-authored feature that reduces friction at goal creation. New users navigating to /goals/create can now tap "Start from a template" in quickMode to browse 12 hand-built templates grouped by theme (fitness, learning, financial, habit/wellness). Selecting a template prefills the goal form with name, category, estimated duration, and milestone suggestions — all editable — and the goal + milestones create atomically in a single addGoal mutation round-trip. Goal detail shows a small "From template: [name]" badge for opted-in users.

The milestone shipped in four sequential phases (82–85), with all code landing on master via direct phase PRs. Phases 82–83 (backend data layer + apply-template plumbing) and Phase 84 (frontend picker UI) shipped in parallel tracks, converging on Phase 85 (telemetry + canonical content drop). Total delivery time: 1 day from plan lock to v3.9.150 tag, driven by pre-mature PRD specification (Phase 4 had locked the contract since November 2025).

This milestone advances the north-star metric (cumulative goals completed) by shortening time-to-first-goal for new users. The Phase 4 PRD activation target — 30%+ of new goals created within the first 7 days via template — is now measurable via PostHog telemetry and feeds a cohort-analysis signal for DAU/MAU lift.

Goal

Eliminate the blank-slate problem in goal creation by shipping a curated library of 12 hand-built GoalTemplates selectable from /goals/create. Selecting a template prefills form state and lets users customize freely before submit. The objective is activation, not breadth: the target is 30%+ of new goals created within the first 7 days via template, which maps to the north-star (goals completed).

Scope — What Shipped

Backend:

  • GoalTemplate model (PublicRecord + acts_as_paranoid); migration creating goal_templates table; goalTemplates GraphQL query; GoalTemplateType + MilestoneInput input types
  • goals.from_template_id nullable string column; Goal#from_template association; GoalType.fromTemplate GraphQL field
  • Mutations::AddGoal extended with optional fromTemplateId + milestones args (backward compatible)
  • GoalTracking::AddGoal interaction with atomic transaction; valid_template existence guard
  • Gamification::GoalCreatedFromTemplateJob + UserAction.goal_created_from_template enum
  • 12 curated placeholder seeds (Phase 82) → Penny's canonical content drop (Phase 85)
  • ≥80% line / 75% branch coverage on all new backend files

Frontend:

  • TemplatePickerModal.vue, TemplateCard.vue components with theme grouping and detail expansion
  • useGoalForm.ts extended with prefillFromTemplate() method; auto-expands quickMode
  • GoalCreate.vue integration with "Start from a template" CTA banner
  • Goal.vue "From template: [name]" badge (glass chip styling)
  • GOAL_TEMPLATES_QUERY + ADD_GOAL_MUTATION with new args in src/constants/graphql/
  • Storybook stories for all new components (light + dark + addon-a11y)
  • ≥80% statement coverage Vitest on all new files

Telemetry:

  • Three PostHog events: template_browsed (TemplatePickerModal.vue:348), template_selected (TemplatePickerModal.vue:381), goal_created_from_template (useGoalForm.ts:231)
  • has_created_from_template user property (set at boot + on mutation success)
  • Cypress E2E golden-path spec covering full flow (OBJ-379)

Documentation:

  • docs/features/goal-templates.md — feature overview, GraphQL surface, telemetry event table, v1 scope boundary
  • docs/product/competitive/feature-matrix.md — Templates column flipped from -- to current capability
  • docs/architecture/data-models.md — GoalTemplate + goals.from_template_id appended
  • CHANGELOG.md v3.9.150 entry
  • Milestone narrative at docs/milestones/v1.21-goal-template-library.md

Phases

PhaseNameStatusKey Deliverable
82Backend foundation: GoalTemplate data layerShippedModel, migration, GraphQL surface, 12 placeholder seeds (PR #671)
83Apply-template plumbing on AddGoalShippedfrom_template_id column, atomic transaction, UserAction (PR #674)
84Frontend template picker UIShippedModal, cards, GoalCreate integration, badge (PR #682 + PR #697)
85Telemetry + canonical content dropShippedThree PostHog events, has_created_from_template property, 12 curated templates (PR #698)
85.2Docs + milestone closeShippedFeature docs, feature matrix flip, PRD status, milestone narrative, audit

Key Decisions

  • Model vs. static YAML — GoalTemplate as ActiveRecord (not static YAML) for future extensibility (ratings, usage metrics). Supports acts_as_paranoid soft deletion and public_id auto-gen.
  • JSONB milestones, not separate table — Template milestones as JSONB array (not separate table) because v1 is read-only curated content. Matches v1.18 EnneagramAssessment.scores pattern.
  • Extended AddGoal, not separate mutation — Optional fromTemplateId + milestones args on existing Mutations::AddGoal for backward compatibility and single round-trip create.
  • Atomic transaction for goal + milestones — Goal + all template milestones create in one ActiveRecord::Base.transaction. Rollback if any milestone validation fails. Verified by regression test.
  • Content-gated frontend with eng-stubs + content-author drop — Phase 82 ships placeholder seeds; Phase 85 holds merge until Penny delivers canonical copy. Proven v1.18 pattern avoids production "TODO" regressions.
  • Public-ID-based linkagefrom_template_id stores template's public_id string (not integer PK), matching goal.parent_goal_id convention.
  • Opt-in, no paywall, no dark patterns — Templates are free-tier core feature. Picker is opt-in CTA parallel to name field. Zero impact on non-template goal creation.

Requirements Coverage

All 14 Phase 4 PRD Feature 5 acceptance criteria satisfied.

CategoryCountStatus
Data model + GraphQL3Satisfied (Phase 82–83)
Frontend discovery + picker4Satisfied (Phase 84)
Atomic create + badge3Satisfied (Phase 83–84)
Telemetry + activation signals2Satisfied (Phase 85)
Documentation + scope boundary2Satisfied (Phase 85.2)

Outcomes

For users: New goal creators have a friction-reducing starting point. "Run Your First 5K" with pre-built milestones is more actionable than a blank form. All fields remain editable.

For the product: Activation funnel is now measurable via PostHog. The Phase 4 PRD target of 30%+ of new goals created within 7 days via template is now owned by Penny post-ship via cohort analysis.

For the platform: Competitive table-stakes gap is closed. Feature matrix Templates column flips from -- to baseline parity with direct competitors.

Tech Debt

Closed:

  • ✅ N+1 on goalTemplates resolver (Phase 83)
  • ✅ Seed re-run guard for canonical content (Phase 85)
  • fromTemplateId on addGoal mutation call (Phase 84-C)
  • fromTemplateName field on GOAL_QUERY (Phase 84-C)
  • valid_template existence guard (Phase 84-C)

Closed:

  • Cypress E2E golden-path spec (OBJ-379) — Shipped PR #707
  • 126ff6d3 — Phase 82: GoalTemplate data layer (PR #671)
  • e5f44dd4 — Phase 83: Apply-template plumbing (PR #674)
  • ab318454 — Phase 84-C: Frontend wiring (PR #697)
  • 901c3714 — Phase 85: Telemetry + content drop (PR #698)

Last updated: 2026-06-22

Loading…