Rename CritterScope → Drones (repo, subdomain, branding)

Worker + subdomain now drones.theradicalparty.com; in-app title/brand,
package names, docs updated. D1 database binding kept as-is.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
King Omar 2026-07-25 17:56:53 +10:00
parent 48866acc97
commit 224792550f
12 changed files with 25 additions and 24 deletions

View file

@ -1,4 +1,4 @@
# 🛰️ CritterScope # 🚁 Drones
Turn a drone survey into **georeferenced animal/object detections on a 3D map.** Turn a drone survey into **georeferenced animal/object detections on a 3D map.**
@ -15,7 +15,7 @@ testable before any drone arrives. Real footage feeds the *same* dashboard via
- **Cloudflare Worker + Hono** (`src/index.js`) - **Cloudflare Worker + Hono** (`src/index.js`)
- **MapLibre GL JS** — satellite imagery + Terrarium DEM for real 3D terrain (no API key) - **MapLibre GL JS** — satellite imagery + Terrarium DEM for real 3D terrain (no API key)
- **D1** (optional) — stores real surveys/detections; schema in `schema.sql` - **D1** (optional) — stores real surveys/detections; schema in `schema.sql`
- Deploys to `critterscope.theradicalparty.com` - Deploys to `drones.theradicalparty.com`
## Run locally ## Run locally
```bash ```bash
@ -41,7 +41,7 @@ Open `/` for the dashboard. Point it anywhere:
`type``deer | fox | rabbit | boar | kangaroo | person | vehicle | unknown`. `type``deer | fox | rabbit | boar | kangaroo | person | vehicle | unknown`.
## Feeding real drone data ## Feeding real drone data
1. `wrangler d1 create critterscope`, paste the id into `wrangler.toml`, uncomment the binding. 1. `wrangler d1 create drones`, paste the id into `wrangler.toml`, uncomment the binding.
2. `npm run db:init` 2. `npm run db:init`
3. `POST /api/ingest` with `{ survey, flight, detections }`. 3. `POST /api/ingest` with `{ survey, flight, detections }`.
4. View it at `/?survey=<id>`. 4. View it at `/?survey=<id>`.

View file

