# Deploy a Svelte single-page app on Yeeted

A color contrast checker written as a **Svelte 5 + Vite** single-page app
(plain Svelte, not SvelteKit), with **no Dockerfile**: Yeeted detects Svelte
from `package.json`, runs `npm ci` from the lockfile and `npm run build`, and
serves `dist/` from nginx with a fallback to `index.html`, so deep links load
the app instead of a 404. SvelteKit is detected separately and is not what
this example covers.

The contrast math is the WCAG 2 formula in `src/contrast.js`, a plain module
with no Svelte imports. The same module backs the [Vue](contrast-vue.md) and
[Astro](contrast-astro.md) examples, and the
[Angular](contrast-angular.md) one carries a typed copy, so any
difference between them is the framework and its build, not the app.

Tests: `npm test` (node:test on the contrast math) · `./smoke.sh https://...`
against a deployment.

## Run locally

Use Node 22.12 or newer. From `node/contrast-svelte`:

```sh
npm ci
npm test
npm run dev
```

Open the URL Vite prints. `npm run build` writes the production files to
`dist/`, which is what the deployed image serves.

## Deploy and verify

Follow the [deployment walkthrough](getting-started.md). Deploy this
folder, including `package-lock.json` and `yeeted.yaml`, with no database.
Do not upload `node_modules/` or `dist/`; the build runs on Yeeted. The
manifest routes to port 80, where nginx listens.

```sh
sh smoke.sh "$PREVIEW_URL"
```

The script checks that the BUILT `index.html` is served (it references
`/assets/`, which the source file does not), that the JavaScript bundle holds
the contrast logic, and that a deep link such as `/check/navy-on-white` falls
back to the app.

## What the app does not do

Everything runs in the browser; there is no API and nothing is stored. The
calculator implements the WCAG 2 ratio only, not APCA or any other contrast
model, and it accepts `#rgb` and `#rrggbb` colors only.

[All examples](index.md) · [Deploy an example](getting-started.md)
