Mood Tracker
I had a really tough year in 2025. So much so that I noticed I had really withdrawn from a lot of things I used to do. I didn’t want to do anything I normally did like going to the gym, programming, going for walks and hikes, or attending family events. I eventually started to get some professional help, and while it does seem to be helping, I noticed my overall mood is still low.
So I decided to build a mood tracker
I figured it could be a fun little project to take on after I built my blog. How hard could it be?
At the time I had initially built my first blog using Eleventy. I liked Eleventy, and what I wanted to do was certainly possible, so I built it out. I wanted to try using Cloudflare workers and their D1 database because I hadn’t used them before. For the API I decided to use Hono, which I had heard about on a Web Dev podcast I listen to, Syntax.
Hono is very cool, and it was insanely easy to get a Cloudflare worker up and running. It makes standing up a simple API almost trivial. The idea is that Cloudflare supplies us with a worker at a URL, you make your request to a route, the worker will hit the D1 database and reply with data. Here is a snippet of the GET request.
app.get("/api/moods/", async (c) => {
const { results } = await c.env.DB.prepare(
`SELECT *
FROM moods
ORDER BY created_at ASC
LIMIT 100`,
).all();
return c.json(results);
});
Very simple! We are grabbing 100 entries from our mood database, ordering it by when they were created, and returning the data.
The POST endpoint is a little more complicated, but not too hard to understand. I wanted a “Key” I could send along with the headers so that someone couldn’t just find my endpoint and start posting data.
app.post("/api/moods/", async (c) => {
const key = c.req.header("X-Mood-Key");
if (!key || key !== c.env.MOOD_KEY) {
return c.json({ error: "Not authorized" }, 401);
}
try {
const data = await c.req.json<MoodInterface>();
await c.env.DB.prepare(
`
INSERT INTO moods (positivity, energy, note, created_at)
VALUES (?, ?, ?, ?)
`,
)
.bind(
data.positivity,
data.energy,
data.note,
Math.floor(Date.now() / 1000),
)
.run();
return c.json({ success: true }, 201);
} catch (e) {
console.error(e);
return c.json({ error: "Failed to insert mood" }, 500);
}
});
Hono makes it so simple to work with, and its all type safe which is great. The code itself is pretty straightforward here. We check if the X-Mood-Key header is supplied, and that it matches our .env value. If it is missing or incorrect, we return at 401, otherwise we insert the data into the database.
We can quickly test requests by setting up a local dev server with a worker, and a local database. Then we can just use curl to send requests. Once that is working, we publish it and Cloudflare handles the rest. On the frontend, I chart positivity and energy over time, and also plot them against each other to see patterns I wouldn’t notice day-to-day.
The main friction I hit was with Eleventy. I had to fetch and cache the data at build time. This is fine for static content, but it meant that new mood entries would not show up unless I rebuilt the site. For something that is inherently ongoing and data driven, it wasn’t really working for me.
I decided to switch to Astro instead. I hadn’t really done anything with the blog yet. It wasn’t live anywhere and I had one post. I was familiar with Astro, having used it before, and I also know Vue so I figured why not? I learned how to use Eleventy, and its collection systems and fetching, but I also learned my initial vision was perhaps too much for it.
I moved over to Astro, implemented better-auth, implemented protected routes so I can push data over from the frontend, and now I can fetch data from my database without having to worry about rebuilding and caching.
Building this gave me a small consistent way to check in with myself. It didn’t fix how I was feeling, but it helps me recognize where I’m at on any given day. More than that, it reminded me that even building something small and personal is something I still enjoy. Sometimes, small steps really are all it takes to get something done.