Blog

Claude Code - Dinner Helper

One of those small annoyances in our house is figuring out where to order from on a Saturday night. We end up rotating through the same few spots by default and half the time we're ordering from somewhere we just went to two weeks ago. I kept thinking there had to be a better way to solve this and it turns out the data I needed was already sitting in a Google Sheet the whole time.

So I built something to solve this! This is my second project using Claude Code as an AI coding partner (the first was my activity dashboard) and I'm really excited to share how it went.

The Idea

We use Tiller Money to track our finances in a Google Sheet. Every restaurant transaction is already categorized with a date. I wanted to build a simple mobile app that the whole family could use to get a suggestion for where to eat based on how recently and how often we've been to a given place. Places we haven't visited in a while should bubble up, places we just went to should get pushed down.

The result is a private, mobile-first web app. It's shared only with the family and it's been a fun little side project to tinker with.

How Claude Code Fits In

I’m an ex-developer turned AI-curious engineer. I can read code and I understand how things fit together at a high level, but building something end-to-end on my own would have taken me weeks of frustration and half-finished Stack Overflow rabbit holes. Claude Code has genuinely changed that for me.

What I've found is that it's not just about the speed (though that's real). It's about the quality of the learning. When I didn't understand why something was built a certain way, I could just ask and get a real explanation in context. When I pushed back on something feeling overcomplicated, Claude would explain the tradeoffs and we'd find a simpler path. I probably learned more about how Next.js App Router actually works this weekend than I had from months of casual reading.

The whole thing took about 6-7 hours spread across a couple of evenings.

Stack

  • Next.js 15 (App Router) with React 19 and TypeScript

  • Tailwind CSS 4 for styling

  • Upstash Redis for storing restaurant data

  • Claude Haiku for cleaning up merchant names

  • Google Apps Script for syncing the data from Tiller

  • Hosted on Vercel

How It Works

A Google Apps Script runs inside the Tiller Sheet every Saturday. It reads only the merchant name and date from restaurant-categorized rows (no dollar amounts, nothing sensitive) and sends that payload to the app. The app never holds any Google credentials which was an intentional decision Claude helped me think through. Basically if anything ever went wrong on the app side, the worst case is someone sees a list of restaurant names.

When new merchant strings come in that the app hasn't seen before, they get sent to Claude Haiku for cleanup. Tiller merchant names are pretty messy in practice. Things like Ls Woking Dragon, Coquitlam or White Spot #141. Claude strips the city suffix, removes branch numbers, flags venue concession vendors (Rogers Arena food stalls kept showing up under "Restaurants"!), and infers the cuisine type. It also picks an emoji and a color theme for each restaurant card in the UI which was a fun bonus. Results get cached permanently so the same string never needs to be parsed twice.

The Suggestion Logic

The scoring is pretty straightforward: score = 50 - recency_penalty + frequency_bonus

Heavy penalty if you were there in the last two weeks, lighter penalty within a month, and a small bonus for places you visit often because you like them for a reason! Anything you haven't been to in over a year drops off the list entirely. From the scored list the app does a weighted random pick so it doesn't just mechanically serve up the top result every time. Hit "Reshuffle" and you get a fresh draw from the same pool.

What I Actually Got Out of It

Beyond just having a working app, I feel like I came out of this project with a much better understanding of how serverless apps actually fit together. The data pipeline, the Redis caching layer, the scoring logic, the mobile UI with per-cuisine color themes... all of it came together in a way that I can actually explain and reason about now. That's the part I'm most proud of.

I'm looking forward to continuing to tinker with this and keep learning through building real things with Claude Code!

Dylan Hansen
Coding with Claude

I was lucky enough to take a week off work in March over the kid’s spring break. We didn’t really have awesome weather during my week off in Vancouver so we spent quite a bit of time inside. During our movie and chill time I finally got a chance to use Claude Code to solve a real-world problem that I had and it was pretty impressive to see how much AI coding tools and agents have evolved in the past few months.

My goal was to create a publicly visible dashboard of my cycling and health data beyond the systems that I store this information in. I thought this would be cool to share with folks who aren’t on Strava or other fitness apps to get a glimpse of the data I track. The dashboard pulls data from my private Strava account as well as Intervals.icu for which I use to plan my training.

Stack

  • Next.js 16 (App Router) with React 19 and TypeScript 5

  • Tailwind CSS 4 for styling, Recharts 3 for data visualization

  • HLS.js for streaming activity videos, date-fns for date handling

  • Hosted on Vercel with standard Next.js deployment; no database required

Data Sources

The dashboard pulls from two APIs:

  • Strava API (OAuth 2.0 refresh token flow): Recent activities and activity photos/videos

  • intervals.icu API (Basic Auth): Wellness metrics (HRV, resting HR, sleep, mood, stress, fatigue, soreness, hydration), fitness modeling (CTL/ATL/TSB), HR zone data and upcoming race events

Architecture

All data fetching happens server-side in a single page component. API calls to Strava and intervals.icu run in parallel using Promise.allSettled(), so a failure in one source doesn't take down the whole page. Interactive components (charts, carousels, rolling-window toggles) are client components that receive data as props.

Caching is handled through Next.js Incremental Static Regeneration (ISR) with a 1-hour revalidation window so the page is statically generated and refreshed in the background hourly. Strava OAuth tokens are cached in-memory with deduplication to prevent concurrent refresh races.

Look & Feel

I was able to prompt Claude to match the look & feel of my website here and it did a fairly good job of matching the template style and colours on the site. It’s not perfect but it does integrate nicely and also stands alone at activity.dylanhansen.ca.

At the time of writing I have probably put about 4 hours of work into this dashboard which would have taken me weeks in the past. It’s been a fun challenge to learn how to prompt an AI system to build this and also have a simple pipeline for deployment (Claude Code to GitHub to Vercel). I’m looking forward to continuing to tinker with this in my (limited) free time as a way to advance my knowledge of AI coding assistants!

Dylan Hansen
Looking Ahead to 2026

As it gets closer to the end of 2025, I’m excited to start looking ahead to next year! This has been another busy year for our family and a lot of personal goals and achievements:

  • I was able to achieve my yearly goal of biking 365 hours this year! I could have easily gone way past it but ended up separating my shoulder at the end of August and was generally burnt out from cycling heading into December.

  • I took on a really awesome and challenging new role at work which I have written about, which continually allows me to leverage my strengths while also making a significant impact on the company’s future direction.

  • Spent a lot of great time with the family including some trips to San Diego (last US family trip for a while), back to the Comox Valley and Vancouver Island and a lot of exploring around Metro Vancouver. We have also been spending a lot of time at home now that we have been in our house for a few years.

As I look forward to 2026, I’m really excited about the new year for a bunch of really awesome reasons:

  • I recently went through a number of medical tests which all came back positive which I’m really grateful for!

  • I’m changing my cycling goals to focus on completing 4 large cycling events throughout the year. I have already registered for 3 and I’m looking forward to more focused training/riding this year, while also including more recovery time in my routine.

  • I’m focusing on “going with the flow” more in my life and developing balance, while also leveraging the structure that I have used to maintain my busy lifestyle.

Here’s to an exciting 2026 for everyone and wishing y’all a Happy New Year!

Dylan Hansen