Currently in pre-alpha and subject to significant breaking changes.
VerdoyLab is an experiment in building a modern SaaS platform from scratch using AI Copilots. Envisioned as an open-source Laboratory (Information) Management System designed for research labs and R&D facilities, VerdoyLab has been fully pair-programmed with Cursor, using an intentional and iterative design/build practice.
The eventual platform will, hopefully, be a simple, performant, and secure system to build the information management of an R&D lab. It will support remote programmatic integration for lab tools and sensors; multimodal data manage with native graph, vector and timeseries storage; project, process experiment and hardware management; and user/back-office management for one to many labs in one to many organizations, in an either multi- or data separated tenancy configuraiton.
VerdoyLab is built on a FastAPI backend with Jinja 2 frontend, connected to a PostgreSQL + TimescaleDB database for high-performance data management and real-time IoT device integration.
Significant history of the work can be found in the project directories under /docs, and more recently stored in a Linear project that Cursor has been using to manage increasingly complicated dependencies and project structures (ask about access if you'd like to review).
As development continues, progress updates will be documented here: (TBD)
- IoT Device Management: ESP32 device registration, configuration, and monitoring (in progress)
- Real-time Data Collection: Time-series sensor data ingestion and storage (in progress)
- User Authentication: JWT-based authentication with organization management (partially implemented)
- Experiment Tracking: Comprehensive experiment and trial management (working prototype)
- Bioreactor Integration: Reference hardware management with settings for sensor reading and actuation (working prototpye)
- RESTful APIs: Full REST API with OpenAPI documentation (working prototype)
- WebSocket Support: Real-time data streaming and device communication (in-progress)
- Multi-tenant Architecture: Organization-based data isolation (in progress)
- Event Sourcing: Immutable audit trail for all system changes (in progress)
- Knowledge Graph: Rich entity relationships and graph queries (working representation)
- MCP Service: An MCP server that streamlines Agentic-LLM-to-API interaction. (future)
The system implements a simple architecture with separated concerns and a low-Javascript frontend:
- Backend: FastAPI with async Python
- Database: PostgreSQL with TimescaleDB extension for time-series data
- Frontend: Server-rendered HTML using Jinja, with progressive enhancement
- IoT Integration: ESP32 device support with MQTT/HTTP protocols
- Containerization: Docker and Docker Compose for easy deployment
.
βββ backend/ # FastAPI backend service
β βββ app/ # Application code
β β βββ models/ # SQLAlchemy models
β β βββ routers/ # API route handlers
β β βββ services/ # Business logic
β β βββ schemas/ # Pydantic schemas
β β βββ templates/ # HTML templates
β β βββ static/ # CSS/JS assets
β βββ tests/ # Backend tests
β βββ requirements.txt # Python dependencies
βββ database/ # Database migrations and schemas
β βββ migrations/ # SQL migration files
β βββ setup_db.py # Database setup script
βββ tests/ # Frontend tests (Playwright)
βββ docs/ # Documentation
βββ docker-compose.yml # Container orchestration
βββ README.md # This file
- Docker and Docker Compose
- Git
-
Clone the repository
git clone https://github.com/lutze/verdoy.git cd verdoy -
Set up environment variables
cp .env.example .env # Edit .env with your configuration -
Start the services
docker compose up -d
-
Access the application
- Web Interface: http://localhost:8000
- API Documentation: http://localhost:8000/docs
- Database: localhost:5432
For development with live reloading:
# Install Python dependencies
cd backend
pip install -r requirements.txt
pip install -r requirements-dev.txt
# Run the development server
uvicorn app.main:app --reload --host 0.0.0.0 --port 8000The VerdoyLab API provides a comprehensive IoT device management system with the following key features:
- User Authentication: JWT-based authentication for web interface users
- Device Management: ESP32 device registration, configuration, and monitoring
- Data Ingestion: Sensor readings collection and storage
- Device Control: Command queuing and device control operations
- Real-time Data: WebSocket endpoints for live data streaming
Users authenticate using JWT tokens:
# Login to get access token
curl -X POST "http://localhost:8000/api/v1/auth/login" \
-H "Content-Type: application/json" \
-d '{
"email": "user@example.com",
"password": "password123"
}'
# Response
{
"access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...",
"token_type": "bearer",
"expires_in": 1800,
"user": {
"id": "uuid",
"email": "user@example.com",
"name": "User Name",
"organization_id": "uuid",
"is_active": true
}
}Use the token in subsequent requests:
curl -X GET "http://localhost:8000/api/v1/devices" \
-H "Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9..."ESP32 devices authenticate using API keys stored in their properties:
# Device sends sensor readings
curl -X POST "http://localhost:8000/api/v1/devices/{device_id}/readings" \
-H "Authorization: Bearer device_abc123def456" \
-H "Content-Type: application/json" \
-d '{
"device_id": "uuid",
"readings": [
{
"sensor_type": "temperature",
"value": 23.5,
"unit": "Β°C",
"timestamp": "2024-01-01T12:00:00Z",
"quality": "good"
}
]
}'# List user's devices
GET /api/v1/devices
# Register new device
POST /api/v1/devices
{
"name": "My ESP32 Device",
"description": "Temperature sensor in lab",
"location": "Lab A",
"firmware_version": "1.0.0",
"hardware_model": "ESP32-WROOM-32",
"mac_address": "24:6F:28:XX:XX:XX"
}
# Get device details
GET /api/v1/devices/{device_id}
# Update device
PUT /api/v1/devices/{device_id}# Send sensor readings
POST /api/v1/devices/{device_id}/readings
# Device heartbeat
POST /api/v1/devices/{device_id}/heartbeat
# Update device status
POST /api/v1/devices/{device_id}/status# Get device readings
GET /api/v1/devices/{device_id}/readings
# Get latest readings
GET /api/v1/devices/{device_id}/readings/latest
# Get reading statistics
GET /api/v1/devices/{device_id}/readings/stats# Queue command for device
POST /api/v1/devices/{device_id}/commands
# Device polls for commands
GET /api/v1/devices/{device_id}/commands
# Mark command as executed
PUT /api/v1/devices/{device_id}/commands/{cmd_id}For real-time data streaming:
// Live sensor data
const ws = new WebSocket('ws://localhost:8000/ws/live-data');
// Device status events
const ws = new WebSocket('ws://localhost:8000/ws/device-status');
// Real-time alerts
const ws = new WebSocket('ws://localhost:8000/ws/alerts');- Swagger UI: http://localhost:8000/docs
- ReDoc: http://localhost:8000/redoc
- OpenAPI JSON: http://localhost:8000/openapi.json
The project uses a custom migration runner to manage database schema changes. Migrations are stored in the database/migrations directory and are applied in alphabetical order.
For detailed instructions on setting up the database, running and rolling back the migrations, refer to database/README.md
Run the test suite:
# Backend tests
cd backend
pytest
# Frontend tests
npm testWe welcome contributions! Please see our Contributing Guidelines for details.
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add some amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
- Native vector storage support
- Robust native graph storage
- Graphical process builder
- Complete task-level role-based permissions
- Tenancy support for multiple organizations
- More robust e2e testing and internal administration dashboards
- MCP and A2A extensions from programmatic APIs
- Multi-language support
- Mobile app support
This project is licensed under the GNU Affero General Public License v3.0 - see the LICENSE.md file for details.
- π Documentation
- π Issue Tracker
- π¬ Discussions
- MVP feature set refined through discussions with Ivan Labra and Alena Tanakra of KaskBIO
- Built with FastAPI
- Database powered by PostgreSQL and TimescaleDB
- IoT integration for ESP32 devices