From 6b86b997561efa9535cf359e94d1b4db4fd27843 Mon Sep 17 00:00:00 2001 From: Wmj Ismail Date: Mon, 10 Aug 2026 12:59:26 +0800 Subject: [PATCH] Add FalahOS design & app building guide for AI agents --- FALAHOS-DESIGN-GUIDE.md | 796 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 796 insertions(+) create mode 100644 FALAHOS-DESIGN-GUIDE.md diff --git a/FALAHOS-DESIGN-GUIDE.md b/FALAHOS-DESIGN-GUIDE.md new file mode 100644 index 0000000..5f6d2a3 --- /dev/null +++ b/FALAHOS-DESIGN-GUIDE.md @@ -0,0 +1,796 @@ +# FalahOS Design & App Building Guide + +> **Purpose:** This document defines the FalahOS design system, UI/UX principles, and Svelte 5 implementation patterns. AI agents building or extending FalahOS apps MUST read and follow this guide. Every design decision in this guide exists for a reason — deviations should be the exception, not the habit. + +--- + +## Table of Contents + +1. [Design Philosophy](#1-design-philosophy) +2. [Visual Identity](#2-visual-identity) +3. [Component Architecture](#3-component-architecture) +4. [UX Patterns](#4-ux-patterns) +5. [Svelte 5 Implementation](#5-svelte-5-implementation) +6. [PWA Configuration](#6-pwa-configuration) +7. [Animation & Motion](#7-animation--motion) +8. [Data & State Management](#8-data--state-management) +9. [Responsive Design](#9-responsive-design) +10. [Accessibility](#10-accessibility) +11. [Performance Budget](#11-performance-budget) +12. [Project Structure](#12-project-structure) +13. [AI Agent Workflow](#13-ai-agent-workflow) +14. [Checklist: New Feature](#14-checklist-new-feature) + +--- + +## 1. Design Philosophy + +### Core Principles + +| Principle | Meaning | +|-----------|---------| +| **Sovereign by default** | No third-party dependencies for core UX. No tracking, no analytics, no external fonts where avoidable. The app works without a server. | +| **Privacy by design** | Zero data collection. All processing is on-device. No accounts. No cookies. | +| **Premium minimalism** | High visual polish with minimal UI chrome. Every pixel earns its place. Dark theme is not a fallback — it's the canvas. | +| **Islamic essence, modern execution** | The spiritual context informs every design choice without resorting to clichés. Gold and green are not decorations — they carry meaning. | +| **Offline-first** | The app must be useful without internet. Core features (Qibla, Tasbih, Quran cache, Hijri) work fully offline after initial load. | + +### Design Tenets + +1. **Dark canvas, warm accents** — The background is always dark (#070A0D). Light is used sparingly as accent, never as background. +2. **Typographic hierarchy** — Three voices: Cinzel (display/serif — authority), DM Sans (body — readability), JetBrains Mono (data/meta — precision). +3. **Geometric intentionality** — The golden ratio, polygons, and clip-paths aren't decorative gimmicks. They echo Islamic geometric tradition in a modern way. +4. **Motion with purpose** — Transitions are brief (150-300ms). They communicate state change, not entertain. No idle animations. +5. **Content over chrome** — Navigation is compact (tabs, not hamburger menus). Cards have thin borders, not heavy shadows. Information density is high for the feature, low for chrome. + +--- + +## 2. Visual Identity + +### 2.1 Color System + +```css +:root { + /* Backgrounds — deep navy-black */ + --bg: #070A0D; /* Page background */ + --surface: #0D1117; /* Card/section surface */ + --card: #111820; /* Elevated cards, overlays */ + --border: #1E2A36; /* Subtle borders */ + + /* Text */ + --text: #E8E6E1; /* Primary body text */ + --text-dim: #8B8B8B; /* Secondary/meta text */ + --text-muted: #5A5A5A; /* Footer/legal text */ + + /* Accents */ + --gold: #C9A84C; /* Primary accent — faith, value, premium */ + --gold-light: #D4B95A; /* Gold hover/gradient variant */ + --gold-dim: rgba(201, 168, 76, 0.15); /* Gold background tint */ + + --emerald: #2ECC71; /* Secondary accent — growth, success, nature */ + --green-dim: rgba(46, 204, 113, 0.12); /* Emerald background tint */ + + /* Functional */ + --error: #E74C3C; /* Errors, destructive actions */ + --warning: #F39C12; /* Warnings */ + --info: #3498DB; /* Information */ +} +``` + +**Usage rules:** +- Gold is for UI that carries spiritual/faith significance: active tabs, prayer times, headings, CTAs +- Emerald is for positive states, success indicators, confirmed data +- Never use white (#FFFFFF) — use `--text` (#E8E6E1) as the lightest color +- Never use pure black (#000000) — use `--bg` (#070A0D) +- Borders are always `--border`, never a lighter shade +- Text on gold backgrounds uses `--bg` (inverted for contrast) + +### 2.2 Typography + +**Voice assignments:** + +| Font | Role | Weight | Size Scale | +|------|------|--------|------------| +| **Cinzel** (Google Fonts, serif) | Display headings, brand name, primary CTAs | 700-900 | 1.0-2.0rem | +| **DM Sans** (Google Fonts, sans-serif) | Body text, labels, paragraph content | 300-700 | 0.75-1.1rem | +| **JetBrains Mono** (Google Fonts, monospace) | Tab labels, meta text, footer, data values | 400-500 | 0.55-0.75rem | + +**Implementation:** +```css +/* app.html */ + + +/* CSS variables */ +--font-display: 'Cinzel', serif; +--font-body: 'DM Sans', sans-serif; +--font-mono: 'JetBrains Mono', monospace; +``` + +**Type scale:** +``` +1.8rem — Brand name (Cinzel 900) +1.3rem — Tab icons (emoji/unicode) +1.0rem — Card headings (Cinzel 700) +0.85rem — Body text (DM Sans 400) +0.72rem — Button labels, data (JetBrains Mono 500) +0.62rem — Tab text, footer (JetBrains Mono 400, 0.25em letter-spacing) +``` + +### 2.3 Spacing System + +Use a 4px baseline grid. Common values: + +```css +--space-xs: 4px; +--space-sm: 8px; +--space-md: 12px; +--space-lg: 16px; +--space-xl: 20px; +--space-2xl: 24px; +``` + +- Card padding: 20px (`--space-xl`) +- Section gaps: 12px (`--space-md`) +- Tab padding: 8px 10px (`--space-sm` variable) +- Content max-width: 480px (mobile-first) + +### 2.4 Surfaces & Depth + +```css +/* Card */ +.card { + background: var(--surface); /* or var(--card) for elevated cards */ + border: 1px solid var(--border); + border-radius: 16px; + padding: 20px; + box-shadow: + 0 4px 20px rgba(0, 0, 0, 0.3), + inset 0 1px 0 rgba(201, 168, 76, 0.05); +} + +/* Header / Nav bar — glassmorphism */ +header, .tab-nav, .footer { + background: rgba(12, 17, 23, 0.8); + backdrop-filter: blur(20px); + -webkit-backdrop-filter: blur(20px); + border-bottom: 1px solid var(--border); + border-radius: 0 0 24px 24px; +} +``` + +### 2.5 Background Effects + +**Noise texture** — applied via SVG filter on the `` pseudoelement: + +```css +body::before { + content: ''; + position: fixed; inset: 0; z-index: 0; + background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' ... %3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23noise)' opacity='0.04'/%3E%3C/svg%3E"); + pointer-events: none; + opacity: 0.4; +} +``` + +**Geometric light** — subtle radial gradients for depth: + +```css +body::after { + content: ''; + position: fixed; inset: 0; z-index: 0; + background: + radial-gradient(ellipse 80% 60% at 50% -10%, rgba(201,168,76,0.06) 0%, transparent 60%), + radial-gradient(ellipse 40% 40% at 90% 80%, rgba(46,204,113,0.04) 0%, transparent 50%), + radial-gradient(ellipse 60% 40% at -10% 50%, rgba(201,168,76,0.03) 0%, transparent 50%); + pointer-events: none; +} +``` + +--- + +## 3. Component Architecture + +### 3.1 Component Categories + +| Category | Convention | Examples | +|----------|------------|----------| +| **Layout** | `src/lib/layout/` | `Header.svelte`, `TabNav.svelte`, `Footer.svelte` | +| **Feature** | `src/lib/*.svelte` (flat) | `PrayerTimes.svelte`, `Qibla.svelte`, `Quran.svelte` | +| **UI Primitives** | Inline in feature or global styles | Card, button (via `:global()`) | +| **State/Data** | Local to component via `$state` runes | No global stores unless truly shared | + +### 3.2 Component Structure (Svelte 5) + +```svelte + + + +
+

