Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -120,8 +120,9 @@ FEDI_DOMAIN=example.com
# --- Optional: Web Push (PWA phone notifications) ---
# Lets you install the site to your phone's home screen and receive push
# notifications for likes/boosts/replies/follows/DMs/comments — even when closed.
# Dormant until these are set. Generate a keypair with:
# npx web-push generate-vapid-keys
# EASIEST: generate keys in Admin → Site settings → Phone notifications (one
# click, stored encrypted at rest — no keys in this file). These env vars are a
# fallback for automated deploys; a key generated in the admin panel wins.
# VAPID_PUBLIC_KEY=
# VAPID_PRIVATE_KEY=
# VAPID_SUBJECT=mailto:you@example.com
Expand Down
22 changes: 22 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,27 @@
# Changelog

## 1.19.0 (2026-07-23)

### Added
- **Set your avatar and banner during first-run setup** (#59) — the setup wizard now takes a profile picture and banner (optional), so a fresh install lands looking like *you* without a later trip to the admin panel. Uploads are gated by your setup token (the same one that protects setup) and go through the same optimise/EXIF-strip pipeline as everywhere else. A corrupt or mislabelled image is now a clear error instead of a 500.
- **Set session + token lifetimes from the admin** (#59) — a new **Security** section in **Admin → Site settings** sets how long an admin session stays signed in (default 30 days) and how long a generated app token lasts (0 = never expires), with no `ADMIN_SESSION_TTL_DAYS` / `APP_TOKEN_TTL_DAYS` env editing. Changes apply to newly-created sessions and tokens; the env vars still work as defaults.
- **A third theme — "Classic Blog"** (#250) — a left sidebar of your bio, recent posts and links beside a serif reading column, on a warm charcoal ground with a pine-green accent: a traditional personal-blog counterpoint to the default's glass and Editorial's sepia. Pick it in **Admin → Site settings → Appearance → Theme** (no restart) or set `THEME=classic`. Default instances render identically — nothing changes unless you choose it. A theme can now also **preset the sidebar's side and blocks** (Classic Blog ships a left sidebar with the nav kept out of it), which you can still override per-site.
- **Turn on phone notifications without touching the server** (#59) — **Admin → Site settings → Phone notifications** generates your Web Push (VAPID) keypair in one click, so PWA push works with no `npx web-push generate-vapid-keys` or `.env` editing. The private signing key is **stored AES-256-GCM-encrypted at rest** and never sent to the browser; the `VAPID_*` env vars still work as a fallback. Regenerating keys correctly **unsubscribes every device** (a subscription is bound to the old key and can't receive new sends) — and this also fixes a latent bug where, after any key change, a device would show notifications as "on" while silently receiving nothing; it now detects the mismatch and prompts you to re-enable.
- **Put the sidebar where you want it, with the blocks you want** (#307) — the sidebar layout can now sit on the **left or right**, and its blocks are an **ordered list you control**: `about, recent, sections, connect`. The order you write is the order they render, and leaving one out hides it — so dropping `sections` stops your nav appearing in both the header and the sidebar. Set both in **Admin → Site settings → Appearance** (they appear once you pick the Sidebar page width), or during first-run setup. On mobile your content always comes first regardless of which side you choose.

- **Themeable text colour** (#250) — text now resolves through a `content-*` ramp (primary → strong → muted → subtle → faint → dim → ghost) instead of fixed Tailwind greys, so a theme can move body copy and not just its background. This is the groundwork a **light theme** and the upcoming in-admin **custom palette** both need: `@theme` extends Tailwind's palette rather than replacing it, so hard-coded `text-white` / `text-gray-*` could never follow a theme — which is why every theme so far has had to be dark. **Nothing changes visually:** each token defaults to the exact neutral it replaces, and every built-in theme shares the default ramp, so the emitted CSS is unchanged. The site's header, footer, sidebar, mobile menu and notification menu are converted; the rest of the app follows in later passes, and until then themes stay dark (the contrast invariant still enforces it).

### Changed
- **Web Push is documented** (#59) — `docs/configuration.md` gains a **Phone Notifications** section. Push had no documentation anywhere: how to switch it on, the iOS home-screen requirement, that regenerating keys deliberately unsubscribes every device, and that the `VAPID_*` env vars are now only a fallback.
- **`docs/theming.md` rewritten for the current theme system** (#250) — the old guide predated themes entirely (it told you to hand-edit `globals.css` and swap avatar files on disk). It now covers what's web-editable in the admin panel, the `Theme` token contract + region×variant model, and a **developer scaffold** for adding a built-in theme (one data file + one registry line, with the dark/contrast and self-hosted-font constraints spelled out).
- Dependency refresh: `next` 16.2.11, `react`/`react-dom` 19.2.8, `postcss` 8.5.22, `marked` 18.0.7, `@atproto/api` 0.20.31, `eslint-config-next` 16.2.11. (`typescript` remains blocked upstream — #234.)

### Fixed
- **Phone notifications couldn't be switched on at all on a fresh install** (#59) — the 🔔 menu offered **Enable phone notifications** even when the server had no Web Push keypair yet, then failed on the click with a terse *"push not configured on server"* — and nothing pointed at the panel that would fix it, which sat in a different screen entirely. The menu now checks first and, when there's no keypair, offers **Set up phone notifications**: one click creates the keys *and* enables the device. If that can't work (for instance `ADMIN_SECRET` isn't set, so the private key can't be encrypted at rest) it now tells you the actual reason. iPhone users still need **Share → Add to Home Screen** first — iOS only gives push to installed apps — and the menu keeps saying so.

### Security
- **Patched a high-severity image-processing vulnerability** (#329) — `sharp` moves to 0.35.3, clearing [GHSA-f88m-g3jw-g9cj](https://github.com/advisories/GHSA-f88m-g3jw-g9cj) (four libvips CVEs, CVSS 7.0). This one was genuinely reachable rather than theoretical: FediHome decodes images fetched from **arbitrary remote instances** when it caches fediverse media, and `/_next/image` is a public endpoint that fetches and decodes thumbnails from the allow-listed PeerTube hosts — so bytes an attacker controls reached the vulnerable decoders. Upgrading alone would **not** have fixed it: Next.js pins its own copy of `sharp`, which would have left a second, still-vulnerable one (and a duplicate native image library) in the tree, invisible to type-checking, tests and builds alike. `sharp` is therefore pinned tree-wide via `overrides`, so exactly one patched copy is installed. Giving `postcss` the same treatment clears the last remaining transitive advisory (#12), and `npm audit` now reports **0 vulnerabilities**.

## 1.18.0 (2026-07-21)

### Fixed
Expand Down
34 changes: 34 additions & 0 deletions docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,40 @@ Some settings are stored in the database (`SiteSettings` table) and managed thro

Changes made in the admin panel are saved to the database and take effect immediately without restarting the server.

## Phone Notifications (Web Push)

FediHome can push likes, boosts, replies, follows, DMs and comments to your phone
or desktop — even when the site isn't open. **There is nothing to configure on the
server:** the keys it needs are generated in-app the first time you turn it on.

**Turning it on:**

1. Open the **🔔 menu** (visible only when you're signed in as the owner) and
choose **Set up phone notifications**. That generates your Web Push **VAPID
keypair**, stores the private half AES-256-GCM-encrypted, and subscribes the
device you're on — one click, no `.env` editing and no restart.
2. Hit **Test** to confirm a notification actually arrives.

**On iPhone/iPad you must install the site first.** iOS only exposes push to
home-screen apps, so in Safari tap **Share → Add to Home Screen**, then open
FediHome *from the Home Screen* and enable notifications there. Until you do, the
menu shows install guidance instead of an enable button — that's expected, not an
error.

Repeat step 1 on each device you want notifications on; subscriptions are
per-device.

**Rotating keys.** **Admin → Site settings → Phone notifications** shows the key
status and can **regenerate** or **clear** the keypair. Regenerating deliberately
**unsubscribes every device**: a subscription is bound to the key it was created
with and can never receive a send signed by a new one. Each device simply detects
the mismatch and offers to re-enable.

**Env fallback.** `VAPID_PUBLIC_KEY`, `VAPID_PRIVATE_KEY` and `VAPID_SUBJECT` still
work for automated deploys, but a key generated in the admin panel takes
precedence. Generating in-app requires `ADMIN_SECRET` to be set, since that's what
encrypts the private key at rest.

## Navigation Configuration

The `nav` object in `site.config.ts` controls which top-level pages appear in the navbar:
Expand Down
Loading
Loading