Skip to content

Repository files navigation

anybrowser-newtab

A personal new-tab page you can make your own in about 5 minutes: a GitHub activity feed rendered like a changelog, and a row of shortcuts to the places you open every day. Static HTML/CSS/JS — no framework, no build step, no dependencies to install.

Point any browser's new-tab page at your deployed URL and you're done.

Screenshot of anybrowser-newtab: a greeting, a search bar, a GitHub contribution heatmap and recent-activity list, and a shortcuts grid

Personal name, GitHub handle, and recent-activity items in the screenshot above are blurred/fictionalized — the heatmap shape and rest of the layout are real.

Using a coding agent (Claude Code, Codex, Cursor, etc.)? Hand it this repo and tell it to read AGENTS.md — it'll interview you for your name, GitHub username, and shortcuts, then set up and optionally deploy your personal copy for you. That's the fastest path through everything below.

Features

  • Search bar — autofocused on load, submits to Google or navigates directly for URL-like input. Restores "open a tab, start typing" now that the browser's own new-tab landing is overridden. Option+K (Mac) / Ctrl+K (elsewhere) refocuses it from anywhere on the page.
  • Shipped — your real GitHub contribution graph (same per-day data as your profile page, not an approximation — always a full year, regardless of maxDays) with the total contribution count for the year alongside it, plus a list of recent activity with relative timestamps and GitHub-style state icons. Out of the box (no token) this reads the public Events API — pushes, PRs opened, merged, new repos. With the optional token below, it switches to the Search API for a richer, more accurate breakdown (real commits, open/draft/merged/closed PRs).
  • AI Agents — a small icon-only dock (Claude, ChatGPT, Gemini) shown above Shortcuts, kept visually separate since it's a fixed set of assistant tabs rather than a growing bookmark list.
  • Shortcuts — a configurable grid of links with official brand icons (GitHub, Gmail, Google Calendar, Notion, LinkedIn, X, YouTube, or any URL via a generic globe icon), muted by default and tinted with the real brand color on hover. The first 9 each get a real keyboard hotkey — Option+1..9 on Mac, Ctrl+1..9 elsewhere — shown right-aligned on the card.
  • Greeting — time-of-day message plus a small SVG moon-phase indicator, because why not.
  • Light/dark — follows the OS/browser color scheme automatically, no toggle needed.
  • Responsive — one column on mobile and tablet, a two-column layout (activity + shortcuts) from 1024px up.
  • No server required — works as a fully static site. An optional serverless function upgrades GitHub data quality if you set it up (see below); everything else works without it.

Quick start

git clone https://github.com/alunadev/anybrowser-newtab.git
cd anybrowser-newtab
cp config.example.js config.js

Open config.js and fill in your name, GitHub username, and shortcuts. Then preview it locally:

python3 -m http.server 4173
# open http://localhost:4173

(Any static file server works — or just open index.html directly in a browser.)

Configuration

Everything you'll ever want to change lives in config.js (copied from config.example.js, and gitignored so your personal data never ends up in git history — even in your own fork):

Field Description
name Used in the greeting: "Good morning, <name>".
githubUser Your GitHub username. Powers the entire "Shipped" section.
maxDays How many days back the recent-activity list looks (default 7). Doesn't affect the heatmap, which always shows a full year.
agents Array of { label, url, icon } for the AI Agents dock. Icon must be claude, openai, gemini, or grok.
shortcuts Array of { label, url, icon }. Order in the array = display order.

Available icon values for shortcuts: github, notion, gmail, gcal, linkedin, x, youtube, or globe (a generic fallback for any other link). Icons are official brand SVG marks — see ICONS in app.js if you want to add another one.

Deploy

Option A — CLI deploy (recommended)

Deploys straight from your local folder, so your personal config.js goes along even though it's gitignored (see .vercelignore, which is what makes that safe — it tells Vercel CLI not to fall back to .gitignore when deciding what to upload):

npm i -g vercel      # once
vercel login         # once
vercel --prod

Option B — Git-connected deploy

