- Docs
- What To Build
- Personalized Daily Tracker
Build a personalized daily tracker
Ship a single-user dashboard that fuses Human Design bodygraph, daily forecast timeline, and Numerology Life Path into one page. Three Roxy domains, three Lit web components, one server route. Time to ship: 60 minutes.
The Personalized Tracker is the showcase for what the May 2026 Roxy catalog can do in one weekend. The bodygraph is computed once per user and cached forever. The Life Path is computed once and cached forever. The forecast timeline refreshes daily. Three calls, three renders, three keys to retention: the user sees something for them, every day, that is grounded in their birth data.
What you can build
- Personal daily companion apps (bodygraph + today transits + life-path on home screen)
- Practitioner dashboards (one client, multi-domain context surfaced)
- Push-notification engines (precompute tomorrow forecast at midnight, push the top event)
- "Today summary" widgets for any spiritual-wellness app
- B2B HR or coaching platforms (team bodygraph + forecast for leadership planning)
Prerequisites
- A Roxy API key from /account.
- The user birth
date,time,name, andcity(you geocode the city in Step 1). - A backend you control (Next.js route, Vercel function, Cloudflare Worker, Bun server). The client never sees the API key.
- A simple persistent store (Postgres, SQLite, Redis, even a JSON file) to cache the bodygraph and Life Path per user.
Install
npm install @roxyapi/sdk
pip install roxy-sdk
composer require roxyapi/sdk
The render layer uses @roxyapi/ui Lit web components from a CDN, no install required.
Suggested project location
A standalone reference project lives at ~/per/roxy/examples/personalized-tracker/ (create this repo yourself, the tutorial does not bootstrap it). Recommended shape:
personalized-tracker/
├── app/
│ ├── api/
│ │ ├── tracker/route.ts # server route: fetches all three calls, returns combined payload
│ │ └── location/route.ts # server route: proxies /location/search
│ ├── page.tsx # the dashboard
│ └── layout.tsx
├── lib/
│ └── cache.ts # cache helpers (you choose: Redis, SQLite, KV)
└── .env.local # ROXY_API_KEY=...
Next.js 16, TypeScript, Tailwind. Substitute your stack of choice.
Step 1: Location lookup (run once per user)
Convert the user free-text city to lat/lng/timezone via searchCities. Persist with the user record.
import { createRoxy } from '@roxyapi/sdk';
const roxy = createRoxy(process.env.ROXY_API_KEY!);
const { data: loc } = await roxy.location.searchCities({ query: { q: 'New York' } });
const city = loc.cities[0];
// { city: "New York", country, iso2, latitude: 40.7128, longitude: -74.006, timezone: "America/New_York", utcOffset, population, province }
Save { latitude, longitude, timezone } to the user row. Never re-geocode unless the user edits their city.
Step 2: Bodygraph (one-time per user, cache forever)
Birth data is immutable, so call generateBodygraph once per user and persist the result. The user type, authority, profile, defined centers, channels, and gates never change.
async function ensureBodygraph(userId: string, birth: {
date: string; time: string;
latitude: number; longitude: number; timezone: string;
}) {
const cached = await cache.get(`bg:${userId}`);
if (cached) return cached;
const { data: bg } = await roxy.humanDesign.generateBodygraph({ body: birth });
await cache.set(`bg:${userId}`, bg); // forever
return bg;
}
Verified operationId: generateBodygraph.
Step 3: Life Path (one-time per user, cache forever)
calculateLifePath takes the integer year, month, day. The Life Path number and meaning are deterministic and immutable. One call, ever.
async function ensureLifePath(userId: string, year: number, month: number, day: number) {
const cached = await cache.get(`lp:${userId}`);
if (cached) return cached;
const { data: lp } = await roxy.numerology.calculateLifePath({
body: { year, month, day },
});
await cache.set(`lp:${userId}`, lp);
return lp;
}
Verified operationId: calculateLifePath. Response shape: { number, type, meaning, calculation, hasKarmicDebt, karmicDebtNumber, karmicDebtMeaning }.
Step 4: Forecast timeline (daily, cache 6 hours)
generateTimeline accepts birthData, startDate, endDate and returns every significant event in that window across Western transits, Vedic dasha, and biorhythm. Refresh per user per day. A 6-hour cache TTL is comfortable.
async function todayForecast(userId: string, birthData: {
date: string; time: string; timezone: string;
}) {
const today = new Date().toISOString().slice(0, 10);
const cached = await cache.get(`fc:${userId}:${today}`);
if (cached) return cached;
const { data: timeline } = await roxy.forecast.generateTimeline({
body: {
birthData,
startDate: today,
endDate: new Date(Date.now() + 7 * 24 * 3600 * 1000).toISOString().slice(0, 10),
},
});
await cache.set(`fc:${userId}:${today}`, timeline, { ttl: 6 * 3600 });
return timeline;
}
Verified operationId: generateTimeline. Response: { birthData, startDate, endDate, count, events[] } with each event carrying date, datetime, domain, type, description, significance.
Step 5: Single server route, all three calls
The server route fans out three calls (two cached forever, one daily) and returns a combined payload. The client renders it. Use Drizzle, raw SQL, KV, whatever, the shape is what matters.
// app/api/tracker/route.ts (Next.js App Router)
import { NextResponse } from 'next/server';
import { createRoxy } from '@roxyapi/sdk';
const roxy = createRoxy(process.env.ROXY_API_KEY!);
export async function GET(req: Request) {
const { searchParams } = new URL(req.url);
const userId = searchParams.get('userId')!;
const user = await db.users.findById(userId); // your DB
const birthData = {
date: user.birthDate,
time: user.birthTime,
timezone: user.timezone,
};
const birthWithLocation = {
...birthData,
latitude: user.latitude,
longitude: user.longitude,
};
const [bodygraph, lifePath, forecast] = await Promise.all([
ensureBodygraph(userId, birthWithLocation),
ensureLifePath(userId, user.birthYear, user.birthMonth, user.birthDay),
todayForecast(userId, birthData),
]);
return NextResponse.json({ bodygraph, lifePath, forecast });
}
Three calls, parallelized via Promise.all. The first two return from cache after the first request per user.
Step 6: Render the dashboard
Three <roxy-*> Lit web components on one page. Pass the SDK responses as data props.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>My Daily Tracker</title>
<script src="https://cdn.jsdelivr.net/npm/@roxyapi/ui@0/dist/cdn/roxy-ui.js" defer></script>
<style>
body { font-family: system-ui, sans-serif; max-width: 900px; margin: 0 auto; padding: 24px; }
.grid { display: grid; grid-template-columns: 1fr 1fr; gap: 24px; margin-top: 24px; }
@media (max-width: 700px) { .grid { grid-template-columns: 1fr; } }
</style>
</head>
<body>
<h1>Your daily tracker</h1>
<section>
<h2>Your Human Design</h2>
<roxy-bodygraph id="bg"></roxy-bodygraph>
</section>
<div class="grid">
<section>
<h2>Your Life Path</h2>
<roxy-numerology-card id="lp" type="life-path"></roxy-numerology-card>
</section>
<section>
<h2>This week</h2>
<roxy-forecast-timeline id="fc"></roxy-forecast-timeline>
</section>
</div>
<script type="module">
const res = await fetch('/api/tracker?userId=' + currentUserId);
const { bodygraph, lifePath, forecast } = await res.json();
document.getElementById('bg').data = bodygraph;
document.getElementById('lp').data = lifePath;
document.getElementById('fc').data = forecast;
</script>
</body>
</html>
All three component tags (roxy-bodygraph, roxy-numerology-card, roxy-forecast-timeline) are exported by @roxyapi/ui, verified in ~/per/roxy/sdks/ui/packages/ui/src/index.ts. Theme via CSS custom properties (--roxy-accent, --roxy-bg, --roxy-border), see the UI components page.
For a browser-side variant that skips the server route entirely, use a publishable key (pk_live_* / pk_test_*, origin-restricted, coming soon) and call the SDK from a <script type="module">. The cache layer moves to localStorage or IndexedDB. Until publishable keys ship, keep the server route.
Ship it
- Deploy the Next.js app to Vercel, Cloudflare Pages, or Render. Add
ROXY_API_KEYto the env. Free tier handles hundreds of users. - Schedule a nightly job (Vercel Cron, GitHub Actions, your own cron) to warm the forecast cache for every active user before they log in.
- Push notifications: pre-fetch tomorrow forecast at user-local 23:00 and schedule a notification for 07:00 with the top significance event of the day.
Ready-made starter
There is no dedicated personalized-tracker starter yet. The closest reference integrations:
- astrology-ai-chatbot covers all 12 domains via Remote MCP, Next.js 16. Adapt the dashboard panel to wire the same three calls. Browse at /starters/astrology-ai-chatbot.
- The suggested project at
~/per/roxy/examples/personalized-tracker/(you create it) is the clean-room build of this tutorial.
Gotchas
birthDatais nested inside the forecast request.{ birthData: { date, time, timezone, ... } }. Easy to flatten by mistake.- Bodygraph timezone is required. Latitude and longitude default to 0 but are recommended for transit precision. Forecast lat/lng do not affect the timeline (transits are calculated from natal positions).
- Life Path takes
{ year, month, day }integers, not a date string. Splitting1990-07-15into 3 ints is the convention. The endpoint also accepts other numerology inputs for the other endpoints in the domain (Expression, Soul Urge, etc.); see the numerology guide. - Cache forever means forever. Bodygraph and Life Path only change if the user fixes a birth-data typo. Invalidate on edit, otherwise leave alone.
- Forecast timeline cache TTL is 6 hours. Daily events do not change inside a day; transit aspects and dasha changes are pre-computed from astronomy and only refresh when the calendar advances.
- Web components stream from jsDelivr at first render. Provide a skeleton or loader for the ~1 second before the bundle arrives. Pin a major version (
@roxyapi/ui@0) in production so a CDN update never surprises you. - Three calls, not three subscriptions. Single Roxy key, all 12 domains, no per-product fees.
- Calculations verified against NASA JPL Horizons. Same Roxy Ephemeris across Human Design, Forecast, and the rest of the catalog.
What to build next
- The Human Design guide covers the rest of the HD endpoints (connection, penta, gates, channels, variables).
- The forecast guide covers the daily digest, significant-dates, and solar-return variants.
- The AI companion with memory tutorial adds an LLM layer on top of this same data stack, with vector recall of past readings.
- The AI chatbot tutorial lets users query their own tracker in natural language ("am I in a good phase?", "what is my type, again?").