{"id":50816010,"url":"https://github.com/vzsoares/open-oembed-widgets","last_synced_at":"2026-06-13T09:33:41.916Z","repository":{"id":360549286,"uuid":"1250404486","full_name":"vzsoares/open-oembed-widgets","owner":"vzsoares","description":"Tiny, monochrome, client-side widgets you can embed in Notion or any oEmbed consumer.","archived":false,"fork":false,"pushed_at":"2026-05-26T23:15:14.000Z","size":148,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-26T23:20:15.746Z","etag":null,"topics":["alpinejs","bitcoin","embed","github-pages","notion","oembed","tailwindcss","typescript","vite","widgets"],"latest_commit_sha":null,"homepage":"https://vzsoares.github.io/open-oembed-widgets/","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/vzsoares.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-05-26T15:42:32.000Z","updated_at":"2026-05-26T23:15:19.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/vzsoares/open-oembed-widgets","commit_stats":null,"previous_names":["vzsoares/open-oembed-widgets"],"tags_count":5,"template":false,"template_full_name":"vzsoares/vite-alpine-tailwind-temaplate","purl":"pkg:github/vzsoares/open-oembed-widgets","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vzsoares%2Fopen-oembed-widgets","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vzsoares%2Fopen-oembed-widgets/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vzsoares%2Fopen-oembed-widgets/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vzsoares%2Fopen-oembed-widgets/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/vzsoares","download_url":"https://codeload.github.com/vzsoares/open-oembed-widgets/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vzsoares%2Fopen-oembed-widgets/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34279898,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-13T02:00:06.617Z","response_time":62,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["alpinejs","bitcoin","embed","github-pages","notion","oembed","tailwindcss","typescript","vite","widgets"],"created_at":"2026-06-13T09:33:39.033Z","updated_at":"2026-06-13T09:33:41.909Z","avatar_url":"https://github.com/vzsoares.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# 🧩 Open oEmbed Widgets\n\n![License](https://img.shields.io/badge/license-MIT-black)\n\nTiny, monochrome, **client-side** widgets you can embed in any\n[oEmbed](https://oembed.com/) consumer — [Notion](https://notion.so) and others.\nNo backend — everything runs in the browser and is hosted on GitHub Pages.\n\n**[Open the gallery →](https://vzsoares.github.io/open-oembed-widgets/)** ·\n**[Showcase](https://vzsoares.github.io/open-oembed-widgets/showcase/)** ·\n**[How to use](https://vzsoares.github.io/open-oembed-widgets/help/)**\n\n[![Open oEmbed Widgets gallery](docs/screenshot.png)](https://vzsoares.github.io/open-oembed-widgets/)\n\nPick a widget, tweak it (theme, options, padding), copy the link, and paste it\ninto your tool — no account, no code. Widgets are transparent and scale to fit\nwhatever box they're embedded in.\n\n## 📦 Widgets\n\n| Widget              | URL           | Description                                          |\n| ------------------- | ------------- | ---------------------------------------------------- |\n| 📈 Bitcoin Price    | `/btc/`       | Live BTC/USD price + sparkline, range 1D–1Y, ~60s.   |\n| 💹 Crypto Ticker    | `/ticker/`    | Live price + chart for any coin (`?coin=ethereum`).  |\n| 🕒 Clock            | `/clock/`     | Flip or analog clock with date, timezone \u0026 24h opts. |\n| 🌍 World Clock      | `/worldclock/`| Current time across several timezones at once.       |\n| ⏳ Timer            | `/timer/`     | Countdown or count-up in days/hours/minutes/seconds. |\n| 📅 Day Counter      | `/counter/`   | Whole days since or until a date (e.g. a deadline).  |\n| 🌙 Moon Phase       | `/moon/`      | Current moon phase + illumination, no API.           |\n| 🖼️ Image Rotator    | `/images/`    | Cross-fades through a list of images on a timer.     |\n| 📊 Progress         | `/progress/`  | Day / week / year / custom (incl. life) progress bar.|\n| 📜 On This Day      | `/onthisday/` | Notable historical events for today (Wikipedia).     |\n| 🌤️ Weather          | `/weather/`   | Current conditions + hi/lo for a place (Open-Meteo). |\n| 🐙 GitHub Card      | `/github/`    | A GitHub user or repo card with key stats.           |\n| 🔗 Button List      | `/links/`     | Link buttons that open in a new tab; custom colors.  |\n| 💬 Quote            | `/quote/`     | A quote from a chosen collection (bundled).          |\n| 📖 Bible Verse      | `/bible/`     | Random verse in English or Portuguese.               |\n| 🗓️ Name Day         | `/nameday/`   | Today's name day(s); 6 locales (CZ/SK/FR/IT/ES/EN).  |\n| 📉 Stocks Ticker    | `/stocks/`    | Live prices for multiple stocks/ETFs with ▲/▼ and daily % change. Requires a free [Finnhub](https://finnhub.io/register) key. |\n| 📈 Stock Chart      | `/stock/`     | Live price chart for any stock or ETF, range 1D–1Y, with hover tooltip and H/L. Requires a free [Finnhub](https://finnhub.io/register) key. |\n\n## 🔗 Embed\n\n1. Open the gallery, pick a theme + range, copy the URL\n   (e.g. `…/open-oembed-widgets/btc/?theme=dark\u0026range=1w`).\n2. Paste the link into your tool's embed block\n   (in Notion: **Create embed**, or type `/embed`).\n\nWidgets have **transparent** backgrounds so they blend into the embedding page.\nEach widget page advertises a static oEmbed document via\n`\u003clink rel=\"alternate\" type=\"application/json+oembed\"\u003e`, so resolvers like\nNotion's (Iframely) get a proper `rich` embed.\n\n### ⚙️ Config (query params)\n\nEvery widget accepts these **global** options (toggled in the gallery header /\nhero, applied to all):\n\n- **Theme** — monochrome, follows the viewer's OS light/dark preference. Pin it\n  when the iframe context doesn't inherit it: `?theme=dark` / `?theme=light`.\n- **Padding** — `?pad=\u003cpx\u003e` overrides the widget's inner padding (e.g. `?pad=0`\n  for edge-to-edge).\n- **Scaling** — widgets render at their natural size by default; `?fit=1` scales\n  them to fill the embed box (text widgets always flow/wrap regardless).\n\nPer-widget options:\n\n- **Range** (BTC) — initial chart window: `?range=1d|1w|1m|3m|1y` (default `1m`).\n  The range buttons inside the widget stay interactive inside the embed too.\n- **Crypto Ticker** — `?coin=ethereum` (any CoinGecko id; default `bitcoin`) and\n  `?vs=usd` (vs-currency). Same chart/range UI as BTC. Known coins\n  (BTC/ETH/SOL/…) get Binance + Coinbase fallbacks; any other id is CoinGecko-only.\n- **Clock** — `?style=flip|analog` (default `flip`), `?show=time|date|both`\n  (default `both`), `?seconds=1` for a seconds tile/hand, `?h24=1` for a\n  24-hour clock (default: locale), and `?tz=Area/City` for an IANA timezone\n  (default: viewer's local).\n- **World Clock** — `?tz=America/Sao_Paulo,Europe/London,Asia/Tokyo` (a\n  comma-separated list; `local` for the viewer's zone). Labels derive from the\n  zone's city. Also `?h24=1` and `?seconds=1`. Defaults to São Paulo / London /\n  Tokyo if unset.\n- **Timer** — `?mode=down|up` (default `down`). Down counts to `?to=ISO`, up\n  counts from `?from=ISO` (e.g. `?to=2026-12-31T23:59:59Z`); both default to the\n  New Year if unset. The gallery's date picker emits the mode-neutral `?date=ISO`\n  (used when `?to`/`?from` are absent). Also `?units=dhms|dhm`, `?label=...`\n  caption, and `?done=...` text shown when a countdown hits zero.\n- **Day Counter** — `?date=2026-01-01` (a bare date counts in local time) and\n  `?mode=auto|until|since` (default `auto` picks the direction from the date).\n  `?label=` adds a caption. Defaults to counting down to the New Year if unset.\n- **Moon Phase** — current phase + illumination, computed from the date (no API).\n  `?date=2026-06-29` pins a specific date for testing/showcase.\n- **Image Rotator** — `?src=url1,url2,url3` (comma-separated image URLs; falls\n  back to bundled demo images if unset), `?mode=sequential|random` (default\n  `sequential`), `?every=8` seconds per image, and `?fit=cover|contain`\n  (default `cover`). Hover to pause. `?orient=landscape|portrait` picks the box\n  shape — the widget fills either; the gallery sizes the preview and copy URL to\n  match (portrait swaps to 270×480). oEmbed advertises the landscape default, so\n  portrait embeds may need the iframe sized manually in strict oEmbed consumers.\n- **Progress** — `?mode=day|week|year|custom` (default `year`). `custom` uses\n  `?value=\u0026max=`, a `?from=\u0026to=` range, or a birth date + lifespan\n  (`?from=2000-01-01\u0026years=80`, i.e. life progress). `?label=` overrides the\n  caption.\n- **On This Day** — `?type=selected|events|births|deaths|holidays` (default\n  `selected`) and `?lang=` Wikipedia language (default `en`). Hit ↻ for another\n  event from the day.\n- **Weather** — `?city=Tokyo` (geocoded) or `?lat=\u0026lon=`, `?unit=c|f` (default\n  `c`), `?label=` place-name override. Defaults to London if unset.\n- **GitHub Card** — `?user=login` or `?repo=owner/name`. Unauthenticated, so\n  the public API allows ~60 requests/hour per viewer IP.\n- **Button List** — `?btns=Text|https://url|hex` with `;` between buttons (e.g.\n  `?btns=Site|https://x.com|1d9bf0;Docs|https://x.com/docs`); only http/https/\n  mailto URLs are allowed. `?layout=list|row` (default `list`).\n- **Quote** — `?collection=motivation|wisdom|stoic|tech` (default `motivation`);\n  quotes are bundled (no API). Hit ↻ for another.\n- **Language** (Bible) — `?lang=en|pt` (default: viewer's locale). EN/PT buttons\n  stay interactive in the embed.\n- **Name Day** — `?lang=cz|sk|fr|it|es|en` (default `cz`). Shows today's name\n  day(s) from a bundled calendar (no API); the date renders in the locale's own\n  language. fr/it/es are sanctorale-based (a few days show a feast rather than\n  personal names); `en` is a loose anglicized set.\n- **Stocks Ticker** — `?symbols=NVDA,AAPL,MSFT,SPY` (comma-separated ticker\n  symbols, default `NVDA,AAPL,MSFT,SPY`) and `?apikey=YOUR_KEY` (required; get a\n  free key at [finnhub.io](https://finnhub.io/register), no credit card). Shows\n  symbol · price · ▲/▼ · daily % change. Refreshes every 60s. When no key is\n  set the widget shows setup instructions. Note: the key is visible in the embed\n  URL — the free tier (60 req/min) is fine for personal use.\n- **Stock Chart** — `?symbol=AAPL` (default `AAPL`) and `?apikey=YOUR_KEY`\n  (required; same Finnhub free key). Same chart UI as BTC: large price, change\n  badge (computed over the selected range), sparkline with hover tooltip, range\n  buttons 1D–1Y, and a today's H/L row. Also `?range=1d|1w|1m|3m|1y` (default\n  `1m`). Works with any US stock or ETF symbol (e.g. `SPY`, `QQQ`, `TSLA`).\n\nThe gallery also has a **paste-a-URL** box: paste any widget URL above the cards\nto load its theme + options back into the UI for further editing.\n\n## 🏗️ Architecture\n\n- **Multi-page** Vite build — one HTML entry per widget gives each a stable\n  embed URL (`/btc/`).\n- **Static oEmbed** — `scripts/gen-oembed.ts` reads `src/widgets/manifest.ts`\n  and writes `dist/\u003cid\u003e/oembed.json` after the Vite build.\n- **Resilient data** — the BTC/ticker chart tries CoinGecko → Binance → Coinbase\n  (all public, key-less, CORS-enabled) and uses the first that answers. The\n  Bible widget uses bible-api.com and falls back to a bundled verse list if the\n  API is unreachable, so it always renders.\n- **Bundled datasets** — Name Day ships an offline `MM-DD → names` calendar\n  (`src/widgets/nameday/data.json`) built from the MIT-licensed\n  [namedays-cs](https://github.com/OzzyCzech/namedays-cs) (cz),\n  [name-day-calendar](https://github.com/peterknezek/name-day-calendar) (sk), and\n  [nameday-api](https://github.com/xnekv03/nameday-api) / [nameday.abalin.net](https://nameday.abalin.net)\n  (fr/it/es/en).\n- **No-dependency chart** — a hand-built SVG sparkline (`chart.ts`), monochrome.\n- **Config via manifest** — each widget declares `params` (range, language, …);\n  the gallery renders selectors and bakes them into the embed URL.\n\n```\n/\n├── index.html                # widget gallery (home)\n# one \u003cid\u003e/index.html per widget: btc, ticker, clock, worldclock, timer, counter,\n# moon, images, progress, onthisday, weather, github, links, quote, bible,\n# nameday (all embeddable pages)\n├── btc/index.html\n├── clock/index.html\n├── …                         # progress/, onthisday/, weather/, github/, links/, …\n├── public/demo/              # bundled demo images for the rotator\n├── src/\n│   ├── home.ts               # gallery logic (incl. paste-URL import)\n│   ├── showcase.ts           # /showcase/ live-demos page logic\n│   ├── styles.css            # Tailwind + monochrome theme vars\n│   ├── lib/                  # theme.ts, duration.ts, interval.ts (+ *.test.ts)\n│   └── widgets/\n│       ├── manifest.ts       # widgets + params (single source)\n│       ├── btc/              # index.ts, price.ts, chart.ts, widget.ts, *.test.ts\n│       ├── ticker/           # index.ts (reuses btc/price + btc/widget)\n│       ├── clock/            # index.ts, time.ts, time.test.ts\n│       ├── worldclock/       # index.ts, worldclock.ts, worldclock.test.ts\n│       ├── timer/            # index.ts, config.ts, config.test.ts\n│       ├── counter/          # index.ts, counter.ts, counter.test.ts\n│       ├── moon/             # index.ts, moon.ts, moon.test.ts\n│       ├── images/           # index.ts, config.ts, config.test.ts\n│       ├── progress/         # index.ts, progress.ts, progress.test.ts\n│       ├── onthisday/        # index.ts, events.ts, events.test.ts\n│       ├── weather/          # index.ts, weather.ts, weather.test.ts\n│       ├── github/           # index.ts, github.ts, github.test.ts\n│       ├── links/            # index.ts, links.ts, links.test.ts\n│       ├── quote/            # index.ts, quote.ts, quotes.json, quote.test.ts\n│       ├── bible/            # index.ts, verse.ts, fallback.json, *.test.ts\n│       ├── nameday/          # index.ts, nameday.ts, data.json, nameday.test.ts\n│       ├── stocks/           # index.ts, stocks.ts, stocks.test.ts\n│       └── stock/            # index.ts, stock.ts, stock.test.ts\n├── e2e/                      # Playwright end-to-end specs\n├── scripts/gen-oembed.ts     # post-build oEmbed JSON generator\n├── playwright.config.ts\n├── vitest.config.ts\n└── vite.config.js\n```\n\n## 🛠️ Develop\n\nRequires [Bun](https://bun.sh).\n\n```bash\nbun install\nbun run dev          # http://localhost:5173  (and /btc/)\nbun run test         # unit tests (vitest, src/)\nbun run test:watch   # unit tests in watch mode\nbun run test:e2e     # Playwright e2e (uses your system Chrome locally)\nbun run typecheck    # tsc, both app + tooling configs\nbun run lint         # biome check\nbun run format       # biome check --write\nbun run build        # vite build + oEmbed generation -\u003e dist/\nbun run preview      # serve the production build\n```\n\nOn push to `main`, CI runs lint, typecheck, unit + e2e tests, and only then\nbuilds and deploys to GitHub Pages (`.github/workflows/deploy.yml`).\n\n## ➕ Add a widget\n\n1. Add an entry to `src/widgets/manifest.ts`.\n2. Create `\u003cid\u003e/index.html` + `src/widgets/\u003cid\u003e/index.ts`.\n3. Register the page in `vite.config.js` (`build.rollupOptions.input`).\n\noEmbed JSON and the gallery card are generated from the manifest. See\n[CONTRIBUTING.md](CONTRIBUTING.md) for the full workflow, config-param types,\nand the quality checks to run.\n\n## 📄 License\n\n[MIT](LICENSE) · Created by [vzsoares](https://github.com/vzsoares)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvzsoares%2Fopen-oembed-widgets","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fvzsoares%2Fopen-oembed-widgets","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvzsoares%2Fopen-oembed-widgets/lists"}