| Read the clock in the reader's zone when /etc/localtime is a file bffe879 nandi 18d ago | 1 | # Working in this repo |
| 2 | |
| 3 | ## Nix |
| 4 | |
| Build the window somewhere with room for it 1451151 nandi 5d ago | 5 | **STOP BUILDING LOCALLY. Build on Modal.** This machine is for editing and for |
| 6 | evaluating — `nix flake check`, `nix eval`, `nix build --dry-run`, `nix repl` |
| 7 | — and not for realising a derivation. A local `nix build .#frq` gets killed for |
| 8 | memory long before it finishes, and the minutes spent finding that out are |
| 9 | minutes not spent on the change. So: |
| Read the clock in the reader's zone when /etc/localtime is a file bffe879 nandi 18d ago | 10 | |
| 11 | ```bash |
| A Mesa nobody needed, and the AppImage that carried it 9db383c nandi 19h ago | 12 | modal run .modal/frq/container.py # the desktop bundle, on Modal |
| Read the clock in the reader's zone when /etc/localtime is a file bffe879 nandi 18d ago | 13 | ``` |
| 14 | |
| Point the docs at .modal/, and at the file they now build 972ab37 nandi 5d ago | 15 | The container is `.modal/`, not a fourth source tree: it is CI config that |
| 16 | happens to live here, the way `.github/` would be. |
| 17 | |
| Build the window somewhere with room for it 1451151 nandi 5d ago | 18 | `--dry-run` locally to see what *would* be built, then hand the build to Modal. |
| 19 | The one exception is a derivation you already know is trivial and already |
| 20 | substitutable; if you are unsure, it is not the exception. |
| 21 | |
| 22 | `modal app logs` is no substitute for watching that command: it resolves |
| 23 | deployed apps by name, not the ephemeral one a `modal run` creates, and carries |
| 24 | nothing until the Sandbox starts — the image build streams to the client and |
| 25 | nowhere else. |
| 26 | |
| 27 | You are already running inside the Arch distrobox, where `nix` lives, so run |
| 28 | the evaluating commands directly — do not wrap them in `distrobox enter`. |
| 29 | |
| 30 | The container runs as a Modal **Sandbox on a real VM**, which is what makes |
| 31 | `nix build` work out there at all: the ptyshim that used to stand in for a |
| 32 | working pty under gVisor is deprecated, and nothing here should reintroduce it. |
| 33 | Substitution comes from the `nix-cache` Modal Volume plus cache.nixos.org and |
| 34 | nix-cache.wasix.org — libjoltcosmic's dependency tree is the one that makes |
| 35 | that cache worth having. |
| 36 | |
| 37 | A remote builder (`eu.nixbuild.net`) is also configured here, for the case |
| 38 | where you want the graph built somewhere other than Modal: `--store |
| 39 | ssh-ng://eu.nixbuild.net --eval-store auto` rather than a `builders` entry, so |
| 40 | the whole graph stays there and only .drv files go up. |
| Read the clock in the reader's zone when /etc/localtime is a file bffe879 nandi 18d ago | 41 | |
| Follow the xorg renames, and stop wrapping nix in distrobox a400a00 nandi 16d ago | 42 | One thing this container is *not* representative of: `/etc/localtime` is a |
| 43 | regular file here rather than a symlink, so anything that reads the zone out |
| Read the clock in the reader's zone when /etc/localtime is a file bffe879 nandi 18d ago | 44 | of its path sees nothing. That is a real deployment shape, not an artefact — |
| 45 | frq.clock handles it. |
| Split the tree three ways, and let the phone be Flutter's 7070931 nandi 7d ago | 46 | |
| Build the window somewhere with room for it 1451151 nandi 5d ago | 47 | ## Never pipe a long task through `tail` |
| 48 | |
| 49 | `tail` and `head` do not emit anything until their input ends, so a build, a |
| 50 | test run or a deploy piped through one shows nothing at all until it is over — |
| 51 | and if it is killed or times out first, its output is lost with it. That is the |
| 52 | opposite of what you want from the commands that take longest. |
| 53 | |
| 54 | Let them write to the terminal, or `tee` them if you want a copy to grep |
| 55 | afterwards: |
| 56 | |
| 57 | ```bash |
| Point the docs at .modal/, and at the file they now build 972ab37 nandi 5d ago | 58 | modal run .modal/frq/container.py 2>&1 | tee /tmp/frq-build.log |
| Build the window somewhere with room for it 1451151 nandi 5d ago | 59 | ``` |
| 60 | |
| 61 | Trim afterwards, on the file, where the whole run is still there to re-read. |
| 62 | The same goes for `grep` and `awk` in a live pipeline: they buffer when their |
| 63 | output is not a terminal, so pass `--line-buffered` / `fflush()` or watch the |
| 64 | file instead. |
| 65 | |
| Split the tree three ways, and let the phone be Flutter's 7070931 nandi 7d ago | 66 | ## The three source trees |
| 67 | |
| 68 | ``` |
| 69 | common/ .cljc jolt AND ClojureDart |
| 70 | src/ .clj jolt only |
| 71 | flutter/ .cljd ClojureDart only |
| 72 | ``` |
| 73 | |
| 74 | The extension is the boundary, not a convention: ClojureDart reads `.cljd` and |
| 75 | `.cljc` and never `.clj`, jolt reads all three. So the rule for anything under |
| 76 | `common/` is that it may not require `jolt.*`, `glimmer*` or a `dart:` library |
| 77 | — if it needs the host, it asks `frq.io`, and the backend that installed itself |
| 78 | answers. `frq.io.jolt` is required for its side effect by `frq.app`; |
| 79 | `frq.io.dart` is installed by `flutter/src/frq/main.cljd`, which has to await |
| 80 | the storage directory first. |
| 81 | |
| 82 | Adding a host call means adding it to the seam in `common/frq/io.cljc` and to |
| 83 | both implementations. Name it for the result rather than the mechanism — the |
| 84 | seam has `write-private-file!` and not a chmod, because Dart has no chmod. |
| 85 | |
| Paint the desktop with Flutter too, beside libcosmic fc5f63c nandi 7d ago | 86 | `flutter/` builds two things, from one `clojure -M:cljd compile`: |
| 87 | |
| 88 | `just apk`, out of the flake's own `.#flutter` shell (clojure, jdk17, flutter) |
| 89 | and its `.#android-sdk` package. Impure on purpose: Gradle fetches its own |
| 90 | dependencies and writes into `ANDROID_HOME`, so the recipe copies the store SDK |
| 91 | to `flutter/.home` and lets it finish there. It is the only APK there is — the |
| 92 | jolt APK, `nix/android.nix`, `android/` and the `.#apk` outputs are gone, |
| 93 | because every backend that APK could paint with is retired. |
| 94 | |
| 95 | `just flutter-desktop`, out of `.#flutter-desktop` (the same clojure and |
| 96 | flutter, with cmake, ninja, pkg-config and gtk3 where the JDK and the SDK are). |
| 97 | Impure for the network half of the same reasons and no writable-SDK dance, since |
| Name the libcosmic recipe for its backend: `just cosmic run` 5ba9382 nandi 7d ago | 98 | nothing writes into the store. nixGL off NixOS, like `just cosmic run`. |
| Paint the desktop with Flutter too, beside libcosmic fc5f63c nandi 7d ago | 99 | |
| Name the libcosmic recipe for its backend: `just cosmic run` 5ba9382 nandi 7d ago | 100 | So there are two desktop GUIs and they are both first-class: `just cosmic |
| 101 | run` is libcosmic under jolt, `just flutter-desktop` is Flutter's Linux target |
| 102 | over |
| Paint the desktop with Flutter too, beside libcosmic fc5f63c nandi 7d ago | 103 | `frq.hiccup`. Same screens out of `common/frq/screens/`, two renderers. jvui and |
| 104 | Vidya were experiments and are gone; libcosmic is a desktop window and does not |
| 105 | cross to a phone, which is what the Flutter half is for. |
| 106 | |
| 107 | The consequence for `common/` is that "the phone" is no longer a synonym for |
| 108 | "the ClojureDart side" — two targets compile it. An implementation that branches |
| 109 | on the platform has to ask (`Platform.isAndroid`) rather than assume; see |
| 110 | `frq.io.dart/write-private-file!`, where assuming cost a token its file mode. |
| 111 | See flutter/README.md. |