camply: Path Forward
This document outlines the strategic roadmap for transitioning camply from a legacy CLI tool to a modern, full-stack, community-facing web application for campsite availability monitoring.
🎯 Vision
A free, open-source, and self-hostable campsite availability scanner. Users can create accounts, set up high-frequency "scans" for specific parks/dates, and receive real-time alerts via Pushover (and other channels) when a spot opens up.
🏗️ Core Architecture & Standards
Backend: FastAPI (Python >=3.11, Python 3.14 runtime defaults, one
camplydistribution managed byuv) using Pydantic v2.Frontend: React (TypeScript, Vite, Tailwind CSS + Shadcn/UI).
Database: SQLite in the base package; PostgreSQL through the
postgresextra for distributed deployment (SQLAlchemy + Alembic).Worker: Shared async de-duplicated poller with Celery + Valkey adapters in distributed mode or bounded local loops in standalone.
Auth: Multi-user Auth0 integration with optional invite-only access (
CAMPLY_INVITE_ONLY). The owner selectsnone(automatic shared-account login),session(in-app password login), orauth0, independently of the environment. HTTP Basic authentication is unsupported.Licensing: Licensed under the GNU Affero General Public License v3.0 (AGPLv3) to ensure camply and all derivative works stay open-source.
Notifications: Initial support for Pushover (extensible to Email/Discord).
Monitoring: Sentry integration enabled for error tracking and performance.
Infrastructure: Docker Compose + Kubernetes manifests.
API Strategy: OpenAPI/Swagger with automated TypeScript client generation for the frontend.
Standards:
- Testing:
pytest(Backend) andvitest(Frontend) with VCR recordings for external APIs. - Typing: Strict static analysis with
mypyandtsc. - Local Dev: Unified orchestration via
Docker ComposeandTaskfile.yaml.
- Testing:
Python distribution boundary
The backend builds one camply distribution with internal server, db, providers, and worker subpackages. Base supplies provider APIs, SQLite, and the population utility; optional extras supply server, distributed, postgres, and sentry dependencies. Server and worker bootstraps remain independent. API-only installs do not execute scheduled scans unless standalone mode is selected. Standalone provides bounded local scheduling and serves the bundled frontend from one Python process. Root source builds produce complete wheels and sdists; prepared sdists rebuild without JavaScript tooling. New CLI subcommands and PyPI publication remain separate work.
🚀 Strategic Feature Requirements
1. High-Frequency Scanning
- Sub-Minute Polling: Architect the worker to support scan intervals as low as 30-45 seconds for highly competitive parks.
- Provider-Specific Intervals: Allow different default intervals based on provider "politeness" policies.
2. Granular Filtering
- Equipment Specifics: Filter by RV/Trailer length and type.
- Site Attributes: Filter by "Electric Only", "Full Hookups", "Pull-through", or "Pets Allowed".
- Specific Site Monitoring: Allow users to watch specific campsite numbers within a facility.
- Minimum Stay Logic: Only alert if a consecutive block of
Xnights is found.
3. Discovery & UX
- Global Search: Unified search across all providers (Recreation.gov, State Parks, etc.).
- Map-Based Discovery: Explore offers MapLibre GL JS mapping across all filtered results, with bounded geographic groups and campground monitoring actions; detail maps share the keyless/configurable basemap. See the mapping plan.
- Permit Monitoring: Extend scanning logic to support Wilderness/Backcountry permits and Tours.
🛤️ Roadmap Phases
Phase 1: Smart Poller & Single-Scan MVP
Goal: Build the "Smart" engine that de-duplicates requests and proves the end-to-end flow.
- [x] DB Schema: Design
Users(with invitation flag),UniqueTargets(unique definitions), andUserScans(user subscriptions). - [x] Sentry: Initialize Sentry SDK for Celery worker; backend Sentry remaining.
- [x] Provider Engine: Define the new
BaseProviderABC and migraterecreation_dot_govlogic. - [x] Celery Worker: Implement de-duplicated polling logic in Celery.
- [x] Infrastructure: Update
docker-compose.yamlto include Valkey and Celery worker/beat services. - [x] Tooling: Add Celery/Worker management tasks to the
taskfiles/python.yaml. - [x] OpenAPI: Expose initial search/scan endpoints and configure client generation.
- [x] Pushover: Integrate basic notification delivery.
Phase 2: User Dashboard & Auth
Goal: Enable secure, multi-user management of scans.
- [x] Auth0: Implement login/signup, API audience configuration, and optional invite-only enforcement.
- [ ] Invitations: Implement approval/revocation, verified identity matching, and notification delivery.
- [ ] Scan Management: Build a dashboard to create, pause, and delete user-specific scans.
- [x] Frontend Refactor: Update
package.jsonscripts and dependency management with pnpm, Oxlint, Oxfmt, Vite 8, Vitest 5, and native TypeScript 7. - [ ] Dockerization: Update
docker-compose.yamlandDockerfilefor optimized frontend builds. - [ ] User Config: Secure storage for user-specific Pushover keys and notification preferences.
- [ ] Validation: Ensure strict schema validation for all user-provided scan parameters.
Phase 3: Provider Parity & Advanced Filtering
Goal: Full feature parity with the legacy CLI and advanced scanning features.
- [ ] Providers: Port
usedirect,going_to_camp,xanterra. - [x] ReserveCalifornia: Port California State Parks availability and metadata to the current Tyler RDR API; preserve modern booking routes on the shared UseDirect ABC.
- [x] Shared UseDirect providers: Implement independent metadata sync and availability for Florida, Virginia, Minnesota, Ohio, Arizona, Missouri, Fairfax County, Oregon Metro, and Northern Territory. Alabama and Maricopa endpoint discovery remain pending; see provider TODOs.
- [ ] Advanced Filters: Implement RV length, electric, and accessibility filters in the worker.
- [ ] Permits: Add support for scanning wilderness permit and tour availability.
Phase 4: Production & Scale
Goal: Finalize for deployment and community use.
- [ ] Rate Limiting: Implement proxy rotation and intelligent backoff strategies.
- [x] Observability: Native Admin UI monitoring backed by Prometheus for usage trends, API/worker performance, scan outcomes, and queue visibility; replaced legacy Grafana deployment as part of the Admin UI plan.
- [ ] Polish: Full mobile-responsive UI/UX with Shadcn/UI refinements.
📝 Interactive Discussion Points
- Notification Costs: SMS sending costs money. Should we prioritize free channels (Email, Push, Discord/Telegram) first before implementing SMS?
- Provider API Limits: Competitive services use extensive proxying to avoid getting banned. How sophisticated do we want to make our request engine initially?
- Scan Limits: Should we limit the number of active scans a user can have at once to manage server load?
- Data Retention: How long should we keep history of campsite availability data?
🏁 Next Immediate Steps
- [x] Database Design: Create SQLAlchemy models for the Multi-User / De-duplicated architecture in
src/camply/db. - [x] Provider Migration: Extract search logic from
cli/tosrc/camply/providers/. - [x] API Scaffolding: Setup OpenAPI client generation in the frontend.
- [x] API Endpoints: FastAPI scan/search/me CRUD endpoints.
- [x] Dashboard UI: Scan management dashboard with creation, toggling, and deletion.
- [x] Auth0 Integration: Wire up JWT validation, API audience, and profile pages.
- [ ] Invitation Workflow: Implement approval/revocation and notification delivery.
- [ ] Provider Parity: Port remaining providers (usedirect, xanterra)."}]}
Standalone runtime delivery
Optional standalone now serves built React assets and the API from one Python process with SQLite, local polling/catalog refresh, and durable notification recovery. The distributed runtime remains the default. See the implementation tasks, developer workflow, and runtime constraints.