Developer guide Preview

Build a goal, routine, and calendar app

Compose Yapture Script, goals, recurring behavior, calendar windows, and local-first tasks into a domain application.

Reference recipe. Goals, Script parsing, recurrence fields, and calendar models exist in Yapture. Routine-management and some external calendar surfaces remain preview features; keep those labels visible in your product.

The outcome

We will model a small training application around one human goal:

Run a comfortable 5K by October 1

The same architecture works for a product launch, family-care plan, learning system, or team operating rhythm.

Goal
├── routines describe repeatable behavior
├── calendar windows describe opportunity
├── tasks describe the next concrete work
└── observations describe what happened over time

1. Keep the source portable

Complete tempo intervals #^comfortable-5k #~tempo-run #@health due:thursday #*{effort_hrs:0.75,energy:high,impact:8}

The line remains understandable without Yapture. A parser can recover its goal, routine, workspace, due date, and metadata.

import { YaptureNLP } from '@yapture/nlp';

const source = 'Complete tempo intervals #^comfortable-5k #~tempo-run #@health due:thursday #*{effort_hrs:0.75,energy:high,impact:8}';
const parsed = YaptureNLP.parse(source);

Check the exact installed parser version and metadata output before persisting an adapter contract.

2. Model the domain outside the parser

Yapture supplies portable intent; your application owns its domain experience.

interface GoalRecipe {
  id: string;
  title: string;
  targetDate?: string;
  routines: Array<{
    id: string;
    label: string;
    recurrence: string;
    durationMinutes: number;
    energy: 'low' | 'medium' | 'high';
  }>;
  windows: Array<{
    day: number;
    start: string;
    end: string;
    timezone: string;
  }>;
  taskSources: string[];
}

Do not make fitness-specific concepts part of Yapture core unless several domains prove the same abstraction.

3. Define routines

const routines = [
  { id: 'easy-run', label: 'Easy run', recurrence: 'FREQ=WEEKLY;BYDAY=TU', durationMinutes: 30, energy: 'low' },
  { id: 'tempo-run', label: 'Tempo run', recurrence: 'FREQ=WEEKLY;BYDAY=TH', durationMinutes: 45, energy: 'high' },
  { id: 'long-run', label: 'Long run', recurrence: 'FREQ=WEEKLY;BYDAY=SA', durationMinutes: 60, energy: 'medium' },
];

Use iCalendar recurrence rules where the product contract supports them. Treat a routine as a template for behavior, not automatically as an infinite set of committed tasks.

4. Propose calendar placement

A task duration plus an available window creates a proposal. It does not become an event until the user or an authorized policy confirms it.

interface CalendarProposal {
  taskId: string;
  startsAt: string;
  endsAt: string;
  status: 'proposed' | 'confirmed' | 'rejected';
  evidence: string[];
}

Keep free/busy data local when possible. If you connect Google Calendar or another provider, request the smallest scopes and explain what leaves the device.

5. Put work in a local-first list

The application can adopt only the layer it needs:

  • @yapture/nlp for parsing.
  • @yapture/script-ui for presentation.
  • @yapture/lists for task/list state and adapters.
  • REST capability lists for a lightweight agent inbox.

The host product keeps its own colors, navigation, domain terms, and user journey. GP.Family is the reference pattern: Yapture supplies the substrate without replacing the product identity.

6. Add a decision policy

Once tasks have goal, effort, time, and history evidence, build a deterministic MAUT case rather than asking an opaque model to choose directly.

const attributes = [
  { id: 'goal-impact', label: 'Goal impact', direction: 'higher', weight: 0.35, min: 0, max: 10 },
  { id: 'effort', label: 'Effort remaining', direction: 'lower', weight: 0.2, min: 0, max: 4 },
  { id: 'calendar-fit', label: 'Calendar fit', direction: 'higher', weight: 0.25, min: 0, max: 10 },
  { id: 'recovery-risk', label: 'Recovery risk', direction: 'lower', weight: 0.2, min: 0, max: 10 },
];

Unknown values remain missing. Do not turn missing effort into a convenient four-hour estimate.

Continue with MAUT task prioritization.

Shipping checklist

  • Make proposed calendar work visually distinct from committed events.
  • Preserve the original Script source.
  • Pin parser and list package versions.
  • Provide keyboard and screen-reader equivalents for drag operations.
  • Label preview integrations accurately.
  • Keep local data useful without a connection.
  • Give agents explicit capability and action boundaries.