Skip to content

META: extract API into django-admin-rest-api dependency — make this repo the React super-layer #544

@MartinCastroAlvarez

Description

@MartinCastroAlvarez

Goal — three-repo separation of concerns

Split the project into three independently-published, cross-referenced repos:

Repo PyPI Role
django-admin-rest-api django-admin-rest-api The JSON REST API for the Django admin — same permissions, same ModelAdmin, no new features. The wire surface.
django-admin-react (this repo) django-admin-react The React SPA frontend. After this migration: a super-layer that depends on django-admin-rest-api for every wire call.
django-admin-mcp (planned) Exposes the SAME ModelAdmin-driven functionality over the MCP protocol (call, manifest, etc.), reusing the same API classes.

The user has already published django-admin-rest-api 0.1.0a0 to PyPI (pip install django-admin-rest-api).

What this issue tracks

Migrating this repo from "self-contained Django + API + SPA" to a thin SPA super-layer that pulls the API from the published django-admin-rest-api dependency. Every API-internals file under django_admin_react/api/ and the matching tests get replaced by the dependency; the SPA-specific files (pwa.py, views.py for the SPA mount, the pre-built React assets under static/admin_react/, the React app's AppConfig) stay.

The consumer experience after migration is genuinely plug-and-play — two INSTALLED_APPS lines + one URL include:

# settings.py
INSTALLED_APPS = [
    # ...,
    "django.contrib.admin",
    "django_admin_rest_api",   # ← the API (pulled in as a dependency)
    "django_admin_react",      # ← the SPA (this package)
]

# urls.py
urlpatterns = [
    path("admin/",       admin.site.urls),
    path("admin-react/", include("django_admin_react.urls")),   # SPA + the API include lives here
]

Migration phases (each = one PR)

  • Phase 1 — add the dependency. Add django-admin-rest-api ^0.1.0a0 to pyproject.toml, regenerate poetry.lock, verify both the local django_admin_react.api.* and the package's django_admin_rest_api.api.* coexist without crashing. Full test suite still green (no behaviour change — the package is just present).
  • Phase 2 — swap the URL include. In django_admin_react/urls.py, replace include("django_admin_react.api.urls") with include("django_admin_rest_api.urls"). The SPA's runtime URL derivation (from request.path) keeps working — the wire shape is identical. Tests that exercise the API through the URL router stay green via the dependency's identical implementation.
  • Phase 3 — drop django_admin_react/api/. Delete the entire local api/ tree. Delete the matching backend tests under tests/ (most of test_*.py test API behaviour, which belongs in the django-admin-api repo's suite, not here). Keep only the tests that exercise SPA-specific glue (the SPA mount, PWA, asset serving, the React app's AppConfig).
  • Phase 4 — drop duplicated supporting files. audit.py, conf.py, apps.py may overlap with the package. Diff each; for any whose role is fully owned by the package, drop the local copy. For any that retain a genuine SPA-side role, narrow them to that.
  • Phase 5 — refresh docs to position this as the React super-layer. Rewrite README.md to lead with the two-line install + the URL include + cross-links to django-admin-rest-api and django-admin-mcp. Update ARCHITECTURE.md to reflect the dependency; move API-internals docs to the API repo. Add a "What's in this repo vs the API/MCP repos" section to PRODUCT_VISION.md. Update CLAUDE.md so agents know API code now lives in the API repo.
  • Phase 6 — PyPI screenshot pack (closes README + PyPI screenshots: registry / list / detail in light + dark, desktop + mobile #87). Capture registry / list / detail / mobile record-cards / dark variants, place under docs/screenshots/, hot-link from README.md so the PyPI landing page renders them. No e2e tooling — manual capture via the dev server.
  • Phase 7 — release hygiene. Bump version, refresh classifiers, confirm the wheel still ships static/admin_react/ (the pre-built React bundle), and that the PyPI long-description renders the screenshots. Tier 6 — release publish is owner-gated.

Guarantees that must survive the refactor

This repo stays open source, which means it must remain:

  • Secure — no csrf_exempt, no Model.objects.all() in the consumer-facing code (the API is now the package's responsibility, but the SPA-side code must not introduce new permission/queryset surface). Existing pre-commit security hooks (bandit, gitleaks, custom pygrep rules) keep running. SHA-pinned actions in CI. No PAT / .env leaks.
  • Compliant — MIT-licensed, classifiers correct, LICENSE shipped in the wheel.
  • Well-documented — every folder keeps its README.md; the three repos cross-link in README.md + ARCHITECTURE.md; the wire contract still lives in the API repo (not duplicated here).
  • Transparent — every step lands in a public PR with a clear description; this issue is the durable audit trail.
  • Plug-and-play — two INSTALLED_APPS lines + one URL include, no Node required (pre-built assets ship in the wheel), no MIDDLEWARE change, no migrations.
  • Modular / clean — same linters as today (ruff, black, isort, mypy, bandit, eslint, stylelint, dark-mode-coverage guard).
  • Unit-testedpytest + vitest + tsc --noEmit. No Playwright / Cypress / e2e (owner preference).

Cross-refs

— filed under the new architecture directive (2026-05-28). Sole-agent execution from here.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions