feat: add Bir Nur (Well of Light) waqf dashboard + reframe Support with bank trustee giving model

- New BirNur.svelte: waqf configuration based on companions' model
- Reframed Support.svelte with dual-track: bank trustee giving + app support
- Updated App.svelte to add Waqf tab (tab 14) between WorshipTracker and Support
- Model inspired by Uthman's Well of Rumah and Abdur Rahman bin Auf's productive endowment
This commit is contained in:
2026-08-08 16:54:51 +08:00
parent b4e9e85f89
commit feb5f1f03b
28 changed files with 6360 additions and 405 deletions
+127
View File
@@ -0,0 +1,127 @@
# ──────────────────────────────────────────────
# Nūr — Muslim Companion · Nginx SPA Config
# Target: moslem02.falahos.my (Cloudflare proxied)
# ──────────────────────────────────────────────
upstream backend_prayer {
# Placeholder for future API upstream (e.g. aladhan.com proxy)
keepalive 32;
}
server {
listen 80;
listen [::]:80;
server_name moslem02.falahos.my;
# ── Cloudflare real-ip ─────────────────────
# Cloudflare sends visitor IP via CF-Connecting-IP header.
# Uncomment and populate with current CF IP ranges:
# https://www.cloudflare.com/ips-v4 / ips-v6
# real_ip_header CF-Connecting-IP;
# real_ip_recursive on;
# set_real_ip_from 173.245.48.0/20;
# set_real_ip_from 103.21.244.0/22;
# … (keep current by syncing from cloudflare.com/ips-v4)
# ── Static root ────────────────────────────
root /var/www/nur-muslim-companion;
index index.html;
error_page 404 =200 /index.html;
# ── Gzip ───────────────────────────────────
gzip on;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 5;
gzip_min_length 512;
gzip_types
text/html
text/plain
text/css
text/javascript
application/javascript
application/json
application/manifest+json
image/svg+xml
image/x-icon
font/woff2;
# ── Security headers ───────────────────────
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "0" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
# HSTS — only enable once TLS is confirmed working via Cloudflare
# add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
# ── SPA fallback ───────────────────────────
# All routes serve index.html; actual 404s are impossible.
# index.html is NOT cached so updates reach clients immediately.
location / {
try_files $uri $uri/ /index.html;
# index.html: no-cache (must always fetch fresh version)
add_header Cache-Control "no-cache, must-revalidate" always;
}
# ── Hashed static assets (immutable) ───────
# Vite emits content-hashed filenames: assets/index-abc123.js
# These can be cached forever on CDN and browsers alike.
location /assets/ {
expires 1y;
add_header Cache-Control "public, immutable, max-age=31536000" always;
access_log off;
}
# ── Favicon ────────────────────────────────
location = /favicon.svg {
expires 7d;
add_header Cache-Control "public, max-age=604800" always;
access_log off;
}
# ── PWA manifest ───────────────────────────
location = /manifest.webmanifest {
expires 1d;
add_header Cache-Control "public, max-age=86400" always;
add_header Content-Type "application/manifest+json";
}
# ── Service Worker ─────────────────────────
# Service-worker script must NOT be cached and must be served
# from its own scope (root). Cloudflare bypasses cache for sw.js.
location /sw.js {
add_header Cache-Control "no-cache, no-store, must-revalidate" always;
add_header Service-Worker-Allowed "/";
expires off;
access_log off;
}
# ── PWA app shell (workbox precached) ──────
# workbox-*.js, worker-*.js are versioned hashed files:
location ~* \.(js|css|woff2)$ {
expires 1y;
add_header Cache-Control "public, immutable, max-age=31536000" always;
}
# ── Icon files ─────────────────────────────
location ~* \.(png|ico)$ {
expires 1y;
add_header Cache-Control "public, immutable, max-age=31536000" always;
access_log off;
}
# ── Deny hidden files ──────────────────────
location ~ /\. {
deny all;
access_log off;
log_not_found off;
}
# ── Deny node_modules & src ────────────────
location ~ ^/(node_modules|src)/ {
deny all;
access_log off;
}
}