Skip to main content

Dependency & unused-library audit

Every finding on this page was verified by grepping actual imports across frontend/app, frontend/src, frontend/modules, and all backend/**/*.py. A package is only called "unused" where a grep found no usage and it is not a required transitive/peer/plugin dependency.

Frontend — remove or relocate

Relocate

@expo/ngrok → devDependencies

Remove (0 imports, non-functional)

react-native-dotenv

react-native-webview

expo-symbols

PackageEvidenceAction
react-native-dotenv0 imports; no @env usage; no babel.config.js to even wire its plugin. All env access is process.env.EXPO_PUBLIC_*. A vestigial expo.doctor exclude still names it.Remove — low risk
react-native-webview0 hits for WebView anywhere. The "widget preview" justification is stale — modules/drape-widget is a native Swift widget, not a WebView.Remove — low risk
expo-symbols0 hits for expo-symbols / SymbolView / SFSymbol.Remove — low risk
@expo/ngrok0 imports; a dev-only tunnel binary sitting in dependencies.Move to devDependencies
expo-web-browserDeclared as an app.json plugin but 0 JS usage.Verify no redirect flow depends on it, then remove — low/medium confidence

Confirmed in use (keep): @expo/vector-icons (46 imports), expo-router (50), react-native-safe-area-context (45), @react-native-async-storage/async-storage (26), expo-image (13), expo-linear-gradient (8), react-native-svg, posthog-react-native, expo-image-picker, expo-camera, expo-file-system, expo-haptics, the three Google-font packages, @sentry/react-native, react-native-view-shot (share cards), and expo-image-manipulator (loaded via a dynamic import() in body-photo.tsx).

Used indirectly — do not remove: posthog-react-native-session-replay (native autolinked peer), react-native-screens / react-native-gesture-handler / react-native-reanimated / react-native-worklets (navigation + Expo infra), react-native-web / react-dom (web build target), and the various expo-* router internals.

The directly-listed @react-navigation/* and @expo/metro-runtime packages are guaranteed transitively by expo-router — removing them declutters the manifest but forfeits version pinning, so it is optional and low priority.

Backend — the big win

The backend requirements.txt is a full pip freeze (157 pinned lines). The code actually imports roughly 25 top-level packages. Entire stacks are installed that nothing imports:

Installed, 0 imports (remove)

litellm + tiktoken + tokenizers + huggingface_hub

google-* (genai, generativeai, api-python-client, auth…)

boto3 + botocore + s3transfer

pandas

pyiceberg + pyroaring + strictyaml + zstandard

s5cmd · jq · fastuuid · passlib · librt

Imported & used (~25)

fastapi · motor · pymongo · pydantic · PyJWT · bcrypt
pillow · numpy · httpx · stripe · supabase · upstash_redis
slowapi · fal_client · fashn · sentry_sdk · langfuse · openai

Each package below returned 0 import matches repo-wide and is not a transitive dependency of anything used:

Package(s)Why it is bloat
litellm (+ tiktoken, tokenizers, huggingface_hub, hf-xet)Langfuse does not require litellm; came in as an unused stack
google-genai, google-generativeai, google-ai-generativelanguage, google-api-python-client, google-auth* (+ gRPC/proto tree)Drape uses OpenAI + fal.ai + Fashn, never Gemini/Google
boto3, botocore, s3transferStorage is Supabase, not S3
pandasNever imported
pyiceberg (+ pyroaring, strictyaml, mmh3, zstandard, fsspec)Apache Iceberg — not in the architecture
s5cmd, jq, fastuuid, passlib, librtUnused CLIs / libs (bcrypt and stdlib uuid are what's actually used)

requirements.txt anti-patterns

  1. Full-freeze, no direct/transitive split. 157 pinned lines mix true direct deps with internals like h11, hpack, anyio, yarl. Upgrades are brittle and the ~25 real deps are hidden.
  2. Dev tooling installed in production. black, flake8, isort, mypy, pytest, pycodestyle, pyflakes, mccabe, pathspec, and friends are installed on a 512 MB Render free tier. There is no requirements-dev.txt.
  3. Inconsistent pinning. Every line is ==-pinned except the first, anthropic>=0.40.0 — and anthropic is only used by a dev cron agent (agents/bug_fixer.py), so it does not belong in the production file.
  4. Orphaned transitives. ecdsa and rsa (classic python-jose deps) remain even though python-jose was removed — the freeze was never regenerated cleanly.
python-jose: good news, and the old audits are wrong

python-jose is not present and imported nowhereserver.py uses import jwt as pyjwt (PyJWT). There is no CVE-2024-33663 / 33664 exposure. The 2026-05-25 audit docs claim the opposite ("python-jose is used, remove PyJWT") — that is inverted and stale, and should be corrected.

Prioritized cleanup

Tier 1 — safe, quick (low risk):

  • Frontend: remove react-native-dotenv, react-native-webview, expo-symbols; move @expo/ngrok to devDependencies. Then reinstall + an Expo build smoke test.
  • Backend: create requirements-dev.txt and move the ~13 dev tools out of prod.

Tier 2 — remove unused heavy stacks (low–medium risk):

  • Drop the Google AI, AWS, litellm, pandas, and Iceberg stacks plus their orphaned transitives. Expected to cut the install by well over half.
  • Move anthropic (pinned) and requests to the dev file — both are agent-script-only.
  • Risk surface is the re-freeze. Rebuild in a clean venv, reinstall the curated direct list, and verify import server succeeds before deploying — following the manual-deploy + staging-smoke-test rules.

Tier 3 — follow-ups (housekeeping):

  • If the legacy POST /api/previews/generate endpoint is deleted (no frontend callers, its key already removed), the openai import becomes removable too.
  • Correct the two stale audit docs.

Net effect: the frontend sheds three to four real dependencies; the backend requirements.txt drops from 157 pinned lines to roughly 25 curated production deps plus a separate dev file.