@@ -27,7 +27,7 @@ To run project in development enviroment:
2727
2828When embedding the Rainbow Relax application in another site (e.g., via an ` <iframe> ` ), you can control specific behaviors via URL parameters.
2929
30- ## ` showquickescape ` (optional )
30+ ## Quick Escape ( ` showquickescape ` )
3131
3232- ** Type:** ` boolean ` (` true ` or ` false ` )
3333- ** Default:** ` false `
@@ -39,6 +39,161 @@ When embedding the Rainbow Relax application in another site (e.g., via an `<ifr
3939<iframe src =" https://trevorproject.github.io/rainbow-relax/dev/?showquickescape=true" width =" 100%" height =" 600" ></iframe >
4040```
4141
42+ ## Asset Customization
43+
44+ ### Logo (` logoUrl ` )
45+
46+ - ** Type:** ` string ` (URL)
47+ - ** Default:** Trevor Project logo (language-specific)
48+ - ** Description:** Replace the default Trevor Project logo with your organization's logo.
49+ - ** Requirements:**
50+ - Must be HTTPS URL
51+ - Recommended: Square aspect ratio (1:1)
52+ - Recommended size: 150x150px to 300x300px
53+ - Supported formats: SVG, PNG, JPG, WebP
54+
55+ ### Audio Files
56+
57+ #### Background Audio (` backgroundUrl ` )
58+
59+ - ** Type:** ` string ` (URL)
60+ - ** Default:** Default ambient background audio
61+ - ** Description:** Custom background audio that plays during the breathing exercise.
62+ - ** Requirements:**
63+ - Must be HTTPS URL
64+ - Supported formats: MP3, WAV, OGG
65+ - Recommended: 2-5 minute loopable audio
66+
67+ #### Instructions Audio (` instructionsUrl ` )
68+
69+ - ** Type:** ` string ` (URL)
70+ - ** Default:** Default instruction audio
71+ - ** Description:** Custom audio for breathing exercise instructions.
72+ - ** Requirements:**
73+ - Must be HTTPS URL
74+ - Supported formats: MP3, WAV, OGG
75+ - Recommended: Clear, calm voice
76+
77+ #### Guided Voice (` guidedVoiceUrl ` )
78+
79+ - ** Type:** ` string ` (URL)
80+ - ** Default:** Default guided voice
81+ - ** Description:** Custom guided voice for the breathing exercise.
82+ - ** Requirements:**
83+ - Must be HTTPS URL
84+ - Supported formats: MP3, WAV, OGG
85+ - Recommended: Calm, soothing voice
86+
87+ #### Breathing Cycle Audio (` audioUrl ` )
88+
89+ - ** Type:** ` string ` (URL)
90+ - ** Default:** Default breathing cycle audio
91+ - ** Description:** Custom audio for the breathing cycle (inhale, hold, exhale).
92+ - ** Requirements:**
93+ - Must be HTTPS URL
94+ - Supported formats: MP3, WAV, OGG
95+ - Recommended: Subtle, non-distracting audio
96+
97+ ## Navigation Customization
98+
99+ ### Donation Button (` donationUrl ` )
100+
101+ - ** Type:** ` string ` (URL) or ` "no" `
102+ - ** Default:** Trevor Project donation page
103+ - ** Description:** Custom donation page URL or hide the donation button entirely.
104+ - ** Special Values:**
105+ - ` "no" ` - Hides the donation button
106+ - Any valid URL - Redirects to custom donation page
107+
108+ ### Help Button (` helpUrl ` )
109+
110+ - ** Type:** ` string ` (URL) or ` "no" `
111+ - ** Default:** Trevor Project help page
112+ - ** Description:** Custom help page URL or hide the help button entirely.
113+ - ** Special Values:**
114+ - ` "no" ` - Hides the help button
115+ - Any valid URL - Redirects to custom help page
116+
117+ ### Home/Logo Link (` homeUrl ` )
118+
119+ - ** Type:** ` string ` (URL) or ` "no" `
120+ - ** Default:** Trevor Project homepage
121+ - ** Description:** Custom home page URL when clicking the logo or hide the home link entirely.
122+ - ** Special Values:**
123+ - ` "no" ` - Removes home link functionality from logo
124+ - Any valid URL - Redirects to custom home page
125+
126+ ## Complete Examples
127+
128+ ### Basic Embed
129+
130+ ``` html
131+ <iframe src =" https://rainbowrelax.web.app/" width =" 100%" height =" 600" ></iframe >
132+ ```
133+
134+ ### Custom Branding
135+
136+ ``` html
137+ <iframe
138+ src =" https://rainbowrelax.web.app/?logoUrl=https://example.com/logo.svg&backgroundUrl=https://example.com/ambient.mp3"
139+ width =" 100%"
140+ height =" 600" >
141+ </iframe >
142+ ```
143+
144+ ### Hidden Navigation
145+
146+ ``` html
147+ <iframe
148+ src =" https://rainbowrelax.web.app/?donationUrl=no&helpUrl=no&homeUrl=no"
149+ width =" 100%"
150+ height =" 600" >
151+ </iframe >
152+ ```
153+
154+ ### All Parameters
155+
156+ ``` html
157+ <iframe
158+ src =" https://rainbowrelax.web.app/?showquickescape=true&logoUrl=https://example.com/logo.svg&backgroundUrl=https://example.com/ambient.mp3&instructionsUrl=https://example.com/instructions.mp3&guidedVoiceUrl=https://example.com/voice.mp3&audioUrl=https://example.com/breathing.mp3&donationUrl=https://example.com/donate&helpUrl=https://example.com/help&homeUrl=https://example.com"
159+ width =" 100%"
160+ height =" 600" >
161+ </iframe >
162+ ```
163+
164+ ## Best Practices & Notes
165+
166+ ### Security & Performance
167+
168+ - ** HTTPS Required:** All custom asset URLs must use HTTPS for security
169+ - ** CORS Headers:** Ensure your asset servers include proper CORS headers
170+ - ** CDN Recommended:** Use a CDN for better performance and reliability
171+ - ** Asset Optimization:** Compress images and audio files for faster loading
172+
173+ ### Audio Guidelines
174+
175+ - ** Format Priority:** MP3 > WAV > OGG (for best browser compatibility)
176+ - ** Quality:** 128kbps is sufficient for most use cases
177+ - ** Duration:** Keep audio files under 5MB for optimal loading
178+ - ** Testing:** Test audio playback across different browsers and devices
179+
180+ ### Image Guidelines
181+
182+ - ** Format Priority:** SVG > PNG > WebP > JPG
183+ - ** Aspect Ratio:** Square (1:1) works best with the existing layout
184+ - ** Size Range:** 150x150px to 300x300px recommended
185+ - ** Fallback:** The app will gracefully fall back to the default Trevor Project logo if your custom logo fails to load
186+
187+ ### URL Encoding
188+
189+ When using special characters in URLs, ensure proper URL encoding:
190+
191+ ``` javascript
192+ // Example: URL with spaces and special characters
193+ const logoUrl = encodeURIComponent (' https://example.com/my logo (v2).svg' );
194+ const iframeSrc = ` https://rainbowrelax.web.app/?logoUrl=${ logoUrl} ` ;
195+ ```
196+
42197# Deployment
43198
44199This project uses Firebase Hosting with three environments:
@@ -108,7 +263,7 @@ This project uses GitHub Actions for automated testing, linting, and deployment.
108263### 2. Playwright Tests (` playwright-tests.yml ` )
109264- ** Triggers** : Pull requests and pushes to ` main `
110265- ** Purpose** : Run end-to-end tests to ensure functionality
111- - ** Runs** :
266+ - ** Runs: **
112267 - ESLint validation
113268 - TypeScript compilation
114269 - Build application
@@ -157,11 +312,62 @@ Before pushing, run locally to catch issues early:
157312
158313``` bash
159314npm run lint # Check for linting errors
160- npx tsc --noEmit # Verify TypeScript compilation
315+ npm run typecheck # Verify TypeScript compilation
161316npm run build # Verify build works
162317npm run test:e2e # Run all tests
318+ npm run precommit # Run all checks (typecheck + lint + e2e tests)
163319```
164320
321+ ---
322+ ## Widget Parameter Persistence
323+
324+ The application automatically preserves widget configuration parameters across React Router navigation. This ensures that custom branding and configuration (logoUrl, audioUrl, etc.) persist when users navigate between pages.
325+
326+ ### How It Works
327+
328+ Widget configuration parameters are automatically extracted from URL query parameters and preserved during navigation:
329+
330+ - ** Internal Navigation** : All internal links use ` useNavigateWithParams() ` hook or ` NavLinkWithParams ` component
331+ - ** Parameter Preservation** : These components automatically append widget config parameters to navigation URLs
332+ - ** Supported Parameters** : ` logoUrl ` , ` backgroundUrl ` , ` instructionsUrl ` , ` guidedVoiceUrl ` , ` audioUrl ` , ` donationUrl ` , ` helpUrl ` , ` homeUrl `
333+
334+ ### Developer Usage
335+
336+ ** For Programmatic Navigation:**
337+ ``` typescript
338+ import { useNavigateWithParams } from ' ../hooks/useNavigateWithParams' ;
339+
340+ function MyComponent() {
341+ const navigate = useNavigateWithParams ();
342+
343+ // Navigate with automatic parameter preservation
344+ navigate (' /breathing' );
345+ navigate (' /thank-you' , { state: { minutes: 3 } });
346+ }
347+ ```
348+
349+ ** For Declarative Navigation:**
350+ ``` typescript
351+ import { NavLinkWithParams } from ' ../components/common/NavLinkWithParams' ;
352+
353+ function MyComponent() {
354+ return (
355+ < NavLinkWithParams to = " /breathing" >
356+ Start Exercise
357+ < / NavLinkWithParams >
358+ );
359+ }
360+ ```
361+
362+ ** External Links:**
363+ External links (donation, help, home) use standard ` <a> ` tags with ` target="_blank" ` and ` rel="noopener" ` for security.
364+
365+ ### Implementation Details
366+
367+ - ` navigationHelpers.ts ` : Utility functions for extracting and building URLs with widget parameters
368+ - ` useNavigateWithParams.ts ` : Custom hook wrapping React Router's ` useNavigate ` with parameter preservation
369+ - ` NavLinkWithParams.tsx ` : Enhanced NavLink component with automatic parameter preservation
370+
165371---
166372# Audio Credits
167373
0 commit comments