diff --git a/README.md b/README.md
index dcc8871..5d36e08 100644
--- a/README.md
+++ b/README.md
@@ -1,20 +1,19 @@
# synq, a tiny android-to-org capture system.
+synq consists of:
+- an Android app for capturing notes items
+- a docker-based agent that pulls notes and saves them to a local .org file
-open app.
-type, optionally mark as todo, optionally add tags, save.
-if home server accessible, post unsynced captures to lan-only service and appended to `synq.org`.
+1. Open Synq app
+2. Type note, mark as TODO (opt), add tags (opt), save.
+3. If home server accessible, post unsynced captures to lan-only service and appended to `synq.org`.
-## non-goals
-- no org parser on android
-- no agenda on android
-- no sync provider dependency
-- no nextcloud file editing
-- no conflict resolution
-- no public internet exposure
-- no ai tagging in v1
-- no account system in v1
+
+
+
+
+
-## architecture
+## Architecture
```text
android app
@@ -28,137 +27,22 @@ home server
python + fastapi
sqlite idempotency store
append-only org writer
-
-flow
- user saves capture locally
- app marks it pending
- sync runs when server is reachable
- app posts pending captures to fastapi
- server validates, dedupes by id, appends to phone.org
- app marks capture synced
```
-## v1 behavior
+1. user saves capture locally
+2. app marks it pending
+3. sync runs when server is reachable
+4. app posts pending captures to fastapi
+5. server validates, dedupes by id, appends to phone.org
+6. app marks capture synced
-the app launches into a focused text box. the user can type immediately.
-controls:
+## Build & Deploy
+1. First, build and deploy `synq-server`, the docker container that listens for new notes and writes to the local file.
+2. Then, build and install the `synq` app.
+3. Finally, retrieve the token (`token.txt` in the docker container's data directory, or from the container logs `docker logs synq-server`)
-- note/todo toggle
-- optional tags field
-- save
-- save and close
-- sync now
-- small history view showing pending, synced, and failed entries
-
-each capture has:
-
-- stable client-generated id
-- created timestamp with timezone
-- kind: `note` or `todo`
-- body text
-- tags
-- device name
-- sync status
-- optional last error
-
-## org output
-
-todo:
-
-```org
-* TODO buy printer paper :home:errands:
-:PROPERTIES:
-:CREATED: [2026-05-17 sun 14:31]
-:SOURCE: android
-:ID: phone-20260517-143122-a8f2
-:END:
-```
-
-note:
-
-```org
-* note :retcon:
-:PROPERTIES:
-:CREATED: [2026-05-17 sun 14:33]
-:SOURCE: android
-:ID: phone-20260517-143322-b91c
-:END:
-
-mobile capture should stay dumb and append-only.
-```
-
-## server paths
-
-default container paths:
-
-```text
-/data/synq.org
-/data/capture.sqlite3
-/data/rejected.log
-```
-
-recommended unraid host mapping:
-
-```text
-/mnt/user/synq/phone-capture:/data
-```
-
-or map `/data/synq.org` directly to wherever the real org file lives. prefer a dedicated capture file first; emacs can include it in agenda later.
-
-## security model
-
-v1 is lan-only. bind the service to the host lan and do not expose it through swag/cloudflare/public dns.
-
-minimum useful controls:
-
-- shared bearer token in app and server env
-- server only accepts json
-- server rejects empty body
-- server dedupes ids
-- server writes append-only org
-- server never edits or parses existing org
-- docker volume is backed up
-
-## repo layout
-
-suggested monorepo:
-
-```text
-synq/
- android/
- app/
- server/
- app/
- main.py
- models.py
- org_writer.py
- store.py
- tests/
- Dockerfile
- pyproject.toml
- docs/
- api.md
- android-notes.md
- server-notes.md
- docker-compose.example.yml
- .env.example
- tasks.org
- README.md
-```
-
-## build order
-
-1. implement server first using curl tests.
-2. implement android local capture with room.
-3. implement manual sync.
-4. add workmanager opportunistic sync.
-5. add history screen and resend handling.
-6. polish launch speed and widget/share-target only after core path works.
-
-## build & deploy
-
-### server (docker)
+### 1. synq-server (docker)
```bash
# build
@@ -171,9 +55,9 @@ docker run -d --name synq --restart=unless-stopped \
synq-server
```
-the server generates a random token on first start and logs it prominently. copy it into the android app settings. to use a fixed token instead, pass `-e PHONE_CAPTURE_TOKEN=yourtoken`.
+The server generates a random token on first start and logs it prominently. copy it into the android app settings. To use a fixed token instead, pass `-e PHONE_CAPTURE_TOKEN=yourtoken`.
-to rebuild after a `git pull`:
+To rebuild after a `git pull`:
```bash
git pull
@@ -182,9 +66,9 @@ docker stop synq && docker rm synq
# re-run the docker run command above
```
-### android
+### 2. synq (android)
-open `android/` in Android Studio and hit **Sync**. then either:
+Open `android/` in Android Studio and hit **Sync**. then either:
- **run on device/emulator directly** from Android Studio (▶), or
- **build a release APK** from the terminal:
@@ -211,36 +95,3 @@ git push gitea v1.0.0
```
then go to **Releases → New Release** in the Gitea UI, pick the tag, and drag the APK into the assets box. anyone on the LAN can download it from there.
-
-## backup
-
-### what to back up
-
-the server writes to one directory (the `/data` volume). back up the whole thing:
-
-```text
-/data/synq.org ← the canonical org capture file
-/data/capture.sqlite3 ← idempotency store (dedup ids)
-/data/token.txt ← auto-generated token (if not using PHONE_CAPTURE_TOKEN env var)
-```
-
-on unraid the host path is whatever you mapped in compose, e.g. `/mnt/user/ben/synq/phone-capture`.
-
-### restore behavior
-
-- restore the `/data` volume to a new container and start it. the server will pick up where it left off.
-- `synq.org` is append-only plain text — it is human-readable and recoverable even without the sqlite db.
-- if `capture.sqlite3` is lost but `synq.org` is intact, the server will accept re-posted captures that were already in the org file (no dedup). the android app marks them synced either way (`already_seen` or `accepted`), so the only side effect is duplicate org entries for anything re-synced. restore the db from backup to avoid this.
-- if `token.txt` is lost, delete it and let the server generate a new one on next start, then update the app settings.
-
-## v2 parking lot
-
-- android share target
-- quick settings tile or widget
-- tag chips from recent tags
-- configurable default tag
-- edit unsynced entries only
-- multi-device capture
-- wireguard-aware sync
-- local export/import
-- optional emacs ingest helpers
diff --git a/docs/history-v1.png b/docs/history-v1.png
new file mode 100644
index 0000000..e5b0435
Binary files /dev/null and b/docs/history-v1.png differ
diff --git a/docs/home-v1.png b/docs/home-v1.png
new file mode 100644
index 0000000..473bdfc
Binary files /dev/null and b/docs/home-v1.png differ
diff --git a/docs/settings-v1.png b/docs/settings-v1.png
new file mode 100644
index 0000000..1f966e1
Binary files /dev/null and b/docs/settings-v1.png differ
diff --git a/docs/spec.md b/docs/spec.md
new file mode 100644
index 0000000..54f3295
--- /dev/null
+++ b/docs/spec.md
@@ -0,0 +1,150 @@
+# Specifications
+
+## v1 behavior
+
+the app launches into a focused text box. the user can type immediately.
+
+controls:
+
+- note/todo toggle
+- optional tags field
+- save
+- save and close
+- sync now
+- small history view showing pending, synced, and failed entries
+
+each capture has:
+
+- stable client-generated id
+- created timestamp with timezone
+- kind: `note` or `todo`
+- body text
+- tags
+- device name
+- sync status
+- optional last error
+
+## org output
+
+todo:
+
+```org
+* TODO buy printer paper :home:errands:
+:PROPERTIES:
+:CREATED: [2026-05-17 sun 14:31]
+:SOURCE: android
+:ID: phone-20260517-143122-a8f2
+:END:
+```
+
+note:
+
+```org
+* note :retcon:
+:PROPERTIES:
+:CREATED: [2026-05-17 sun 14:33]
+:SOURCE: android
+:ID: phone-20260517-143322-b91c
+:END:
+
+mobile capture should stay dumb and append-only.
+```
+
+## server paths
+
+default container paths:
+
+```text
+/data/synq.org
+/data/capture.sqlite3
+/data/rejected.log
+```
+
+recommended host mapping:
+
+```text
+/mnt/user/synq/phone-capture:/data
+```
+
+or map `/data/synq.org` directly to wherever the real org file lives. prefer a dedicated capture file first; emacs can include it in agenda later.
+
+## security model
+
+v1 is lan-only. bind the service to the host lan and do not expose it through swag/cloudflare/public dns.
+
+minimum useful controls:
+
+- shared bearer token in app and server env
+- server only accepts json
+- server rejects empty body
+- server dedupes ids
+- server writes append-only org
+- server never edits or parses existing org
+- docker volume is backed up
+
+## repo layout
+
+suggested monorepo:
+
+```text
+synq/
+ android/
+ app/
+ server/
+ app/
+ main.py
+ models.py
+ org_writer.py
+ store.py
+ tests/
+ Dockerfile
+ pyproject.toml
+ docs/
+ api.md
+ android-notes.md
+ server-notes.md
+ docker-compose.example.yml
+ .env.example
+ tasks.org
+ README.md
+```
+## build order
+
+1. implement server first using curl tests.
+2. implement android local capture with room.
+3. implement manual sync.
+4. add workmanager opportunistic sync.
+5. add history screen and resend handling.
+6. polish launch speed and widget/share-target only after core path works.
+
+## non-goals
+- no org parser on android
+- no agenda on android
+- no sync provider dependency
+- no nextcloud file editing
+- no conflict resolution
+- no public internet exposure
+- no ai tagging in v1
+- no account system in v1
+
+
+## backup
+
+### what to back up
+
+the server writes to one directory (the `/data` volume). back up the whole thing:
+
+```text
+/data/synq.org ← the canonical org capture file
+/data/capture.sqlite3 ← idempotency store (dedup ids)
+/data/token.txt ← auto-generated token (if not using PHONE_CAPTURE_TOKEN env var)
+```
+
+on unraid the host path is whatever you mapped in compose, e.g. `/mnt/user/ben/synq/phone-capture`.
+
+### restore behavior
+
+- restore the `/data` volume to a new container and start it. the server will pick up where it left off.
+- `synq.org` is append-only plain text — it is human-readable and recoverable even without the sqlite db.
+- if `capture.sqlite3` is lost but `synq.org` is intact, the server will accept re-posted captures that were already in the org file (no dedup). the android app marks them synced either way (`already_seen` or `accepted`), so the only side effect is duplicate org entries for anything re-synced. restore the db from backup to avoid this.
+- if `token.txt` is lost, delete it and let the server generate a new one on next start, then update the app settings.
diff --git a/logo/icon-fg-ns-512.png b/logo/icon-fg-ns-512.png
new file mode 100644
index 0000000..a35c0a4
Binary files /dev/null and b/logo/icon-fg-ns-512.png differ