Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,14 @@ jobs:
app_location: "./" # App source code path
api_location: "" # Api source code path - optional
output_location: "build" # Built app content directory - optional
# Not the default `npm run build`. `PUBLIC_`-prefixed values are inlined into the
# client bundle, and the tracked `.env` holds real PUBLIC_ADMIN_USERNAME /
# PUBLIC_ADMIN_PASSWORD values for local convenience. `.env.production` blanking
# them is what keeps the deployed bundle clean today — but that is a convention,
# not a check, and any mode file that simply omitted the keys would fall through to
# the real ones. `build:verified` blanks them AND fails the build if either string
# survives into build/, which is the only version of this that cannot rot.
app_build_command: "npm run build:verified"
###### End of Repository/Build Configurations ######

close_pull_request_job:
Expand Down
4 changes: 4 additions & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ node_modules
.env.*
!.env.example

# Rust crate for the desktop app: Cargo build output plus JSON that the Tauri
# CLI owns and rewrites. None of it is Prettier's to format.
/src-tauri

# Ignore files for PNPM, NPM and YARN
pnpm-lock.yaml
package-lock.json
Expand Down
77 changes: 75 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,16 +48,89 @@ You can preview the production build with `npm run preview`.

> To deploy your app, you may need to install an [adapter](https://kit.svelte.dev/docs/adapters) for your target environment.

## Desktop app

The same UI ships as a [Tauri](https://tauri.app) desktop app, using the system
WebView (WebView2 on Windows, WKWebView on macOS).

One-time setup: install [Rust](https://rustup.rs) and, on Windows, the
"Desktop development with C++" workload from the Visual Studio Installer.

```bash
# run the desktop app
npm run tauri:dev

# run it against a specific .env file
npm run tauri:dev -- --mode staging

# build installers into src-tauri/target/release/bundle/
npm run tauri:build -- --mode staging
```

Without `--mode`, `tauri:dev` looks for `.env.development` and `tauri:build` for
`.env.production`, matching Vite's own defaults. Neither has to exist — the
committed `.env` supplies the defaults, so a fresh clone builds as-is.

The window title and bundle identifier come from `PUBLIC_BRAND_NAME` in the
selected env file, so each brand installs as its own app. Set
`PUBLIC_DESKTOP_IDENTIFIER` to override the derived identifier.

App icons are compiled into the binary, so they are generated as a separate
step from `PUBLIC_LOGO_URL` (ideally a 1024x1024 PNG or an SVG). Non-square
logos are padded onto a square canvas automatically:

```bash
# regenerate the default icon set from the .env logo
npm run tauri:icon

# use another env file's logo instead
npm run tauri:icon -- --mode staging
```

Only the sizes listed in `bundle.icon` in
[src-tauri/tauri.conf.json](src-tauri/tauri.conf.json) are committed. The mobile
and Microsoft Store sizes `tauri icon` also emits are gitignored — rerun the
command if you start building for those targets.

The shell exposes **no native commands** to the page. It is a window around the same app the
browser loads, so a feature that works in one works in the other. It did once bridge to a
service running on the user's own machine — that is what a native process was needed for —
and when that service moved into a container with an HTTP API, the bridge had nothing left to
do. Adding a Tauri command means adding a capability the browser build will not have, so
prefer a backend endpoint unless the thing genuinely requires the OS.

## Deployment

To manual deploy as [Azure Static Web Apps](https://learn.microsoft.com/en-us/azure/static-web-apps/) at scale.
Deployed as an [Azure Static Web App](https://learn.microsoft.com/en-us/azure/static-web-apps/).
CI runs `npm run build:verified`, not `npm run build` — see the credential note below.

```bash
npm run build -- --mode production
npm run build:verified -- --mode production
npm install -g @azure/static-web-apps-cli
swa deploy ./build/ --env production --deployment-token {token}
```

### Credentials are never inlined into a distributed bundle

`PUBLIC_`-prefixed values are compiled into the client bundle, and the committed `.env`
holds real `PUBLIC_ADMIN_USERNAME` / `PUBLIC_ADMIN_PASSWORD` values for the local login
prefill. `npm run build:verified` blanks them for the build **and then searches the output
to prove they are gone**, failing rather than deploying a readable credential.

The verification is the part that matters. `.env.production` and `.env.staging` define both
keys as empty today, which is what keeps the deployed bundle clean — but that is a
convention nothing enforces, and any future mode file that simply omitted the keys would
fall through to `.env`'s real values. `npm run build` alone performs no such check.

`npm run dev` and `npm run tauri:dev` are untouched: nothing is distributed, so the prefill
stays useful.

Both distributable paths run the same check. `tauri:build` invokes
`scripts/build-frontend.mjs` as its `beforeBuildCommand`, and CI invokes it through
`build:verified`. The check began life on the desktop path only, where an installer anyone
could unpack made the risk obvious; a static bundle served over HTTPS is just as readable, so
it now guards both.

## Customization

Create a new `.env.production` file in the root folder.
Expand Down
230 changes: 230 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,15 @@
"scripts": {
"start": "npm run open-browser && vite",
"dev": "npm run open-browser && vite dev",
"dev:vite": "vite dev",
"open-browser": "start http://localhost:5015/",
"build": "vite build",
"build:verified": "node scripts/build-frontend.mjs",
"preview": "vite preview",
"tauri": "tauri",
"tauri:dev": "node scripts/tauri-run.mjs dev",
"tauri:build": "node scripts/tauri-run.mjs build",
"tauri:icon": "node scripts/generate-tauri-icon.mjs",
"check": "svelte-kit sync && svelte-check --tsconfig ./jsconfig.json",
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./jsconfig.json --watch",
"lint": "prettier --check . && eslint .",
Expand All @@ -20,6 +26,8 @@
"@sveltejs/adapter-auto": "^3.0.0",
"@sveltejs/kit": "^2.55.0",
"@sveltejs/vite-plugin-svelte": "^5.0.0",
"@tauri-apps/api": "^2.11.1",
"@tauri-apps/cli": "^2.11.4",
"@types/drawflow": "^0.0.10",
"eslint": "^8.28.0",
"eslint-config-prettier": "^9.0.0",
Expand Down
Loading