diff --git a/README.md b/README.md index 3bb8e8d..908593c 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # frontend-svelte -Copier template for a SvelteKit frontend on Bun with Tailwind v4, biome or ESLint + Prettier and optional shadcn-svelte: SSR on Bun, a static SPA behind `serve.ts`, or a static SPA served by the backend api. A `frontend/` part or the whole project (`layout`), on top of `infra`. +Copier template for a SvelteKit frontend on Bun with Tailwind v4, biome or ESLint + Prettier and optional shadcn-svelte, plain or with the [claddcn](https://git.kotikot.com/lib/claddcn-svelte) skin: SSR on Bun, a static SPA behind `serve.ts`, or a static SPA served by the backend api. A `frontend/` part or the whole project (`layout`), on top of `infra`. ```sh copier copy --trust -d project_name="My Thing" -d serve=bun diff --git a/copier.yml b/copier.yml index b06f71d..6050bb1 100644 --- a/copier.yml +++ b/copier.yml @@ -35,6 +35,7 @@ ui_library: choices: none (Tailwind v4): none shadcn-svelte: shadcn + shadcn-svelte with the claddcn skin: claddcn default: none linter: @@ -66,6 +67,7 @@ prefix: default: "{{ 'frontend/' if layout == 'part' else '' }}" _tasks: + - "{% if _copier_operation == 'copy' and ui_library == 'claddcn' %}npx -y git+https://git.kotikot.com/lib/claddcn-svelte.git init --cwd {{ part_dir }} --no-install{% else %}true{% endif %}" # Generated values (project name) can push lines past the formatter width, # so every fresh copy is formatted once by its own linter. - "{% if _copier_operation == 'copy' and install_deps %}sh -c 'cd {{ part_dir }} && bun install && bun --bun run fix'{% else %}true{% endif %}" diff --git a/template/{{ part_dir }}/package.json.jinja b/template/{{ part_dir }}/package.json.jinja index ed80089..90ff06e 100644 --- a/template/{{ part_dir }}/package.json.jinja +++ b/template/{{ part_dir }}/package.json.jinja @@ -50,17 +50,21 @@ "typescript-eslint": "^8.71.1", }) %}{% endif -%} {%- if frontend_adapter == 'bun' %}{% set _ = deps.update({"@sveltejs/adapter-bun": "^1.0.0"}) %}{% else %}{% set _ = deps.update({"@sveltejs/adapter-static": "^4.0.0"}) %}{% endif -%} -{%- if ui_library == 'shadcn' %}{% set _ = deps.update({ +{%- if ui_library != 'none' %}{% set _ = deps.update({ "@internationalized/date": "^3.12.0", "@lucide/svelte": "^1.23.0", "bits-ui": "^2.16.3", "clsx": "^2.1.1", "mode-watcher": "^1.1.0", - "shadcn-svelte": "^1.3.0", + "shadcn-svelte": "^1.7.0", "svelte-sonner": "^1.1.0", "tailwind-merge": "^3.5.0", "tailwind-variants": "^3.2.2", "tw-animate-css": "^1.4.0", +}) %}{% endif -%} +{%- if ui_library == 'claddcn' %}{% set _ = deps.update({ + "@fontsource-variable/geist": "^5.3.0", + "@fontsource-variable/geist-mono": "^5.3.0", }) %}{% endif %} {%- for name, version in deps | dictsort %} "{{ name }}": "{{ version }}"{{ "," if not loop.last }} diff --git a/template/{{ part_dir }}/src/routes/+layout.svelte.jinja b/template/{{ part_dir }}/src/routes/+layout.svelte.jinja index a115c22..35634d9 100644 --- a/template/{{ part_dir }}/src/routes/+layout.svelte.jinja +++ b/template/{{ part_dir }}/src/routes/+layout.svelte.jinja @@ -1,12 +1,12 @@ -{% if ui_library == 'shadcn' %} +{% if ui_library != 'none' %} {% endif %}{@render children()} diff --git a/template/{{ part_dir }}/src/routes/+page.svelte.jinja b/template/{{ part_dir }}/src/routes/+page.svelte.jinja index 2c4616d..9eaf9cf 100644 --- a/template/{{ part_dir }}/src/routes/+page.svelte.jinja +++ b/template/{{ part_dir }}/src/routes/+page.svelte.jinja @@ -3,10 +3,10 @@

{{ project_name }}

-

+

Edit src/routes/+page.svelte.

