feat(ui,biome,eslint): #lib aliases, vendor ui out of biome, claddcn skin option

This commit is contained in:
hh committed 2026-10-19 12:16:21 +02:00
1 parent 0fadb740fb
commit 23b60a6de1
9 files changed
+38 -23

No files matched your search

+1 -1
View File
@@ -1,6 +1,6 @@
# frontend-svelte # 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 ```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>
+2
View File
@@ -35,6 +35,7 @@ ui_library:
choices: choices:
none (Tailwind v4): none none (Tailwind v4): none
shadcn-svelte: shadcn shadcn-svelte: shadcn
shadcn-svelte with the claddcn skin: claddcn
default: none default: none
linter: linter:
@@ -66,6 +67,7 @@ prefix:
default: "{{ 'frontend/' if layout == 'part' else '' }}" default: "{{ 'frontend/' if layout == 'part' else '' }}"
_tasks: _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, # Generated values (project name) can push lines past the formatter width,
# so every fresh copy is formatted once by its own linter. # 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 %}" - "{% if _copier_operation == 'copy' and install_deps %}sh -c 'cd {{ part_dir }} && bun install && bun --bun run fix'{% else %}true{% endif %}"
+6 -2
View File
@@ -50,17 +50,21 @@
"typescript-eslint": "^8.71.1", "typescript-eslint": "^8.71.1",
}) %}{% endif -%} }) %}{% 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 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", "@internationalized/date": "^3.12.0",
"@lucide/svelte": "^1.23.0", "@lucide/svelte": "^1.23.0",
"bits-ui": "^2.16.3", "bits-ui": "^2.16.3",
"clsx": "^2.1.1", "clsx": "^2.1.1",
"mode-watcher": "^1.1.0", "mode-watcher": "^1.1.0",
"shadcn-svelte": "^1.3.0", "shadcn-svelte": "^1.7.0",
"svelte-sonner": "^1.1.0", "svelte-sonner": "^1.1.0",
"tailwind-merge": "^3.5.0", "tailwind-merge": "^3.5.0",
"tailwind-variants": "^3.2.2", "tailwind-variants": "^3.2.2",
"tw-animate-css": "^1.4.0", "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 %} }) %}{% endif %}
{%- for name, version in deps | dictsort %} {%- for name, version in deps | dictsort %}
"{{ name }}": "{{ version }}"{{ "," if not loop.last }} "{{ name }}": "{{ version }}"{{ "," if not loop.last }}
@@ -1,12 +1,12 @@
<script lang="ts"> <script lang="ts">
import "./layout.css"; import "./layout.css";
{%- if ui_library == 'shadcn' %} {%- if ui_library != 'none' %}
import { ModeWatcher } from "mode-watcher"; import { ModeWatcher } from "mode-watcher";
{%- endif %} {%- endif %}
let { children } = $props(); let { children } = $props();
</script> </script>
{% if ui_library == 'shadcn' %}<ModeWatcher /> {% if ui_library != 'none' %}<ModeWatcher />
{% endif %}{@render children()} {% endif %}{@render children()}
@@ -3,10 +3,10 @@
</svelte:head> </svelte:head>
<main <main
class="flex min-h-dvh flex-col items-center justify-center gap-4 px-6 text-center {% if ui_library == 'shadcn' %}bg-background text-foreground{% else %}bg-white text-neutral-900 dark:bg-neutral-950 dark:text-neutral-50{% endif %}" class="flex min-h-dvh flex-col items-center justify-center gap-4 px-6 text-center {% if ui_library != 'none' %}bg-background text-foreground{% else %}bg-white text-neutral-900 dark:bg-neutral-950 dark:text-neutral-50{% endif %}"
> >
<h1 class="font-bold text-4xl tracking-tight sm:text-5xl">{{ project_name }}</h1> <h1 class="font-bold text-4xl tracking-tight sm:text-5xl">{{ project_name }}</h1>
<p class="max-w-prose text-base {% if ui_library == 'shadcn' %}text-muted-foreground{% else %}text-neutral-500{% endif %}"> <p class="max-w-prose text-base {% if ui_library != 'none' %}text-muted-foreground{% else %}text-neutral-500{% endif %}">
Edit Edit
<code class="font-mono">src/routes/+page.svelte</code>. <code class="font-mono">src/routes/+page.svelte</code>.
</p> </p>
@@ -1,11 +1,14 @@
{% if ui_library == 'shadcn' -%} {% if ui_library != 'none' -%}
@import "tailwindcss"; @import "tailwindcss";
@import "tw-animate-css"; @import "tw-animate-css";
@import "shadcn-svelte/tailwind.css"; @import "shadcn-svelte/tailwind.css";
{%- if ui_library == 'claddcn' %}
@import "./claddcn.css";
{%- endif %}
@custom-variant dark (&:is(.dark *)); @custom-variant dark (&:is(.dark *));
:root { {% if ui_library == 'shadcn' %}:root {
--radius: 0.625rem; --radius: 0.625rem;
--background: oklch(1 0 0); --background: oklch(1 0 0);
--foreground: oklch(0.145 0 0); --foreground: oklch(0.145 0 0);
@@ -100,7 +103,7 @@
--color-sidebar-ring: var(--sidebar-ring); --color-sidebar-ring: var(--sidebar-ring);
} }
@layer base { {% endif %}@layer base {
* { * {
@apply border-border outline-ring/50; @apply border-border outline-ring/50;
} }
@@ -2,16 +2,22 @@
"$schema": "./node_modules/@biomejs/biome/configuration_schema.json", "$schema": "./node_modules/@biomejs/biome/configuration_schema.json",
"extends": ["ultracite/biome/core", "ultracite/biome/svelte"], "extends": ["ultracite/biome/core", "ultracite/biome/svelte"],
"files": { "files": {
{%- if ui_library == 'none' %}
"includes": ["!.claude", "!.svelte-kit", "!build", "!.mcp.json"] "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"] }, "javascript": { "globals": ["Bun"] },
"overrides": [ "overrides": [
{%- if ui_library == 'shadcn' %} {%- if ui_library != 'none' %}
{
"includes": ["src/lib/components/ui/**"],
"linter": { "enabled": false },
"assist": { "enabled": false }
},
{ {
"includes": ["src/lib/utils.ts"], "includes": ["src/lib/utils.ts"],
"linter": { "rules": { "suspicious": { "noExplicitAny": "off" } } } "linter": { "rules": { "suspicious": { "noExplicitAny": "off" } } }
@@ -35,10 +35,10 @@ export default defineConfig(
"no-undef": "off", "no-undef": "off",
}, },
}, },
{%- if ui_library == 'shadcn' %} {%- if ui_library != 'none' %}
{ {
// shadcn-svelte primitives are copied in and changed upstream only. // 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: { rules: {
"@typescript-eslint/no-explicit-any": "off", "@typescript-eslint/no-explicit-any": "off",
"svelte/no-navigation-without-resolve": "off", "svelte/no-navigation-without-resolve": "off",
@@ -5,11 +5,11 @@
"baseColor": "neutral" "baseColor": "neutral"
}, },
"aliases": { "aliases": {
"components": "$lib/components", "components": "#lib/components",
"utils": "$lib/utils", "utils": "#lib/utils",
"ui": "$lib/components/ui", "ui": "#lib/components/ui",
"hooks": "$lib/hooks", "hooks": "#lib/hooks",
"lib": "$lib" "lib": "#lib"
}, },
"typescript": true, "typescript": true,
"registry": "https://shadcn-svelte.com/registry", "registry": "https://shadcn-svelte.com/registry",