{"id":28709189,"url":"https://github.com/devwaseem/django-frontend-kit","last_synced_at":"2026-03-14T03:03:02.452Z","repository":{"id":269264192,"uuid":"882455893","full_name":"devwaseem/django-frontend-kit","owner":"devwaseem","description":"Django Frontend Kit is an opinionated frontend scaffolder for Django that integrates seamlessly with ViteJS, offering a streamlined setup for modern frontend tooling within your Django projects.","archived":false,"fork":false,"pushed_at":"2025-05-09T18:34:45.000Z","size":283,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-06-13T21:17:08.299Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://pypi.org/project/django-frontend-kit/","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/devwaseem.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-11-02T20:25:22.000Z","updated_at":"2025-05-09T18:34:48.000Z","dependencies_parsed_at":null,"dependency_job_id":"c1ed8644-671c-4798-9abb-f52530c2424f","html_url":"https://github.com/devwaseem/django-frontend-kit","commit_stats":null,"previous_names":["devwaseem/django_frontend"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/devwaseem/django-frontend-kit","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/devwaseem%2Fdjango-frontend-kit","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/devwaseem%2Fdjango-frontend-kit/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/devwaseem%2Fdjango-frontend-kit/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/devwaseem%2Fdjango-frontend-kit/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/devwaseem","download_url":"https://codeload.github.com/devwaseem/django-frontend-kit/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/devwaseem%2Fdjango-frontend-kit/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":259875184,"owners_count":22925125,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-06-14T20:00:45.030Z","updated_at":"2026-03-14T03:03:02.432Z","avatar_url":"https://github.com/devwaseem.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Django Frontend Kit\n\n[![PyPI](https://img.shields.io/pypi/v/django-frontend-kit.svg)](https://pypi.org/project/django-frontend-kit/)\n[![Python](https://img.shields.io/pypi/pyversions/django-frontend-kit.svg)](https://pypi.org/project/django-frontend-kit/)\n[![Django](https://img.shields.io/badge/Django-4.2%2B%20%28incl%206.0%29-0C4B33)](https://www.djangoproject.com/)\n[![License](https://img.shields.io/pypi/l/django-frontend-kit.svg)](LICENSE)\n\nAn opinionated way to structure and ship modern frontend assets in Django using Vite. It provides:\n\n- A `manage.py scaffold` command to bootstrap a `frontend/` workspace.\n- Template tags for injecting Vite assets (dev server in `DEBUG`, manifest in production).\n- A lightweight “Page” abstraction that keeps templates, JS/CSS entrypoints, and views aligned.\n\n## Why this exists\n\nMost Django + Vite integrations solve “include the scripts”. Django Frontend Kit also nudges you into a consistent project layout:\n\n- `frontend/layouts/...` for shared shells (base template + base JS/CSS).\n- `frontend/pages/...` for page-level templates and entrypoints.\n- Optional “custom entries” for React/Vue/Alpine widgets without adopting a full SPA.\n\n## Features\n\n- Vite dev server in development (`DEBUG=True`) with automatic `@vite/client` injection.\n- Production asset resolution via Vite `manifest.json` + Django `static()` URLs.\n- Modulepreload + stylesheet tags generated from the manifest (better performance by default).\n- Scaffolding for a working `frontend/` structure and a `vite.config.js`.\n\n## Requirements\n\n- Python `\u003e= 3.9`\n- Django `\u003e= 4.2` (including 6.0)\n- Node.js + npm/pnpm/yarn (for Vite)\n\n## Installation\n\n```bash\npip install django-frontend-kit\n```\n\nAlternative installers:\n\n```bash\nuv add django-frontend-kit\n```\n\n```bash\npoetry add django-frontend-kit\n```\n\n## Quickstart\n\n### 1) Add the app\n\n`settings.py`:\n\n```python\nINSTALLED_APPS = [\n    # ...\n    \"frontend_kit\",\n]\n```\n\n### 2) Scaffold the frontend workspace\n\nFrom the same directory as `manage.py`:\n\n```bash\npython manage.py scaffold\n```\n\nThis creates:\n\n- `frontend/` (templates + entrypoints + Python modules)\n- `vite.config.js` (configured for this kit)\n\n### 3) Install JS dependencies\n\n```bash\nnpm init -y\nnpm install --save-dev vite @iamwaseem99/vite-plugin-django-frontend-kit\n```\n\nAdd scripts to `package.json`:\n\n```json\n{\n  \"scripts\": {\n    \"dev\": \"vite\",\n    \"build\": \"vite build\"\n  }\n}\n```\n\n### 4) Configure Django settings\n\nAt minimum:\n\n```python\nDJFK_FRONTEND_DIR = BASE_DIR / \"frontend\"\nVITE_OUTPUT_DIR = BASE_DIR / \"dist\"\nVITE_DEV_SERVER_URL = \"http://localhost:5173/\"\nDJFK_DEV_ENV = True\n\nTEMPLATES = [\n    {\n        # ...\n        \"DIRS\": [DJFK_FRONTEND_DIR],\n    }\n]\n\nSTATICFILES_DIRS = [VITE_OUTPUT_DIR]\n```\n\nNotes:\n\n- `DJFK_FRONTEND_DIR` must exist on disk (the scaffold command creates it).\n- `VITE_OUTPUT_DIR` must match your Vite `build.outDir` (see `vite.config.js`).\n- `DJFK_DEV_ENV` controls dev behavior. When `True`, assets are served from the Vite dev server; when `False`, assets are resolved from the manifest.\n\n### 5) Run in development\n\nIn two terminals:\n\n```bash\nnpm run dev\n```\n\n```bash\npython manage.py runserver\n```\n\n## How it works\n\n- When `DJFK_DEV_ENV=True`, asset tags point to the Vite dev server and HMR works as usual.\n- When `DJFK_DEV_ENV=False`, Django Frontend Kit reads `VITE_OUTPUT_DIR/.vite/manifest.json` and emits:\n  - `\u003clink rel=\"modulepreload\" ...\u003e` for imported chunks\n  - `\u003clink rel=\"stylesheet\" ...\u003e` for CSS\n  - `\u003cscript type=\"module\" ...\u003e\u003c/script\u003e` for the entry module\n\n### CSP nonce behavior (dev only)\n\nIf `DJFK_DEV_ENV=True` and `request.csp_nonce` is available in the template context, Django Frontend Kit (Django 6+ compatible) adds a `nonce` attribute to:\n\n- `\u003cscript type=\"module\"\u003e`\n- `\u003clink rel=\"stylesheet\"\u003e`\n\nNo nonce is added when `DJFK_DEV_ENV=False` (production/manifest mode), and `modulepreload` tags never receive a nonce.\n\n## Project layout\n\nAfter scaffolding, you’ll have a structure like:\n\n```text\nfrontend/\n  layouts/\n    base/\n      __init__.py\n      index.html\n      entry.head.ts   # optional, loaded in \u003chead\u003e\n      entry.ts        # loaded at end of \u003cbody\u003e\n      main.css\n  pages/\n    home/\n      __init__.py\n      index.html\n      entry.ts\n```\n\nImportant: `frontend/` is a Python package. Keep `__init__.py` files so Django can import your `Page` classes.\n\n## Creating pages and layouts\n\n### Layouts (`frontend/layouts/...`)\n\nLayouts are just `Page` subclasses. By convention they define shared HTML + shared entrypoints.\n\n`frontend/layouts/base/__init__.py`:\n\n```python\nfrom frontend_kit.page import Page\n\nclass BaseLayout(Page): ...\n```\n\n`frontend/layouts/base/index.html` (scaffolded):\n\n```django\n{% load fk_tags %}\n\u003c!doctype html\u003e\n\u003chtml\u003e\n  \u003chead\u003e\n    {% fk_preloads %}\n    {% fk_stylesheets %}\n    {% fk_head_scripts %}\n  \u003c/head\u003e\n  \u003cbody\u003e\n    {% block body %}{% endblock %}\n    {% fk_body_scripts %}\n  \u003c/body\u003e\n\u003c/html\u003e\n```\n\n### Pages (`frontend/pages/...`)\n\n`frontend/pages/home/__init__.py`:\n\n```python\nfrom frontend.layouts.base import BaseLayout\n\nclass HomePage(BaseLayout):\n    def __init__(self, name: str) -\u003e None:\n        super().__init__()\n        self.name = name\n```\n\n`frontend/pages/home/index.html`:\n\n```django\n{% extends \"layouts/base/index.html\" %}\n{% block body %}\n  \u003ch1\u003eHello {{ page.name }}\u003c/h1\u003e\n{% endblock %}\n```\n\nAnd in a view:\n\n```python\nfrom django.http import HttpRequest, HttpResponse\nfrom django.views import View\nfrom frontend.pages.home import HomePage\n\nclass HomeView(View):\n    def get(self, request: HttpRequest) -\u003e HttpResponse:\n        return HomePage(name=\"User\").as_response(request=request)\n```\n\n## Template tags\n\nLoad tags with `{% load fk_tags %}`. All tags expect a `page` object in template context (the `Page` base class provides it).\n\n- `{% fk_preloads %}`: modulepreload links (production only)\n- `{% fk_stylesheets %}`: CSS links\n- `{% fk_head_scripts %}`: `\u003cscript type=\"module\"\u003e` tags intended for `\u003chead\u003e`\n- `{% fk_body_scripts %}`: `\u003cscript type=\"module\"\u003e` tags intended for end of `\u003cbody\u003e`\n- `{% fk_custom_entry \"name\" %}`: loads `name.entry.ts`/`name.entry.js` relative to the current page directory\n\n## Guides\n\n### Tailwind CSS\n\nThe included example project uses **Tailwind v4** via the official Vite plugin.\n\n1. Install dependencies:\n   ```bash\n   npm install --save-dev tailwindcss @tailwindcss/vite\n   ```\n2. Add Tailwind to `vite.config.js` (before `DjangoFrontendKit()`):\n   ```js\n   import tailwindcss from \"@tailwindcss/vite\";\n\n   export default defineConfig({\n     plugins: [tailwindcss(), DjangoFrontendKit()],\n   });\n   ```\n3. Add a Tailwind config (example `tailwind.config.cjs`):\n   ```js\n   export default {\n     content: [\"./frontend/**/*.{html,js,ts,jsx,tsx,vue,py}\"],\n     theme: { extend: {} },\n     plugins: [],\n   };\n   ```\n4. Import Tailwind in your base CSS (scaffolded `frontend/layouts/base/main.css`):\n   ```css\n   @import \"tailwindcss\";\n   ```\n5. Ensure the CSS is imported by a Vite entrypoint that’s loaded on your pages (scaffolded `frontend/layouts/base/entry.head.ts` is a good place):\n   ```ts\n   import \"./main.css\";\n   ```\n\n### React (widgets / islands)\n\n1. Install dependencies:\n   ```bash\n   npm install react react-dom\n   npm install --save-dev @vitejs/plugin-react\n   ```\n2. Enable the React plugin in `vite.config.js`:\n   ```js\n   import react from \"@vitejs/plugin-react\";\n\n   export default defineConfig({\n     plugins: [react(), DjangoFrontendKit()],\n   });\n   ```\n3. Create a custom entry file in a page directory (must end with `.entry.js` or `.entry.ts` so it’s included in the manifest):\n   - `frontend/pages/home/react.entry.js`:\n     ```js\n     import React from \"react\";\n     import { createRoot } from \"react-dom/client\";\n\n     function App() {\n       return \u003cdiv\u003eHello from React\u003c/div\u003e;\n     }\n\n     const el = document.getElementById(\"react-app\");\n     if (el) createRoot(el).render(\u003cApp /\u003e);\n     ```\n4. Add a mount point + include the entry in your template:\n   ```django\n   \u003cdiv id=\"react-app\"\u003e\u003c/div\u003e\n   {% fk_custom_entry \"react\" %}\n   ```\n\n### Vue (widgets / islands)\n\n1. Install dependencies:\n   ```bash\n   npm install vue\n   npm install --save-dev @vitejs/plugin-vue\n   ```\n2. Enable the Vue plugin in `vite.config.js`:\n   ```js\n   import vue from \"@vitejs/plugin-vue\";\n\n   export default defineConfig({\n     plugins: [vue(), DjangoFrontendKit()],\n   });\n   ```\n3. Create a Vue component + an entry file (entry must end with `.entry.js` or `.entry.ts`):\n   - `frontend/pages/home/HelloVue.vue`:\n     ```vue\n     \u003ctemplate\u003e\n       \u003cdiv\u003eHello from Vue\u003c/div\u003e\n     \u003c/template\u003e\n     ```\n   - `frontend/pages/home/vue.entry.ts`:\n     ```ts\n     import { createApp } from \"vue\";\n     import HelloVue from \"./HelloVue.vue\";\n\n     const el = document.getElementById(\"vue-app\");\n     if (el) createApp(HelloVue).mount(el);\n     ```\n4. Add a mount point + include the entry in your template:\n   ```django\n   \u003cdiv id=\"vue-app\"\u003e\u003c/div\u003e\n   {% fk_custom_entry \"vue\" %}\n   ```\n\n### Notes about entrypoints\n\nThe Vite plugin bundled with this project only treats these files as build inputs:\n\n- `entry.js` / `entry.ts`\n- `entry.head.js` / `entry.head.ts`\n- `*.entry.js` / `*.entry.ts`\n\nSo keep “entry” files as `.js`/`.ts` (they can import `.jsx`, `.tsx`, `.vue`, CSS, etc.).\n\n## Production checklist\n\n1. Build assets:\n   ```bash\n   npm run build\n   ```\n2. Ensure `DEBUG=False`.\n3. Ensure Django can serve static assets in production (e.g. WhiteNoise, CDN, or your platform’s static hosting).\n4. Collect static files:\n   ```bash\n   python manage.py collectstatic\n   ```\n\nIf you use WhiteNoise, consider `CompressedManifestStaticFilesStorage` so hashed assets are served efficiently.\n\n## Troubleshooting\n\n- `DJFK_FRONTEND_DIR is not set / does not exist`: set it in `settings.py` and run `python manage.py scaffold`.\n- `VITE_OUTPUT_DIR is not set / does not exist`: set it in `settings.py` and ensure it matches your Vite build output directory.\n- `manifest.json` not found: run `npm run build` and verify `VITE_OUTPUT_DIR/.vite/manifest.json` exists.\n- `...was not included in Vite manifest`: ensure the file is part of Vite build inputs (entrypoints must be reachable/declared).\n\n## Example project\n\nThis repo includes a working example in `example/` showing:\n\n- A base layout (`frontend/layouts/base/`) with `entry.head.ts` and `entry.ts`\n- A page (`frontend/pages/home/`) that renders Django template HTML and mounts optional JS widgets\n\n## Versioning \u0026 stability\n\nThis project is currently in **Beta**. Expect occasional breaking changes until `1.0.0`.\n\n## Contributing\n\n- Run linting: `ruff check .`\n- Run type checking: `mypy .`\n\nPRs are welcome. If you’re proposing a behavior change, include a short rationale and an example project diff.\n\n## License\n\nMIT — see [LICENSE](LICENSE).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdevwaseem%2Fdjango-frontend-kit","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdevwaseem%2Fdjango-frontend-kit","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdevwaseem%2Fdjango-frontend-kit/lists"}