Disclaimer
Is this project open source? No
Is this project completely free? Yes. The snippet and the endpoint it uses need no account or API key. WhenPeak does have paid tiers for high-volume developer use, but nothing in this template touches them.
Is this project made with AI beyond the author’s ability to comprehend how it works? No
Every hour in my daily note looks the same, but 9am and 3pm are completely different for me, and it shifts depending on how I slept. So I put together a small Templater snippet for it.
Disclosure up front: I’m one of the founders of WhenPeak, the API this calls. It’s built on the Two-Process Model, the standard framework in chronobiology, rather than a rule of thumb.
How it works: everything runs inside Obsidian. When the daily note is created, Templater prompts for when you slept and woke up, calls a public endpoint using Obsidian’s own requestUrl, and writes a callout straight into the note. Nothing to install beyond Templater, no account, no API key.
The result looks like this:
[!tip] Focus forecast
Peak: 09:00 · Second wind: 16:00 · Dip: 14:00
Readiness: 82/100 · Third BirdPut the hard thing at 09:00. Keep 14:00 for admin.
Paste this at the top of your daily note template:
<%*
const sleepTime = await tp.system.prompt("What time did you go to sleep? (HH:MM, 24h)", "23:30");
const wakeTime = await tp.system.prompt("What time did you wake up? (HH:MM, 24h)", "07:00");
const quality = (await tp.system.suggester(
["Good", "Fair", "Poor"],
["good", "fair", "poor"],
false,
"How was the sleep?"
)) || "fair";
let output = "";
try {
const res = await requestUrl({
url: "https://api.whenpeak.com/api/v1/predict",
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
sleep_time: sleepTime,
wake_time: wakeTime,
sleep_quality: quality
})
});
const d = res.json;
output =
`> [!tip] Focus forecast\n` +
`> **Peak:** ${d.peak_1.time} · **Second wind:** ${d.peak_2.time} · **Dip:** ${d.dip.time}\n` +
`> **Readiness:** ${Math.round(d.dps)}/100 · ${d.chronotype}\n` +
`>\n` +
`> Put the hard thing at ${d.peak_1.time}. Keep ${d.dip.time} for admin.`;
} catch (e) {
output = `> [!warning] Focus forecast unavailable\n> Could not reach WhenPeak. ${e.message}`;
}
tR += output;
%>
If it can’t reach the endpoint it writes a warning callout instead of failing, so the note still gets created.
The response returns more than the callout uses: the full 24-hour curve, chronotype, and a confidence level, so you can build something more involved if you want. It’s the same endpoint behind our ChatGPT, Claude and OpenClaw integrations. Docs: https://whenpeak.com/docs
If you already have your sleep times from a tracker, you can swap the two prompts for however you pull those numbers in.
Thanks for reading, and let me know if you try it. Always keen to hear how people adapt it.