System Design
The backend is a Django 4.2 project structured around a deliberate core/ and apps/ split, with config/ holding settings, URL roots and WSGI/ASGI entry points. core/ carries the shared substrate — base models, common serialiser and view mixins, storage adapters, integration clients — while each feature lives as a self-contained Django app under apps/. This keeps the dependency direction one-way: feature apps import from core, never from each other. The HTTP surface is Django REST Framework, with djangorestframework-simplejwt providing stateless access/refresh token authentication, django-filter giving list endpoints declarative filtering and query-parameter search, and django-cors-headers allowing the separately deployed front end to call the API cross-origin. Configuration is read from the environment via python-dotenv, so the same image runs against SQLite locally (db.sqlite3 is checked in for development) and a managed database in deployment.
Media handling is the backend's centre of gravity. django-storages is configured with a boto3 S3 backend so that Django's FileField/ImageField write straight to object storage instead of the local filesystem, and reads resolve to S3 URLs. Pillow handles image processing — validation, dimension inspection and derivation of the renditions the front end consumes — so the API returns processed, correctly sized assets rather than raw originals. AI assistance is a separate integration seam: the openai client, with httpx as the underlying transport, sits behind service functions in the backend rather than being called from views directly, which keeps model interaction swappable and testable and prevents an external timeout from becoming an unhandled request failure. The whole thing ships as a container — there is a Dockerfile, a .dockerignore and a deploy/ directory, driven by a .gitlab-ci.yml pipeline.
The front end is a Next.js 14 application on the app router, written in TypeScript with strict typing throughout. Rather than the conventional flat components/ tree, it separates concerns across modules/ (feature-scoped composites), components/ (presentational primitives), lib/ (API clients, formatting and shared helpers), types/ (the TypeScript contracts mirroring the DRF payloads) and data/ (static and structured content). Styling is Tailwind CSS with PostCSS and Autoprefixer; iconography comes from lucide-react. Because the app router renders on the server by default, list and detail pages fetch from the Django API server-side, keeping payloads and credentials off the client and letting individual segments opt into client interactivity only where they need it. Deployment targets Vercel via vercel.json, with .env.production supplying the API base URL — the two halves of the system are versioned, built and released independently.