A full-stack project management and approval system for scientific research at the Department of Biodiversity, Conservation and Attractions (DBCA), Western Australia. SPMS handles the complete lifecycle of science projects — from creation through multi-level document approval to annual reporting and PDF generation.
- Project Creation Wizard — Multi-step guided wizard with four project types (Science, Core Function, Student, External Partnership), server-side draft persistence, live preview panel, and per-step validation
- Project Editing — Full edit form with permission-based access control, unsaved changes detection, and navigation blocking to prevent data loss
- Project Search and Filtering — Paginated project listing with filters for business area, project kind, status, year, and assigned user. Includes saved search with localStorage persistence
- Interactive Project Map — Leaflet-based map with circular markers, heatmap visualisation, GeoJSON region overlays, fullscreen mode with floating sidebar, and comprehensive filtering. Accessible with keyboard navigation
- Multi-Level Approval System — Documents progress through Team → Lead → Business Area Lead → Directorate approval stages with status tracking at each level
- Inline Rich Text Editing — Lexical-based editor with formatting toolbar variants, image upload, @mentions, and document locking to prevent concurrent editing conflicts
- Document Types — Concept Plans, Project Plans, Progress Reports, Student Reports, and Project Closures — each with type-specific workflows controlled by project kind
- PDF Generation — Server-side PDF rendering via Prince for annual reports and project documents with customisable templates
- Batch Approvals — Bulk document approval for business area leads and directorate with consolidated email notifications
- Team Management — Add/remove team members, promote to project lead, role-based permissions for document actions
- Comments and Reactions — Threaded comment system with rich text, @mentions that trigger email notifications, and emoji reactions
- Caretaker System — Request-based workflow for temporary project ownership delegation during leave or absence, with admin approval and full permission inheritance
- Published Reports — Browse official, draft, and legacy annual reports with tabbed navigation
- Report Details — View pending/approved projects, media assets, and print preview for the current reporting cycle
- Business Area Lead View — Dedicated dashboard showing problematic projects, unapproved documents, and business area appearance editing
- My Division — Key stakeholder view of divisional project status
- New Reporting Cycle — Open new cycles with custom messaging, email preview, recipient management, and division year safeguards
- User Search — Paginated user directory with role and business area filters, saved search, and quick-view detail sheet overlay
- User Profiles — Tabbed profile page (SPMS Profile, Public Staff Profile, Caretaker Mode) with modal-based editing for personal information and organisational membership
- Invite System — Search DBCA's IT Assets directory to invite internal staff users with confirmation dialog and automatic account provisioning
- External Users — Add external collaborators for annual report reference
- Staff Directory — Public-facing directory with search, pagination, and JSON-LD structured data for search engine optimisation
- Staff Profile Detail — Hero section, tabbed content (About, Projects, CV/Background, Publications), in-place editing, and Person schema markup
- Visibility Controls — Toggle public profile visibility and configure rerouted email addresses
- Data Lists — Tabbed admin view for staff users, email lists, unapproved documents, problematic projects, and staff profiles
- Reference Data CRUD — Full create/read/update/delete for addresses, affiliations, branches, business areas, divisions, locations, and services
- Admin Tasks Dashboard — Centralised view of pending caretaker requests, project deletion requests, user merge requests, and endorsement tasks (AEC, BM, HC)
- Email Management — Divisional email list configuration
- Admin Test Page — Email delivery testing and document PDF generation testing
- Role-Based Guides — Sections filtered by user role (all users, business area leads, key stakeholders, admins) with category grid and article accordion
- Search — Debounced full-text search across all knowledge base articles
- Admin Editing — Inline content editing for superusers with download capability
- Seed Command — Management command to populate knowledge base with
update_or_createupserts and--clearflag
- 17 email templates covering the full document lifecycle: submission, recall, send-back, approval (per level), batch approval, review requests, comment notifications, @mentions, project closure/reopening, new cycle announcements, staff profile updates, feedback receipt, and invitation links
- Dark Mode — Toggle between light and dark themes with persistence
- Saved Search — "Remember my search" across projects, users, and map pages with localStorage persistence
- Navigation Blocking — Global blocker prevents losing unsaved form data across all edit pages
- Responsive Design — Mobile-first layouts with breakpoint-based adaptations and mobile tab dropdowns
- Page Transitions — Animated transitions with loading states
- Breadcrumb Navigation — Automatic route-based breadcrumbs with manual override support
- Accessibility — WCAG 2.2 Level AA compliance target with semantic HTML, ARIA attributes, keyboard navigation, and screen reader announcements
# Clone and start with Docker (recommended)
git clone https://github.com/dbca-wa/science-projects.git
cd science-projects
docker-compose -f docker-compose.dev.yml up
# Frontend: http://127.0.0.1:3000
# Backend: http://127.0.0.1:8000science-projects/
├── frontend/ # React 19 + TypeScript + Tailwind + shadcn/ui
├── backend/ # Django + DRF + PostgreSQL
├── documentation/ # Comprehensive docs
├── kustomize/ # Kubernetes configs
└── docker-compose.dev.yml
Frontend: React 19, TypeScript, Vite, TanStack Query, MobX, Tailwind CSS v4, Bun
Backend: Django, DRF, Python 3.14, PostgreSQL 17, Poetry, pytest
DevOps: GitHub Actions, Docker, Kubernetes, Kustomize
- Bun 1.3.9+ - install
- Python 3.14.3+ - download
- Poetry - install
- Docker Desktop (optional) - download
# Start all services
docker-compose -f docker-compose.dev.yml up
# Run migrations (first time)
docker-compose -f docker-compose.dev.yml exec backend python manage.py migrate
# Create superuser (optional)
docker-compose -f docker-compose.dev.yml exec backend python manage.py createsuperuserFrontend:
cd frontend
bun install
cp .env.example .env
bun run dev # http://127.0.0.1:3000Backend:
cd backend
poetry install
cp .env.example .env
poetry run python manage.py migrate
poetry run python manage.py runserver # http://127.0.0.1:8000# Frontend
cd frontend
bun run test # Run once
bun run test:watch # Watch mode
bun run test:coverage # With coverage
# Backend
cd backend
poetry run pytest # All tests
poetry run pytest --cov # With coveragefeature/* → staging (Staging) → main (production) → v* tags
- staging: Auto-deploys to Staging on push
- main: Production-ready code (merge from staging)
- v* tags: Triggers production deployment
# 1. Create feature branch from staging
git checkout staging
git pull origin staging
git checkout -b feature/my-feature
# 2. Make changes and commit
git add .
git commit -m "feat: add new feature"
git push origin feature/my-feature
# 3. Create PR to staging
# Tests run automatically on PR
# 4. After merge to staging
# Staging auto-deploys within 5 minutes
# 5. When ready for production
git checkout main
git merge staging --no-ff
git push origin main
# 6. Create version tag
git tag v1.0.0
git push origin v1.0.0
# Production images build automaticallyStaging (automatic):
- Trigger: Push to
staging - URL: https://scienceprojects-test.dbca.wa.gov.au
- Images:
latest,testtags
Production (manual):
- Trigger: Version tag (e.g.,
v1.0.0) - URL: https://scienceprojects.dbca.wa.gov.au
- Images:
v1.0.0,stabletags - Deploy: Update Kubernetes via Rancher UI or kubectl
Rollback:
# Staging: Revert commit on staging and push
git revert <commit-hash>
git push origin staging
# Production: Update image tag to previous version
kubectl set image deployment/spms-deployment-prod \
frontend=ghcr.io/dbca-wa/science-projects-frontend:v1.0.0 \
backend=ghcr.io/dbca-wa/science-projects-backend:v1.0.0 \
-n spms-prodHooks run automatically on commit and check only changed files.
Install:
pre-commit installWhat's checked:
- General: Trailing whitespace, large files, merge conflicts
- Frontend: Prettier (auto-fix), ESLint, TypeScript, security
- Backend: Black (auto-fix), isort (auto-fix), flake8, bandit
Bypass (emergency only):
git commit --no-verify -m "emergency fix"The CI/CD pipeline uses a modular approach with reusable workflows:
test.yml (reusable workflow):
- Called by deploy-staging.yml and deploy-prod.yml
- Frontend tests (2-way sharding, ~2 min) - includes accessibility tests
- Backend tests (4-way sharding, ~10 min)
- Coverage combining and validation
- Path-based execution (only test changed code)
deploy-staging.yml (on push to staging):
- Detects changes (frontend/backend)
- Runs tests via test.yml (test gating)
- Builds and pushes
testimages (only if tests pass) - Total time: ~12 minutes
deploy-prod.yml (on version tags):
- Always tests and builds both frontend and backend
- Runs tests via test.yml (test gating)
- Builds and pushes versioned +
stableimages - Updates coverage badges in README
- Updates Kustomize configs automatically
sync-staging.yml (on push to main):
- Syncs staging branch with main
- Uses
[skip ci]to prevent unnecessary builds
Staging (test environment):
- Frontend:
testtag withVITE_SENTRY_ENVIRONMENT=test - Backend:
testtag - Note: Frontend test and production images are different builds (Vite bakes environment variables)
Production (tagged releases):
- Frontend:
v1.0.0+stabletags withVITE_SENTRY_ENVIRONMENT=production - Backend:
v1.0.0+stabletags stabletag always points to latest production release
Add [skip ci] to commit message to skip workflows:
git commit -m "docs: update README [skip ci]"Use cases:
- Documentation-only changes
- README updates
- Non-code changes that don't require testing/building
- Complete Documentation - Comprehensive docs for all aspects
- Frontend README - Quick start
- Backend README - Quick start
Run migrations:
# Docker
docker-compose -f docker-compose.dev.yml exec backend python manage.py migrate
# Manual
cd backend && poetry run python manage.py migrateCreate superuser:
# Docker
docker-compose -f docker-compose.dev.yml exec backend python manage.py createsuperuser
# Manual
cd backend && poetry run python manage.py createsuperuserView logs:
# Docker
docker-compose -f docker-compose.dev.yml logs -f
# Kubernetes (Staging)
kubectl logs -f deployment/spms-deployment-test -n spms-test
# Kubernetes (Production)
kubectl logs -f deployment/spms-deployment-prod -n spms-prodUpdate dependencies:
# Frontend
cd frontend && bun update
# Backend
cd backend && poetry updateTests failing on CI but passing locally:
- Check Node/Bun/Python versions match CI
- Use UTC for dates in tests
- Ensure import paths match file names exactly
Staging not updating after deploy:
- Check Rancher UI → Staging namespace → Click "Redeploy"
- Verify
imagePullPolicy: Alwaysin deployment
Docker build failing:
- Clean Docker cache:
docker system prune -a - Check Dockerfile syntax
- Verify all build args are provided
Pre-commit hooks failing:
- Run manually:
pre-commit run --all-files - Fix TypeScript errors:
cd frontend && bun run type-check - Fix Python formatting:
cd backend && black .
Copyright © 2023-2026 Department of Biodiversity, Conservation and Attractions, Western Australia