vela 0.1.0 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (104) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +186 -0
  3. package/dist/bin.js +6245 -0
  4. package/dist/bin.js.map +7 -0
  5. package/package.json +85 -17
  6. package/templates/minimal/.ignore +3 -0
  7. package/templates/minimal/.prettierignore +9 -0
  8. package/templates/minimal/.prettierrc +15 -0
  9. package/templates/minimal/.vscode/extensions.json +3 -0
  10. package/templates/minimal/.vscode/settings.json +5 -0
  11. package/templates/minimal/_gitignore +30 -0
  12. package/templates/minimal/_npmrc +1 -0
  13. package/templates/minimal/components.json +16 -0
  14. package/templates/minimal/data/fixtures/README.md +1 -0
  15. package/templates/minimal/data/hooks/README.md +3 -0
  16. package/templates/minimal/data/seeds/README.md +1 -0
  17. package/templates/minimal/package.template.json +54 -0
  18. package/templates/minimal/src/app.css +121 -0
  19. package/templates/minimal/src/app.d.ts +19 -0
  20. package/templates/minimal/src/app.html +13 -0
  21. package/templates/minimal/src/hooks.server.ts +8 -0
  22. package/templates/minimal/src/lib/assets/favicon.svg +8 -0
  23. package/templates/minimal/src/lib/components/ui/button/button.svelte +80 -0
  24. package/templates/minimal/src/lib/components/ui/button/index.ts +17 -0
  25. package/templates/minimal/src/lib/components/ui/navbar/index.ts +11 -0
  26. package/templates/minimal/src/lib/components/ui/navbar/navbar-brand.svelte +8 -0
  27. package/templates/minimal/src/lib/components/ui/navbar/navbar-brandname.svelte +8 -0
  28. package/templates/minimal/src/lib/components/ui/navbar/navbar-item.svelte +6 -0
  29. package/templates/minimal/src/lib/components/ui/navbar/navbar-link.svelte +13 -0
  30. package/templates/minimal/src/lib/components/ui/navbar/navbar-list.svelte +22 -0
  31. package/templates/minimal/src/lib/components/ui/navbar/navbar-logo.svelte +10 -0
  32. package/templates/minimal/src/lib/components/ui/navbar/navbar-mobile-toggle.svelte +20 -0
  33. package/templates/minimal/src/lib/components/ui/navbar/navbar-mode.svelte +12 -0
  34. package/templates/minimal/src/lib/components/ui/navbar/navbar-store.ts +5 -0
  35. package/templates/minimal/src/lib/components/ui/navbar/navbar.svelte +20 -0
  36. package/templates/minimal/src/lib/components/ui/sonner/index.ts +1 -0
  37. package/templates/minimal/src/lib/components/ui/sonner/sonner.svelte +13 -0
  38. package/templates/minimal/src/lib/index.ts +1 -0
  39. package/templates/minimal/src/lib/utils.ts +13 -0
  40. package/templates/minimal/src/routes/(public)/+layout.svelte +9 -0
  41. package/templates/minimal/src/routes/(public)/+page.svelte +65 -0
  42. package/templates/minimal/src/routes/(public)/root-layout.svelte +55 -0
  43. package/templates/minimal/src/routes/(public)/server.test.ts +10 -0
  44. package/templates/minimal/src/routes/+error.svelte +29 -0
  45. package/templates/minimal/src/routes/+layout.server.ts +30 -0
  46. package/templates/minimal/src/routes/+layout.svelte +38 -0
  47. package/templates/minimal/src/routes/api/README.md +26 -0
  48. package/templates/minimal/static/og.jpg +0 -0
  49. package/templates/minimal/static/robots.txt +3 -0
  50. package/templates/minimal/template.json +4 -0
  51. package/templates/minimal/test/setup.ts +46 -0
  52. package/templates/minimal/tsconfig.json +15 -0
  53. package/templates/minimal/vite.config.ts +17 -0
  54. package/templates/minimal/vitest.config.ts +15 -0
  55. package/templates/static/.ignore +3 -0
  56. package/templates/static/.prettierignore +9 -0
  57. package/templates/static/.prettierrc +15 -0
  58. package/templates/static/.vscode/extensions.json +3 -0
  59. package/templates/static/.vscode/settings.json +5 -0
  60. package/templates/static/_gitignore +23 -0
  61. package/templates/static/_npmrc +1 -0
  62. package/templates/static/components.json +16 -0
  63. package/templates/static/package.template.json +44 -0
  64. package/templates/static/src/app.css +121 -0
  65. package/templates/static/src/app.d.ts +13 -0
  66. package/templates/static/src/app.html +13 -0
  67. package/templates/static/src/hooks.server.ts +26 -0
  68. package/templates/static/src/lib/assets/favicon.svg +8 -0
  69. package/templates/static/src/lib/components/ui/button/button.svelte +80 -0
  70. package/templates/static/src/lib/components/ui/button/index.ts +17 -0
  71. package/templates/static/src/lib/components/ui/navbar/index.ts +11 -0
  72. package/templates/static/src/lib/components/ui/navbar/navbar-brand.svelte +8 -0
  73. package/templates/static/src/lib/components/ui/navbar/navbar-brandname.svelte +8 -0
  74. package/templates/static/src/lib/components/ui/navbar/navbar-item.svelte +6 -0
  75. package/templates/static/src/lib/components/ui/navbar/navbar-link.svelte +13 -0
  76. package/templates/static/src/lib/components/ui/navbar/navbar-list.svelte +22 -0
  77. package/templates/static/src/lib/components/ui/navbar/navbar-logo.svelte +10 -0
  78. package/templates/static/src/lib/components/ui/navbar/navbar-mobile-toggle.svelte +20 -0
  79. package/templates/static/src/lib/components/ui/navbar/navbar-mode.svelte +12 -0
  80. package/templates/static/src/lib/components/ui/navbar/navbar-store.ts +5 -0
  81. package/templates/static/src/lib/components/ui/navbar/navbar.svelte +20 -0
  82. package/templates/static/src/lib/components/ui/sonner/index.ts +1 -0
  83. package/templates/static/src/lib/components/ui/sonner/sonner.svelte +13 -0
  84. package/templates/static/src/lib/index.ts +1 -0
  85. package/templates/static/src/lib/site.template.ts +11 -0
  86. package/templates/static/src/lib/utils.ts +13 -0
  87. package/templates/static/src/routes/(public)/+layout.svelte +9 -0
  88. package/templates/static/src/routes/(public)/+page.svelte +65 -0
  89. package/templates/static/src/routes/(public)/root-layout.svelte +55 -0
  90. package/templates/static/src/routes/+error.svelte +29 -0
  91. package/templates/static/src/routes/+layout.svelte +25 -0
  92. package/templates/static/src/routes/+layout.ts +35 -0
  93. package/templates/static/static/og.jpg +0 -0
  94. package/templates/static/static/robots.txt +3 -0
  95. package/templates/static/template.json +4 -0
  96. package/templates/static/tsconfig.json +15 -0
  97. package/templates/static/vite.config.ts +31 -0
  98. package/templates/ui/css/gray.css +68 -0
  99. package/templates/ui/css/neutral.css +68 -0
  100. package/templates/ui/css/slate.css +68 -0
  101. package/templates/ui/css/stone.css +68 -0
  102. package/templates/ui/css/zinc.css +68 -0
  103. package/src/Component.js +0 -10
  104. package/src/index.js +0 -14