diff --git a/template/{{ part_dir }}/src/routes/layout.css.jinja b/template/{{ part_dir }}/src/routes/layout.css.jinja index 17b75f8..4dfe4f5 100644 --- a/template/{{ part_dir }}/src/routes/layout.css.jinja +++ b/template/{{ part_dir }}/src/routes/layout.css.jinja @@ -1,11 +1,14 @@ -{% if ui_library == 'shadcn' -%} +{% if ui_library != 'none' -%} @import "tailwindcss"; @import "tw-animate-css"; @import "shadcn-svelte/tailwind.css"; +{%- if ui_library == 'claddcn' %} +@import "./claddcn.css"; +{%- endif %} @custom-variant dark (&:is(.dark *)); -:root { +{% if ui_library == 'shadcn' %}:root { --radius: 0.625rem; --background: oklch(1 0 0); --foreground: oklch(0.145 0 0); @@ -100,7 +103,7 @@ --color-sidebar-ring: var(--sidebar-ring); } -@layer base { +{% endif %}@layer base { * { @apply border-border outline-ring/50; } diff --git a/template/{{ part_dir }}/{% if linter == 'biome' %}biome.jsonc{% endif %}.jinja b/template/{{ part_dir }}/{% if linter == 'biome' %}biome.jsonc{% endif %}.jinja index 514d228..0c3aec2 100644 --- a/template/{{ part_dir }}/{% if linter == 'biome' %}biome.jsonc{% endif %}.jinja +++ b/template/{{ part_dir }}/{% if linter == 'biome' %}biome.jsonc{% endif %}.jinja @@ -2,16 +2,22 @@ "$schema": "./node_modules/@biomejs/biome/configuration_schema.json", "extends": ["ultracite/biome/core", "ultracite/biome/svelte"], "files": { +{%- if ui_library == 'none' %} "includes": ["!.claude", "!.svelte-kit", "!build", "!.mcp.json"] +{%- else %} + "includes": [ + "!.claude", + "!.svelte-kit", + "!build", + "!.mcp.json", + "!src/lib/components/ui"{% if ui_library == 'claddcn' %}, + "!src/routes/claddcn.css"{% endif %} + ] +{%- endif %} }, "javascript": { "globals": ["Bun"] }, "overrides": [ -{%- if ui_library == 'shadcn' %} - { - "includes": ["src/lib/components/ui/**"], - "linter": { "enabled": false }, - "assist": { "enabled": false } - }, +{%- if ui_library != 'none' %} { "includes": ["src/lib/utils.ts"], "linter": { "rules": { "suspicious": { "noExplicitAny": "off" } } } diff --git a/template/{{ part_dir }}/{% if linter == 'eslint' %}eslint.config.js{% endif %}.jinja b/template/{{ part_dir }}/{% if linter == 'eslint' %}eslint.config.js{% endif %}.jinja index 9cb50a8..2d4c61f 100644 --- a/template/{{ part_dir }}/{% if linter == 'eslint' %}eslint.config.js{% endif %}.jinja +++ b/template/{{ part_dir }}/{% if linter == 'eslint' %}eslint.config.js{% endif %}.jinja @@ -35,10 +35,10 @@ export default defineConfig( "no-undef": "off", }, }, -{%- if ui_library == 'shadcn' %} +{%- if ui_library != 'none' %} { // shadcn-svelte primitives are copied in and changed upstream only. - files: ["src/lib/components/ui/**"], + files: ["src/lib/components/ui/**"{% if ui_library == 'shadcn' %}, "src/lib/utils.ts"{% endif %}], rules: { "@typescript-eslint/no-explicit-any": "off", "svelte/no-navigation-without-resolve": "off", diff --git a/template/{{ part_dir }}/{% if ui_library == 'shadcn' %}components.json{% endif %}.jinja b/template/{{ part_dir }}/{% if ui_library != 'none' %}components.json{% endif %}.jinja similarity index 70% rename from template/{{ part_dir }}/{% if ui_library == 'shadcn' %}components.json{% endif %}.jinja rename to template/{{ part_dir }}/{% if ui_library != 'none' %}components.json{% endif %}.jinja index 9c0e5b3..d36315d 100644 --- a/template/{{ part_dir }}/{% if ui_library == 'shadcn' %}components.json{% endif %}.jinja +++ b/template/{{ part_dir }}/{% if ui_library != 'none' %}components.json{% endif %}.jinja @@ -5,11 +5,11 @@ "baseColor": "neutral" }, "aliases": { - "components": "$lib/components", - "utils": "$lib/utils", - "ui": "$lib/components/ui", - "hooks": "$lib/hooks", - "lib": "$lib" + "components": "#lib/components", + "utils": "#lib/utils", + "ui": "#lib/components/ui", + "hooks": "#lib/hooks", + "lib": "#lib" }, "typescript": true, "registry": "https://shadcn-svelte.com/registry",