Creating a Notion widget was one of those spontaneous side projects that started with a simple need—but quickly turned into a rabbit hole of design tweaks, API quirks, and late-night debugging. The end result? A compact, embeddable widget that I now use daily in my Notion dashboard—and surprisingly, so do a few hundred others.
In this post, I’m walking you through how I built it—from the initial idea to the final launch. Whether you’re a fellow tinkerer, a Notion power user, or just curious about what goes into building something like this, I hope it gives you a peek into the process (and maybe even inspires your own build).
The Spark: Solving My Own Problem
Like many Notion fans, I use it to run my entire life—tasks, notes, journal entries, even goal tracking. But there was one thing missing: a tiny, glanceable widget that could show me the current weather and time in different cities (I work across time zones a lot).
Sure, I could open a tab or check my phone—but that broke my flow. What I wanted was a live widget that could sit quietly on my Notion homepage and show key info at a glance.
So, I set out to build it.
Step 1: Scoping the MVP
Before writing any code, I jotted down a quick list of “must-haves”:
- Real-time weather (temperature + icon)
- City name and current time
- Mobile-friendly and embeddable
- Lightweight (no Notion slowdown)
- Customizable with URL parameters (for multiple cities)
The nice-to-haves (like themes, location auto-detect, or animations) would come later. First, I needed something functional.
Step 2: Picking the Stack
Since this widget would be displayed inside Notion via an iframe, I needed something hosted and responsive, without heavy dependencies.
I went with:
- Frontend: Vanilla HTML, Tailwind CSS, and Alpine.js (super lightweight)
- Backend: A small Node.js/Express server (hosted on Vercel)
- APIs: OpenWeatherMap for weather, and
Intl.DateTimeFormat
for time formatting
Why Alpine.js? It gave me just enough reactivity without needing a full React build, which would’ve been overkill for something this simple.
Step 3: Designing for the Notion Canvas
Designing for Notion is a bit tricky. You’re working within a constrained space, and users can embed your widget at wildly different widths.
I followed these principles:
- Minimalist design: Large icons, readable text, no clutter
- Dark mode friendly: Many people use Notion in dark mode, so high contrast was key
- Responsive: The widget had to scale gracefully from 300px to 800px widths
I prototyped everything in Figma first, then translated it into Tailwind. Lots of margin and font-size tweaking to make it feel “just right.”
Step 4: The API Hurdles
The weather API part seemed simple—until I realized that OpenWeatherMap’s free tier had a limit of 60 calls per minute. For a public widget, that wouldn’t scale.
So I added basic caching on the backend. Every city’s weather data is cached for 10 minutes. This reduced API calls dramatically, and for most users, a 10-minute refresh is more than enough.
For time zones, I skipped external APIs and used JavaScript’s Intl.DateTimeFormat()
with timeZone
options. This kept the widget fast and avoided unnecessary API overhead.
Step 5: Making It Customizable
One of my goals was to let users personalize the widget via the embed URL. So I added simple query parameters:
?city=New York
?theme=dark
?units=imperial
I wrote logic on the frontend to parse those parameters and apply them. Eventually, I may add a full UI for generating these embed links—but for now, tech-savvy users are fine copying/pasting a template.
Step 6: Testing in Notion
This part was surprisingly tricky. Notion’s embed blocks don’t support every iframe size or behavior, so I had to tweak:
- Viewport settings: to prevent unwanted zoom on mobile
- Overflow behavior: to avoid clipping
- CSP headers: to make sure it loaded cleanly over HTTPS
Once it worked, I tried it across devices and themes. It felt satisfying to see it working in my personal dashboard—like building my own mini weather station.
Step 7: Launching (Softly)
I posted the widget on Twitter and a Notion subreddit. I also added a tiny landing page with usage instructions and examples.
Within a week, I had:
- ~1,200 unique views
- 400+ embeds
- 25 GitHub stars
- A few kind emails from strangers saying, “This is exactly what I needed!”
That’s what I love about side projects—they don’t need to go viral to feel meaningful.
What I Learned
- Constraints are your friend: Designing inside an iframe forced me to be focused and intentional.
- Simple stacks scale: You don’t need a huge framework to build something useful.
- Start with a personal itch: The best projects solve your own problems first.
- Community is fuel: Even a handful of thank-yous from users can keep your momentum going.
What’s Next
I’m planning to:
- Add more themes (maybe seasonal/weather-based)
- Create a simple link builder tool
- Explore other widget types (habit tracker, Pomodoro timer, quote of the day)