@@ -0,0 +1,5 @@
1
+ export const MOBILE_MENU_CONTEXT_KEY = Symbol('mobile-menu');
2
+ export type MobileMenuContext = {
3
+ menuOpen: { isOpen: boolean };
4
+ toggleMenu: () => void;
5
+ };
@@ -0,0 +1,20 @@
1
+ <script lang="ts">
2
+ import { setContext } from 'svelte';
3
+ import { cn } from '$lib/utils.js';
4
+ let { children, class: className = '' } = $props();
5
+
6
+ import { MOBILE_MENU_CONTEXT_KEY } from './navbar-store';
7
+
8
+ let menuOpen = $state({ isOpen: false });
9
+
10
+ setContext(MOBILE_MENU_CONTEXT_KEY, {
11
+ menuOpen,
12
+ toggleMenu: () => (menuOpen.isOpen = !menuOpen.isOpen)
13
+ });
14
+ </script>
15
+
16
+ <nav class={cn(className)}>
17
+ <div class="max-w-7xl flex flex-wrap items-center justify-between mx-auto p-4">
18
+ {@render children?.()}
19
+ </div>
20
+ </nav>
@@ -0,0 +1 @@
1
+ export { default as Toaster } from './sonner.svelte';
@@ -0,0 +1,13 @@
1
+ <script lang="ts">
2
+ import { Toaster as Sonner, type ToasterProps as SonnerProps } from 'svelte-sonner';
3
+ import { mode } from 'mode-watcher';
4
+
5
+ let { ...restProps }: SonnerProps = $props();
6
+ </script>
7
+
8
+ <Sonner
9
+ theme={mode.current}
10
+ class="toaster group"
11
+ style="--normal-bg: var(--color-popover); --normal-text: var(--color-popover-foreground); --normal-border: var(--color-border);"
12
+ {...restProps}
13
+ />
@@ -0,0 +1 @@
1
+ // place files you want to import through the `$lib` alias in this folder.
@@ -0,0 +1,13 @@
1
+ import { clsx, type ClassValue } from 'clsx';
2
+ import { twMerge } from 'tailwind-merge';
3
+
4
+ export function cn(...inputs: ClassValue[]) {
5
+ return twMerge(clsx(inputs));
6
+ }
7
+
8
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
9
+ export type WithoutChild<T> = T extends { child?: any } ? Omit<T, 'child'> : T;
10
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
11
+ export type WithoutChildren<T> = T extends { children?: any } ? Omit<T, 'children'> : T;
12
+ export type WithoutChildrenOrChild<T> = WithoutChildren<WithoutChild<T>>;
13
+ export type WithElementRef<T, U extends HTMLElement = HTMLElement> = T & { ref?: U | null };
@@ -0,0 +1,9 @@
1
+ <script lang="ts">
2
+ import RootLayout from './root-layout.svelte';
3
+
4
+ let { data, children } = $props();
5
+ </script>
6
+
7
+ <RootLayout {data}>
8
+ {@render children?.()}
9
+ </RootLayout>
@@ -0,0 +1,65 @@
1
+ <script lang="ts">
2
+ import favicon from '$lib/assets/favicon.svg';
3
+
4
+ let { data } = $props();
5
+ </script>
6
+
7
+ <main class="flex-1">
8
+ <section class="px-6 py-16 md:py-24">
9
+ <div class="mx-auto max-w-4xl text-center">
10
+ <a href="/" class="inline-flex items-center gap-2 font-medium">
11
+ <span
12
+ class="bg-primary text-primary-foreground inline-flex size-6 items-center justify-center rounded-md"
13
+ >
14
+ <img src={favicon} alt="logo" class="size-4" />
15
+ </span>
16
+ {data.meta.appName}
17
+ </a>
18
+
19
+ <h1 class="mt-6 text-4xl font-semibold tracking-tight sm:text-5xl">
20
+ A modern way to get things done
21
+ </h1>
22
+ <p class="text-muted-foreground mt-4 text-lg">
23
+ Everything you need to launch faster, collaborate better, and stay focused.
24
+ </p>
25
+
26
+ <div class="mt-8 flex items-center justify-center gap-3">
27
+ <a
28
+ href="/signup"
29
+ class="bg-primary text-primary-foreground inline-flex items-center rounded-md px-5 py-2.5"
30
+ >
31
+ Get started
32
+ </a>
33
+ <a
34
+ href="/login"
35
+ class="border border-border text-foreground inline-flex items-center rounded-md px-5 py-2.5"
36
+ >
37
+ Sign in
38
+ </a>
39
+ </div>
40
+ </div>
41
+ </section>
42
+
43
+ <section class="px-6 pb-16 md:pb-24">
44
+ <div class="mx-auto grid max-w-5xl gap-6 sm:grid-cols-2 lg:grid-cols-3">
45
+ <div class="bg-card text-card-foreground rounded-lg border p-6">
46
+ <h3 class="font-medium">Fast</h3>
47
+ <p class="text-muted-foreground mt-2">
48
+ Simple workflows that help you move from idea to done.
49
+ </p>
50
+ </div>
51
+ <div class="bg-card text-card-foreground rounded-lg border p-6">
52
+ <h3 class="font-medium">Flexible</h3>
53
+ <p class="text-muted-foreground mt-2">
54
+ Works for teams of any size and adapts to your process.
55
+ </p>
56
+ </div>
57
+ <div class="bg-card text-card-foreground rounded-lg border p-6">
58
+ <h3 class="font-medium">Secure</h3>
59
+ <p class="text-muted-foreground mt-2">
60
+ Built with best practices and modern standards in mind.
61
+ </p>
62
+ </div>
63
+ </div>
64
+ </section>
65
+ </main>
@@ -0,0 +1,55 @@
1
+ <script lang="ts">
2
+ import favicon from '$lib/assets/favicon.svg';
3
+
4
+ import { toggleMode } from 'mode-watcher';
5
+ import * as Navbar from '$lib/components/ui/navbar';
6
+ import { Button } from '$lib/components/ui/button';
7
+
8
+ let { children, data } = $props();
9
+ </script>
10
+
11
+ <div class="min-h-dvh grid grid-rows-[max-content_1fr_max-content] root-layout">
12
+ <Navbar.Root>
13
+ <Navbar.Brand href="/">
14
+ <Navbar.Logo src={favicon} alt="Logo" />
15
+ </Navbar.Brand>
16
+
17
+ <Navbar.MobileToggle />
18
+
19
+ <Navbar.List>
20
+ <Navbar.Item>
21
+ <Button class="w-full justify-start md:justify-center md:w-auto" href="/" variant="ghost">
22
+ Home
23
+ </Button>
24
+ </Navbar.Item>
25
+ </Navbar.List>
26
+ </Navbar.Root>
27
+
28
+ {@render children?.()}
29
+
30
+ <footer class="border-t border-border py-4">
31
+ <div
32
+ class="mx-auto flex max-w-7xl px-4 flex-col items-center justify-between gap-3 sm:flex-row"
33
+ >
34
+ <p class="text-muted-foreground text-sm">
35
+ &copy; {new Date().getFullYear()}
36
+ {data.meta.appName}. All rights reserved.
37
+ </p>
38
+ <nav class="flex items-center gap-4 text-sm">
39
+ <Button onclick={toggleMode} variant="ghost" size="icon">
40
+ <Navbar.Mode />
41
+ </Button>
42
+ <a href="/privacy" class="underline-offset-4 hover:underline">Privacy</a>
43
+ <a href="/terms" class="underline-offset-4 hover:underline">Terms</a>
44
+ </nav>
45
+ </div>
46
+ </footer>
47
+ </div>
48
+
49
+ <style lang="postcss">
50
+ @reference "tailwindcss";
51
+
52
+ .root-layout :global(section[data-role='content']) {
53
+ @apply container mx-auto max-w-7xl px-4 py-8 w-full;
54
+ }
55
+ </style>
@@ -0,0 +1,10 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import type { Match } from '@velastack/pocketbase';
3
+ import type { RouteId } from './$types';
4
+
5
+ describe('/', () => {
6
+ it('should return a 200 status code', async (context) => {
7
+ const response = await context.request.get('/' satisfies Match<RouteId>);
8
+ expect(response.status).toBe(200);
9
+ });
10
+ });
@@ -0,0 +1,29 @@
1
+ <script lang="ts">
2
+ import { page } from '$app/state';
3
+ import { Button } from '$lib/components/ui/button';
4
+ import RootLayout from './(public)/root-layout.svelte';
5
+
6
+ let { data } = $props();
7
+ </script>
8
+
9
+ <RootLayout {data}>
10
+ <main class="mx-auto max-w-7xl px-4 w-full flex items-center justify-center">
11
+ <div class="text-center space-y-4">
12
+ <div class="text-9xl font-bold text-primary">
13
+ {page.status}
14
+ </div>
15
+ <div class="relative">
16
+ <h1 class="text-4xl font-bold relative inline-block bg-background">
17
+ Oops! Something went wrong
18
+ </h1>
19
+ </div>
20
+ <p class="text-xl text-muted-foreground max-w-lg mx-auto">
21
+ {page.error?.message ||
22
+ "We couldn't find what you were looking for. Let's get you back on track!"}
23
+ </p>
24
+ <div>
25
+ <Button href="/" variant="default" size="lg">Take me home</Button>
26
+ </div>
27
+ </div>
28
+ </main>
29
+ </RootLayout>
@@ -0,0 +1,30 @@
1
+ import { loadFlash } from 'sveltekit-flash-message/server';
2
+ import { defineBaseMetaTags } from 'svelte-meta-tags';
3
+
4
+ export const load = loadFlash(async ({ locals, url }) => {
5
+ const canonical = new URL(url.pathname, url.origin).href;
6
+
7
+ const baseTags = defineBaseMetaTags({
8
+ title: '',
9
+ titleTemplate: `%s | ${locals.meta.appName}`,
10
+ description: '',
11
+ canonical,
12
+ openGraph: {
13
+ type: 'website',
14
+ url: canonical,
15
+ images: [
16
+ {
17
+ url: `${locals.meta.appURL}/og.jpg`,
18
+ alt: locals.meta.appName,
19
+ width: 1200,
20
+ height: 630
21
+ }
22
+ ]
23
+ }
24
+ });
25
+
26
+ return {
27
+ meta: locals.meta,
28
+ ...baseTags
29
+ };
30
+ });
@@ -0,0 +1,38 @@
1
+ <script lang="ts">
2
+ import '../app.css';
3
+
4
+ import favicon from '$lib/assets/favicon.svg';
5
+
6
+ import { ModeWatcher } from 'mode-watcher';
7
+ import { getFlash } from 'sveltekit-flash-message';
8
+ import { toast } from 'svelte-sonner';
9
+ import { page } from '$app/state';
10
+ import { Toaster } from '$lib/components/ui/sonner';
11
+ import { MetaTags, deepMerge } from 'svelte-meta-tags';
12
+
13
+ let { data, children } = $props();
14
+ const flash = getFlash(page);
15
+
16
+ $effect(() => {
17
+ if (!$flash || $flash.type !== 'toast') {
18
+ return;
19
+ }
20
+
21
+ toast.message($flash.message);
22
+
23
+ $flash = undefined;
24
+ });
25
+
26
+ let metaTags = $derived(deepMerge(data.baseMetaTags, page.data.pageMetaTags));
27
+ </script>
28
+
29
+ <svelte:head>
30
+ <title>{data.meta.appName}</title>
31
+ <link rel="icon" href={favicon} />
32
+ </svelte:head>
33
+
34
+ <MetaTags {...metaTags} />
35
+ <ModeWatcher />
36
+ <Toaster />
37
+
38
+ {@render children?.()}
@@ -0,0 +1,26 @@
1
+ # API Routes
2
+
3
+ If API is enabled in hooks.server.ts, the PocketBase API is exposed on the API URL:
4
+
5
+ ```
6
+ export const handle = handlePocketbase({
7
+ pocketbaseUrl: POCKETBASE_URL,
8
+ superuserEmail: POCKETBASE_SUPERUSER_EMAIL,
9
+ superuserPassword: POCKETBASE_SUPERUSER_PASSWORD,
10
+ api: { enabled: true }
11
+ });
12
+ ```
13
+
14
+ The following PocketBase routes are exposed:
15
+
16
+ /api/batch
17
+ /api/collections
18
+ /api/realtime
19
+ /api/files
20
+ /api/settings
21
+ /api/logs
22
+ /api/crons
23
+ /api/backups
24
+ /api/health
25
+
26
+ Any other routes added to the `src/routes/api` directory are handled by SvelteKit as normal routes.
Binary file
@@ -0,0 +1,3 @@
1
+ # allow crawling everything by default
2
+ User-agent: *
3
+ Disallow:
@@ -0,0 +1,4 @@
1
+ {
2
+ "description": "SvelteKit with a PocketBase backend, wired up and migrated",
3
+ "backend": true
4
+ }
@@ -0,0 +1,46 @@
1
+ import { beforeEach, afterEach, beforeAll } from 'vitest';
2
+ import supertest, { type Agent } from 'supertest';
3
+ import PocketBase from 'pocketbase-sveltekit';
4
+ import type { TestContext } from '@velastack/pocketbase';
5
+
6
+ const admin = new PocketBase(process.env.POCKETBASE_URL!) as App.Locals['admin'];
7
+ const pb = new PocketBase(process.env.POCKETBASE_URL!) as App.Locals['pb'];
8
+
9
+ const testUserPassword = 'password';
10
+
11
+ async function authenticateUser(agent: Agent, user: { email: string }) {
12
+ await agent.post('/login').type('form').send({
13
+ type: 'password',
14
+ email: user.email,
15
+ password: testUserPassword
16
+ });
17
+ }
18
+
19
+ beforeAll(async () => {
20
+ await admin
21
+ // @ts-ignore
22
+ .collection('_superusers')
23
+ .authWithPassword(
24
+ process.env.POCKETBASE_SUPERUSER_EMAIL!,
25
+ process.env.POCKETBASE_SUPERUSER_PASSWORD!
26
+ );
27
+ });
28
+
29
+ beforeEach(async (context: TestContext) => {
30
+ context.request = supertest(process.env.VITE_TEST_URL!);
31
+ context.agent = supertest.agent(process.env.VITE_TEST_URL!) as TestContext['agent'];
32
+ context.admin = admin;
33
+ context.pb = pb;
34
+ context.user = await context.admin.collection('users').create({
35
+ email: `test-${Math.random().toString(36).slice(2)}@example.com`,
36
+ password: testUserPassword,
37
+ passwordConfirm: testUserPassword
38
+ });
39
+ context.agent.authenticateUser = () => authenticateUser(context.agent, context.user);
40
+ await context.pb.collection('users').authWithPassword(context.user.email, testUserPassword);
41
+ });
42
+
43
+ afterEach(async (context: TestContext) => {
44
+ await context.pb.authStore.clear();
45
+ await context.admin.collection('users').delete(context.user.id);
46
+ });
@@ -0,0 +1,15 @@
1
+ {
2
+ "extends": "./.svelte-kit/tsconfig.json",
3
+ "compilerOptions": {
4
+ "rewriteRelativeImportExtensions": true,
5
+ "allowJs": true,
6
+ "checkJs": true,
7
+ "esModuleInterop": true,
8
+ "forceConsistentCasingInFileNames": true,
9
+ "resolveJsonModule": true,
10
+ "skipLibCheck": true,
11
+ "sourceMap": true,
12
+ "strict": true,
13
+ "moduleResolution": "bundler"
14
+ }
15
+ }
@@ -0,0 +1,17 @@
1
+ import { defineConfig } from 'vite';
2
+ import tailwindcss from '@tailwindcss/vite';
3
+ import { sveltekit } from '@sveltejs/kit/vite';
4
+ import adapter from '@sveltejs/adapter-auto';
5
+
6
+ export default defineConfig({
7
+ plugins: [
8
+ tailwindcss(),
9
+ sveltekit({
10
+ compilerOptions: {
11
+ runes: ({ filename }) =>
12
+ filename.split(/[/\\]/).includes('node_modules') ? undefined : true
13
+ },
14
+ adapter: adapter()
15
+ })
16
+ ]
17
+ });
@@ -0,0 +1,15 @@
1
+ import { defineConfig, mergeConfig } from 'vitest/config';
2
+ import viteConfig from './vite.config';
3
+
4
+ export default mergeConfig(
5
+ viteConfig,
6
+ defineConfig({
7
+ test: {
8
+ name: 'server',
9
+ environment: 'node',
10
+ include: ['src/**/*.{test,spec}.{js,ts}'],
11
+ exclude: ['src/**/*.svelte.{test,spec}.{js,ts}'],
12
+ setupFiles: ['test/setup.ts']
13
+ }
14
+ })
15
+ );
@@ -0,0 +1,3 @@
1
+ package.json
2
+ .meta.json
3
+ .turbo
@@ -0,0 +1,9 @@
1
+ # Package Managers
2
+ package-lock.json
3
+ pnpm-lock.yaml
4
+ yarn.lock
5
+ bun.lock
6
+ bun.lockb
7
+
8
+ # Miscellaneous
9
+ /static/
@@ -0,0 +1,15 @@
1
+ {
2
+ "useTabs": true,
3
+ "singleQuote": true,
4
+ "trailingComma": "none",
5
+ "printWidth": 100,
6
+ "plugins": ["prettier-plugin-svelte"],
7
+ "overrides": [
8
+ {
9
+ "files": "*.svelte",
10
+ "options": {
11
+ "parser": "svelte"
12
+ }
13
+ }
14
+ ]
15
+ }
@@ -0,0 +1,3 @@
1
+ {
2
+ "recommendations": ["svelte.svelte-vscode", "bradlc.vscode-tailwindcss"]
3
+ }
@@ -0,0 +1,5 @@
1
+ {
2
+ "files.associations": {
3
+ "*.css": "tailwindcss"
4
+ }
5
+ }
@@ -0,0 +1,23 @@
1
+ node_modules
2
+
3
+ # Output
4
+ .output
5
+ .vercel
6
+ .netlify
7
+ .wrangler
8
+ /.svelte-kit
9
+ /build
10
+
11
+ # OS
12
+ .DS_Store
13
+ Thumbs.db
14
+
15
+ # Env
16
+ .env
17
+ .env.*
18
+ !.env.example
19
+ !.env.test
20
+
21
+ # Vite
22
+ vite.config.js.timestamp-*
23
+ vite.config.ts.timestamp-*
@@ -0,0 +1 @@
1
+ engine-strict=true
@@ -0,0 +1,16 @@
1
+ {
2
+ "$schema": "https://shadcn-svelte.com/schema.json",
3
+ "tailwind": {
4
+ "css": "src/app.css",
5
+ "baseColor": "slate"
6
+ },
7
+ "aliases": {
8
+ "components": "$lib/components",
9
+ "utils": "$lib/utils",
10
+ "ui": "$lib/components/ui",
11
+ "hooks": "$lib/hooks",
12
+ "lib": "$lib"
13
+ },
14
+ "typescript": true,
15
+ "registry": "https://shadcn-svelte.com/registry"
16
+ }
@@ -0,0 +1,44 @@
1
+ {
2
+ "name": "~TODO~",
3
+ "private": true,
4
+ "version": "0.0.1",
5
+ "type": "module",
6
+ "engines": {
7
+ "node": "^20.19.0 || >=22.12.0"
8
+ },
9
+ "scripts": {
10
+ "dev": "vite dev",
11
+ "build": "vite build",
12
+ "preview": "vite preview",
13
+ "prepare": "svelte-kit sync || echo \"\"",
14
+ "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
15
+ "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
16
+ "lint": "prettier --check .",
17
+ "format": "prettier --write ."
18
+ },
19
+ "devDependencies": {
20
+ "@lucide/svelte": "^1.8.0",
21
+ "@sveltejs/adapter-static": "^3.0.10",
22
+ "@sveltejs/kit": "^2.63.0",
23
+ "@sveltejs/vite-plugin-svelte": "^7.1.2",
24
+ "@tailwindcss/forms": "^0.5.11",
25
+ "@tailwindcss/typography": "^0.5.19",
26
+ "@tailwindcss/vite": "^4.3.0",
27
+ "clsx": "^2.1.1",
28
+ "mode-watcher": "^1.1.0",
29
+ "prettier": "^3.9.6",
30
+ "prettier-plugin-svelte": "^4.1.1",
31
+ "shadcn-svelte": "^1.2.7",
32
+ "svelte": "^5.56.10",
33
+ "svelte-check": "^4.6.0",
34
+ "svelte-meta-tags": "^4.6.0",
35
+ "svelte-sonner": "^1.1.0",
36
+ "tailwind-merge": "^3.5.0",
37
+ "tailwind-variants": "^3.2.2",
38
+ "tailwindcss": "^4.3.0",
39
+ "tw-animate-css": "^1.3.5",
40
+ "typescript": "^6.0.3",
41
+ "vela": "^~VELA_VERSION~",
42
+ "vite": "^8.0.16"
43
+ }
44
+ }