🕌 Title

+ +
+ + +``` + +### 3.3 The Card Pattern + +The `.card` is the primary content container. Every feature tab is wrapped in one or more cards: + +```svelte +
+

📖 Feature Title

+
+ +
+
+``` + +Cards stack vertically with `12px` (`--space-md`) margin-bottom. + +### 3.4 Button System + +```svelte + + + + + + + + +``` + +**Primary button style:** +```css +button.primary { + font-family: var(--font-display); /* Cinzel */ + font-size: 0.82rem; + letter-spacing: 0.18em; + text-transform: uppercase; + padding: 10px 20px; + background: linear-gradient(135deg, var(--gold), var(--gold-light)); + color: var(--bg); + border-radius: 10px; + clip-path: polygon(0 0, calc(100% - 10px) 0, 100% 10px, 100% 100%, 10px 100%, 0 calc(100% - 10px)); + /* Dipped corner is a signature FalahOS detail */ +} +``` + +--- + +## 4. UX Patterns + +### 4.1 Tab Navigation + +The app uses a **flat tab bar** — no nested navigation, no hamburger menus, no back buttons. All features are one tap away. + +```svelte + + +
+ {#if activeTab === 0} + + {:else if activeTab === 1} + + {/each} +
+``` + +**Keyboard navigation:** ArrowLeft/ArrowRight cycles tabs: +```js +function handleKeydown(e) { + if (e.key === 'ArrowRight') activeTab = (activeTab + 1) % tabs.length; + if (e.key === 'ArrowLeft') activeTab = (activeTab - 1 + tabs.length) % tabs.length; +} +``` + +### 4.2 Loading States + +Every data-dependent component must handle four states: + +```svelte +{#if loading} +
Loading...
+{:else if error} +
{error}
+{:else if data} + +{:else} +
No data available
+{/if} +``` + +- **Loading:** Show a centered, subtle loading indicator (no spinners — use text or skeleton) +- **Error:** Show error message in gold/red with a retry action +- **Empty:** Show a helpful message, not a blank screen +- **Success:** Render the data + +### 4.3 Notification Permissions + +Prayer notification toggle uses a graceful permission flow: + +```js +async function requestNotificationPermission() { + if (!('Notification' in window)) return false; + const perm = await Notification.requestPermission(); + if (perm === 'granted') { + // Schedule prayer notifications + } else if (perm === 'denied') { + // Show a non-blocking hint about browser settings + } +} +``` + +Notifications are opt-in, never assumed. The checkbox is visible but unchecked by default. + +### 4.4 Data Persistence + +Use `localStorage` for user preferences only. Never use it for app data. + +```js +function saveMethod() { + localStorage.setItem('prayer_method', String(method)); +} + +function loadSettings() { + const saved = localStorage.getItem('prayer_method'); + if (saved) method = parseInt(saved, 10); +} +``` + +--- + +## 5. Svelte 5 Implementation + +### 5.1 Runes — The Only Pattern + +Use `$state` for all reactive declarations. Never use `let` alone for reactive variables. + +```svelte + +``` + +### 5.2 $derived + +Use `$derived` for computed values that depend on state: + +```svelte + +``` + +### 5.3 $effect + +Use `$effect` sparingly — only for side effects that interact with the outside world (localStorage, DOM APIs, timers): + +```svelte + +``` + +**Do NOT use `$effect` for:** +- Derived values (use `$derived`) +- Event handlers (use `onclick`, `oninput`, etc.) +- Fetch calls triggered by state changes (use async functions called from events) + +### 5.4 No Stores Unless Necessary + +For single-page tab apps, component-local state with `$state` is sufficent. Only introduce Svelte stores (or `$state` in a shared module) when two or more unrelated components need the same reactive value. + +If needed, use a `.js` module with module-level `$state`: + +```js +// src/lib/stores.js +let activeTab = $state(0); +export function getActiveTab() { return activeTab; } +export function setActiveTab(n) { activeTab = n; } +``` + +### 5.5 Event Handling + +Use modern Svelte 5 event syntax (not `on:click`): + +```svelte + + +` for reliable touch behavior + +--- + +## 10. Accessibility + +### 10.1 ARIA Labels + +```svelte +