If you'd rather have Vercel auto-deploy on every push, fork this repo privately, commit your own config.js to your fork (it's your data, your repo, your call), and connect that fork to a new Vercel project. Don't do this on a public fork — your config.js would be visible to anyone.

Point your browser's new tab at it

  • Chrome / Edge / Brave: install a "New Tab Redirect" extension and set your deployed URL.
  • Firefox: install "New Tab Override" and set the URL.
  • Safari: Settings → General → set Homepage to the URL, and set "New tabs open with: Homepage".
  • Arc: doesn't support custom new-tab URLs; pin the tab or use the home button instead.

Optional: authenticated GitHub data

By default, GitHub activity comes from the public, unauthenticated Events API — no setup needed, and it's plenty for personal use.

If you want private-repo activity to show up too (or just higher rate limits), api/github-stats.js is a Vercel serverless function that proxies GitHub's Search API with a token that never reaches the browser. Set these on your Vercel project (Settings → Environment Variables):

  • GITHUB_TOKEN — a fine-grained personal access token, read-only. Grant:
    • Repository permissions → Contents: Read-only (lets the token read commits).
    • Repository permissions → Pull requests: Read-only (lets the token read PR data).
    • Repository access: the specific private repos you want counted, or "All repositories".
  • GITHUB_USERNAME — required, must match the account the token belongs to.

Why this works with fine-grained tokens (and the old approach didn't): an earlier version of this app used GitHub's Events feed (GET /users/{username}/events), which has no fine-grained permission that can unlock private activity at all — its own docs mention an "Events" user permission that doesn't actually exist in the fine-grained system (it's only an organization-level permission for an unrelated endpoint). Switching to the Search API (commits, PRs, repos) sidesteps that entirely: Search respects normal per-repo permissions, so a properly-scoped read-only fine-grained token just works — no need for a broader classic token.

Never put a token in config.js or anything that ships to the browser — only in Vercel's environment variables, which the serverless function reads server-side. Without it configured, the page still works: it automatically falls back to the public Events API (public activity only).

Requirements

  • No local runtime needed to preview — it's a static site; any static file server (or just opening index.html directly) works.
  • The two optional serverless functions in api/ (used only when deployed to Vercel) need Node's built-in fetch/AbortSignal.timeout, so package.json pins Vercel's Node runtime to 20.x. Bump that if you deploy elsewhere and need a different version — anything ≥18 works.

Notes and limitations

  • The public (unauthenticated) fallback path counts push events, not individual commits — GitHub's Events API no longer returns a commit count on push events (a 2024 privacy change). The authenticated Search API path doesn't have this limitation; it counts real commits.
  • GitHub's Search API has its own rate limit (30 requests/min authenticated, 10/min unauthenticated) — plenty for a new-tab page, but worth knowing if you're debugging.
  • The contribution heatmap is built from GitHub's own real per-day contribution data (api/contributions.js fetches github.com/users/<user>/contributions, the same public page your profile uses — no token needed), rendered as our own SVG so it can be themed with this app's own tokens. If that endpoint isn't reachable (local static preview, or before the function is deployed), it falls back to the free ghchart.rshah.org image service instead — a third-party dependency, only used as a fallback.
  • The heatmap mirrors your public GitHub profile graph. If you want private contributions included, enable "Include private contributions on my profile" in your GitHub account settings — the graph (and this heatmap) will then reflect it.
  • The recent-activity list caps at 5 items regardless of how much happened in the maxDays window — it's meant to be a glance, not a full log.
  • The "Shipped" section header always reads "last year activity" (matching the heatmap above it), even though the stat row and recent-activity list below it are windowed to maxDays — the header describes the heatmap, not the whole section.
  • The page sets <meta name="robots" content="noindex, nofollow"> since it's meant to be a personal, unlisted URL rather than a discoverable page.

Contributing

Issues and PRs welcome — this is meant to be a small, hackable template, not a product. If you build a new icon, module, or layout variant that others might want, a PR is very welcome.

License

MIT — see LICENSE.

About

A personal new-tab page you can make your own in about 5 minutes: GitHub activity feed + shortcuts row.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages