implausible/README.md

155 lines
4.6 KiB
Markdown
Raw Permalink Normal View History

# Implausibly
An open-source Android dashboard app for self-hosted [Plausible Analytics](https://plausible.io/) CE.
The existing third-party apps are all closed-source. If you're running self-hosted Plausible specifically because you care about control and transparency, a closed-source dashboard app is an odd fit.
Implausibly is:
- **Fully open source** (GPL-3.0) — audit it, fork it, contribute
- **Self-hosted first** — configurable base URL, no Plausible.io assumptions
- **No account or subscription** — just your Plausible API key
- **Zero telemetry** — no analytics in the analytics app
- **No Google Play Services** — pure AndroidX, F-Droid compatible
## Screenshots
*Coming soon — the app is functional but screenshots haven't been captured yet.*
## Features
- **Multi-instance support** — connect to multiple Plausible servers
- **Full dashboard** — visitors, pageviews, bounce rate, visit duration
- **Visitor chart** — custom Canvas line chart with area fill
- **Dimension breakdowns** — top sources, pages, countries, devices, browsers, OS
- **Date range selector** — today, 7d, 30d, 6mo, 12mo
- **Pull-to-refresh** — swipe down to reload
- **Caching** — SQLDelight cache with TTL per date range; shows cached data instantly on launch
- **Encrypted API keys** — stored via EncryptedSharedPreferences (AES-256-GCM)
- **Clone instances** — duplicate an instance config to track a different site with the same credentials
- **Smart navigation** — remembers your last-viewed dashboard and opens directly to it
- **Material 3** — light and dark theme
## Requirements
- Android 8.0+ (API 26)
- A self-hosted Plausible CE instance with API v2 enabled
- An API key (or a public shared link)
## Building
```bash
# Clone
git clone ssh://git@kode.naiv.no:2222/olemd/implausible.git
cd implausible
# Build debug APK
./gradlew assembleDebug
# Run unit tests
./gradlew test
# Install on connected device
./gradlew installDebug
# Lint
./gradlew lint
```
Requires JDK 17. The Gradle wrapper is included — no separate Gradle installation needed.
## Architecture
Four-layer unidirectional data flow:
```
UI (Jetpack Compose + Material 3)
| observes StateFlow
ViewModel (per screen, sealed UiState)
| calls
Repository (cache-first, coordinates API + DB)
| delegates to
Remote (Ktor) + Local Cache (SQLDelight)
```
Everything goes through one API endpoint: `POST /api/v2/query`. The dashboard fires 8 concurrent queries per load.
### Tech stack
| Component | Library |
|-----------|---------|
| UI | Jetpack Compose + Material 3 |
| HTTP | Ktor (OkHttp engine) |
| Serialization | kotlinx.serialization |
| Local DB | SQLDelight |
| DI | Hilt |
| Preferences | DataStore |
| Secrets | EncryptedSharedPreferences |
| Charts | Custom Canvas (no library) |
### Package structure
```
no.naiv.implausibly/
data/
remote/ Ktor API client, DTOs
local/ SQLDelight generated code
repository/ StatsRepository, InstanceRepository, SiteRepository, CacheManager
ApiKeyStore Encrypted key storage
AppPreferences DataStore preferences
domain/model/ Domain models (decoupled from API/DB)
di/ Hilt modules
ui/
setup/ Instance onboarding
sites/ Site list / management
dashboard/ Stats dashboard, components, sections
navigation/ NavHost, routes
theme/ Material 3 theme
common/ Shared UI (UiState, LoadingIndicator, ErrorState)
```
## API
The app uses the [Plausible Stats API v2](https://plausible.io/docs/stats-api). Rate limit is 600 requests/hour — with 8 queries per dashboard load, that's ~75 refreshes/hour.
### Caching
Cache key = SHA-256 hash of `(instanceId, siteId, dateRange)`. TTL varies:
| Date range | Cache TTL |
|------------|-----------|
| Realtime | Never cached |
| Today | 5 min |
| 7d, 30d | 30 min |
| 6mo, 12mo | 2 hours |
On app open: show cached data immediately, refresh in background.
## Roadmap
### Phase 2 (planned)
- Filter system (bottom sheet, combinable filters)
- Material You dynamic color
- Landscape layout
- Realtime polling
- Sites API auto-discovery
- Custom date ranges
- F-Droid submission
### Phase 3 (future)
- Comparison mode (this period vs previous)
- Goal conversions
- Segments support
- Home screen widgets (Glance)
## License
[GPL-3.0-only](LICENSE)
This means any distributed fork must also be open source under the same license. All dependencies are GPL-compatible (Apache 2.0, MIT).
## Contributing
Contributions welcome. The project is hosted on Forgejo at `kode.naiv.no`.
All source files must include the SPDX header: `// SPDX-License-Identifier: GPL-3.0-only`