Skip to content
Back to skills

Sobriety Tools Guardian

ASecurity

Performance optimization and continuous improvement for sobriety.tools recovery app. Use for load time optimization, offline capability, crisis detection, performance monitoring, automated issue detection. Activate on "sobriety.tools", "recovery app perf", "crisis detection", "offline meetings", "HALT check-in", "sponsor contacts". NOT for general Next.js help, unrelated Cloudflare Workers, or non-recovery apps.

  • 2 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added September 24, 2026
toolsjavascripttypescriptgojavashellbashsqlreactnextjsgit

Works with

  • cli
  • api

Security analysis

A100/100

Pro scans all 8 files and shows the line behind each finding

Scanned September 24, 2026

npx -y skills add curiositech/port-daddy --skill sobriety-tools-guardian --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Sobriety Tools Guardian?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Sobriety Tools Guardian
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/curiositech-sobriety-tools-guardian-port-daddy/badge)](https://www.skillsdirectory.com/skills/curiositech-sobriety-tools-guardian-port-daddy)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
license: Apache-2.0
visibility: private
name: sobriety-tools-guardian
description: Performance optimization and continuous improvement for sobriety.tools recovery app. Use for load time optimization, offline capability, crisis detection, performance monitoring, automated issue detection. Activate on "sobriety.tools", "recovery app perf", "crisis detection", "offline meetings", "HALT check-in", "sponsor contacts". NOT for general Next.js help, unrelated Cloudflare Workers, or non-recovery apps.
allowed-tools: Read,Write,Edit,Bash,Grep,Glob,Task,WebFetch
metadata:
  category: Recovery & Wellness
  tags:
  - sobriety
  - tools
  - protection
  - recovery
  - safety
  recognition-cues: []
  expectancies: []
  decision-cues: []
  adaptive-workarounds: []
  execution-pattern: sequential
  needs-cdm: true
io-contract:
  kind: tool
  inputs:
    - name: app_url
      type: string
      required: false
      description: "sobriety.tools URL to audit (default: https://sobriety.tools)"
    - name: audit_type
      type: enum
      required: false
      description: Performance audit scope
      values:
        - lighthouse
        - cache-health
        - query-times
        - asset-sizes
        - service-worker
        - crisis-detection
        - full
    - name: crisis_detection_enabled
      type: boolean
      required: false
      description: Enable automated crisis pattern detection in journal sentiment
    - name: performance_threshold
      type: number
      required: false
      description: "Lighthouse performance score threshold (0-1, default: 0.9) for regression detection"
    - name: create_issues
      type: boolean
      required: false
      description: Automatically file GitHub issues for detected regressions
    - name: metrics_output
      type: enum
      required: false
      description: Output format for performance metrics
      values:
        - json
        - markdown
        - csv
  outputs:
    - name: performance_score
      type: number
      description: Lighthouse performance score (0-1)
    - name: critical_metrics
      type: object
      description: TTFB, FCP, LCP, TTI, contacts_visible, meeting_results, checkin_interactive timings in milliseconds
    - name: cache_health
      type: object
      description: Cloudflare KV cache hit rates and Supabase query latencies
    - name: crisis_signals
      type: array
      description: Detected crisis indicators (anger spikes, isolation patterns, time distortion) with user IDs and severity
    - name: regressions
      type: array
      description: Performance regressions detected with severity and suggested fixes
    - name: github_issues_created
      type: array
      description: URLs of automatically filed GitHub issues
---

# Sobriety Tools Guardian

**Mission**: Keep sobriety.tools fast enough to save lives. A fentanyl addict in crisis has seconds, not minutes. The app must load instantly, work offline, and surface help before they ask.

## Why Performance Is Life-or-Death

```
CRISIS TIMELINE:
0-30 seconds:  User opens app in distress
30-60 seconds: Looking for sponsor number or meeting
60-120 seconds: Decision point - call someone or use
2+ minutes:    If still searching, may give up

EVERY SECOND OF LOAD TIME = LIVES AT RISK
```

**Core truth**: This isn't a business app. Slow performance isn't "bad UX" - it's abandonment during crisis. The user staring at a spinner might be deciding whether to live or die.

## Stack-Specific Optimization Knowledge

### Architecture (Know This Cold)
```
Next.js 15 (static export) → Cloudflare Pages
    ↓
Supabase (PostgREST + PostGIS)
    ↓
Cloudflare Workers:
  - meeting-proxy (KV cached, geohash-based)
  - meeting-harvester (hourly cron)
  - claude-api (AI features)
```

### Critical Performance Paths

**1. Meeting Search (MUST be <500ms)**
```
User location → Geohash (3-char ~150km cell)
    → KV cache lookup (edge, ~5ms)
    → Cache HIT: Return immediately
    → Cache MISS: Supabase RPC find_current_meetings
        → PostGIS ST_DWithin query
        → Store in KV, return
```
**Bottleneck**: Cold Supabase queries. **Fix**: Pre-warm top 30 metros via /warm endpoint.

**2. Sponsor/Contact List (MUST be <200ms)**
```
User opens contacts → Local IndexedDB first
    → Show cached contacts instantly
    → Background sync with Supabase
    → Update UI if changes
```
**Anti-pattern**: Waiting for network before showing contacts. In crisis, show stale data immediately.

**3. Check-in Flow (MUST be <100ms to first input)**
```
Open check-in → Pre-rendered form shell
    → Load previous patterns async
    → Submit optimistically
```

### Offline-First Requirements (NON-NEGOTIABLE)

```typescript
// Service Worker must cache:
const CRISIS_CRITICAL = [
  '/contacts',           // Sponsor phone numbers
  '/safety-plan',        // User's safety plan
  '/meetings?saved=true', // Saved meetings list
  '/crisis',             // Crisis resources page
];

// These MUST work with zero network:
// 1. View sponsor contacts
// 2. View safety plan
// 3. View saved meetings (even if stale)
// 4. Record check-in (sync when online)
```

## Crisis Detection Patterns

### Journal Sentiment Signals
```typescript
// RED FLAGS (surface help proactively):
const CRISIS_INDICATORS = {
  anger_spike: 'HALT angry score jumps 3+ points',
  ex_mentions: 'Mentions ex-partner 3+ times in week',
  isolation: 'No check-ins for 3+ days after daily streak',
  time_distortion: 'Check-ins at unusual hours (2-5am)',
  negative_spiral: 'Consecutive declining mood scores',
};

// When detected: Surface sponsor contact, safety plan link
// DO NOT: Be preachy or alarming. Gentle nudge only.
```

### Check-in Analysis
```sql
-- Detect concerning patterns
SELECT user_id,
  AVG(angry_score) as avg_anger,
  AVG(angry_score) FILTER (WHERE created_at > NOW() - INTERVAL '3 days') as recent_anger,
  COUNT(*) FILTER (WHERE EXTRACT(HOUR FROM created_at) BETWEEN 2 AND 5) as late_night_checkins
FROM daily_checkins
WHERE created_at > NOW() - INTERVAL '30 days'
GROUP BY user_id
HAVING AVG(angry_score) FILTER (WHERE created_at > NOW() - INTERVAL '3 days') >
       AVG(angry_score) + 2;
```

## Performance Monitoring & Logging

### Key Metrics to Track
```typescript
// Client-side (log to analytics)
const PERF_METRICS = {
  ttfb: 'Time to First Byte',
  fcp: 'First Contentful Paint',
  lcp: 'Largest Contentful Paint',
  tti: 'Time to Interactive',

  // App-specific critical paths
  contacts_visible: 'Time until sponsor list renders',
  meeting_results: 'Time until first meeting card shows',
  checkin_interactive: 'Time until check-in form accepts input',
};

// Log slow paths
if (contactsVisibleTime > 500) {
  logPerf('contacts_slow', { duration: contactsVisibleTime, network: navigator.connection?.effectiveType });
}
```

### Automated Performance Regression Detection
```bash
# scripts/perf-audit.sh - Run in CI
lighthouse https://sobriety.tools/meetings --output=json --output-path=./perf.json
SCORE=$(jq '.categories.performance.score' perf.json)
if (( $(echo "$SCORE < 0.9" | bc -l) )); then
  echo "Performance regression: $SCORE"
  # Create GitHub issue automatically
fi
```

## Automated Issue Detection & Filing

### Background Performance Scanner
```typescript
// Run hourly via Cloudflare Worker cron
async function performanceAudit() {
  const checks = [
    checkMeetingCacheHealth(),
    checkSupabaseQueryTimes(),
    checkStaticAssetSizes(),
    checkServiceWorkerCoverage(),
  ];

  const issues = await Promise.all(checks);
  const problems = issues.flat().filter(i => i.severity === 'high');

  for (const problem of problems) {
    await createGitHubIssue({
      title: `[Auto] Perf: ${problem.title}`,
      body: problem.description + '\n\n' + problem.suggestedFix,
      labels: ['performance', 'automated'],
    });
  }
}
```

## Common Anti-Patterns

### 1. Network-Blocking Contact Display
**Symptom**: Contacts page shows spinner while fetching
**Problem**: User in crisis sees loading state instead of sponsor number
**Solution**:
```typescript
// WRONG
const { data: contacts } = useQuery(['contacts'], fetchContacts);

// RIGHT
const { data: contacts } = useQuery(['contacts'], fetchContacts, {
  initialData: () => getCachedContacts(), // IndexedDB
  staleTime: Infinity, // Never refetch automatically
});
```

### 2. Uncached Meeting Searches
**Symptom**: Every search hits Supabase
**Problem**: 200-500ms latency on every search
**Solution**: Geohash-based KV caching (already implemented in meeting-proxy)

### 3. Large Bundle Blocking Interactivity
**Symptom**: High TTI despite fast TTFB
**Problem**: JavaScript bundle blocks main thread
**Solution**:
```typescript
// Lazy load non-critical features
const JournalAI = dynamic(() => import('./JournalAI'), { ssr: false });
const Charts = dynamic(() => import('./Charts'), { loading: () => <ChartSkeleton /> });
```

### 4. Synchronous Check-in Submission
**Symptom**: Button stays disabled during network request
**Problem**: User thinks it didn't work, closes app
**Solution**: Optimistic UI + background sync queue

## Performance Optimization Checklist

### Before Every Deploy
- [ ] Bundle size delta < 5KB
- [ ] No new synchronous network calls in critical paths
- [ ] Lighthouse performance score >= 90
- [ ] Offline mode tested (disable network in DevTools)

### Weekly Audit
- [ ] Review slow query logs in Supabase
- [ ] Check KV cache hit rate (should be &gt;80%)
- [ ] Analyze Real User Metrics (RUM) for P95 load times
- [ ] Test on 3G throttled connection

### Monthly Deep Dive
- [ ] Profile React renders (why did this re-render?)
- [ ] Audit third-party scripts
- [ ] Review and prune unused dependencies
- [ ] Test crisis flows end-to-end on real device

## Scripts Available

| Script | Purpose |
|--------|---------|
| `scripts/perf-audit.ts` | Run Lighthouse + custom checks, file issues |
| `scripts/cache-health.ts` | Check KV cache hit rates and staleness |
| `scripts/crisis-path-test.ts` | Automated test of crisis-critical flows |
| `scripts/bundle-analyzer.ts` | Track bundle size over time |

## Integration Points

### With meeting-harvester
- After harvest, warm cache for top metros
- Monitor harvest duration and meeting counts
- Alert if harvest fails (stale data = wrong meeting times)

### With check-in system
- Analyze patterns for crisis detection
- Track submission success rate
- Monitor offline queue depth

### With contacts/sponsors
- Ensure offline availability
- Track time-to-display
- Monitor sync failures

## When to Escalate

**File GitHub issue immediately if:**
- Lighthouse score drops below 85
- P95 meeting search > 1 second
- Contacts page has any loading state > 200ms
- Service Worker fails to cache crisis pages
- Any user-reported "couldn't load" during crisis hours (evenings/weekends)

**This is a recovery app. Performance isn't a feature - it's the difference between someone getting help and someone dying alone.**

## Imported bundle navigation

These preserved source files add depth when their stated topic is needed.

- [references/CRISIS_DETECTION.md](references/CRISIS_DETECTION.md) — Crisis Detection Patterns for Recovery Apps.
- [references/PERFORMANCE_PATTERNS.md](references/PERFORMANCE_PATTERNS.md) — Performance Patterns for Recovery Apps.

Files in this skill

  • SKILL.md11.1 KB
  • references/CRISIS_DETECTION.md8.9 KB
  • references/INDEX.md326 B
  • references/PERFORMANCE_PATTERNS.md7.8 KB
  • scripts/bundle-analyzer.ts11.7 KB
  • scripts/cache-health.ts9.3 KB
  • scripts/crisis-path-test.ts10.2 KB
  • scripts/perf-audit.ts12.3 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…