diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e4531b4..cf7f630 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -10,10 +10,10 @@ jobs: name: Lint + Tests steps: - name: Checkout code - uses: actions/checkout@v4 + uses: actions/checkout@v6 - name: Checkout legal content from being repo - uses: actions/checkout@v4 + uses: actions/checkout@v6 with: repository: mp2ez/being ref: development @@ -30,7 +30,7 @@ jobs: rm -rf .tmp-being - name: Setup Node.js - uses: actions/setup-node@v4 + uses: actions/setup-node@v6 with: node-version: '20' cache: 'npm' @@ -59,10 +59,10 @@ jobs: NOTION_WAITLIST_DB_ID: test-db-not-used steps: - name: Checkout code - uses: actions/checkout@v4 + uses: actions/checkout@v6 - name: Checkout legal content from being repo - uses: actions/checkout@v4 + uses: actions/checkout@v6 with: repository: mp2ez/being ref: development @@ -79,7 +79,7 @@ jobs: rm -rf .tmp-being - name: Setup Node.js - uses: actions/setup-node@v4 + uses: actions/setup-node@v6 with: node-version: '20' cache: 'npm' @@ -92,6 +92,10 @@ jobs: run: npm ci - name: Build worker with OpenNext + env: + # Match the production build mode so the / → /home redirect path + # and the rest of the (main) layout behavior is what gets smoked. + NEXT_PUBLIC_SHOW_FULL_SITE: 'true' run: npx opennextjs-cloudflare build - name: Start wrangler dev in background @@ -101,8 +105,9 @@ jobs: - name: Wait for worker readiness run: | + # Probe /home (always 200) instead of / (now 307 under SHOW_FULL_SITE=true). for i in {1..30}; do - if curl -sf -o /dev/null http://localhost:8787/; then + if curl -sf -o /dev/null http://localhost:8787/home; then echo "Worker ready after ${i} attempt(s)" exit 0 fi @@ -158,6 +163,63 @@ jobs: fi echo "GET /crisis smoke + headers smoke passed." + - name: GET / redirects to /home (production codepath) + run: | + HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" http://localhost:8787/) + if [ "$HTTP_CODE" != "307" ] && [ "$HTTP_CODE" != "308" ]; then + echo "Expected 307/308 redirect from /, got $HTTP_CODE" + exit 1 + fi + LOCATION=$(curl -sI http://localhost:8787/ | grep -i '^location:' | tr -d '\r' | awk '{print $2}') + if [ "$LOCATION" != "/home" ]; then + echo "Expected location: /home, got '$LOCATION'" + exit 1 + fi + echo "GET / redirect smoke passed." + + - name: GET /home renders + run: | + curl -s -i -o /tmp/home.txt http://localhost:8787/home + if ! head -1 /tmp/home.txt | grep -q " 200 "; then + echo "Expected HTTP 200 on /home" + exit 1 + fi + if ! grep -qi "Mindfulness with meaning" /tmp/home.txt; then + echo "Expected 'Mindfulness with meaning' in /home body" + exit 1 + fi + echo "GET /home smoke passed." + + - name: GET /download renders pre-launch waitlist + run: | + curl -s -i -o /tmp/download.txt http://localhost:8787/download + if ! head -1 /tmp/download.txt | grep -q " 200 "; then + echo "Expected HTTP 200 on /download" + exit 1 + fi + if ! grep -qi "Coming soon" /tmp/download.txt; then + echo "Expected 'Coming soon' in /download body (pre-launch waitlist marker)" + exit 1 + fi + if grep -qi "graphic needed" /tmp/download.txt; then + echo "Found 'graphic needed' placeholder text — /download regressed to old badges" + exit 1 + fi + echo "GET /download smoke passed." + + - name: GET /privacy/multi-state renders + run: | + curl -s -i -o /tmp/multistate.txt http://localhost:8787/privacy/multi-state + if ! head -1 /tmp/multistate.txt | grep -q " 200 "; then + echo "Expected HTTP 200 on /privacy/multi-state" + exit 1 + fi + if ! grep -qi "Multi-State" /tmp/multistate.txt; then + echo "Expected 'Multi-State' in /privacy/multi-state body" + exit 1 + fi + echo "GET /privacy/multi-state smoke passed." + - name: Stop wrangler dev if: always() run: | diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 88679b3..2540605 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -14,10 +14,10 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@v4 + uses: actions/checkout@v6 - name: Checkout legal content from being repo - uses: actions/checkout@v4 + uses: actions/checkout@v6 with: repository: mp2ez/being ref: development @@ -34,7 +34,7 @@ jobs: rm -rf .tmp-being - name: Setup Node.js - uses: actions/setup-node@v4 + uses: actions/setup-node@v6 with: node-version: '20' cache: 'npm' @@ -56,8 +56,35 @@ jobs: NEXT_PUBLIC_SHOW_FULL_SITE: 'true' - name: Deploy to Cloudflare Workers - uses: cloudflare/wrangler-action@v3 + uses: cloudflare/wrangler-action@v4 with: apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }} accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }} command: deploy ${{ github.ref_name == 'preview' && '--env preview' || '' }} + + - name: Post-deploy smoke against live URL + run: | + URL="${{ github.ref_name == 'main' && 'https://being.fyi' || 'https://being-website-preview.palouselabs.workers.dev' }}" + echo "Smoke testing $URL ..." + # Brief wait for Cloudflare edge propagation after deploy + sleep 15 + # Cache-bust query param to avoid stale edge responses + CB="?cb=$(date +%s)" + # /home must return 200 + HOME_CODE=$(curl -s -o /dev/null -w "%{http_code}" "$URL/home$CB") + if [ "$HOME_CODE" != "200" ]; then + echo "FAIL: $URL/home returned $HOME_CODE (expected 200)" + exit 1 + fi + # /download must contain pre-launch marker (update at app launch) + if ! curl -sf "$URL/download$CB" | grep -q "Coming soon"; then + echo "FAIL: $URL/download body missing 'Coming soon' marker" + exit 1 + fi + # /privacy must serve security headers (HSTS proves the security + # headers pipeline is intact end-to-end through Cloudflare) + if ! curl -sI "$URL/privacy" | grep -qi "strict-transport-security"; then + echo "FAIL: $URL/privacy missing Strict-Transport-Security header" + exit 1 + fi + echo "Post-deploy smoke passed for $URL" diff --git a/app/(main)/features/page.tsx b/app/(main)/features/page.tsx index 8b8c4b7..d64437c 100644 --- a/app/(main)/features/page.tsx +++ b/app/(main)/features/page.tsx @@ -1,7 +1,12 @@ /** * Features Page - Being app capabilities * Professional SaaS Design - * Showcases daily check-ins, wellness self-assessments, crisis support, privacy + * Showcases daily check-ins, mood/wellbeing reflection tools, crisis-resource + * access, and privacy-first design. + * + * Copy is intentionally consumer-wellness register (not clinical). The + * page uses PHQ-9 and GAD-7 self-reflection tools but does NOT make + * detection or diagnostic claims — Being is not a SaMD. */ import BrainIcon from '@/components/shared/BrainIcon'; @@ -20,8 +25,9 @@ export default function FeaturesPage() { App Features
- Being combines ancient Stoic wisdom with modern mental health science. Daily check-ins, - wellness self-assessments, and crisis support, with privacy-first design and AES-256 encryption. + Being combines ancient Stoic wisdom with modern wellbeing research. Daily check-ins, + mood and anxiety reflection tools, and crisis-resource access, with privacy-first + design and AES-256 encryption.
@@ -127,26 +133,27 @@ export default function FeaturesPage() { - {/* Mental Health Self-Monitoring */} + {/* Mood & Wellbeing Tracking */}- Standardized self-assessments help you track your mental health patterns over time. - All data encrypted and stored locally on your device. + Research-based reflection tools help you track your mood and wellbeing patterns + over time. All data encrypted and stored locally on your device.
- The Patient Health Questionnaire-9 is a widely-used self-assessment questionnaire - for monitoring depression symptoms. Being uses exact PHQ-9 wording and scoring. + The Patient Health Questionnaire-9 is a widely-used self-reflection tool for + tracking mood patterns over time. Being uses the standard PHQ-9 wording so your + self-reported scores stay consistent, letting you track your own patterns.
- The Generalized Anxiety Disorder-7 scale helps you monitor anxiety symptoms over time. - Self-assessment tool with standardized scoring. + The Generalized Anxiety Disorder-7 scale is a widely-used self-reflection tool + for tracking anxious thought and feeling patterns over time.
Your safety is our top priority. Immediate access to crisis resources from every screen.
- One tap to connect with trained crisis counselors. Available 24/7/365. - Completely confidential. +
+ Call 988 or text HOME to 741741 to + connect with trained crisis counselors. Available 24/7/365. Completely confidential.
-✓ Less than 3 seconds from any screen to 988
✓ - Auto-triggered on PHQ-9 ≥20 or GAD-7 ≥15 + Surfaced immediately when self-assessment scores are elevated
✓ @@ -239,10 +246,10 @@ export default function FeaturesPage() {
- Your mental health data is yours. We protect it with AES-256 encryption + Your wellbeing data is yours. We protect it with AES-256 encryption and local-first storage.
- Military-grade encryption protects your check-ins, assessments, and journal entries. + AES-256 encryption protects your check-ins, self-assessments, and journal entries. Even if your device is compromised, your data remains secure.
- We don't sell, share, or monetize your mental health data. Ever. + We don't sell, share, or monetize your wellbeing data. Ever. Your privacy is not for sale.
- Experience Stoic Mindfulness with evidence-based self-monitoring tools. + Experience Stoic Mindfulness with research-based self-reflection tools. Start your 1 month free trial today.