@ -1,5 +1,5 @@
{ {
"name": "critterscope", "name": "drones",
"version": "0.1.0", "version": "0.1.0",
"description": "Thermal/RGB drone survey → georeferenced animal detections on a 3D map", "description": "Thermal/RGB drone survey → georeferenced animal detections on a 3D map",
"private": true, "private": true,

View file

@ -1,7 +1,7 @@
# CritterScope drone ingest pipeline # Drones drone ingest pipeline
Turns drone footage + telemetry into georeferenced detections and pushes them to Turns drone footage + telemetry into georeferenced detections and pushes them to
a CritterScope instance. a Drones instance.
``` ```
video / RTMP frames + telemetry (DJI .SRT) video / RTMP frames + telemetry (DJI .SRT)
@ -24,7 +24,7 @@ would send — proves the whole chain:
cd pipeline cd pipeline
node src/run.js --synthetic --dry-run node src/run.js --synthetic --dry-run
``` ```
Push it into a running local CritterScope (with local D1, see root README): Push it into a running local Drones (with local D1, see root README):
```bash ```bash
node src/run.js --synthetic --name "test-survey" --base-url http://localhost:8787 node src/run.js --synthetic --name "test-survey" --base-url http://localhost:8787
# → View it: http://localhost:8787/?survey=sv-test-survey-... # → View it: http://localhost:8787/?survey=sv-test-survey-...
@ -37,7 +37,7 @@ node src/run.js \
--detector onnx --model yolo-thermal.onnx \ --detector onnx --model yolo-thermal.onnx \
--width 1920 --height 1080 \ --width 1920 --height 1080 \
--drone "DJI Mavic 2 Enterprise Advanced" \ --drone "DJI Mavic 2 Enterprise Advanced" \
--base-url https://critterscope.theradicalparty.com --base-url https://drones.theradicalparty.com
``` ```
## Live RTMP (DJI Fly app livestream) ## Live RTMP (DJI Fly app livestream)

View file

@ -1,10 +1,10 @@
{ {
"name": "critterscope-pipeline", "name": "drones-pipeline",
"version": "0.1.0", "version": "0.1.0",
"description": "Drone footage + telemetry → georeferenced detections → CritterScope", "description": "Drone footage + telemetry → georeferenced detections → Drones",
"private": true, "private": true,
"type": "module", "type": "module",
"bin": { "critterscope-ingest": "src/run.js" }, "bin": { "drones-ingest": "src/run.js" },
"scripts": { "scripts": {
"demo": "node src/run.js --synthetic --dry-run", "demo": "node src/run.js --synthetic --dry-run",
"demo:ingest": "node src/run.js --synthetic --base-url http://localhost:8787" "demo:ingest": "node src/run.js --synthetic --base-url http://localhost:8787"

View file

@ -8,7 +8,7 @@
// - stub: deterministic synthetic detections so the whole pipeline runs and // - stub: deterministic synthetic detections so the whole pipeline runs and
// can be validated end-to-end without a model or real footage. // can be validated end-to-end without a model or real footage.
// //
// The class list is COCO-ish remapped to the CritterScope species vocabulary. // The class list is COCO-ish remapped to the Drones species vocabulary.
// For thermal you'd train/fine-tune on thermal wildlife imagery; the interface // For thermal you'd train/fine-tune on thermal wildlife imagery; the interface
// is identical. // is identical.

View file

@ -1,4 +1,4 @@
// POST an assembled survey to a CritterScope instance. // POST an assembled survey to a Drones instance.
export async function postSurvey({ baseUrl, survey, flight, detections }) { export async function postSurvey({ baseUrl, survey, flight, detections }) {
const res = await fetch(`${baseUrl.replace(/\/$/, "")}/api/ingest`, { const res = await fetch(`${baseUrl.replace(/\/$/, "")}/api/ingest`, {

View file

@ -1,5 +1,5 @@
#!/usr/bin/env node #!/usr/bin/env node
// CritterScope drone ingest pipeline. // Drones drone ingest pipeline.
// //
// video/RTMP frames + telemetry (DJI SRT) → detector → georeferencer // video/RTMP frames + telemetry (DJI SRT) → detector → georeferencer
// → survey JSON → POST /api/ingest → view at /?survey=<id> // → survey JSON → POST /api/ingest → view at /?survey=<id>
@ -10,7 +10,7 @@
// //
// # real footage: // # real footage:
// node src/run.js --source flight.MP4 --srt flight.SRT --detector onnx \ // node src/run.js --source flight.MP4 --srt flight.SRT --detector onnx \
// --model yolo-thermal.onnx --base-url https://critterscope.theradicalparty.com // --model yolo-thermal.onnx --base-url https://drones.theradicalparty.com
// //
// # live RTMP stream from the DJI Fly app: // # live RTMP stream from the DJI Fly app:
// node src/run.js --source rtmp://localhost/live/stream --srt live.SRT --fps 1 // node src/run.js --source rtmp://localhost/live/stream --srt live.SRT --fps 1

View file

@ -1,4 +1,4 @@
-- CritterScope data model. -- Drones data model.
-- A "survey" is one drone flight over an area; "detections" are georeferenced -- A "survey" is one drone flight over an area; "detections" are georeferenced
-- animals/objects found in that survey. The demo runs off the live simulator, -- animals/objects found in that survey. The demo runs off the live simulator,
-- but real drone footage lands here via POST /api/ingest. -- but real drone footage lands here via POST /api/ingest.

View file

@ -69,7 +69,7 @@ app.post("/api/ingest", async (c) => {
return c.json({ ok: true, survey: id, detections: (body.detections || []).length }); return c.json({ ok: true, survey: id, detections: (body.detections || []).length });
}); });
app.get("/health", (c) => c.json({ ok: true, service: "critterscope" })); app.get("/health", (c) => c.json({ ok: true, service: "drones" }));
async function loadSurvey(db, id) { async function loadSurvey(db, id) {
const survey = await db.prepare(`SELECT * FROM surveys WHERE id=?`).bind(id).first(); const survey = await db.prepare(`SELECT * FROM surveys WHERE id=?`).bind(id).first();

View file

@ -1,4 +1,4 @@
// The CritterScope dashboard, served as a single self-contained HTML document. // The Drones dashboard, served as a single self-contained HTML document.
// MapLibre GL JS (free, no API key): satellite imagery + Terrarium DEM for real // MapLibre GL JS (free, no API key): satellite imagery + Terrarium DEM for real
// 3D terrain relief. Detections render as species markers draped on the terrain; // 3D terrain relief. Detections render as species markers draped on the terrain;
// a timeline scrubber replays the survey as the drone flew it. // a timeline scrubber replays the survey as the drone flew it.
@ -10,7 +10,7 @@ export function page(cfg) {
<head> <head>
<meta charset="utf-8" /> <meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1" /> <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1" />
<title>CritterScope drone wildlife survey</title> <title>Drones drone wildlife survey</title>
<link href="https://unpkg.com/maplibre-gl@4.7.1/dist/maplibre-gl.css" rel="stylesheet" /> <link href="https://unpkg.com/maplibre-gl@4.7.1/dist/maplibre-gl.css" rel="stylesheet" />
<script src="https://unpkg.com/maplibre-gl@4.7.1/dist/maplibre-gl.js"></script> <script src="https://unpkg.com/maplibre-gl@4.7.1/dist/maplibre-gl.js"></script>
<style> <style>
@ -56,7 +56,7 @@ export function page(cfg) {
<div id="loading">Loading terrain &amp; survey</div> <div id="loading">Loading terrain &amp; survey</div>
<div id="hud" class="panel"> <div id="hud" class="panel">
<h1>🛰 CritterScope <span id="mode" class="badge sim">SIM</span></h1> <h1>🚁 Drones <span id="mode" class="badge sim">SIM</span></h1>
<div class="sub" id="surveyName"></div> <div class="sub" id="surveyName"></div>
<div class="stats"> <div class="stats">
<div class="stat"><b id="sTotal">0</b><span>detections</span></div> <div class="stat"><b id="sTotal">0</b><span>detections</span></div>
@ -230,6 +230,7 @@ playBtn.onclick=()=>{
// initialise clock once loaded // initialise clock once loaded
const _origRender=renderSurvey; const _origRender=renderSurvey;
</script> </script>
<script src="https://theradicalparty.com/footer.js" data-mode="pill" defer></script>
</body> </body>
</html>`; </html>`;
} }

View file

@ -5,7 +5,7 @@
# The live deploy uses wrangler.toml (simulator; no D1) until a D1-capable # The live deploy uses wrangler.toml (simulator; no D1) until a D1-capable
# Cloudflare token is available — then move this binding into wrangler.toml # Cloudflare token is available — then move this binding into wrangler.toml
# with the real database_id. # with the real database_id.
name = "critterscope" name = "drones"
main = "src/index.js" main = "src/index.js"
compatibility_date = "2024-11-01" compatibility_date = "2024-11-01"
compatibility_flags = ["nodejs_compat"] compatibility_flags = ["nodejs_compat"]

View file

@ -1,12 +1,12 @@
name = "critterscope" name = "drones"
main = "src/index.js" main = "src/index.js"
compatibility_date = "2024-11-01" compatibility_date = "2024-11-01"
compatibility_flags = ["nodejs_compat"] compatibility_flags = ["nodejs_compat"]
routes = [{ pattern = "critterscope.theradicalparty.com", custom_domain = true }] routes = [{ pattern = "drones.theradicalparty.com", custom_domain = true }]
[vars] [vars]
BASE_URL = "https://critterscope.theradicalparty.com" BASE_URL = "https://drones.theradicalparty.com"
# Default map center [lon, lat] and survey radius (metres). Override per-survey via ?lat=&lon=&r= # Default map center [lon, lat] and survey radius (metres). Override per-survey via ?lat=&lon=&r=
DEFAULT_LON = "150.3119" DEFAULT_LON = "150.3119"
DEFAULT_LAT = "-33.7300" DEFAULT_LAT = "-33.7300"