No description
  • TypeScript 97.3%
  • Kotlin 1.4%
  • JavaScript 1.1%
  • Shell 0.2%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
Morten Olsen 4b472fbf58
All checks were successful
ci/woodpecker/push/draft-release Pipeline was successful
ci/woodpecker/push/compliance Pipeline was successful
ci/woodpecker/push/quality Pipeline was successful
ci/woodpecker/cron/renovate Pipeline was successful
feat: stories for every app, on fake services
Every app now has stories on the phone, the phone on its side and the
tablet: Home Assistant's tiles and sheets, Clock, Timers, Calendar,
Photos, the tile home with its editor, and the rail and bar shells. Each
app's fake lives next to it (fake-home-assistant.ts, fake-calendar.ts,
fake-timers.ts, fake-immich.ts, fake-shell.tsx), in memory, never a
network.

- App stories take their fakes as parameters.services; the preview makes
  them once around the whole device frame, so sheets drawn through Portal
  see them too. A story can also be framed as a tile
  (parameters.tile: cells, and live for a live tile).
- The screenshot run asks Chrome for reduced motion and gives each shot
  its own profile, so no screen catches an arrival or a glide halfway.
  Segmented now honours reduced motion too.
- The 1×1 soundbar tile's volume steps span the tile instead of spilling
  past it on a phone, and the Calendar's "No calendars" title is centred.
2026-10-16 21:13:09 +02:00
.woodpecker ci: build releases on the android-react-native runner 2026-10-16 10:18:36 +02:00
apps feat: stories for every app, on fake services 2026-10-16 21:13:09 +02:00
packages feat: stories for every app, on fake services 2026-10-16 21:13:09 +02:00
panel feat: adapt panels to phones with size classes and installable shells 2026-10-16 18:48:50 +02:00
scripts ci: check every push and release the signed APK from Woodpecker 2026-10-16 09:22:20 +02:00
storybook feat: stories for every app, on fake services 2026-10-16 21:13:09 +02:00
.gitignore feat(android): run the panel as one app that is also the screensaver and home app 2026-10-16 09:22:15 +02:00
.prettierignore Flatten the design language and add the controls music and photos need 2026-10-16 08:45:14 +02:00
.prettierrc init 2026-10-15 22:53:58 +02:00
ARCHITECTURE.md docs: quirks and shared layouts are fixed in ui primitives, not in apps 2026-10-16 20:24:48 +02:00
CLAUDE.md feat: app stories in a shared Storybook, with a phone and tablet screenshot run 2026-10-16 20:55:06 +02:00
eslint.config.mjs feat(ui): spacing and corners scale with reach and text size 2026-10-16 20:11:04 +02:00
GLOSSARY.md refactor(home-assistant): work out the media device in one place 2026-10-16 18:00:44 +02:00
mise.toml ci: check every push and release the signed APK from Woodpecker 2026-10-16 09:22:20 +02:00
package.json init 2026-10-15 22:53:58 +02:00
pnpm-lock.yaml feat: stories for every app, on fake services 2026-10-16 21:13:09 +02:00
pnpm-workspace.yaml feat: app stories in a shared Storybook, with a phone and tablet screenshot run 2026-10-16 20:55:06 +02:00
PRODUCT.md feat(android): run the panel as one app that is also the screensaver and home app 2026-10-16 09:22:15 +02:00
README.md feat: app stories in a shared Storybook, with a phone and tablet screenshot run 2026-10-16 20:55:06 +02:00
renovate.json ci: check every push and release the signed APK from Woodpecker 2026-10-16 09:22:20 +02:00
Taskfile.yml feat: app stories in a shared Storybook, with a phone and tablet screenshot run 2026-10-16 20:55:06 +02:00
tsconfig.json feat: app stories in a shared Storybook, with a phone and tablet screenshot run 2026-10-16 20:55:06 +02:00
vitest.config.ts init 2026-10-15 22:53:58 +02:00

Panalist

A React Native panel ecosystem: wall and desk panels made by composing installables (apps, home tiles, live tiles, settings views) over shared services. One app runs on every panel in the house; what differs per room comes from its settings.

packages/
  config/    shared tsconfig + vitest preset
  kernel/    shared definitions: Services, Storage, LiveTiles, Launcher, defineInstallable
  ui/        shared RN components, shells, layouts, Tailwind tokens, the Storybook's book
  runtime/   PanelRuntime: loads installables, keeps apps running, draws the chosen shell around the home and apps
  android-host/  Android screensaver, lock-screen mode and home-app role
apps/
  <name>/    installables: the tile home, the rail and bar shells, clock, timers, calendar, Home Assistant, Music Assistant, Immich, Mealie
panel/       the app (Expo): lists the installables and the first home tiles
storybook/   the Storybook: ui's book and components, and every app's stories on phone and tablet

Getting started

mise install          # node 24 + task
task install          # pnpm install (via corepack)
task storybook        # UI components in the browser, http://localhost:6006
task panel:web        # run the panel in the browser
task panel            # Expo dev server (devices/simulators)
task panel:android    # build the development variant and run it on the emulator

task ci:quality is the quality gate (type-check, ESLint, tests); task ci:compliance checks licenses.

Releases

Local builds are the development variant (cloud.olsen.panalist.dev). Releases (cloud.olsen.panalist) come from CI: every push to main updates a draft release on Forgejo from the conventional commits since the last tag. Publishing the draft creates the tag, and the tag pipeline (.woodpecker/release.yaml) builds the signed APK and attaches it, with a SHA-256 checksum, to the release.

Adding things

  • An installable: copy apps/clock, rename it to @panalist/app-<name>, and export a defineInstallable(...). Add it to panel/package.json and its sources in panel/src/panel.ts.
  • Add every new workspace to the root tsconfig.json references (and to those of each workspace that imports it).