Framework Migration Assistant
ArabelaTso/Skills-4-SE
Automatically migrate Python web applications between frameworks (Flask → FastAPI, Django → FastAPI).
Implement a Django feature following the opinionated architecture — prefixed ULID IDs, repository pattern, Pydantic DTOs, svcs service locator, project-scoped django-ninja API, Celery reliable…
$ npx skills add dvf/opinionated-django --skill dj-architecture -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install dvf/opinionated-django dj-architecture --agent claude-codeProject scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).
$ git clone --depth 1 https://github.com/dvf/opinionated-django.git skills-src && mkdir -p .claude/skills && cp -r skills-src/skills/dj-architecture .claude/skills/dj-architecture && rm -rf skills-srcUse ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.
Claude Code skills documentation · loads skills from .claude/skills/
Install the "dj-architecture" agent skill from https://github.com/dvf/opinionated-django/tree/master/skills/dj-architecture into .claude/skills/dj-architecture/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "dj-architecture", then confirm the skill loads.Claude Code copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$skill-installer install https://github.com/dvf/opinionated-django/tree/master/skills/dj-architectureType this inside Codex. $skill-installer <name> installs a curated skill from openai/skills. The installer writes to $CODEX_HOME/skills (default ~/.codex/skills). Restart Codex if the skill does not show up.
$ npx skills add dvf/opinionated-django --skill dj-architecture -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install dvf/opinionated-django dj-architecture --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/dvf/opinionated-django.git skills-src && mkdir -p .agents/skills && cp -r skills-src/skills/dj-architecture .agents/skills/dj-architecture && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "dj-architecture" agent skill from https://github.com/dvf/opinionated-django/tree/master/skills/dj-architecture into .agents/skills/dj-architecture/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "dj-architecture", then confirm the skill loads.Codex copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add dvf/opinionated-django --skill dj-architecture -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install dvf/opinionated-django dj-architecture --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/dvf/opinionated-django.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/skills/dj-architecture .cursor/skills/dj-architecture && rm -rf skills-srcUse ~/.cursor/skills/ instead of .cursor/skills for a personal install.
Cursor skills documentation · loads skills from .cursor/skills/, .agents/skills/, .claude/skills/, .codex/skills/
Install the "dj-architecture" agent skill from https://github.com/dvf/opinionated-django/tree/master/skills/dj-architecture into .cursor/skills/dj-architecture/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "dj-architecture", then confirm the skill loads.Cursor copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gemini skills install https://github.com/dvf/opinionated-django.git --path skills/dj-architecture--scope user (default) or --scope workspace; --path is the subfolder of the repo that holds the skill; --consent skips the security confirmation prompt.
$ npx skills add dvf/opinionated-django --skill dj-architecture -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install dvf/opinionated-django dj-architecture --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/dvf/opinionated-django.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/skills/dj-architecture .gemini/skills/dj-architecture && rm -rf skills-srcUse ~/.gemini/skills/ instead of .gemini/skills for a personal install, then run /skills reload.
Gemini CLI skills documentation · loads skills from .gemini/skills/, .agents/skills/
Install the "dj-architecture" agent skill from https://github.com/dvf/opinionated-django/tree/master/skills/dj-architecture into .gemini/skills/dj-architecture/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "dj-architecture", then confirm the skill loads.Gemini CLI copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gh skill install dvf/opinionated-django dj-architectureInstalls for Copilot at project scope by default; add --scope user for a personal install. Preview a skill first with gh skill preview. Needs GitHub CLI 2.90.0 or later (public preview).
$ npx skills add dvf/opinionated-django --skill dj-architecture -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/dvf/opinionated-django.git skills-src && mkdir -p .github/skills && cp -r skills-src/skills/dj-architecture .github/skills/dj-architecture && rm -rf skills-srcUse ~/.copilot/skills/ instead of .github/skills for a personal install. Commit .github/skills so cloud agent and code review can use it.
GitHub Copilot skills documentation · loads skills from .github/skills/, .claude/skills/, .agents/skills/
Install the "dj-architecture" agent skill from https://github.com/dvf/opinionated-django/tree/master/skills/dj-architecture into .github/skills/dj-architecture/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "dj-architecture", then confirm the skill loads.GitHub Copilot copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add dvf/opinionated-django --skill dj-architecture -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install dvf/opinionated-django dj-architecture --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/dvf/opinionated-django.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/skills/dj-architecture .opencode/skills/dj-architecture && rm -rf skills-srcUse ~/.config/opencode/skills/ instead of .opencode/skills for a personal install.
OpenCode skills documentation · loads skills from .opencode/skills/, .claude/skills/, .agents/skills/
Install the "dj-architecture" agent skill from https://github.com/dvf/opinionated-django/tree/master/skills/dj-architecture into .opencode/skills/dj-architecture/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "dj-architecture", then confirm the skill loads.OpenCode copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
dj-architectureImplement a Django feature following the opinionated architecture — prefixed ULID IDs, repository pattern, Pydantic DTOs, svcs service locator, project-scoped django-ninja API, Celery reliable…
Dj Architecture is an agent skill from dvf/opinionated-django. Implement a Django feature following the opinionated architecture — prefixed ULID IDs, repository pattern, Pydantic DTOs, svcs service locator, project-scoped django-ninja API, Celery reliable signals, and layered tests. Use when the user asks to add a new entity, endpoint, app, or business logic in a Django project that follows these conventions.
Its SKILL.md is about 4k tokens, which your agent loads only when the skill is triggered. It is a single SKILL.md file with no bundled scripts.
It sits in Backend & APIs, covering Backend development, Design patterns and Background jobs. It works with Django and Pydantic. The repository describes itself as: An opinionated Django project with Repository pattern, Pydantic DTOs, svcs DI, and Stripe-style ULID IDs. The licence is MIT.
Read from SKILL.md and the folder at commit f17fc2d. It shows what the files ask for, not the result of running them.
Pre-approves these tools, so the agent can use them without asking each time:
ReadWriteEditBashGrepGlobFrom allowed-tools in the SKILL.md frontmatter.
Shell commands in SKILL.md call:
uvruffFrom the folder's file list and the shell code blocks in SKILL.md.
No URLs in SKILL.md. Its commands use uv, which can reach the network depending on how they are called.
From URLs in SKILL.md, links to its own repository left out.
Names no API keys, tokens, secrets or passwords.
From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
Dj Architecture loads about 4k tokens when it runs. Until then it costs about 91 tokens; SKILL.md has 1,199 words of instructions outside code blocks.
Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.
The automated check noted patterns worth knowing about, such as sudo or a known installer.
allowed-tools: Read, Write, Edit, Bash, Grep, GlobAutomated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.
The full file from dvf/opinionated-django at commit f17fc2d, republished under its MIT licence (© dvf). 1,199 words, ~3,961 tokens.
.claude/skills/dj-architecture/SKILL.md (or your agent's skills folder).You are implementing a feature in an opinionated, fully type-safe Django project managed with uv. Every convention below is mandatory. Do not deviate.
Why this architecture exists: Django's ORM is powerful but hard to type — querysets, model instances, related managers, and F()/Q() expressions don't play well with static type checkers. This project solves that by pushing all ORM usage into repositories that return Pydantic DTOs. Services receive repos via constructor injection and contain pure business logic with zero ORM imports. Views are thin dispatchers. The result: everything from the repository boundary outward is fully typed, IDE-friendly, and testable in isolation.
Tooling: uv is the package manager. All commands use uv run. Never use pip, poetry, or raw python — always uv run python, uv run pytest, etc. To add a dependency: uv add <package>.
Gather current project state by reading:
src/project/ids.py — existing ID prefixes (must be unique)src/project/services.py — registered repos/servicessrc/project/settings.py — INSTALLED_APPSsrc/project/api/__init__.py — NinjaAPI(), mounted resource routers, exception handlerssrc/project/api/<resource>/ — existing per-resource route packagessrc/project/types.py — AuthedRequest and other shared request typesThen state your implementation plan: models, DTOs, repos, services, routes, tests, and ID prefixes.
Follow this exact order. Do not skip layers. Each layer has rules that are non-negotiable.
Add to src/project/ids.py:
generate_xxx_id = _make_generator("xxx") # 3-4 char prefixPrefixes must be unique across the project and short enough to be readable in logs.
File: src/<app>/models/<entity>.py
Follow the models skill for full conventions. The key rules:
class Meta is always first inside the model body — with verbose_name, verbose_name_plural, and indexesCharField(max_length=64) primary key with prefixed ULID default — NEVER UUIDs, NEVER auto-increment__prefix__: ClassVar[str] on every modelMeta.indexes — never db_index=True on fields. Optimize for queries the repository actually runs.save() overrides, no signals, no properties that compute__str__ is the only method allowedfrom typing import ClassVar
from django.db import models
from project.ids import generate_xxx_id
class MyEntity(models.Model):
class Meta:
verbose_name = "my entity"
verbose_name_plural = "my entities"
indexes = [
models.Index(fields=["created_at"], name="idx_%(class)s_created"),
]
__prefix__: ClassVar[str] = "xxx"
id = models.CharField(max_length=64, primary_key=True, default=generate_xxx_id, editable=False)
# fields...
def __str__(self):
return self.nameIf this is a new app, add it to INSTALLED_APPS in src/project/settings.py using the dotted path to its AppConfig (e.g., "myapp.apps.MyAppConfig").
Then run:
uv run python src/manage.py makemigrations && uv run python src/manage.py migrateFile: src/<app>/dtos/<entity>.py
RULES:
str — never UUIDmodel_config = ConfigDict(from_attributes=True) — alwaysRelatedManager fields (reverse FKs, M2M), add the coercion validator:@field_validator("children", mode="before")
@classmethod
def coerce_related_manager(cls, v):
if hasattr(v, "all"):
return list(v.all())
return vFile: src/<app>/repositories/<entity>.py
RULES:
list[DTO]MyEntityDTO.model_validate(orm_obj)prefetch_related() when the DTO has nested relations@transaction.atomic on any method with multiple writesstrFile: src/<app>/services/<entity>.py
RULES:
__init__ — NEVER instantiates them, NEVER imports models.objects, no F(), no Q(), no model importsAdd to src/project/services.py:
from myapp.repositories.my_entity import MyEntityRepository
from myapp.services.my_entity import MyEntityService
# Register the repository
registry.register_factory(MyEntityRepository, MyEntityRepository)
# Register the service with a factory that pulls its repo dependencies
def _my_entity_service_factory(container: svcs.Container) -> MyEntityService:
repo = container.get(MyEntityRepository)
return MyEntityService(repo)
registry.register_factory(MyEntityService, _my_entity_service_factory)Both repos and services get registered. Service factories wire up repo dependencies via the container. The get() helper at the bottom of the file makes them available anywhere.
Routes live in a per-resource package under src/project/api/ — NOT in app directories. Each resource is its own subpackage:
src/project/
└── api/
├── __init__.py # NinjaAPI(), exception handlers, mounts routers
├── my_entities/
│ ├── __init__.py # re-exports `router` from routes
│ ├── routes.py # handlers
│ └── schemas.py # ninja.Schema input models
└── other_resource/
├── __init__.py
├── routes.py
└── schemas.pyRULES:
ninja.Schema classes defined in schemas.py next to the routes__init__.py re-exports the router from routes (e.g. from .routes import router)src/project/api/__init__.py creates the NinjaAPI() instance, registers exception handlers, and mounts each resource router with api.add_router("/my-entities", my_entities_router)from project.services import get, then get(MyEntityService) to obtain a wired servicerequest: AuthedRequest — never untyped. AuthedRequest lives in src/project/types.py and narrows request.user to an authenticated Django Userstrsrc/project/api/my_entities/routes.py:
from typing import List
from ninja import Router, Status
from myapp.dtos.my_entity import MyEntityDTO
from myapp.services.my_entity import MyEntityService
from project.services import get
from project.types import AuthedRequest
from .schemas import CreateMyEntityIn
router = Router()
@router.get("/", response=List[MyEntityDTO])
def list_entities(request: AuthedRequest):
return get(MyEntityService).list_entities()
@router.post("/", response={201: MyEntityDTO})
def create_entity(request: AuthedRequest, payload: CreateMyEntityIn):
return Status(201, get(MyEntityService).create_entity(name=payload.name))
@router.get("/{entity_id}/", response=MyEntityDTO)
def get_entity(request: AuthedRequest, entity_id: str):
return get(MyEntityService).get_entity(entity_id)Services raise plain Python exceptions — ValueError for bad input, LookupError for missing records, PermissionError for forbidden access. They do NOT know about HTTP. The mapping happens once, centrally, in src/project/api/__init__.py:
ValueError → 400 {"detail": str(exc)}LookupError → 404 {"detail": str(exc)}PermissionError → 403 {"detail": str(exc)}@api.exception_handler(ValueError)
def on_value_error(request, exc: ValueError):
return api.create_response(request, {"detail": str(exc)}, status=400)Route handlers MUST NOT wrap service calls in try/except — errors bubble up and the central handler turns them into responses.
File: src/<app>/admin.py
Follow the models skill for full admin conventions. The key rules:
@admin.registerlist_display — id first, then 3-5 most useful columnslist_per_page = 25 — keeps the admin fast on large tablessearch_fields — always include id, plus name/title fieldsreadonly_fields — always include id (ULID PKs are never edited)ordering — explicit, usually -created_at or the primary time fieldlist_select_related — specify FKs shown in list_display to avoid N+1sraw_id_fields or autocomplete_fields for FKs to large tablesTabularInline for child models — extra = 0, show_change_link = TrueWrite three test layers in tests/<app>/. No test file may be skipped.
test_repo.py — Real database, validate ORM ↔ DTO conversion@pytest.mark.django_db
def test_create_and_get():
repo = MyEntityRepository()
dto = repo.create(name="Test", ...)
assert isinstance(dto, MyEntityDTO)
assert dto.id.startswith("xxx_")
fetched = repo.get_by_id(dto.id)
assert fetched == dto
@pytest.mark.django_db
def test_list_all():
repo = MyEntityRepository()
repo.create(name="A", ...)
repo.create(name="B", ...)
assert len(repo.list_all()) == 2test_service.py — Mock the repos, validate business logicServices are tested WITHOUT a database. Mock the repository. This is the most important test layer — it proves your business logic is correct independently of Django.
from unittest.mock import MagicMock
def test_create_delegates_to_repo():
repo = MagicMock()
expected = MyEntityDTO(id="xxx_fake", name="Test", ...)
repo.create.return_value = expected
service = MyEntityService(repo)
result = service.create_entity(name="Test", ...)
assert result == expected
repo.create.assert_called_once_with(name="Test", ...)
def test_business_rule_rejects_bad_input():
repo = MagicMock()
# configure mock to trigger the rule
service = MyEntityService(repo)
with pytest.raises(ValueError, match="..."):
service.do_something_invalid(...)test_api.py — Integration through HTTP@pytest.mark.django_db
def test_create(client):
resp = client.post("/api/my-entities/", data={...}, content_type="application/json")
assert resp.status_code == 201
assert resp.json()["id"].startswith("xxx_")
@pytest.mark.django_db
def test_list_empty(client):
resp = client.get("/api/my-entities/")
assert resp.status_code == 200
assert resp.json() == []
@pytest.mark.django_db
def test_get_by_id(client):
create_resp = client.post("/api/my-entities/", data={...}, content_type="application/json")
eid = create_resp.json()["id"]
resp = client.get(f"/api/my-entities/{eid}/")
assert resp.status_code == 200
assert resp.json()["id"] == eidWhen a business operation needs to trigger async side-effects (notifications, cache invalidation, analytics), use reliable signals — NOT standard Django signals.
File: src/<app>/signals.py
from project.signals import ReliableSignal
my_event = ReliableSignal()Call send_reliable() inside a transaction.atomic() block in the service layer. Arguments MUST be JSON-serializable — pass entity IDs, never model instances:
# In the service method
def create_entity(self, name: str) -> MyEntityDTO:
with transaction.atomic():
entity = self.repo.create(name=name)
my_event.send_reliable(sender=None, entity_id=entity.id)
return entityFile: src/<app>/receivers.py
Register with @receiver. Load receivers in apps.py → ready().
CRITICAL: Every receiver MUST be idempotent. The system guarantees at-least-once delivery, not exactly-once. A receiver may run more than once for the same event. Design accordingly:
from django.dispatch import receiver
from .signals import my_event
@receiver(my_event)
def on_my_event(obj_id: str, **kwargs):
# Idempotent: guard against duplicate execution
if already_processed(obj_id):
return
do_work(obj_id)class MyAppConfig(AppConfig):
def ready(self):
from . import receivers # noqa: F401Test receivers in isolation. Mock external dependencies. Verify idempotency by calling the receiver twice with the same arguments:
def test_receiver_is_idempotent():
on_my_event(obj_id="xxx_fake")
on_my_event(obj_id="xxx_fake") # second call must be safe
# assert side-effect happened exactly oncesend() for post-commit side-effects — use send_reliable()Run all four checks. ALL must pass before you report done.
uv run ruff check src
uv run ruff format --check src
uv run pyrefly check src
uv run pytestIf anything fails, fix it and re-run.
Before reporting done, confirm every item:
src/project/ids.py with unique 3-4 char prefixMeta first (verbose names + indexes), __prefix__ ClassVar, CharField PK with ULID default, zero logicstr IDs, from_attributes=True, RelatedManager coercion if neededmodel_validate(), @transaction.atomic for multi-writes__init__, zero ORM, business logic onlysrc/project/services.pysrc/project/api/<resource>/routes.py, schemas in schemas.py, mounted in src/project/api/__init__.py using from project.services import getrequest: AuthedRequest annotation on every handlersrc/project/api/__init__.py (ValueError→400, LookupError→404, PermissionError→403)list_display, list_per_page = 25, search_fields, readonly_fields, ordering, raw_id_fields/autocomplete_fields for large FKs, inlines with extra = 0)INSTALLED_APPS (if new) using dotted AppConfig pathtest_repo.py: real DB, asserts ID prefixtest_service.py: mocked repos, tests business logictest_api.py: HTTP integration, asserts status codes + response shapesrc/<app>/signals.py if async side-effects neededsrc/<app>/receivers.py — idempotent, loaded in ready()ruff check, ruff format --check, pyrefly check, pytest all pass© dvf, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file
Just SKILL.md in skills/dj-architecture of dvf/opinionated-django.
Open the folder on GitHubat commit f17fc2d
Dj Architecture next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.
| Skill | Stars | Used in | Tokens | Auto-check | Licence | Repo updated |
|---|---|---|---|---|---|---|
| Dj Architecture this skilldvf/opinionated-django | 109 | — | ~4k | Automated safety check: Notes | MIT | |
| Framework Migration AssistantArabelaTso/Skills-4-SE | 253 | — | ~1.9k | Automated safety check: Pass | Apache-2.0 | |
| Django Celery Expertvintasoftware/django-ai-plugins | 153 | — | ~1.2k | Automated safety check: Pass | None | |
| Django Modelsgetsentry/sentry | 46k | — | ~2.6k | Automated safety check: Pass | Custom licence | |
| Sentry Python SDKgetsentry/sentry-for-ai | 268 | — | ~4.1k | Automated safety check: Pass | Apache-2.0 | |
| Django Prodavila7/claude-code-templates | 32k | 8 repos | ~1.7k | Automated safety check: Pass | MIT |
ArabelaTso/Skills-4-SE
Automatically migrate Python web applications between frameworks (Flask → FastAPI, Django → FastAPI).
vintasoftware/django-ai-plugins
Expert Django Celery guidance for asynchronous task processing.
getsentry/sentry
Design Django ORM models for Sentry following architectural conventions for silos, replication, relocation, and foreign keys.
getsentry/sentry-for-ai
Full Sentry SDK setup for Python. An agent skill from getsentry/sentry-for-ai.
davila7/claude-code-templates
Master Django 5.x with async views, DRF, Celery, and Django Channels.
affaan-m/ECC
Django + Celery async task patterns — configuration, task design, beat scheduling, retries, canvas workflows, monitoring, and testing.
dvf/opinionated-django
Structure Django models with proper Meta classes, verbose names, and optimized indexes.
dvf/opinionated-django
Use Stripe-style prefixed ULID primary keys (e.g. An agent skill from dvf/opinionated-django.
dvf/opinionated-django
Set up and write pytest tests for an op-django project — pytest-django configuration, two-sided Celery testing (patched dispatch sites + plain-function task bodies, never eager mode), freezegun for…
dvf/opinionated-django
Set up a Django project into the op-django layout so the architecture, signals, and settings skills have a foundation to build on.
dvf/opinionated-django
Structure Django business logic as plain services that receive their dependencies via constructor injection, and wire them through an svcs registry so they can be resolved anywhere — views, Celery…
dvf/opinionated-django
Add reliable signals (async side-effects via Celery) to a Django feature.
Categories
Implement a Django feature following the opinionated architecture — prefixed ULID IDs, repository pattern, Pydantic DTOs, svcs service locator, project-scoped django-ninja API, Celery reliable…. Dj Architecture is an agent skill from dvf/opinionated-django. Implement a Django feature following the opinionated architecture — prefixed ULID IDs, repository pattern, Pydantic DTOs, svcs service locator, project-scoped django-ninja API, Celery reliable signals, and layered tests.
Dj Architecture fits situations like: the user asks to add a new entity; business logic in a Django project that follows these conventions.
Run `npx skills add dvf/opinionated-django --skill dj-architecture -a claude-code`. Or copy the skill folder (skills/dj-architecture in dvf/opinionated-django) into .claude/skills/dj-architecture in your project. Claude Code loads it when a task matches its description.
Run `npx skills add dvf/opinionated-django --skill dj-architecture -a codex`. Or copy the skill folder (skills/dj-architecture in dvf/opinionated-django) into .agents/skills/dj-architecture in your project. Codex loads it when a task matches its description.
Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add dvf/opinionated-django --skill dj-architecture -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/dj-architecture, .gemini/skills/dj-architecture, .github/skills/dj-architecture and .opencode/skills/dj-architecture in your project.
Going by SKILL.md and its folder, Dj Architecture needs the command-line tools its instructions call (uv and ruff). Our summary lists: Python 3. Its frontmatter pre-approves these tools: Read, Write, Edit, Bash, Grep, Glob.
SKILL.md contains no URLs. Its commands use uv, which can reach the network depending on how they are called. This is read from the text; nothing was executed.
Our automated static check of SKILL.md found notes only (pre-approves every shell command (allowed-tools: bash)), nothing it rates as a warning. It is not a guarantee. Review the folder before installing.
Dj Architecture is published under the MIT licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.
About 4k tokens (SKILL.md is roughly 16k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.
Skills that share tags, products or a category with Dj Architecture: Framework Migration Assistant (ArabelaTso/Skills-4-SE, 253 stars), Django Celery Expert (vintasoftware/django-ai-plugins, 153 stars), Django Models (getsentry/sentry, 46k stars) and Sentry Python SDK (getsentry/sentry-for-ai, 268 stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
dvf (a GitHub user) maintains it in dvf/opinionated-django, which has 109 GitHub stars. The repository holds 9 skills in this directory. The repository was last updated on August 14, 2026.
Source: dvf/opinionated-django on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.