Compare commits
5
Commits
v0.1.1
...
695742019d
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
695742019d | ||
|
|
a4994ce234 | ||
|
|
1dafc5e2a7 | ||
|
|
e0d55e12e9 | ||
|
|
ecd38ee28b |
No files matched your search
@@ -1,8 +1,8 @@
|
|||||||
# frontend-svelte
|
# frontend-svelte
|
||||||
|
|
||||||
Copier template for a `frontend/` part: SvelteKit on Bun with Tailwind v4, ultracite (biome) and optional shadcn-svelte, served by a Bun server with SSR, as a static SPA behind `serve.ts`, or as a static SPA that the backend api serves from `frontend/build`.
|
Copier template for a SvelteKit frontend, either as a `frontend/` part next to other parts or alone at the root of the project (`layout`): SvelteKit on Bun with Tailwind v4, ultracite (biome) and optional shadcn-svelte, served by a Bun server with SSR, as a static SPA behind `serve.ts`, or as a static SPA that the backend api serves from `frontend/build`.
|
||||||
|
|
||||||
Ships `frontend/docker-compose.yml` with root-relative paths, `docker-compose.local.yml` (published ports) and `docker-compose.prod.yml` (the `caddy` network), a `Makefile` with `fmt`, `check`, `build` and `dev`, `.env.example`, `CLAUDE.md`, `.claude/rules` for Svelte and ultracite, the Svelte MCP server and `.impeccable/` scaffolding. Meant to be applied on top of the `infra` template.
|
Ships `frontend/docker-compose.yml` with root-relative paths and profiles per service, `docker-compose.override.yml.example` (the `caddy` network aliases, copied by `make env`), a `Makefile` with `fmt`, `check`, `build` and `dev`, `.env.example`, `CLAUDE.md`, `.claude/rules` for Svelte and ultracite, the Svelte MCP server and `.impeccable/` scaffolding. Applied on top of the `infra` template, `layout: parts` or `layout: single` respectively.
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
copier copy --trust -d project_name="My Thing" -d serve=bun <this-repo> <dest>
|
copier copy --trust -d project_name="My Thing" -d serve=bun <this-repo> <dest>
|
||||||
|
|||||||
+19
-1
@@ -13,6 +13,14 @@ project_slug:
|
|||||||
help: Package name, snake_case
|
help: Package name, snake_case
|
||||||
default: "{{ project_name | lower | replace(' ', '_') | replace('-', '_') | replace('.', '_') }}"
|
default: "{{ project_name | lower | replace(' ', '_') | replace('-', '_') | replace('.', '_') }}"
|
||||||
|
|
||||||
|
layout:
|
||||||
|
type: str
|
||||||
|
help: Where the frontend lives
|
||||||
|
choices:
|
||||||
|
In frontend/ next to other parts: part
|
||||||
|
At the root of the project: root
|
||||||
|
default: part
|
||||||
|
|
||||||
serve:
|
serve:
|
||||||
type: str
|
type: str
|
||||||
help: How the frontend is served
|
help: How the frontend is served
|
||||||
@@ -44,5 +52,15 @@ frontend_adapter:
|
|||||||
when: false
|
when: false
|
||||||
default: "{{ 'bun' if serve == 'bun' else 'static' }}"
|
default: "{{ 'bun' if serve == 'bun' else 'static' }}"
|
||||||
|
|
||||||
|
part_dir:
|
||||||
|
type: str
|
||||||
|
when: false
|
||||||
|
default: "{{ 'frontend' if layout == 'part' else '.' }}"
|
||||||
|
|
||||||
|
prefix:
|
||||||
|
type: str
|
||||||
|
when: false
|
||||||
|
default: "{{ 'frontend/' if layout == 'part' else '' }}"
|
||||||
|
|
||||||
_tasks:
|
_tasks:
|
||||||
- "{% if _copier_operation == 'copy' and install_deps %}sh -c 'cd frontend && bun install'{% else %}true{% endif %}"
|
- "{% if _copier_operation == 'copy' and install_deps %}sh -c 'cd {{ part_dir }} && bun install'{% else %}true{% endif %}"
|
||||||
@@ -4,7 +4,7 @@
|
|||||||
{
|
{
|
||||||
"hooks": [
|
"hooks": [
|
||||||
{
|
{
|
||||||
"command": "cd frontend && bun run fix --skip=correctness/noUnusedImports",
|
"command": "{% if layout == 'part' %}cd frontend && {% endif %}bun run fix --skip=correctness/noUnusedImports",
|
||||||
"type": "command"
|
"type": "command"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@@ -1 +0,0 @@
|
|||||||
PUBLIC_API_BASE_URL=/api
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
COMPOSE := docker compose --project-directory ..
|
|
||||||
|
|
||||||
.PHONY: fmt check build dev
|
|
||||||
|
|
||||||
fmt:
|
|
||||||
bun run fix
|
|
||||||
|
|
||||||
check:
|
|
||||||
bun run check
|
|
||||||
bun run lint
|
|
||||||
|
|
||||||
build:
|
|
||||||
{% if serve == 'api' %} $(COMPOSE) run --rm frontend-dev sh -c "bun install && bun run build"
|
|
||||||
{% else %} $(COMPOSE) build frontend
|
|
||||||
{% endif %}
|
|
||||||
dev:
|
|
||||||
bun run dev
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
services:
|
|
||||||
{% if serve != 'api' %} frontend:
|
|
||||||
ports:
|
|
||||||
- "127.0.0.1:3000:3000"
|
|
||||||
|
|
||||||
{% endif %} frontend-dev:
|
|
||||||
ports:
|
|
||||||
- "127.0.0.1:3000:3000"
|
|
||||||
File renamed without changes.
@@ -0,0 +1,4 @@
|
|||||||
|
{% if layout == 'root' %}COMPOSE_PROFILES=services
|
||||||
|
|
||||||
|
{% endif %}PUBLIC_API_BASE_URL=/api
|
||||||
|
ALLOWED_HOSTS=
|
||||||
File renamed without changes.
@@ -0,0 +1,52 @@
|
|||||||
|
COMPOSE := {% if layout == 'part' %}cd .. && {% endif %}docker compose
|
||||||
|
{% if serve != 'api' %}IMAGE := {{ project_slug }}/frontend
|
||||||
|
{% endif %}changed = ! git diff --quiet $(1) -- $(2) 2>/dev/null
|
||||||
|
stamp = { git update-ref $(1) HEAD 2>/dev/null || true; }
|
||||||
|
|
||||||
|
.PHONY: {% if layout == 'root' %}env recreate rebuild restart logs down deploy {% endif %}fmt check build pre-deploy post-deploy dev
|
||||||
|
|
||||||
|
fmt:
|
||||||
|
bun run fix
|
||||||
|
|
||||||
|
check:
|
||||||
|
bun run check
|
||||||
|
bun run lint
|
||||||
|
|
||||||
|
build:
|
||||||
|
{% if serve == 'api' %} $(COMPOSE) run --rm frontend-dev sh -c "bun install && bun run build"
|
||||||
|
{% else %} $(COMPOSE) build frontend
|
||||||
|
{% endif %}
|
||||||
|
pre-deploy:
|
||||||
|
@if $(call changed,refs/deploy/frontend,.) || {% if serve == 'api' %}! test -d build{% else %}! docker image inspect $(IMAGE) >/dev/null 2>&1{% endif %}; then \
|
||||||
|
$(MAKE) build && $(call stamp,refs/deploy/frontend); \
|
||||||
|
fi
|
||||||
|
|
||||||
|
post-deploy:
|
||||||
|
@:
|
||||||
|
|
||||||
|
dev:
|
||||||
|
bun run dev
|
||||||
|
{% if layout == 'root' %}
|
||||||
|
env:
|
||||||
|
@test -f .env || cp .env.example .env
|
||||||
|
@test -f docker-compose.override.yml || cp docker-compose.override.yml.example docker-compose.override.yml
|
||||||
|
|
||||||
|
recreate:
|
||||||
|
$(COMPOSE) up -d --force-recreate
|
||||||
|
|
||||||
|
rebuild: build
|
||||||
|
$(COMPOSE) up -d
|
||||||
|
|
||||||
|
restart:
|
||||||
|
$(COMPOSE) restart
|
||||||
|
|
||||||
|
logs:
|
||||||
|
$(COMPOSE) logs -f --tail=100
|
||||||
|
|
||||||
|
down:
|
||||||
|
$(COMPOSE) down
|
||||||
|
|
||||||
|
deploy: pre-deploy
|
||||||
|
$(COMPOSE) up -d
|
||||||
|
$(MAKE) post-deploy
|
||||||
|
{% endif %}
|
||||||
File renamed without changes.
+9
-5
@@ -1,8 +1,15 @@
|
|||||||
{%- set dash = project_slug | replace('_', '-') -%}
|
{%- set dash = project_slug | replace('_', '-') -%}
|
||||||
{% if serve != 'api' -%}
|
|
||||||
services:
|
services:
|
||||||
frontend:
|
{% if serve != 'api' %} frontend:
|
||||||
networks:
|
networks:
|
||||||
|
default: {}
|
||||||
|
caddy:
|
||||||
|
aliases:
|
||||||
|
- {{ dash }}-frontend
|
||||||
|
|
||||||
|
{% endif %} frontend-dev:
|
||||||
|
networks:
|
||||||
|
default: {}
|
||||||
caddy:
|
caddy:
|
||||||
aliases:
|
aliases:
|
||||||
- {{ dash }}-frontend
|
- {{ dash }}-frontend
|
||||||
@@ -10,6 +17,3 @@ services:
|
|||||||
networks:
|
networks:
|
||||||
caddy:
|
caddy:
|
||||||
external: true
|
external: true
|
||||||
{%- else -%}
|
|
||||||
services: {}
|
|
||||||
{%- endif %}
|
|
||||||
+6
-6
@@ -1,15 +1,15 @@
|
|||||||
services:
|
services:
|
||||||
{% if serve != 'api' %} frontend:
|
{% if serve != 'api' %} frontend:
|
||||||
build: frontend
|
build: {{ part_dir }}
|
||||||
image: {{ project_slug }}/frontend
|
image: {{ project_slug }}/frontend
|
||||||
profiles: [frontend, services]
|
profiles: [frontend, services]
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
env_file:
|
env_file:
|
||||||
- path: .env
|
- path: .env
|
||||||
required: false
|
required: false
|
||||||
- path: frontend/.env
|
{% if layout == 'part' %} - path: frontend/.env
|
||||||
required: false
|
required: false
|
||||||
command: {% if serve == 'bun' %}[build/index.js]{% else %}[run, serve.ts]{% endif %}
|
{% endif %} command: {% if serve == 'bun' %}[build/index.js]{% else %}[run, serve.ts]{% endif %}
|
||||||
|
|
||||||
{% endif %} frontend-dev:
|
{% endif %} frontend-dev:
|
||||||
image: oven/bun:alpine
|
image: oven/bun:alpine
|
||||||
@@ -19,12 +19,12 @@ services:
|
|||||||
env_file:
|
env_file:
|
||||||
- path: .env
|
- path: .env
|
||||||
required: false
|
required: false
|
||||||
- path: frontend/.env
|
{% if layout == 'part' %} - path: frontend/.env
|
||||||
required: false
|
required: false
|
||||||
environment:
|
{% endif %} environment:
|
||||||
API_PROXY_TARGET: http://api:8080
|
API_PROXY_TARGET: http://api:8080
|
||||||
volumes:
|
volumes:
|
||||||
- ./frontend:/app
|
- {{ './frontend' if layout == 'part' else '.' }}:/app
|
||||||
- frontend_node_modules:/app/node_modules
|
- frontend_node_modules:/app/node_modules
|
||||||
- frontend_svelte_kit:/app/.svelte-kit
|
- frontend_svelte_kit:/app/.svelte-kit
|
||||||
command: [sh, -c, "bun install && bun run dev --host 0.0.0.0 --port 3000"]
|
command: [sh, -c, "bun install && bun run dev --host 0.0.0.0 --port 3000"]
|
||||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -2,9 +2,14 @@ import { sveltekit } from "@sveltejs/kit/vite";
|
|||||||
import tailwindcss from "@tailwindcss/vite";
|
import tailwindcss from "@tailwindcss/vite";
|
||||||
import { defineConfig } from "vite";
|
import { defineConfig } from "vite";
|
||||||
|
|
||||||
|
const allowedHosts = process.env.ALLOWED_HOSTS
|
||||||
|
? process.env.ALLOWED_HOSTS.split(",")
|
||||||
|
: undefined;
|
||||||
|
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
plugins: [tailwindcss(), sveltekit()],
|
plugins: [tailwindcss(), sveltekit()],
|
||||||
server: {
|
server: {
|
||||||
|
allowedHosts,
|
||||||
proxy: {
|
proxy: {
|
||||||
"/api": {
|
"/api": {
|
||||||
changeOrigin: true,
|
changeOrigin: true,
|
||||||
File renamed without changes.
File renamed without changes.
@@ -0,0 +1,14 @@
|
|||||||
|
# {{ project_name }}
|
||||||
|
|
||||||
|
Runs in Docker, locally the same way as in production. `COMPOSE_PROFILES` in `.env` selects the services that run on this machine. `docker-compose.override.yml` holds what differs between machines: published ports and the aliases on the external `caddy` network.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
make env
|
||||||
|
make recreate
|
||||||
|
```
|
||||||
|
|
||||||
|
`make env` creates `.env` and `docker-compose.override.yml` from their examples. `make recreate` starts the selected profiles, `make rebuild` builds the image first, `make logs`, `make restart` and `make down` do what they say.
|
||||||
|
|
||||||
|
To deploy, `git pull && make deploy`. It runs `make pre-deploy`, which rebuilds the image only when something in the repository changed, then `docker compose up -d`. A deploy system with its own `up` step calls `make pre-deploy` before it and `make post-deploy` after. What was built is remembered as `refs/deploy/*` in the clone.
|
||||||
|
|
||||||
|
`make dev` runs the Vite dev server on the host, `make fmt` formats, `make check` runs svelte-check and the linter.
|
||||||
File renamed without changes.
File renamed without changes.
Reference in new issue
Block a user