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/nlpfor parsing.@yapture/script-uifor presentation.@yapture/listsfor 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.