Platforms control your audience. Payment processors control your revenue. Bits gives you both back.
What you get:
- Subscriptions, one-time purchases, digital downloads
- Video hosting and delivery
- Your data, your domain, your rules
- Permissive content policies for persecuted creators
Why it works:
- Self-host on a $5/month VPS or use managed hosting
- Single binary deployment - no complex setup
- Built with care to minimize resource usage and maximize reliability
- Open source - audit the code, modify what you need, contribute back
The model: Like WordPress.org - free to self-host, managed option available. You’re never locked in.
Current state: Active development. Your funding accelerates delivery.
devenv upTo get our *.test URLs to work takes some effort with DNS.
drill bits.test | awk '/^bits/ { print $1 "\t" $5 }'| Host | Address |
|---|---|
| bits.test. | 127.0.0.1 |
cat /etc/resolver/testThe marketing site and “catch-all” homepage where we have no realm aren’t a priority so will return non-200 status codes.
urls=(
# These will work, provided you've applied the seeds in `bits.dev.realm`.
http://localhost:3000
https://bits.page.test
https://charlie.bits.page.test
https://charlie.bits.page.test
https://jcf.bits.page.test
)
for url in $urls; do
http_code="$(curl --silent --output /dev/null --write-out "%{http_code}" "$url")"
if [ "$http_code" -eq 200 ]; then
echo "✅ $url"
else
echo "❌ $url ($http_code)"
fi
doneAnd with a non-existent tenant, we expect a 404 response:
url="https://foo.bits.page.test"
http_code="$(curl --silent --output /dev/null --write-out "%{http_code}" "$url")"
if [ "$http_code" -eq 404 ]; then
echo "✅ $url"
else
echo "❌ $url ($http_code)"
fi- Get the message out
- Python-style environment variables
- Mission over SaaS startup playbook
- CI can wait
- Clojure over Rust
- Vanilla JS over ClojureScript for bits.js
- Crypto-Shredding for GDPR Compliance
- Datahike vs Datomic for distributed coordination
- Body-style indentation for UI component functions
Available recipes:
[build]
build # Build an AOT-compiled uberjar
build-datomic # Build Datomic Pro output
docker-build tag="bits:latest" # Build the Docker image
docker-run tag="bits:latest" *args # Run the Docker image against the local devenv database
[dev]
clean # Clean up generated classes and screenshots
clj-kondo-import # Import clj-kondo configs
cluster-certs # Generate cluster keystores
css # Regenerate Tailwind CSS from template
fmt # Format project files
market # Run the marketing site
mkcert # Create self-signed SSL certificates via mkcert
nrepl *args
setup # Setup a local development environment
tailwind # Watch source code for Tailwind classes
[docs]
decide +title # Create a new decision record
[iac]
apply dir # Apply one or all Terraform projects
init dir *args # Initialize one or all Terraform projects
output dir *args # Interact with outputs one or all Terraform projects
plan dir # Plan one or all Terraform projects
[locales]
locales-build # Build translation bundles from .po files
locales-extract # Extract translatable strings to .pot file
[postgres]
migration name # Create a new migration
psql *args # Start an interactive psql session connected to the local development database
[test]
compile # Compile bits.main
lint # Run lints
perf *args # Run tests with performance tracing output
test *args # Run tests
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ Language Files Lines Code Comments Blanks ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ Astro 10 165 139 0 26 Clojure 66 6749 5328 505 916 CSS 2 84 69 4 11 Dockerfile 1 82 58 7 17 Edn 2 136 121 1 14 HCL 12 389 323 13 53 JavaScript 5 317 262 20 35 JSON 4 59 59 0 0 Just 1 288 179 60 49 MDX 1 56 0 39 17 Nix 6 626 525 15 86 Org 15 2325 2031 5 289 SQL 4 43 37 0 6 SVG 2 12 12 0 0 TOML 1 46 41 0 5 TypeScript 3 36 30 1 5 XML 1 18 14 1 3 YAML 3 5056 3971 0 1085 ───────────────────────────────────────────────────────────────────────────────── HTML 1 76 72 0 4 |- CSS 1 171 151 0 20 (Total) 247 223 0 24 ───────────────────────────────────────────────────────────────────────────────── Markdown 1 353 0 229 124 |- Clojure 1 238 152 50 36 |- Org 1 19 12 0 7 |- Rust 1 68 49 10 9 (Total) 678 213 289 176 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ Total 141 17412 13635 960 2817 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ b7e5dbd @ 2026/02/23 00:00
src/bits/app.clj:;; TODO Use Malli (or clojure.spec) to coerce and parse/validate configuration. src/bits/asset.clj:;; TODO Make content-type explicit or more intelligent. src/bits/brotli.clj: ;; TODO: Default buffer size for brotli library, needs to be tuned. src/bits/middleware.clj: ;; TODO Rename :sid to :session/id src/bits/module/creator.clj: ;; TODO: Real data from database src/bits/module/creator.clj: ;; TODO Extract platform/realm domain src/bits/morph.clj:;; FIXME Relocate `morphable`. src/bits/schema.clj: ;; FIXME Avoid stringly typed entities - use `:db/ident`. src/bits/ui.clj: ;; TODO: I18n - error presentation test/bits/session_test.clj: ;; FIXME Remove `:sid` from `data`.