Skip to content

Repository files navigation

This is a Next.js project bootstrapped with create-next-app.

Getting Started

First, run the development server:

npm run dev
# or
yarn dev
# or
pnpm dev
# or
bun dev

Open http://localhost:3000 with your browser to see the result.

You can start editing the page by modifying app/page.js. The page auto-updates as you edit the file.

This project uses next/font to automatically optimize and load Geist, a new font family for Vercel.

Learn More

To learn more about Next.js, take a look at the following resources:

You can check out the Next.js GitHub repository - your feedback and contributions are welcome!

Deploy on Vercel

The easiest way to deploy your Next.js app is to use the Vercel Platform from the creators of Next.js.

Check out our Next.js deployment documentation for more details.

Sitemap

The sitemap (/sitemap.xml) is generated by src/app/sitemap.js. It includes:

  1. Hand-listed static routes (/, /talks, /projects, /blog, …)
  2. Dynamic talk + project pages from src/data/{talks,projects}.js
  3. Cloudflare Bulk Redirect sources (optional, see below)

The route is regenerated hourly via export const revalidate = 3600, so items added in Cloudflare appear within ~1h without a redeploy.

Cloudflare Bulk Redirect sync

Cloudflare doesn't push events when you add a Bulk Redirect, so the sitemap pulls from the CF API on regeneration. Set these env vars in Vercel (Project → Settings → Environment Variables) to enable:

Var Required Notes
CLOUDFLARE_API_TOKEN yes Scoped token with Account → Account Filter Lists: Read (read-only is enough at runtime)
CLOUDFLARE_ACCOUNT_ID yes Found in Cloudflare dashboard, right sidebar
CLOUDFLARE_SITEMAP_HOSTS no Comma-separated host whitelist (e.g. stimmie.dev,workshops.stimmie.dev,talks.stimmie.dev,links.stimmie.dev). Defaults to the value of CLOUDFLARE_SITEMAP_HOST or stimmie.dev
CLOUDFLARE_SITEMAP_HOST no Legacy single-host fallback (still honoured)
CLOUDFLARE_REVALIDATE no TTL in seconds for CF API fetch cache. Defaults to 3600

Without these vars the integration is a no-op; the sitemap still builds fine. Transient API errors are logged to console.warn and do not break the build.

Wildcard sources (* in the redirect source URL) and asset paths (.png, .css, etc.) are filtered out so the sitemap only contains crawlable HTML pages.

The default behaviour is to consult getSitemapHosts() from src/data/redirects.js so apex + every category subdomain (workshops, talks, links) are covered without extra config.

Migrating in-code redirects to Cloudflare Bulk Redirects

The single source of truth for short-link redirects lives in src/data/redirects.js and is consumed by:

  • middleware.js: handles <category>.stimmie.dev/<slug> at the edge runtime
  • src/app/r/[...slug]/page.js: handles stimmie.dev/r/<slug> on apex
  • scripts/cf-migrate-redirects.mjs: syncs the map into a Cloudflare Bulk Redirect List so the redirect happens at Cloudflare's edge, before the request ever reaches Next.js.

To run the migration (idempotent, safe to re-run):

# Token needs:
#   Account → Account Filter Lists: Edit
#   Account → Account Rulesets: Edit
export CLOUDFLARE_API_TOKEN=...
export CLOUDFLARE_ACCOUNT_ID=...

# Plan only; no mutations:
npm run cf:migrate-redirects -- --dry-run

# Apply changes:
npm run cf:migrate-redirects

# Apply + delete CF items missing from the local map:
npm run cf:migrate-redirects -- --prune

The script:

  1. Creates (or finds) a Bulk Redirect List named stimmie_redirects.
  2. Computes a diff between local + CF state, then adds/deletes items.
  3. Ensures the account-level http_request_redirect ruleset has a rule that consults the list (http.request.full_uri in $stimmie_redirects).

After the migration runs, both the apex /r/<slug> and the <category>.stimmie.dev/<slug> URLs redirect at the CF edge. The in-app middleware + /r/ page remain as graceful fallbacks for local dev and preview deployments.

Releases

This repo uses semantic-release to automate versioning, CHANGELOG.md, and GitHub Releases from Conventional Commits.

Writing commits

The commit type controls what kind of release (if any) is produced:

Type Bump Appears in changelog
feat: minor yes (Features)
fix: patch yes (Bug Fixes)
perf: patch yes (Performance)
refactor: patch yes (Refactors)
docs: patch yes (Documentation)
BREAKING CHANGE:* major yes
chore: ci: style: test: build: none no

*Either include BREAKING CHANGE: in the commit body, or use feat!: / fix!: etc.

How releases happen

  1. A commit lands on main.
  2. .github/workflows/release.yml runs npx semantic-release.
  3. semantic-release inspects all commits since the last tag, decides the next version, updates package.json + CHANGELOG.md, tags the commit, and creates a GitHub Release.
  4. The bot's release commit is marked [skip ci] so it does not retrigger.

Dry-run locally

npx semantic-release --dry-run --no-ci

This prints what would be released without actually creating tags or pushes.


If this project helped you out, consider treating me to a coffee

📊 Current State of the Code

  • Tech Stack: React, TailwindCSS, Next.js, Node.js/NPM
  • Repository Size: 513 tracked files
  • Latest Update: b5f9aac chore: add stale issue and PR validators

☕ If you found this project useful, you can support my work at kape.stimmie.dev!

About

stimmie.dev: Simonee Mariquit's personal portfolio (Next.js + Vercel) with semantic-release-driven changelog and GitHub Releases.

Topics

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages