Skip to content

rushhiii/notion-widgets

Notion Widgets Banner

✮ Notion Widgets Framework

Static, embeddable Notion widgets built with Next.js App Router, TypeScript, and Tailwind CSS.

Includes clock, timer, stopwatch, D-Day, quotes, weather, progress, and music player widgets with URL-based customization and per-instance settings.

Notion Next.js TypeScript TailwindCSS Vercel

Table of Contents

What's Included

  • Clock, Timer, Stopwatch, Quotes, D-Day, Weather, and Progress widgets
  • Music Player widget (APlayer + MetingJS)
  • Static-compatible, iframe-safe embeds for Notion
  • Theme, layout, color, and behavior customization through query params
  • Responsive UI with transparent-friendly embeds
  • Per-instance settings for widgets that store state

Showcase

Notion widgets dashboard

Screenshots:

Clock Timer Stopwatch
Clock Timer Stopwatch
Weather Quotes Progress
Weather Quotes Progress
D-Day Music Player
D-Day Music Player

Quick Start

npm install
npm run sync:quotes
npm run dev

Open http://localhost:3000/clock or http://localhost:3000/quotes.

Fork & Deploy Your Own

  1. Fork the repo on GitHub: https://github.com/rushhiii/notion-widgets

  2. Clone your fork locally:

    git clone https://github.com/YOUR_USERNAME/notion-widgets.git
    cd notion-widgets
  3. Install dependencies:

    npm install
  4. (Optional) Sync Notion quotes locally:

    • Create .env.local with NOTION_TOKEN and NOTION_DATABASE_ID
    • Run npm run sync:quotes
  5. Test locally:

    npm run dev

    Open http://localhost:3000/clock to verify.

  6. Push to your GitHub fork:

    git add .
    git commit -m "Deploy to Vercel"
    git push origin main
  7. Deploy to Vercel:

    • Go to https://vercel.com and sign in
    • Click "Add New" → "Project"
    • Select your forked repo
    • Click "Deploy"
  8. (Optional) Add environment variables in Vercel:

    • Go to project Settings → Environment Variables
    • Add NEXT_PUBLIC_OPENWEATHER_API_KEY if you use weather widgets
    • Redeploy for changes to take effect

Your widgets will be live at https://YOUR_VERCEL_APP.vercel.app/clock, /timer, etc.

Widget Routes

  • /clock
  • /timer
  • /stopwatch
  • /dday
  • /quotes
  • /weather
  • /progress
  • /music-player

Instance IDs

Use instance to isolate settings or saved state across multiple embeds of the same widget. Only a-z, 0-9, _, and - are kept.

Supported for stateful widgets (clock, progress, music player). Safe to include on quotes and D-Day for consistent link naming.

Example:

  • /progress?instance=work&embed=1

Common Query Params

  • Clock: tz, format, seconds, theme, controls, size, bg, text, instance
  • Timer: t, start, theme, controls, size
  • Stopwatch: t, start, theme, controls, size
  • Quotes: category, source, mode, rotate, interval, bg, border, text, accent, instance
  • D-Day: date, mode, align, showdate, bg, color, titleColor, dayColor, timeColor, instance
  • Weather: location, lat, lon, units, mode, details, theme, bg, text, accent
  • Progress: title, label, goal, progress, prefix, suffix, accent, track, text, bg, embed, instance
  • Music Player: server, type, id, colorscheme, theme, loop, order, preload, volume, list-folded, list-max-height, storage-name, instance

Music Player (English)

Powered by APlayer + MetingJS, supports both Netease and Tencent playlists/songs/albums/artists/search.

Examples:

  • Tencent playlist: https://notion.busiyi.world/music-player/?server=tencent&type=playlist&id=7888484143
  • Netease playlist with list height: https://notion.busiyi.world/music-player/?server=netease&type=playlist&id=12528089157&list-max-height=96
  • Netease song with forced dark mode: https://notion.busiyi.world/music-player/?server=netease&type=song&id=28285910&colorscheme=dark

Options:

option default description
server required Music provider: netease, tencent
type required Type: song, playlist, album, search, artist
id required song id, playlist id, album id, search keyword, artist id
colorscheme auto dark, light, or auto (follow system)
theme #2980b9 Primary accent color
loop all Loop mode: all, one, none
order list Play order: list, random
preload auto Preload mode: none, metadata, auto
volume 0.7 Default volume (overridden after manual adjustment)
list-folded false Fold playlist by default
list-max-height 340px Playlist max height (numeric values treated as px)
storage-name metingjs localStorage key for player settings
instance (optional) Suffixes storage-name and isolates settings per embed

Recent Updates

  • Instance IDs added to progress, quotes, D-Day, and music player builders; stateful widgets now scope storage by instance.
  • D-Day builder now supports compact mode, default/dark/light theme handling, centered compact tiles, and separate title/text color controls.
  • Progress widget now persists +/- edits in embedded mode across refreshes.
  • Landing page typography and hero styling were updated to use Libre Baskerville for headings.
  • CSS import typing issue in app/layout.tsx was fixed with a global declaration file.

Notion Quotes Sync

  1. Duplicate .env.example to .env.local.
  2. Set NOTION_TOKEN and NOTION_DATABASE_ID.
  3. Share your Notion database with the integration.
  4. Run npm run sync:quotes.

Vercel Quote Sync (Free Plan)

This repo is configured so production deploys always sync Notion quotes before building:

  • vercel.json uses buildCommand: npm run sync:quotes && next build
  • A daily cron is configured at /api/cron/sync-quotes

Important for Vercel Hobby (free) plan:

  • Cron frequency is limited to once per day.
  • Invocation can happen any minute within the configured hour (UTC).

Required Vercel environment variables:

  • NOTION_TOKEN
  • NOTION_DATABASE_ID
  • VERCEL_DEPLOY_HOOK_URL
  • CRON_SECRET (recommended, must be random and long)

Set up steps:

  1. In Vercel, create a Deploy Hook for your production branch.
  2. Add VERCEL_DEPLOY_HOOK_URL from that hook.
  3. Add a random CRON_SECRET.
  4. Redeploy once so cron + env changes are active.

How to Confirm Cron Is Running

Use this quick checklist in Vercel:

  1. Open project Settings -> Cron Jobs.
  2. Confirm /api/cron/sync-quotes is listed and enabled.
  3. Click View Logs on that cron entry.
  4. Look for logs from app/api/cron/sync-quotes like:
    • [cron/sync-quotes] Trigger accepted
    • [cron/sync-quotes] Deploy hook queued successfully
  5. Open Deployments and confirm a new production deployment was created near that timestamp.

Manual health test (recommended):

  • Send POST https://YOUR_DOMAIN/api/cron/sync-quotes with header Authorization: Bearer <CRON_SECRET>
  • Expected response: JSON with ok: true
  • Then verify a new deployment starts in Vercel.

Notes for Hobby plan:

  • Cron can run any minute within the configured hour (UTC), not always exact minute.
  • Cron failures are not retried automatically, so check logs when a run is missed.

Trigger Sync On Notion Changes

Because Hobby cron only runs daily, you can trigger an early sync whenever new quotes are added.

Use this endpoint:

  • POST /api/cron/sync-quotes

Authorize with either:

  • Header: Authorization: Bearer <CRON_SECRET>
  • Or query param: ?secret=<CRON_SECRET>

What happens next:

  1. Endpoint verifies secret.
  2. Endpoint calls your Vercel deploy hook.
  3. New production build runs npm run sync:quotes.
  4. Updated quotes are included in your live site.

You can connect this endpoint to any automation tool (for example Make/Zapier/n8n) that fires on Notion database changes.

SEO and Indexing

SEO baseline added in this repo:

  • Rich global metadata in app/layout.tsx
  • app/sitemap.ts for all public widget routes
  • app/robots.ts with sitemap reference and crawl rules
  • Private routes under app/prvt/ are marked noindex

To use your real domain in canonical metadata and sitemap, set:

  • NEXT_PUBLIC_SITE_URL=https://your-domain.com

Code of Conduct

See CODE_OF_CONDUCT.md.

Contributing

See CONTRIBUTING.md for workflow, PR checklist, and test expectations.

Security

See SECURITY.md for vulnerability reporting and security practices.

License

This project is licensed under MIT. See LICENSE.

Repo Structure

See docs/REPO_STRUCTURE.md for architecture and folder conventions.

Contact / Requests

Open an issue or discussion for feature requests, collaboration ideas, or bugs.

Notes

  • No backend/database is required.
  • Widgets are optimized for Vercel and Notion embeds.

About

Custom Notion widgets with Next.js — static, embeddable, and themeable.

Topics

Resources

License

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks

Contributors