halkyon/README.md
Tizian 「ティツィアーン」 8369304ccd
build(app): the editor from its hosted fork
The app took the editor from our fork of AppFlowy Editor in a folder next to the
repository, which nobody else had, and which CI can't reach either. The fork now lives at
https://code.halkyon.app/project-halkyon/appflowy-editor (public; dual-licensed AGPL-3.0
or MPL-2.0 like upstream), on its branch halkyon/win32-v6, and the app depends on it by
git URL, pinned to the signed commit 0dac8a0. That commit adds `publish_to: none` to the
fork: it is a git dependency only, and the package name belongs to AppFlowy on pub.dev.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-09-30 21:49:04 +02:00

3.7 KiB

Halkyon Learn

A spaced-repetition learning app: studysets of flashcards with rich text, studied offline on every device and synced between a person's devices. Anyone can run an instance.

  • Offline first. Each device keeps its own database and syncs in the background (serverpod_offline_sync). Edits made on two devices while offline are never lost: card content is stored as append-only revisions, and a side changed differently on two devices is shown as a conflict until the person picks a version (ADR 0001, ADR 0003).
  • No sign-up needed. The app starts with an anonymous account; signing in with GitHub later keeps everything. A GitHub sign-in stores only the numeric GitHub ID.
  • No end-to-end encryption. Content is readable by the operator of the instance, as on Mastodon; whoever trusts no operator can run their own (ADR 0002).

Targets: Linux, Windows, macOS, Android and iOS. There is no web build.

Packages

Package What it is Licence
halkyon_learn_server The Serverpod server: endpoints, models, migrations SSPL-1.0
halkyon_learn_client The client, generated from the server's models AGPL-3.0-or-later
halkyon_learn_flutter The app (app.halkyon.learn) AGPL-3.0-or-later

Running it locally

You need Flutter (Dart v3.13 or later) and the Serverpod CLI v4.0.3 (dart install serverpod_cli@4.0.3). Linux builds also need libwebkit2gtk-4.1-dev and libsecret-1-dev. The rich-text editor comes from our fork of AppFlowy Editor (project-halkyon/appflowy-editor), which flutter pub get fetches by itself.

The server's secrets live in halkyon_learn_server/config/passwords.yaml, which is never committed. In a fresh clone, create it with a development and a test section, each holding database, serverSideSessionKeyHashPepper and serviceSecret (for example from openssl rand -base64 32). GitHub sign-in is optional: add githubClientId and githubClientSecret of your own GitHub OAuth app to development, registered with the callback URLs app.halkyon.learn://github-callback and http://127.0.0.1/github-callback.

Then start the server, its embedded database and the app:

cd halkyon_learn_server
serverpod --no-analytics start

serverpod start applies pending migrations and reloads on changes. The app talks to the server named by --dart-define=SERVER_URL=…, or else to the one in halkyon_learn_flutter/assets/config.json (http://localhost:8080). Without --no-analytics, the Serverpod CLI reports usage to Serverpod.

Tests

tool/check.sh

runs the format check, the analyzer with the strict lints of leancode_lint, the server's tests (against an embedded PostgreSQL, no Docker needed) and the app's tests. To run it before every push: ln -s ../../tool/check.sh .git/hooks/pre-push.

The sync tests need a running server (serverpod start); run them in halkyon_learn_flutter with flutter test -t requires-server.

Running an instance

deploy/ holds a Docker Compose setup: Caddy (HTTPS), the server and PostgreSQL. Copy deploy/.env.example to deploy/.env and fill it in; it explains every value. The licences require offering the source of what the instance runs to the people who use it.

More

  • AGENTS.md: how the code is organised and the rules it follows.
  • docs/adr/: the architecture decisions and their reasons.
  • CONTRIBUTING.md: licences of contributions and the sign-off.
  • LICENSE.md: which licence covers what.