diff --git a/.env.alpha b/.env.alpha
new file mode 100644
index 0000000..255f919
--- /dev/null
+++ b/.env.alpha
@@ -0,0 +1,15 @@
+APP_NAME=Lean 101 Clients API
+CLIENT_NAME=Hunter Premium Produce
+CLIENT_EMAIL=alex@lean-101.com
+CLIENT_PASSWORD=JBBwVCDqmPA7
+CLIENT_TENANT_ID=hunter-premium-produce
+ADMIN_NAME=Lean 101
+ADMIN_EMAIL=matt@lean-101.com
+ADMIN_PASSWORD=XgHvUju6BYQZ
+AUTH_SECRET=735895b72fcc87b601b1e68bb614b65c876cf7b4516c9a3872b0cc7a98dbde5f
+ORIGIN=https://clients.lean-101.com.au
+PUBLIC_API_BASE_URL=https://clients.lean-101.com.au
+INTERNAL_API_BASE_URL=http://backend:8000
+CORS_ALLOW_ORIGINS=https://clients.lean-101.com.au
+CLIENTS_APP_PORT=808
+DATABASE_URL=sqlite:////data/data_entry_app.db
diff --git a/.env.alpha.example b/.env.alpha.example
index 0f130c0..a230ba5 100644
--- a/.env.alpha.example
+++ b/.env.alpha.example
@@ -7,9 +7,9 @@ ADMIN_NAME=Lean 101
ADMIN_EMAIL=admin@lean101.local
ADMIN_PASSWORD=lean101-admin
AUTH_SECRET=replace-with-a-long-random-secret
-ORIGIN=https://clients.lean-101.com
-PUBLIC_API_BASE_URL=https://clients.lean-101.com
+ORIGIN=https://clients.lean-101.com.au
+PUBLIC_API_BASE_URL=https://clients.lean-101.com.au
INTERNAL_API_BASE_URL=http://backend:8000
-CORS_ALLOW_ORIGINS=https://clients.lean-101.com
+CORS_ALLOW_ORIGINS=https://clients.lean-101.com.au
CLIENTS_APP_PORT=8081
DATABASE_URL=sqlite:////data/data_entry_app.db
diff --git a/README.md b/README.md
index fb7e000..968bbba 100644
--- a/README.md
+++ b/README.md
@@ -40,7 +40,7 @@ The frontend now supports:
- `PUBLIC_API_BASE_URL` for browser requests
- `INTERNAL_API_BASE_URL` for server-side SvelteKit requests inside Docker
-This is important for a same-domain deployment such as `https://clients.lean-101.com`, where the browser should call the public domain while the frontend container should call the backend container directly.
+This is important for a same-domain deployment such as `https://clients.lean-101.com.au`, where the browser should call the public domain while the frontend container should call the backend container directly.
### Example `/srv` deploy
@@ -56,7 +56,7 @@ This follows the same external pattern as your website container:
- one compose project under `/srv/lean101-clients`
- one host-facing port, `8081`, for the app
-- your existing public reverse proxy forwards `clients.lean-101.com` to `127.0.0.1:8081`
+- your existing public reverse proxy forwards `clients.lean-101.com.au` to `127.0.0.1:8081`
If your server already has a host-level nginx handling domains and TLS, use `deploy/nginx/clients.lean-101.proxy.conf` as the upstream template and point the domain at `http://127.0.0.1:8081`.
diff --git a/deploy/nginx/clients.lean-101.proxy.conf b/deploy/nginx/clients.lean-101.proxy.conf
index aa3e0e7..fd580bd 100644
--- a/deploy/nginx/clients.lean-101.proxy.conf
+++ b/deploy/nginx/clients.lean-101.proxy.conf
@@ -1,6 +1,6 @@
server {
listen 80;
- server_name clients.lean-101.com;
+ server_name clients.lean-101.com.au;
location / {
proxy_pass http://127.0.0.1:8081;
diff --git a/docker-compose.alpha.yml b/docker-compose.alpha.yml
index 615f486..bb283fb 100644
--- a/docker-compose.alpha.yml
+++ b/docker-compose.alpha.yml
@@ -16,7 +16,7 @@ services:
ADMIN_EMAIL: ${ADMIN_EMAIL:-admin@lean101.local}
ADMIN_PASSWORD: ${ADMIN_PASSWORD:-lean101-admin}
AUTH_SECRET: ${AUTH_SECRET:-change-me-in-production}
- CORS_ALLOW_ORIGINS: ${CORS_ALLOW_ORIGINS:-https://clients.lean-101.com}
+ CORS_ALLOW_ORIGINS: ${CORS_ALLOW_ORIGINS:-https://clients.lean-101.com.au}
volumes:
- clients_app_data:/data
healthcheck:
@@ -33,10 +33,10 @@ services:
dockerfile: frontend/Dockerfile
restart: unless-stopped
environment:
- ORIGIN: ${ORIGIN:-https://clients.lean-101.com}
+ ORIGIN: ${ORIGIN:-https://clients.lean-101.com.au}
PORT: 3000
HOST: 0.0.0.0
- PUBLIC_API_BASE_URL: ${PUBLIC_API_BASE_URL:-https://clients.lean-101.com}
+ PUBLIC_API_BASE_URL: ${PUBLIC_API_BASE_URL:-https://clients.lean-101.com.au}
INTERNAL_API_BASE_URL: ${INTERNAL_API_BASE_URL:-http://backend:8000}
PUBLIC_API_PORT: ${PUBLIC_API_PORT:-8000}
depends_on:
diff --git a/docker-compose.yml b/docker-compose.yml
index 615f486..bb283fb 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -16,7 +16,7 @@ services:
ADMIN_EMAIL: ${ADMIN_EMAIL:-admin@lean101.local}
ADMIN_PASSWORD: ${ADMIN_PASSWORD:-lean101-admin}
AUTH_SECRET: ${AUTH_SECRET:-change-me-in-production}
- CORS_ALLOW_ORIGINS: ${CORS_ALLOW_ORIGINS:-https://clients.lean-101.com}
+ CORS_ALLOW_ORIGINS: ${CORS_ALLOW_ORIGINS:-https://clients.lean-101.com.au}
volumes:
- clients_app_data:/data
healthcheck:
@@ -33,10 +33,10 @@ services:
dockerfile: frontend/Dockerfile
restart: unless-stopped
environment:
- ORIGIN: ${ORIGIN:-https://clients.lean-101.com}
+ ORIGIN: ${ORIGIN:-https://clients.lean-101.com.au}
PORT: 3000
HOST: 0.0.0.0
- PUBLIC_API_BASE_URL: ${PUBLIC_API_BASE_URL:-https://clients.lean-101.com}
+ PUBLIC_API_BASE_URL: ${PUBLIC_API_BASE_URL:-https://clients.lean-101.com.au}
INTERNAL_API_BASE_URL: ${INTERNAL_API_BASE_URL:-http://backend:8000}
PUBLIC_API_PORT: ${PUBLIC_API_PORT:-8000}
depends_on:
diff --git a/frontend/src/routes/+page.svelte b/frontend/src/routes/+page.svelte
index 06f285f..be2682e 100644
--- a/frontend/src/routes/+page.svelte
+++ b/frontend/src/routes/+page.svelte
@@ -32,6 +32,7 @@
let password = $state('changeme');
let isLoggingIn = $state(false);
let loginError = $state('');
+ let passwordInput: HTMLInputElement | null = null;
const currentYear = new Date().getFullYear();
const appVersion = `v${packageInfo.version}`;
const releaseStage = 'Alpha';
@@ -48,11 +49,37 @@
clientSession.set(session);
} catch (error) {
loginError = error instanceof Error ? error.message : 'Unable to sign in';
+ triggerPasswordShake();
} finally {
isLoggingIn = false;
}
}
+ function triggerPasswordShake() {
+ if (typeof window === 'undefined' || !passwordInput) {
+ return;
+ }
+
+ if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) {
+ return;
+ }
+
+ passwordInput.animate(
+ [
+ { transform: 'translateX(0)' },
+ { transform: 'translateX(-8px)' },
+ { transform: 'translateX(8px)' },
+ { transform: 'translateX(-6px)' },
+ { transform: 'translateX(6px)' },
+ { transform: 'translateX(0)' }
+ ],
+ {
+ duration: 360,
+ easing: 'cubic-bezier(0.36, 0.07, 0.19, 0.97)'
+ }
+ );
+ }
+
function currency(value: number | null | undefined, digits = 2) {
if (value === null || value === undefined) {
return 'N/A';
@@ -325,9 +352,15 @@
-