+1
-1
.gitignore
+1
-1
.gitignore
readme-brainstorm.org
docs/readme-brainstorm.org
readme-brainstorm.org
docs/readme-brainstorm.org
readme-devlog.org
docs/readme-devlog.org
readme-devlog.org
docs/readme-devlog.org
+126
-40
readme.org
+126
-40
readme.org
···
2
2
#+AUTHOR: Jonathan Raphaelson
3
3
#+EMAIL: jon@accidental.cc
4
4
5
-
An offline first RSS & Podcast PWA Application
5
+
an offline-first RSS & podcast PWA application
6
6
7
-
* What is Skypod?
7
+
* what is skypod?
8
8
9
9
- rss/podcast subscription management
10
10
- offline first; cache audio locally, and p2p sync between devices
11
-
- podcast playback with nice features; skip silence, volume correction, etc.
11
+
- podcast playback with nice features; skip silence, volume
12
+
correction, etc.
12
13
- fun to hack on
13
14
14
-
* How does it work?
15
+
* how does it work?
15
16
16
-
- PWA stores and displays cached feeds, subscription, and listening history data locally
17
-
- Feed proxy server provides a nice API for fetching feeds and extracting metadata
18
-
- WebSocket signaling server for WebRTC peering, devices sync cached data and play state
17
+
- PWA stores and displays cached feeds, subscription, and listening
18
+
history data locally in IndexedDB
19
+
- WebSocket signaling server for WebRTC peering, devices sync cached
20
+
data and play state using a hybrid logical clock for causal ordering
21
+
- feed proxy server provides a nice API for fetching feeds and
22
+
extracting metadata
19
23
20
-
* Development
24
+
* getting started with devenv
21
25
22
-
Run the pwa+server with:
26
+
this project uses [[https://devenv.sh][devenv.sh]] for reproducible development environments.
27
+
28
+
if you have devenv installed:
29
+
30
+
#+BEGIN_SRC bash
31
+
$ devenv shell
32
+
$ npm install
33
+
$ npm run dev
34
+
#+END_SRC
35
+
36
+
if you don't have devenv, you can install it from [[https://devenv.sh][devenv.sh]] or just
37
+
use node v24+ directly.
38
+
39
+
* development
40
+
41
+
run the pwa+server with:
23
42
24
43
#+BEGIN_SRC bash
25
44
$ npm install
26
45
$ npm run dev # lots of stuff concurrently with wireit
27
46
#+END_SRC
28
47
29
-
- Common
30
-
- ES2024 Javascript, running on in modern browsers or [[https://nodejs.org][Node v24]]
31
-
- [[https://github.com/panva/jose][~jose~]] for cross-platform webcrypto and JWT management
32
-
- [[https://zod.dev/][Zod v4]] describes schema and builds transformation pipelines
33
-
- Backend
34
-
- [[https://expressjs.com/][Express]] and Node's ~stdlib~ for HTTP and WebSocket servers
35
-
- Frontend
36
-
- [[https://vite.dev/][Vite]] does FE builds
37
-
- [[https://preactjs.com/][Preact]] + [[https://zustand.docs.pmnd.rs][Zustand]] for UI
38
-
- Build & DX
39
-
- [[https://github.com/google/wireit][Wireit]] does script dependencies and services
40
-
- [[https://jsdoc.app/][JSDoc]], along with [[https://www.typescriptlang.org/docs/handbook/jsdoc-supported-types.html][Typescript's JSDoc support]] does typechecking
41
-
- [[https://eslint.org][ESLint]] and a plethora of plugins keeps the code nice
48
+
this starts:
49
+
- vite dev server at ~http://127.0.0.1:4000~ (frontend)
50
+
- backend server at ~http://127.0.0.1:4001~ (WebSocket + API)
51
+
- live type-checking and linting in watch mode
52
+
53
+
** technology stack
42
54
43
-
Still thinking about:
55
+
*** common
56
+
- typescript with strict mode
57
+
- [[https://github.com/panva/jose][~jose~]] for cross-platform webcrypto and JWT management
58
+
- [[https://zod.dev/][Zod]] describes schema and builds transformation pipelines
44
59
45
-
- [[https://dexie.org/][Dexie]] for browser storage and enabling syncing
46
-
- per-realm SQLite databases with node's native sqlite support
47
-
- docker compose for deployment with self-hosted realm storage
60
+
*** backend
61
+
- [[https://expressjs.com/][Express]] for HTTP and WebSocket servers
62
+
- [[https://github.com/Level/level][Level]] for persistent realm kv storage
48
63
49
-
See [[./readme-devlog.org]] for design and architecture thoughts.
64
+
*** frontend
65
+
- [[https://vite.dev/][Vite]] for builds
66
+
- [[https://preactjs.com/][Preact]] for UI
67
+
- [[https://dexie.org/][Dexie]] for IndexedDB storage
68
+
- [[https://github.com/feross/simple-peer][simple-peer]] for WebRTC
50
69
51
-
** Scripts
70
+
*** build & dx
71
+
- typescript for type-checking
72
+
- [[https://github.com/google/wireit][Wireit]] does script dependencies and services
73
+
- [[https://eslint.org][ESLint]] and prettier keep the code nice
52
74
53
-
All scripts can have ~--watch~ passed as an argument to have ~wireit~ rerun when inputs change.
54
-
This is not useful for everything.
75
+
** scripts
55
76
56
77
- ~npm run dev~ :: alias for ~npm run start:dev~
57
78
- ~npm run lint~ :: runs ~eslint~
58
79
- ~npm run types~ :: runs ~tsc~ (no emitting, just typechecking)
59
-
- ~npm run docs~ :: runs ~jsdoc~ to generate docs in ~./docs~
80
+
- ~npm run build~ :: build production frontend
60
81
- ~npm run test~ :: runs ~jest~ as a one-off
61
-
- ~npm run start:dev~ :: runs BE/FE, tests in watch mode, and typecheck/linting
82
+
- ~npm run start:tests~ :: runs ~jest~ in watch mode
83
+
- ~npm run start:dev~ :: runs BE/FE with live type-checking and linting
62
84
- ~npm run start:prod~ :: builds and runs everything in production mode
63
85
64
-
* Contributing
86
+
** running tests
87
+
88
+
There's not much here yet, I want to figure it out first.
89
+
90
+
#+BEGIN_SRC bash
91
+
$ npm run test # run all tests once
92
+
$ npm run start:tests # run tests in watch mode
93
+
#+END_SRC
94
+
95
+
to run a single test file:
96
+
97
+
#+BEGIN_SRC bash
98
+
$ npx jest src/path/to/file.spec.ts
99
+
#+END_SRC
100
+
101
+
** git hooks
102
+
103
+
pre-commit hook runs type-checking and linting automatically. enable with:
104
+
105
+
#+BEGIN_SRC bash
106
+
$ git config core.hooksPath .githooks
107
+
#+END_SRC
108
+
109
+
* architecture
110
+
111
+
the codebase is organized into modules with path aliases:
112
+
113
+
- ~#client/*~ (~src/client/~) - preact frontend application
114
+
- ~#server/*~ (~src/server/~) - node.js express backend
115
+
- ~#common/*~ (~src/common/~) - shared code (protocol, crypto, utilities)
116
+
- ~#realm/*~ (~src/realm/~) - p2p connection and sync protocol
117
+
- ~#skypod/*~ (~src/skypod/~) - domain-specific schemas and actions
118
+
119
+
** key architectural components
120
+
121
+
*** p2p synchronization
122
+
123
+
uses a hybrid logical clock (HLC) for causal ordering of events across
124
+
distributed peers. clients PULL complete action history when catching
125
+
up, and PUSH tailored updates to each peer based on knowledge vectors.
126
+
127
+
*** offline-first
128
+
129
+
all user data lives in IndexedDB via dexie. the server is stateless
130
+
regarding user data (only maintains ephemeral realm/peer state).
131
+
132
+
*** webrtc for p2p
133
+
134
+
peers communicate directly via WebRTC data channels. the WebSocket
135
+
connection to the server is only used for signaling and as a fallback
136
+
broadcast mechanism.
137
+
138
+
*** realm system
139
+
140
+
a realm is a collection of verified identities that can communicate
141
+
securely. realms are not publicly routable; access requires the realm
142
+
id and an invitation from an existing member.
143
+
144
+
see [[./docs/readme-brainstorm.org]] for detailed architecture thoughts
145
+
and connection flow diagrams.
65
146
66
-
- run ~git config core.hooksPath .githooks~ to install pre-commit hooks for lint/fmt
67
-
- not really open to contributions right now, come back later.
147
+
* contributing
68
148
69
-
* License & Copyright
149
+
- run ~git config core.hooksPath .githooks~ to install pre-commit
150
+
hooks for lint/fmt
151
+
- honestly, not really open to contributions right now, come back
152
+
later.
70
153
71
-
Copyright (C) 2025 Jonathan Raphaelson
154
+
* license & copyright
72
155
73
-
This program is free software: you can redistribute it and/or modify it under the terms of
74
-
the **Affero General Public License verson 3 or later** (AGPLv3+).
156
+
copyright (C) 2025 jonathan raphaelson
75
157
76
-
Please see [[./readme-license.txt]] for a copy of the full license.
158
+
this program is free software: you can redistribute it and/or modify
159
+
it under the terms of the **affero general public license version 3 or
160
+
later** (AGPLv3+).
161
+
162
+
see [[./readme-license.txt]] for a copy of the full license.