Skip to content

Repository files navigation

Daybreak

A personal dashboard — the homepage to your life. Weather, the news you care about, your todos, concerts near you, and the football matches worth watching, all in one calm place.

Run it

npm install
npm run dev

Open http://localhost:5173.

Note: the Concerts, Football, and Stocks cards proxy their APIs through the Vite dev server (vite.config.ts), since Bandsintown, ESPN, and Yahoo Finance don't send CORS headers for browser requests. The Reading queue's title/favicon enrichment (/api/unfurl) works the same way — it fetches each saved page directly, so no third-party unfurl service ever sees your saved URLs. All four only run under vite dev by default.

To use Generate Widget (the sparkle in the floating bubble menu) locally, copy .env.example to .env and set OPENAI_API_KEY — it's the one feature that needs a key. Everything else works without it. In dev, generation runs in-process through the Vite middleware (an in-memory job map), so you don't need Supabase locally — only the OpenAI key.

Deploying to Netlify

netlify.toml is already set up — connect the repo and deploy as-is. The built-in cards need no environment variables (every data source above is keyless). Generate Widget is the exception, and in production its job metadata and AI endpoints live on Supabase. OpenAI background mode owns the long-running generation itself, so it is not limited by Netlify or Supabase request timeouts.

Set up the Supabase backend once:

supabase link --project-ref <your-project-ref>
supabase db push                       # creates/updates the widget_jobs table
supabase secrets set OPENAI_API_KEY=sk-...   # optionally OPENAI_MODEL / OPENAI_REPAIR_MODEL / OPENAI_DATA_MODEL / *_REASONING_EFFORT
supabase functions deploy             # deploys all three functions

Netlify's automatic deploy only publishes the frontend and Netlify functions. For backend PRs to go live on merge too, enable Deploy to production in the Supabase GitHub integration. Otherwise run supabase db push and supabase functions deploy after merging.

Then set two variables in the Netlify site env (both public by design — the frontend calls the Supabase functions directly with them):

  • VITE_SUPABASE_URLhttps://<ref>.supabase.co
  • VITE_SUPABASE_ANON_KEY — the project's publishable key

How it fits together:

  • The Bandsintown/ESPN/Yahoo proxies become [[redirects]] rewrites in netlify.toml.
  • The widget AI backends are three Supabase edge functions in supabase/functions/: generate-widget starts an OpenAI background response (GPT-5.6 Sol with medium reasoning and selective web search), persists its response id with a job row, and returns a Daybreak job id immediately; widget-status publishes a valid first pass immediately and starts one targeted, tool-free repair only when deterministic checks reject it while it is polled (the frontend stores the job id, so a reload mid-generation resumes instead of losing the widget); and widget-data answers runtime widget.ai(...) lookups (OpenAI + web search, for real-world data with no free API — local gas prices, rankings, current headlines, …). Runtime lookups default independently to GPT-5 mini with low reasoning, two tool calls, and a 30-second deadline; they never inherit the heavier generation model. The finished widget spec is stored (and runs) in your browser's localStorage. Cores in supabase/functions/_shared/ are plain fetch-only TS so the Vite dev middleware runs the same code in-process.
  • Generated scripts execute in an opaque-origin iframe with a restrictive CSP (connect-src 'none') rather than in the Daybreak page. The frame can only render its own card. Persistence, public JSON requests, live AI data, theme tokens, sizing, and refreshes cross a versioned message bridge that validates the caller and capability; the frame cannot read Daybreak localStorage, cookies, or page globals, and each rerun replaces it to stop old timers.
  • The one server helper still on Netlify is netlify/functions/proxy.ts — the JSON CORS fallback behind widget.getJSON(...) (a fast fetch with no timeout concern).
  • /api/unfurl is instead a real serverless function at netlify/functions/unfurl.ts, doing the same server-side fetch-and-parse as the dev middleware. It's intentionally self-contained (no imports outside netlify/functions/) so Netlify's function bundler doesn't need to resolve paths elsewhere in the repo.

Deploying to a host other than Netlify (Vercel, Cloudflare Pages, …) needs equivalent rewrites for the three proxies plus a serverless function for /api/unfurl — without it, saved links still work, just falling back to a humanized title guessed from the URL with no favicon.

Make it yours

Everything is editable in the app itself — no file editing needed:

  • Your name — click it in the greeting.
  • Home cityEdit on the weather card; type any city, it's geocoded automatically.
  • News tabsEdit on the News card: add a tab with a name and comma-separated search terms (searched on Hacker News over the last week, ranked by points), remove tabs, and pick which NBA team's news to follow.
  • ShowsEdit on the Shows card to track anyone on Bandsintown (musicians, comedians, …), each scoped to a city of your choice or to "anywhere".
  • FootballEdit shows a checklist of competitions.
  • StocksEdit to add/remove tickers.
  • Anything else — click the Daybreak bubble (bottom right) to generate a widget: describe what you want ("track my friends' birthdays") and an AI-built widget matching Daybreak's design is added to your board. Hovering the bubble fans out the rest: lock the view (hides reposition handles and edit/remove controls), switch between the Dashboard and Flow layouts, and toggle light/dark mode.

All choices persist in localStorage. src/config.ts only provides the defaults used on first run.

Refresh cadence

Every card refreshes itself in the background: football every 2 minutes (live scores), stocks every 5, news every 15, weather every 30, concerts every 6 hours. A failed refresh keeps the last good data on screen.

Data sources

Card Source Key required
Weather Open-Meteo No
News (topics) HN Algolia Search No
News (team) ESPN public API No
Football ESPN public API No
Shows Bandsintown (+ Open-Meteo geocoding for city lookup) No
Stocks Yahoo Finance No
Todos, Reading queue localStorage
Generated widgets OpenAI API (generation only; widgets run locally) OPENAI_API_KEY, server-side

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages