Init new PWA Repository

This commit is contained in:
2026-02-12 20:32:06 +00:00
parent 898ceaf004
commit fb1d4a0e61
25 changed files with 4158 additions and 2 deletions

25
.gitignore vendored Normal file
View File

@@ -0,0 +1,25 @@
node_modules
# Output
.output
.vercel
.netlify
.wrangler
/.svelte-kit
/build
# OS
.DS_Store
Thumbs.db
# Env
.env
.env.*
!.env.example
!.env.test
# Vite
vite.config.js.timestamp-*
vite.config.ts.timestamp-*
# Playwright
test-results

1
.npmrc Normal file
View File

@@ -0,0 +1 @@
engine-strict=true

9
.prettierignore Normal file
View File

@@ -0,0 +1,9 @@
# Package Managers
package-lock.json
pnpm-lock.yaml
yarn.lock
bun.lock
bun.lockb
# Miscellaneous
/static/

15
.prettierrc Normal file
View File

@@ -0,0 +1,15 @@
{
"useTabs": true,
"singleQuote": true,
"trailingComma": "none",
"printWidth": 100,
"plugins": ["prettier-plugin-svelte"],
"overrides": [
{
"files": "*.svelte",
"options": {
"parser": "svelte"
}
}
]
}

View File

@@ -1,3 +1,42 @@
# web-pwa # sv
OwlBoard web application Everything you need to build a Svelte project, powered by [`sv`](https://github.com/sveltejs/cli).
## Creating a project
If you're seeing this, you've probably already done this step. Congrats!
```sh
# create a new project
npx sv create my-app
```
To recreate this project with the same configuration:
```sh
# recreate this project
npx sv create --template minimal --types ts --add prettier eslint sveltekit-adapter="adapter:static" vitest="usages:unit,component" playwright --install npm .
```
## Developing
Once you've created a project and installed dependencies with `npm install` (or `pnpm install` or `yarn`), start a development server:
```sh
npm run dev
# or start the server and open the app in a new browser tab
npm run dev -- --open
```
## Building
To create a production version of your app:
```sh
npm run build
```
You can preview the production build with `npm run preview`.
> To deploy your app, you may need to install an [adapter](https://svelte.dev/docs/kit/adapters) for your target environment.

6
e2e/demo.test.ts Normal file
View File

@@ -0,0 +1,6 @@
import { expect, test } from '@playwright/test';
test('home page has expected h1', async ({ page }) => {
await page.goto('/');
await expect(page.locator('h1')).toBeVisible();
});

39
eslint.config.js Normal file
View File

@@ -0,0 +1,39 @@
import prettier from 'eslint-config-prettier';
import path from 'node:path';
import { includeIgnoreFile } from '@eslint/compat';
import js from '@eslint/js';
import svelte from 'eslint-plugin-svelte';
import { defineConfig } from 'eslint/config';
import globals from 'globals';
import ts from 'typescript-eslint';
import svelteConfig from './svelte.config.js';
const gitignorePath = path.resolve(import.meta.dirname, '.gitignore');
export default defineConfig(
includeIgnoreFile(gitignorePath),
js.configs.recommended,
...ts.configs.recommended,
...svelte.configs.recommended,
prettier,
...svelte.configs.prettier,
{
languageOptions: { globals: { ...globals.browser, ...globals.node } },
rules: {
// typescript-eslint strongly recommend that you do not use the no-undef lint rule on TypeScript projects.
// see: https://typescript-eslint.io/troubleshooting/faqs/eslint/#i-get-errors-from-the-no-undef-rule-about-global-variables-not-being-defined-even-though-there-are-no-typescript-errors
'no-undef': 'off'
}
},
{
files: ['**/*.svelte', '**/*.svelte.ts', '**/*.svelte.js'],
languageOptions: {
parserOptions: {
projectService: true,
extraFileExtensions: ['.svelte'],
parser: ts.parser,
svelteConfig
}
}
}
);

3849
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

43
package.json Normal file
View File

@@ -0,0 +1,43 @@
{
"name": "web-pwa",
"private": true,
"version": "0.0.1",
"type": "module",
"scripts": {
"dev": "vite dev",
"build": "vite build",
"preview": "vite preview",
"prepare": "svelte-kit sync || echo ''",
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
"lint": "prettier --check . && eslint .",
"format": "prettier --write .",
"test:unit": "vitest",
"test": "npm run test:unit -- --run && npm run test:e2e",
"test:e2e": "playwright test"
},
"devDependencies": {
"@eslint/compat": "^2.0.2",
"@eslint/js": "^9.39.2",
"@playwright/test": "^1.58.1",
"@sveltejs/adapter-static": "^3.0.10",
"@sveltejs/kit": "^2.50.2",
"@sveltejs/vite-plugin-svelte": "^6.2.4",
"@types/node": "^22",
"@vitest/browser-playwright": "^4.0.18",
"eslint": "^9.39.2",
"eslint-config-prettier": "^10.1.8",
"eslint-plugin-svelte": "^3.14.0",
"globals": "^17.3.0",
"playwright": "^1.58.1",
"prettier": "^3.8.1",
"prettier-plugin-svelte": "^3.4.1",
"svelte": "^5.49.2",
"svelte-check": "^4.3.6",
"typescript": "^5.9.3",
"typescript-eslint": "^8.54.0",
"vite": "^7.3.1",
"vitest": "^4.0.18",
"vitest-browser-svelte": "^2.0.2"
}
}

6
playwright.config.ts Normal file
View File

@@ -0,0 +1,6 @@
import { defineConfig } from '@playwright/test';
export default defineConfig({
webServer: { command: 'npm run build && npm run preview', port: 4173 },
testDir: 'e2e'
});

13
src/app.d.ts vendored Normal file
View File

@@ -0,0 +1,13 @@
// See https://svelte.dev/docs/kit/types#app.d.ts
// for information about these interfaces
declare global {
namespace App {
// interface Error {}
// interface Locals {}
// interface PageData {}
// interface PageState {}
// interface Platform {}
}
}
export {};

11
src/app.html Normal file
View File

@@ -0,0 +1,11 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
%sveltekit.head%
</head>
<body data-sveltekit-preload-data="hover">
<div style="display: contents">%sveltekit.body%</div>
</body>
</html>

7
src/demo.spec.ts Normal file
View File

@@ -0,0 +1,7 @@
import { describe, it, expect } from 'vitest';
describe('sum test', () => {
it('adds 1 + 2 to equal 3', () => {
expect(1 + 2).toBe(3);
});
});

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" viewBox="0 0 562.09 562.09"><defs><radialGradient xlink:href="#a" id="b" cx="256" cy="256" r="254.04" fx="256" fy="256" gradientTransform="translate(27 27)" gradientUnits="userSpaceOnUse"/><linearGradient id="a"><stop offset="0" stop-color="#2b343c"/><stop offset="1" stop-color="#404c55"/></linearGradient></defs><path fill="url(#b)" d="M694.32 283a411.32 393.92 0 0 1-410.68 393.92 411.32 393.92 0 0 1-411.96-392.69 411.32 393.92 0 0 1 409.4-395.14A411.32 393.92 0 0 1 694.3 280.54" transform="translate(-1.96 -1.96)"/><path fill="#4fd1d1" d="M281.04 126.9a154.15 154.15 0 0 0-118.28 55.3c10.93 9.51 23.77 16.07 38.94 19.9 6.89 1.73 6.85 1.73 12.03-.5 38.46-16.63 95.89-16.65 135.05-.05 10.2 4.32 34.35-4.98 50.75-19.1a154.15 154.15 0 0 0-118.49-55.56Zm-124.8 63.66a154.15 154.15 0 0 0-29.35 90.48A154.15 154.15 0 0 0 281.04 435.2 154.15 154.15 0 0 0 435.2 281.04a154.15 154.15 0 0 0-29.05-90.07 73.62 73.62 0 0 1-13.68 35.91l-2.2 3.06 1.04 1.4c56.5 76.5-11.05 171.27-89.91 126.14-1.94-1.1-3.65-1.85-3.82-1.66-.28.3-8.15 15.1-13.95 26.23-2.62 5.03-2.1 5.05-4.83-.19-7.09-13.54-13.93-26.29-14.1-26.29-.13 0-1.76.88-3.64 1.96-78.05 44.66-146.96-50.65-90.49-125.15 1.15-1.51 1.63-2.46 1.4-2.77-9.13-12.43-14.48-25.78-15.72-39.05zm66.68 43.93c-7.51.09-15.24 1.99-22.97 5.82-52.33 25.93-25.2 106.53 32.13 95.47 13.54-2.61 25.17-10.22 33.38-21.84 1.87-2.64 2.5-3.28 2.8-2.86.21.3 3.18 5.36 6.59 11.26 7.23 12.51 6.09 11.61 8.77 6.94a779.9 779.9 0 0 1 10.84-18.47c.16-.18 1.4 1.3 2.76 3.3 23.88 35.05 78.26 27.43 91.16-12.77 12.66-39.44-25.19-76.87-64.65-63.94-18 5.9-29.87 18.78-41.48 45.01l-1.03 2.32-2.05-4.65c-13.07-29.69-33.71-45.83-56.25-45.59zm113.4 26.8a24.66 24.66 0 0 1 18.3 7.34c17.55 17.55.52 46.82-23.82 40.92-12.5-3.03-20.51-15.91-17.88-28.8 2.44-11.96 12.67-19.16 23.4-19.46zm-112.33.05c12.66-.7 25.2 8.42 26.1 23.14 1 16.36-14.99 29.32-30.93 25.07-18.55-4.96-24.82-27.25-11.45-40.76a24.63 24.63 0 0 1 16.28-7.45zm9.22 7.31a6.32 6.32 0 0 0-4.45 2.28c-4.83 5.74 1.9 13.72 8.44 10.02a6.71 6.71 0 0 0 3.3-5.71c0-4.18-3.7-6.84-7.29-6.59zm94.93.1c-4.67.29-7.45 4.9-5.4 9.44 1.56 3.42 6.33 4.84 9.36 2.77 5.59-3.8 3.62-11.8-3-12.21a7.71 7.71 0 0 0-.96 0z"/></svg>

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" viewBox="0 0 1991.09 508.09"><defs><radialGradient xlink:href="#a" id="b" cx="256" cy="256" r="254.04" fx="256" fy="256" gradientUnits="userSpaceOnUse"/><linearGradient id="a"><stop offset="0" stop-color="#2b343c"/><stop offset="1" stop-color="#404c55"/></linearGradient></defs><circle cx="256" cy="256" r="254.04" fill="url(#b)" transform="translate(-1.96 -1.96)"/><path fill="#4fd1d1" d="M254.04 99.9a154.15 154.15 0 0 0-118.28 55.3c10.93 9.51 23.77 16.07 38.94 19.9 6.89 1.73 6.85 1.73 12.03-.5 38.46-16.63 95.89-16.65 135.05-.05 10.2 4.32 34.35-4.98 50.75-19.1a154.15 154.15 0 0 0-118.49-55.56Zm-124.8 63.66a154.15 154.15 0 0 0-29.35 90.48A154.15 154.15 0 0 0 254.04 408.2 154.15 154.15 0 0 0 408.2 254.04a154.15 154.15 0 0 0-29.05-90.07 73.62 73.62 0 0 1-13.68 35.91l-2.2 3.06 1.04 1.4c56.5 76.5-11.05 171.27-89.91 126.14-1.94-1.1-3.65-1.85-3.82-1.66-.28.3-8.15 15.1-13.95 26.23-2.62 5.03-2.1 5.05-4.83-.19-7.09-13.54-13.93-26.29-14.1-26.29-.13 0-1.76.88-3.64 1.96-78.06 44.67-146.97-50.65-90.5-125.15 1.15-1.51 1.63-2.46 1.4-2.77-9.13-12.43-14.48-25.78-15.72-39.05zm66.68 43.93c-7.51.09-15.24 1.99-22.97 5.82-52.33 25.93-25.2 106.53 32.13 95.47 13.54-2.61 25.17-10.22 33.38-21.84 1.87-2.64 2.5-3.28 2.8-2.86.21.3 3.18 5.36 6.59 11.26 7.23 12.51 6.09 11.61 8.77 6.94a779.9 779.9 0 0 1 10.84-18.47c.16-.18 1.4 1.3 2.76 3.3 23.88 35.05 78.26 27.43 91.16-12.77 12.66-39.44-25.19-76.87-64.65-63.94-18 5.9-29.87 18.78-41.48 45.01l-1.03 2.32-2.05-4.65c-13.07-29.69-33.71-45.83-56.25-45.59zm113.4 26.8a24.66 24.66 0 0 1 18.3 7.34c17.55 17.55.52 46.82-23.82 40.92-12.5-3.03-20.51-15.91-17.88-28.8 2.44-11.96 12.67-19.16 23.4-19.46zm-112.33.05c12.66-.7 25.2 8.42 26.1 23.14 1 16.36-14.99 29.32-30.93 25.07-18.55-4.96-24.82-27.25-11.45-40.76a24.63 24.63 0 0 1 16.28-7.45zm9.22 7.31a6.32 6.32 0 0 0-4.45 2.28c-4.83 5.74 1.9 13.72 8.44 10.02a6.71 6.71 0 0 0 3.3-5.71c0-4.18-3.7-6.84-7.29-6.59zm94.93.1c-4.67.29-7.45 4.9-5.4 9.44 1.56 3.42 6.33 4.84 9.36 2.77 5.59-3.8 3.62-11.8-3-12.21a7.71 7.71 0 0 0-.96 0z"/><g fill="#ebebeb" aria-label="OwlBoard" font-family="URW Gothic" font-size="306.67" letter-spacing="0" style="line-height:1;text-align:center;white-space:pre"><path d="M649.11 27.13c-67.46 0-119.6 51.21-119.6 117.45 0 65.63 52.75 117.15 119.3 117.15 65.93 0 116.84-51.22 116.84-117.15 0-65.32-51.83-117.45-116.54-117.45zm-.6 40.48c42 0 74.82 33.73 74.82 77.28 0 43.85-31.9 76.36-74.83 76.36s-76.67-33.74-76.67-76.67c0-43.85 33.12-76.97 76.67-76.97zm189.2 190.13h25.15l32.81-110.1 32.2 110.1h25.46l61.33-169.9h-43.55L940.14 191.5l-27.9-103.65h-32.51L851.2 191.5 820.85 87.85h-43.86zm195.35 0h40.79V31.11h-40.79z" font-weight="600" style="-inkscape-font-specification:&quot;URW Gothic Semi-Bold&quot;" transform="translate(40.6 109.62)"/><path d="M1113.4 257.74h56.13c30.36 0 47.53-3.37 61.94-11.96 15.95-9.81 25.46-29.75 25.46-53.05 0-27.91-11.66-44.78-38.03-55.82 17.48-9.81 25.15-24.53 25.15-46.92 0-19.62-7.36-36.18-20.24-45.69-12.88-9.2-29.75-13.19-57.35-13.19h-53.05zm22.7-20.55v-88.01h26.99c26.68 0 40.17 1.84 49.68 6.44 13.5 6.75 21.16 20.24 21.16 38.33 0 15.64-7.06 29.44-17.79 34.96-10.73 5.83-26.07 8.28-49.07 8.28zm0-108.56V51.66h27.3c23.3 0 35.87 2.15 44.46 7.97 7.97 5.22 13.19 17.18 13.19 30.67 0 15.64-6.14 27.3-17.48 32.5-9.5 4.3-19.32 5.83-39.87 5.83zm230.92-42.62c-49.99 0-88.01 37.72-88.01 86.78 0 51.83 37.72 88.94 89.85 88.94 49.07 0 85.25-37.11 85.25-87.4 0-51.22-36.49-88.32-87.09-88.32zm0 20.85c37.1 0 64.1 28.52 64.1 67.77 0 38.64-26.38 66.24-62.87 66.24-38.64 0-66.24-27.9-66.24-67.46 0-38.03 27.9-66.55 65.01-66.55zm290.1-16.87h-22.69v29.75c-16.86-23.3-37.1-33.73-66.24-33.73-50.29 0-88.32 38.02-88.32 88.32 0 50.29 38.34 87.4 90.16 87.4 28.52 0 46.31-9.2 64.4-33.43v29.44h22.7zm-88.31 16.87c37.1 0 65.62 28.83 65.62 66.24 0 38.33-28.2 67.77-64.4 67.77-38.02 0-67.16-29.74-67.16-68.08a65.83 65.83 0 0 1 65.94-65.93zm126.96 150.88h22.7v-97.83c-.32-30.36 16.55-49.06 47.53-51.52V86.01c-24.23 1.22-38.65 9.5-47.54 27.9V90h-22.7zm253.61-226.63h-22.7v85.56c-16.55-19.93-39.55-30.66-65.93-30.66-50.9 0-89.24 38.02-89.24 88.32 0 49.68 39.56 87.4 91.4 87.4 28.2 0 46.6-10.12 63.78-34.35v30.36h22.7zm-89.24 75.75c37.41 0 67.47 29.75 67.47 66.55 0 37.1-29.44 67.46-65.32 67.46-38.64 0-67.78-29.13-67.78-67.77 0-36.8 29.14-66.24 65.63-66.24z" style="-inkscape-font-specification:&quot;URW Gothic&quot;" transform="translate(40.6 109.62)"/></g></svg>

After

Width:  |  Height:  |  Size: 4.4 KiB

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" viewBox="0 0 508.09 508.09"><defs><radialGradient xlink:href="#a" id="b" cx="256" cy="256" r="254.04" fx="256" fy="256" gradientUnits="userSpaceOnUse"/><linearGradient id="a"><stop offset="0" stop-color="#2b343c"/><stop offset="1" stop-color="#404c55"/></linearGradient></defs><circle cx="256" cy="256" r="254.04" fill="url(#b)" transform="translate(-1.96 -1.96)"/><path fill="#4fd1d1" d="M254.04 99.9a154.15 154.15 0 0 0-118.28 55.3c10.93 9.51 23.77 16.07 38.94 19.9 6.89 1.73 6.85 1.73 12.03-.5 38.46-16.63 95.89-16.65 135.05-.05 10.2 4.32 34.35-4.98 50.75-19.1a154.15 154.15 0 0 0-118.49-55.56Zm-124.8 63.66a154.15 154.15 0 0 0-29.35 90.48A154.15 154.15 0 0 0 254.04 408.2 154.15 154.15 0 0 0 408.2 254.04a154.15 154.15 0 0 0-29.05-90.07 73.62 73.62 0 0 1-13.68 35.91l-2.2 3.06 1.04 1.4c56.5 76.5-11.05 171.27-89.91 126.14-1.94-1.1-3.65-1.85-3.82-1.66-.28.3-8.15 15.1-13.95 26.23-2.62 5.03-2.1 5.05-4.83-.19-7.09-13.54-13.93-26.29-14.1-26.29-.13 0-1.76.88-3.64 1.96-78.06 44.67-146.97-50.65-90.5-125.15 1.15-1.51 1.63-2.46 1.4-2.77-9.13-12.43-14.48-25.78-15.72-39.05zm66.68 43.93c-7.51.09-15.24 1.99-22.97 5.82-52.33 25.93-25.2 106.53 32.13 95.47 13.54-2.61 25.17-10.22 33.38-21.84 1.87-2.64 2.5-3.28 2.8-2.86.21.3 3.18 5.36 6.59 11.26 7.23 12.51 6.09 11.61 8.77 6.94a779.9 779.9 0 0 1 10.84-18.47c.16-.18 1.4 1.3 2.76 3.3 23.88 35.05 78.26 27.43 91.16-12.77 12.66-39.44-25.19-76.87-64.65-63.94-18 5.9-29.87 18.78-41.48 45.01l-1.03 2.32-2.05-4.65c-13.07-29.69-33.71-45.83-56.25-45.59zm113.4 26.8a24.66 24.66 0 0 1 18.3 7.34c17.55 17.55.52 46.82-23.82 40.92-12.5-3.03-20.51-15.91-17.88-28.8 2.44-11.96 12.67-19.16 23.4-19.46zm-112.33.05c12.66-.7 25.2 8.42 26.1 23.14 1 16.36-14.99 29.32-30.93 25.07-18.55-4.96-24.82-27.25-11.45-40.76a24.63 24.63 0 0 1 16.28-7.45zm9.22 7.31a6.32 6.32 0 0 0-4.45 2.28c-4.83 5.74 1.9 13.72 8.44 10.02a6.71 6.71 0 0 0 3.3-5.71c0-4.18-3.7-6.84-7.29-6.59zm94.93.1c-4.67.29-7.45 4.9-5.4 9.44 1.56 3.42 6.33 4.84 9.36 2.77 5.59-3.8 3.62-11.8-3-12.21a7.71 7.71 0 0 0-.96 0z"/></svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

11
src/routes/+layout.svelte Normal file
View File

@@ -0,0 +1,11 @@
<script lang="ts">
import favicon from '$lib/assets/round-logo.svg';
let { children } = $props();
</script>
<svelte:head>
<link rel="icon" href={favicon} />
</svelte:head>
{@render children()}

2
src/routes/+page.svelte Normal file
View File

@@ -0,0 +1,2 @@
<h1>Welcome to SvelteKit</h1>
<p>Visit <a href="https://svelte.dev/docs/kit">svelte.dev/docs/kit</a> to read the documentation</p>

View File

@@ -0,0 +1,13 @@
import { page } from 'vitest/browser';
import { describe, expect, it } from 'vitest';
import { render } from 'vitest-browser-svelte';
import Page from './+page.svelte';
describe('/+page.svelte', () => {
it('should render h1', async () => {
render(Page);
const heading = page.getByRole('heading', { level: 1 });
await expect.element(heading).toBeInTheDocument();
});
});

BIN
static/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 127 KiB

3
static/robots.txt Normal file
View File

@@ -0,0 +1,3 @@
# allow crawling everything by default
User-agent: *
Disallow:

6
svelte.config.js Normal file
View File

@@ -0,0 +1,6 @@
import adapter from '@sveltejs/adapter-static';
/** @type {import('@sveltejs/kit').Config} */
const config = { kit: { adapter: adapter() } };
export default config;

20
tsconfig.json Normal file
View File

@@ -0,0 +1,20 @@
{
"extends": "./.svelte-kit/tsconfig.json",
"compilerOptions": {
"rewriteRelativeImportExtensions": true,
"allowJs": true,
"checkJs": true,
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"resolveJsonModule": true,
"skipLibCheck": true,
"sourceMap": true,
"strict": true,
"moduleResolution": "bundler"
}
// Path aliases are handled by https://svelte.dev/docs/kit/configuration#alias
// except $lib which is handled by https://svelte.dev/docs/kit/configuration#files
//
// To make changes to top-level options such as include and exclude, we recommend extending
// the generated config; see https://svelte.dev/docs/kit/configuration#typescript
}

35
vite.config.ts Normal file
View File

@@ -0,0 +1,35 @@
import { defineConfig } from 'vitest/config';
import { playwright } from '@vitest/browser-playwright';
import { sveltekit } from '@sveltejs/kit/vite';
export default defineConfig({
plugins: [sveltekit()],
test: {
expect: { requireAssertions: true },
projects: [
{
extends: './vite.config.ts',
test: {
name: 'client',
browser: {
enabled: true,
provider: playwright(),
instances: [{ browser: 'chromium', headless: true }]
},
include: ['src/**/*.svelte.{test,spec}.{js,ts}'],
exclude: ['src/lib/server/**']
}
},
{
extends: './vite.config.ts',
test: {
name: 'server',
environment: 'node',
include: ['src/**/*.{test,spec}.{js,ts}'],
exclude: ['src/**/*.svelte.{test,spec}.{js,ts}']
}
}
]
}
});