An open-source application designed to guide and support users in practicing the 4-7-8 breathing technique, an effective strategy for reducing anxiety and stress. The app would provide visual and auditory instructions to help synchronize breathing, creating a calming environment with soothing sounds and an intuitive interface. Additionally, it would include personalized reminders and progress tracking to encourage consistent practice. Its goal is to offer an accessible and effective tool to reassure users during moments of emotional or nervous distress.
You must have Git and NodeJS on your terminal.
git clone [Repository-Link]
cd Breathing-exerciseTo install dependencies:
npm installTo run project in development enviroment:
npm run devWhen embedding the Rainbow Relax application in another site (e.g., via an <iframe>), you can control specific behaviors via URL parameters.
- Type:
boolean(trueorfalse) - Default:
false - Description: Controls whether the Quick Escape instructions are visible when the app is embedded.
<iframe src="https://trevorproject.github.io/rainbow-relax/dev/?showquickescape=true" width="100%" height="600"></iframe>- Type:
string(URL) - Default: Trevor Project logo (language-specific)
- Description: Replace the default Trevor Project logo with your organization's logo.
- Requirements:
- Must be HTTPS URL
- Recommended: Square aspect ratio (1:1)
- Recommended size: 150x150px to 300x300px
- Supported formats: SVG, PNG, JPG, WebP
- Type:
string(URL) - Default: Default ambient background audio
- Description: Custom background audio that plays during the breathing exercise.
- Requirements:
- Must be HTTPS URL
- Supported formats: MP3, WAV, OGG
- Recommended: 2-5 minute loopable audio
- Type:
string(URL) - Default: Default instruction audio
- Description: Custom audio for breathing exercise instructions.
- Requirements:
- Must be HTTPS URL
- Supported formats: MP3, WAV, OGG
- Recommended: Clear, calm voice
- Type:
string(URL) - Default: Default guided voice
- Description: Custom guided voice for the breathing exercise.
- Requirements:
- Must be HTTPS URL
- Supported formats: MP3, WAV, OGG
- Recommended: Calm, soothing voice
- Type:
string(URL) - Default: Default breathing cycle audio
- Description: Custom audio for the breathing cycle (inhale, hold, exhale).
- Requirements:
- Must be HTTPS URL
- Supported formats: MP3, WAV, OGG
- Recommended: Subtle, non-distracting audio
- Type:
string(URL) or"no" - Default: Trevor Project donation page
- Description: Custom donation page URL or hide the donation button entirely.
- Special Values:
"no"- Hides the donation button- Any valid URL - Redirects to custom donation page
- Type:
string(URL) or"no" - Default: Trevor Project help page
- Description: Custom help page URL or hide the help button entirely.
- Special Values:
"no"- Hides the help button- Any valid URL - Redirects to custom help page
- Type:
string(URL) or"no" - Default: Trevor Project homepage
- Description: Custom home page URL when clicking the logo or hide the home link entirely.
- Special Values:
"no"- Removes home link functionality from logo- Any valid URL - Redirects to custom home page
<iframe src="https://rainbowrelax.web.app/" width="100%" height="600"></iframe><iframe
src="https://rainbowrelax.web.app/?logoUrl=https://example.com/logo.svg&backgroundUrl=https://example.com/ambient.mp3"
width="100%"
height="600">
</iframe>Hidden Navigation
<iframe
src="https://rainbowrelax.web.app/?donationUrl=no&helpUrl=no&homeUrl=no"
width="100%"
height="600">
</iframe><iframe
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"
width="100%"
height="600">
</iframe>- HTTPS Required: All custom asset URLs must use HTTPS for security
- CORS Headers: Ensure your asset servers include proper CORS headers
- CDN Recommended: Use a CDN for better performance and reliability
- Asset Optimization: Compress images and audio files for faster loading
- Format Priority: MP3 > WAV > OGG (for best browser compatibility)
- Quality: 128kbps is sufficient for most use cases
- Duration: Keep audio files under 5MB for optimal loading
- Testing: Test audio playback across different browsers and devices
- Format Priority: SVG > PNG > WebP > JPG
- Aspect Ratio: Square (1:1) works best with the existing layout
- Size Range: 150x150px to 300x300px recommended
- Fallback: The app will gracefully fall back to the default Trevor Project logo if your custom logo fails to load
When using special characters in URLs, ensure proper URL encoding:
// Example: URL with spaces and special characters
const logoUrl = encodeURIComponent('https://example.com/my logo (v2).svg');
const iframeSrc = `https://rainbowrelax.web.app/?logoUrl=${logoUrl}`;This project uses Firebase Hosting with three environments:
| Environment | Site Name | URL | Trigger |
|---|---|---|---|
| Development | rainbowrelax-dev |
https://rainbowrelax-dev.web.app | Push to main branch |
| QA | rainbowrelax-qa |
https://rainbowrelax-qa.web.app | Push tag qa-* |
| Production | rainbowrelax |
https://rainbowrelax.web.app | Push tag prod-* |
Deploys automatically when pushing to the main branch.
Steps:
- Commit your changes to the
mainbranch - Push to trigger deployment:
git push origin main
- View deployment: https://rainbowrelax-dev.web.app
- Monitor status: Actions > Deploy to Firebase DEV
Deploys when pushing a tag with the qa- prefix.
Steps:
- Create and push a QA tag:
git tag qa-0.4.14 git push origin qa-0.4.14
- View deployment: https://rainbowrelax-qa.web.app
- Monitor status: Actions > Deploy to Firebase QA
Deploys when pushing a tag with the prod- prefix.
Steps:
- Create and push a production tag:
git tag prod-v1.0 git push origin prod-v1.0
- View deployment: https://rainbowrelax.web.app
- Monitor status: Actions > Deploy to Firebase PROD
This project uses GitHub Actions for automated testing, linting, and deployment. All workflows run on pull requests and pushes to ensure code quality.
- Triggers: Pull requests and pushes to
main - Purpose: Validates code quality before merge
- Runs: ESLint and TypeScript compilation checks
- Duration: ~2-3 minutes
- Benefit: Prevents linting errors from reaching main branch, avoiding deployment failures
- Triggers: Pull requests and pushes to
main - Purpose: Run end-to-end tests to ensure functionality
- Runs:
- ESLint validation
- TypeScript compilation
- Build application
- Run all 84+ E2E tests (using 4 parallel workers)
- Duration: ~5-7 minutes
- Benefit: Comprehensive validation before merge and deployment
All deployment workflows use the reusable firebase-deployment.yml workflow which ensures:
- ✅ ESLint validation passes
- ✅ TypeScript compilation succeeds
- ✅ Application builds successfully
- ✅ Only validated code reaches production
- Triggers: Push to
mainbranch - Includes: Full validation (linting, TypeScript, build)
- Deploy: Automatically to
rainbowrelax-devsite - URL: https://rainbowrelax-dev.web.app
- Triggers: Push tag matching
qa-*pattern - Includes: Full validation before deployment
- Deploy: To
rainbowrelax-qasite - URL: https://rainbowrelax-qa.web.app
- Triggers: Push tag matching
prod-*pattern - Includes: Full validation before deployment
- Deploy: To
rainbowrelaxsite - URL: https://rainbowrelax.web.app
The CI/CD pipeline ensures that:
- Pull Requests: Lint validation and tests run automatically
- Main Branch: All validations pass before any deployment
- Deployments: Only validated code reaches DEV, QA, and PROD environments
This prevents duplicate PRs caused by linting failures and ensures only tested, validated code is deployed.
Before pushing, run locally to catch issues early:
npm run lint # Check for linting errors
npm run typecheck # Verify TypeScript compilation
npm run build # Verify build works
npm run test:e2e # Run all tests
npm run precommit # Run all checks (typecheck + lint + e2e tests)This project uses Playwright for end-to-end (E2E) testing. Playwright enables us to test the application by automating real browser interactions, ensuring that all features work correctly across different scenarios.
Our test suite includes 84+ E2E tests covering:
- Homepage loading and responsive design
- Navigation and language switching
- Breathing exercise functionality
- Widget configuration and customization
Tests run automatically in our CI/CD pipeline on every pull request and push to main, ensuring code quality before deployment. See the CI/CD Pipeline section for more details.
To run tests locally, use the following commands:
npm run test:e2e # Run all E2E tests
npm run test:e2e:ui # Interactive test runner (great for debugging!)
npm run test:e2e:headed # Run tests with visible browser
npm run test:e2e:report # View detailed test reportsPrerequisites:
- Install Playwright browsers:
npx playwright install chromium - Development server must be running (tests use
http://localhost:3000)
The app includes a bandwidth consent prompt that appears for users on slow connections (3G, 2G, slow-2G) before loading heavy assets. To test this feature locally:
-
Build with asset size calculation:
npm run build:performance
This builds the app and calculates total asset size, creating
dist/app-size.json. -
Start preview server:
npm run preview
-
Simulate slow connection in browser:
- Open DevTools (F12)
- Go to Console tab
- Run this code:
Object.defineProperty(navigator, 'connection', { writable: true, value: { effectiveType: '3g', downlink: 1.5, rtt: 600, saveData: false } }); location.reload();
-
Test the flow:
- Navigate to the app (should redirect to
/consent) - Consent prompt should appear with asset size estimate
- Test "Load Full Experience" button (should consent and redirect)
- Test "Stay Lightweight" button (should keep you blocked)
- Navigate to the app (should redirect to
- Slow Connection: Prompt appears with size estimate
- Fast Connection: Auto-consents and redirects (no prompt)
- No Connection API: Auto-consents (assumes fast connection)
- After Consent: App works normally, no re-prompt
After building, check the generated file:
cat dist/app-size.jsonFor comprehensive testing documentation, including:
- Writing your first test
- Test architecture and best practices
- Debugging tips and troubleshooting
- Common testing patterns
See the Testing README for complete details.
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.
Widget configuration parameters are automatically extracted from URL query parameters and preserved during navigation:
- Internal Navigation: All internal links use
useNavigateWithParams()hook orNavLinkWithParamscomponent - Parameter Preservation: These components automatically append widget config parameters to navigation URLs
- Supported Parameters:
logoUrl,backgroundUrl,instructionsUrl,guidedVoiceUrl,audioUrl,donationUrl,helpUrl,homeUrl
For Programmatic Navigation:
import { useNavigateWithParams } from '../hooks/useNavigateWithParams';
function MyComponent() {
const navigate = useNavigateWithParams();
// Navigate with automatic parameter preservation
navigate('/breathing');
navigate('/thank-you', { state: { minutes: 3 } });
}For Declarative Navigation:
import { NavLinkWithParams } from '../components/common/NavLinkWithParams';
function MyComponent() {
return (
<NavLinkWithParams to="/breathing">
Start Exercise
</NavLinkWithParams>
);
}External Links:
External links (donation, help, home) use standard <a> tags with target="_blank" and rel="noopener" for security.
navigationHelpers.ts: Utility functions for extracting and building URLs with widget parametersuseNavigateWithParams.ts: Custom hook wrapping React Router'suseNavigatewith parameter preservationNavLinkWithParams.tsx: Enhanced NavLink component with automatic parameter preservation
Español: Abraham Roldán (elle/they/them/él/he/him) English: Chris Camacho (elle/they/them)
- [The Trevor Project] https://www.thetrevorproject.org/