System Design
The backend is a Django 5 project with the REST layer isolated into a single api application, keeping models, serialisers, viewsets, and URL routing in one place rather than scattered across a dozen half-populated apps. Authentication runs on djangorestframework-simplejwt, which fits the shape of the problem: the mobile client has no cookie jar and no session affinity to lean on, so access and refresh tokens carried in the Authorization header let both clients authenticate against exactly the same code path. django-cors-headers sits in front of that to let the browser-based surface issue cross-origin requests against the API host without relaxing anything for other callers.
Media handling goes through Pillow, which is what Django's ImageField reaches for when it needs to validate and process uploads — dimension checks, format verification, and any resizing done on the way to storage. Static assets are served by whitenoise from inside the application process, which means the container is self-sufficient for statics and Nginx is free to do what it is actually good at: terminating connections, serving user-uploaded media off disk, and reverse-proxying everything else to gunicorn. Configuration is externalised through python-dotenv against a checked-in .env.example, so the same image runs in every environment with nothing baked in but code. The default persistence layer is SQLite (db.sqlite3), which keeps local development to a single manage.py migrate with no service dependencies.
Two operational concerns are handled as first-class code rather than tribal knowledge. Reporting is built on openpyxl for spreadsheet output and reportlab for PDF generation, both driven server-side so a mobile client can request a document without shipping a rendering engine. And bootstrapping is scripted: create_admin.py provisions the initial superuser non-interactively, while setup_categories.py seeds the category taxonomy the product depends on — two scripts that turn a fresh container into a usable instance without anybody clicking through the admin. Delivery is defined by a Dockerfile, a docker-compose.yml that wires the app to the nginx configuration, and a .gitlab-ci.yml that drives the pipeline, with backups/ holding the recovery tooling.