-
-
Notifications
You must be signed in to change notification settings - Fork 27
feat(frontend): add Vite bundling option for HTMX+Tailwind #32
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 4 commits
ca32845
afe8e4e
32d5aeb
42803a0
43ef2f5
36f505c
4c71471
ac91dba
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||
|---|---|---|---|---|
|
|
@@ -31,6 +31,9 @@ db.sqlite3-journal | |||
| /media | ||||
| /staticfiles | ||||
| /static_root | ||||
| {% if frontend_bundling == 'vite' -%} | ||||
|
||||
| /static/dist | ||||
| {% endif -%} | ||||
|
|
||||
| # Environment | ||||
| .env | ||||
|
|
@@ -42,6 +45,12 @@ db.sqlite3-journal | |||
| .venv/ | ||||
| poetry.lock | ||||
| {% endif -%} | ||||
| {% if frontend_bundling == 'vite' -%} | ||||
|
||||
|
|
||||
| # Node | ||||
| node_modules/ | ||||
| frontend/node_modules/ | ||||
|
||||
| frontend/node_modules/ |
| Original file line number | Diff line number | Diff line change | ||||||
|---|---|---|---|---|---|---|---|---|
| @@ -1,4 +1,23 @@ | ||||||||
| # syntax=docker/dockerfile:1 | ||||||||
| {% if frontend_bundling == 'vite' -%} | ||||||||
|
||||||||
| # Build frontend assets | ||||||||
| FROM node:20-slim AS frontend-builder | ||||||||
|
|
||||||||
| WORKDIR /app/frontend | ||||||||
|
|
||||||||
| # Copy frontend files | ||||||||
| COPY frontend/package*.json ./ | ||||||||
|
|
||||||||
| # Install dependencies | ||||||||
| RUN npm ci | ||||||||
|
|
||||||||
| # Copy rest of frontend | ||||||||
| COPY frontend/ ./ | ||||||||
|
|
||||||||
| # Build assets | ||||||||
|
||||||||
| # Build assets | |
| # Build assets | |
| RUN mkdir -p /app/static |
Outdated
Copilot
AI
Nov 29, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same issue - frontend_bundling is undefined when frontend != 'htmx-tailwind'. Use {% if frontend == 'htmx-tailwind' and frontend_bundling == 'vite' -%} or {% if frontend_bundling is defined and frontend_bundling == 'vite' -%}.
Outdated
Copilot
AI
Nov 29, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same issue - frontend_bundling is undefined when frontend != 'htmx-tailwind'. Use {% if frontend == 'htmx-tailwind' and frontend_bundling == 'vite' -%} or {% if frontend_bundling is defined and frontend_bundling == 'vite' -%}.
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -44,6 +44,9 @@ DJANGO_APPS = [ | |||||
| ] | ||||||
|
|
||||||
| THIRD_PARTY_APPS = [ | ||||||
| {% if frontend_bundling == 'vite' -%} | ||||||
|
||||||
| {% if frontend_bundling == 'vite' -%} | |
| {% if frontend_bundling is defined and frontend_bundling == 'vite' -%} |
Outdated
Copilot
AI
Nov 29, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same issue - frontend_bundling is undefined when frontend != 'htmx-tailwind'. Use {% if frontend == 'htmx-tailwind' and frontend_bundling == 'vite' -%} or {% if frontend_bundling is defined and frontend_bundling == 'vite' -%}.
| {% if frontend_bundling == 'vite' -%} | |
| {% if frontend_bundling is defined and frontend_bundling == 'vite' -%} |
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -26,6 +26,9 @@ services: | |||||
| - EMAIL_PORT=1025 | ||||||
| {% if dependency_manager == 'uv' %} | ||||||
| - UV_NO_CACHE=1 | ||||||
| {% endif %} | ||||||
| {% if frontend_bundling == 'vite' %} | ||||||
|
||||||
| {% if frontend_bundling == 'vite' %} | |
| {% if frontend_bundling is defined and frontend_bundling == 'vite' %} |
Outdated
Copilot
AI
Nov 29, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same issue - frontend_bundling is undefined when frontend != 'htmx-tailwind'. Use {% if frontend == 'htmx-tailwind' and frontend_bundling == 'vite' %} or {% if frontend_bundling is defined and frontend_bundling == 'vite' %}.
| {% if frontend_bundling == 'vite' %} | |
| {% if frontend_bundling is defined and frontend_bundling == 'vite' %} |
Outdated
Copilot
AI
Nov 30, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider using npm ci instead of npm install for more deterministic and faster installs in the development container. npm ci is designed for automated environments and provides reproducible builds.
Suggested change:
command: sh -c "npm ci && npm run dev"This aligns with the production Dockerfile which uses npm ci (line 12).
| command: sh -c "npm install && npm run dev" | |
| command: sh -c "npm ci && npm run dev" |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| { | ||
| "name": "{{ project_slug }}-frontend", | ||
| "version": "0.1.0", | ||
| "private": true, | ||
| "type": "module", | ||
| "scripts": { | ||
| "dev": "vite", | ||
| "build": "vite build", | ||
| "preview": "vite preview" | ||
| }, | ||
| "dependencies": { | ||
| "htmx.org": "^1.9.10", | ||
| "alpinejs": "^3.13.3" | ||
| }, | ||
| "devDependencies": { | ||
| "autoprefixer": "^10.4.16", | ||
| "postcss": "^8.4.32", | ||
| "tailwindcss": "^3.4.0", | ||
| "vite": "^5.0.10" | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| export default { | ||
| plugins: { | ||
| tailwindcss: {}, | ||
| autoprefixer: {}, | ||
| }, | ||
| }; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| // Import styles | ||
| import "./styles.css"; | ||
|
|
||
| // Import HTMX | ||
| import htmx from "htmx.org"; | ||
| window.htmx = htmx; | ||
|
|
||
| // Import Alpine.js | ||
| import Alpine from "alpinejs"; | ||
| window.Alpine = Alpine; | ||
| Alpine.start(); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| @tailwind base; | ||
| @tailwind components; | ||
| @tailwind utilities; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| /** @type {import('tailwindcss').Config} */ | ||
| export default { | ||
| content: [ | ||
| "../templates/**/*.html", | ||
| "./src/**/*.js", | ||
| ], | ||
| theme: { | ||
| extend: {}, | ||
| }, | ||
| plugins: [], | ||
| }; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,20 @@ | ||
| import { defineConfig } from "vite"; | ||
| import { resolve } from "path"; | ||
|
|
||
| export default defineConfig({ | ||
| base: "/static/", | ||
| build: { | ||
| manifest: "manifest.json", | ||
| outDir: resolve(__dirname, "../static/dist"), | ||
| rollupOptions: { | ||
| input: { | ||
| main: resolve(__dirname, "src/main.js"), | ||
| }, | ||
| }, | ||
| }, | ||
| server: { | ||
| host: "0.0.0.0", | ||
| port: 5173, | ||
| origin: "http://localhost:5173", | ||
| }, | ||
| }); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,10 +1,15 @@ | ||
| <!DOCTYPE html> | ||
| {% if frontend_bundling == 'vite' %}{% raw %}{% load django_vite %}{% endraw %} | ||
| {% endif %}<!DOCTYPE html> | ||
| <html lang="en"> | ||
| <head> | ||
| <meta charset="UTF-8"> | ||
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | ||
| <title>{% raw %}{% block title %}{% endraw %}{{ project_name }}{% raw %}{% endblock %}{% endraw %}</title> | ||
|
|
||
| {% if frontend_bundling == 'vite' %} | ||
| {% raw %}{% vite_hmr_client %}{% endraw %} | ||
| {% raw %}{% vite_asset 'src/main.js' %}{% endraw %} | ||
| {% else %} | ||
| <!-- Tailwind CSS --> | ||
| <script src="https://cdn.tailwindcss.com"></script> | ||
|
|
||
|
|
@@ -13,6 +18,7 @@ | |
|
|
||
| <!-- Alpine.js --> | ||
| <script defer src="https://cdn.jsdelivr.net/npm/[email protected]/dist/cdn.min.js"></script> | ||
| {% endif %} | ||
|
|
||
| {% raw %}{% block extra_head %}{% endblock %}{% endraw %} | ||
| </head> | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -204,16 +204,36 @@ def test_no_api_excludes_frameworks(generate): | |
|
|
||
|
|
||
| def test_htmx_frontend_templates_generated(generate): | ||
| """Test that HTMX frontend generates templates.""" | ||
| """Test that HTMX frontend generates templates with Vite (default).""" | ||
| project = generate(frontend="htmx-tailwind") | ||
|
|
||
| templates_dir = project / "templates" | ||
| assert (templates_dir / "base.html").exists() | ||
|
|
||
| base_html = (templates_dir / "base.html").read_text() | ||
| assert "{% block" in base_html | ||
| # Vite is the default, so check for vite tags | ||
| assert "django_vite" in base_html | ||
| assert "vite_asset" in base_html | ||
|
|
||
| # Vite frontend files should exist | ||
| frontend_dir = project / "frontend" | ||
| assert (frontend_dir / "package.json").exists() | ||
| assert (frontend_dir / "vite.config.js").exists() | ||
| assert (frontend_dir / "tailwind.config.js").exists() | ||
|
|
||
|
Comment on lines
206
to
+224
|
||
|
|
||
| def test_htmx_frontend_cdn_mode(generate): | ||
| """Test that HTMX frontend with CDN mode uses CDN links.""" | ||
| project = generate(frontend="htmx-tailwind", frontend_bundling="cdn") | ||
|
||
|
|
||
| templates_dir = project / "templates" | ||
| base_html = (templates_dir / "base.html").read_text() | ||
| assert "{% block" in base_html | ||
| assert "tailwindcss" in base_html | ||
| assert "htmx" in base_html | ||
| # Should not have vite tags | ||
| assert "django_vite" not in base_html | ||
|
Comment on lines
+232
to
+242
|
||
|
|
||
|
|
||
| def test_nextjs_frontend_generated(generate): | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[nitpick] The documentation mentions using
docker-compose upbut doesn't provide guidance on how to build frontend assets for local development outside of Docker, or how to run the Vite dev server independently. Consider adding sections for: