Property purchase portal for the Genesee County Land Bank Authority (GCLBA).
- Buyer application flow:
/apply/ - Staff admin and review tools:
/admin/ - Staff review queue:
/admin/review/
- Property-first accordion application flow (HTMX + server-rendered templates)
- Program support:
- Featured Homes
- Ready for Rehab
- VIP Spotlight
- Vacant Lot is present in metadata but intentionally disabled
- Draft save/resume with magic-link email (
/apply/save/,/apply/resume/<token>/) - Conditional document requirements by program and purchase type
- VIP multi-file uploads for portfolio photos and support letters
- Eligibility disqualification gate before full submission
- Draft-to-submission conversion with typed
Documentrows - Buyer confirmation email + staff new-submission email on submit
- Staff review queue with auto-claim and "update and next" workflow
- Admin assignment endpoint, pending-count endpoint, and per-document review status API
- Status transition audit trail (
StatusLog) with transition validation - Buyer status emails on:
needs_more_infoapproveddeclined
- Required note enforcement for:
needs_more_infodeclined
- Python 3.13
- Django 6.0.2
django-smartbase-admin(admin UI layer)- HTMX + Alpine.js
- Tailwind CSS (built via
django-tailwind+ Node toolchain) - PostgreSQL in production (
DATABASE_URL), SQLite locally by default - WhiteNoise for static files
django-anymail(Resend backend option) for outbound emaildjango-storagesfor S3-compatible media storage in production
applications/
admin.py # SmartBase admin registrations, actions, filters
admin_utils.py # Dashboard widget helpers
models.py # User, Property, ApplicationDraft, Application, Document, StatusLog
status_notifications.py # Buyer-status email + transition-note rules
csv_import.py # CSV/Excel import logic for Property inventory
views/
accordion.py # Main /apply/ accordion flow
submission.py # Draft -> Application conversion + submit emails
review_queue.py # /admin/review/* workflow
admin_api.py # assign/pending/doc-review/admin import endpoints
documents.py # Staff-only document access
config/
settings.py # Runtime config (DB, email, storage, security)
urls.py # Root routes
sbadmin_config.py # SmartBase menu + dashboard config
templates/
apply/ # Buyer flow templates
admin/review_queue/ # Staff queue templates
emails/ # Outbound email templates
ApplicationDraft: in-progress JSON-backed draft with 14-day expiry tokenApplication: submitted record used for staff filtering/reviewDocument: uploaded file metadata per applicationStatusLog: immutable audit log of status transitionsProperty: searchable inventory used by property picker/autocompleteUser: custom auth model (AUTH_USER_MODEL=applications.User)
- Python 3.13+
- Node.js (required for Tailwind build)
python3.13 -m venv venv
source venv/bin/activate
pip install -r requirements.txtFor lint/test tooling:
pip install -r requirements/development.txtnpm --prefix theme/static_src install
./venv/bin/python manage.py tailwind buildCreate .env in repo root:
DJANGO_SECRET_KEY=dev-only-secret
DJANGO_DEBUG=True
DJANGO_ALLOWED_HOSTS=localhost,127.0.0.1
CSRF_TRUSTED_ORIGINS=http://localhost:8000,http://127.0.0.1:8000,http://localhost:8199,http://127.0.0.1:8199
EMAIL_BACKEND=django.core.mail.backends.console.EmailBackend
DEFAULT_FROM_EMAIL=applications@thelandbank.org
STAFF_NOTIFICATION_EMAIL=offers@thelandbank.org
RESEND_API_KEY=./venv/bin/python manage.py migrate
./venv/bin/python manage.py createsuperuser
./venv/bin/python manage.py runserver 8199Open:
- Buyer:
http://127.0.0.1:8199/apply/ - Admin:
http://127.0.0.1:8199/admin/
./venv/bin/python manage.py check
./venv/bin/python manage.py makemigrations --check
./venv/bin/python manage.py test
ruff check .Property import commands:
./venv/bin/python manage.py import_properties path/to/file.csv
./venv/bin/python manage.py import_properties path/to/file.xlsx --replace --batch "March 2026"
./venv/bin/python manage.py import_fm_csv featured_homes path/to/filemaker.csv --replaceStatuses:
receivedunder_reviewneeds_more_infoapproveddeclined
Allowed transitions:
received -> under_reviewunder_review -> approved|declined|needs_more_infoneeds_more_info -> under_reviewdeclined -> under_review(re-open allowed)approvedis terminal
- Deployment scripts currently run:
- Node install for Tailwind assets
python manage.py tailwind buildpython manage.py collectstatic --noinputpython manage.py migrate --noinputpython manage.py ensure_superusergunicorn config.wsgi --bind 0.0.0.0:$PORT --workers 3
- These commands are defined in:
Procfilenixpacks.tomlrailpack.json
ensure_superusercurrently creates/resets usernameAdminwith passwordAdmin123unless that command is changed.
DATABASE_URLDJANGO_SECRET_KEYDJANGO_DEBUG=FalseDJANGO_ALLOWED_HOSTSCSRF_TRUSTED_ORIGINSEMAIL_BACKENDRESEND_API_KEYDEFAULT_FROM_EMAILSTAFF_NOTIFICATION_EMAIL- Optional S3-compatible media storage:
AWS_STORAGE_BUCKET_NAME(orAWS_S3_BUCKET_NAME)AWS_ACCESS_KEY_IDAWS_SECRET_ACCESS_KEYAWS_S3_REGION_NAME(orAWS_DEFAULT_REGION)AWS_S3_ENDPOINT_URLAWS_S3_CUSTOM_DOMAIN
Install dependencies into the active environment:
source venv/bin/activate
pip install -r requirements.txtExpected when DJANGO_DEBUG=False and DJANGO_SECRET_KEY is not set.
Rebuild Tailwind output:
npm --prefix theme/static_src install
./venv/bin/python manage.py tailwind buildneeds_more_info and declined require a staff note.
Check:
EMAIL_BACKENDRESEND_API_KEY(if using Resend backend)DEFAULT_FROM_EMAIL