Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7a7fbab3c4 |
No files matched your search
@@ -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>
|
||||||
|
|||||||
@@ -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 %}"
|
||||||
@@ -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" } } }
|
||||||
|
|||||||
+2
-2
@@ -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
-5
@@ -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",
|
||||||
Reference in new issue
Block a user