Skip to content

HAN-5: Scaffold StashtagAI Expo app, Supabase schema, link intake and lists - #1

Open
StashtagAI wants to merge 2 commits into
mainfrom
han-5-expo-scaffold
Open

StashtagAI wants to merge 2 commits into
mainfrom
han-5-expo-scaffold

Conversation

@StashtagAI

Copy link
Copy Markdown
Owner

Summary

This is the first scaffold of the StashtagAI app. It is built with Expo SDK 58, Expo Router and TypeScript. iOS is the main target, and Android and web also build.

  • Config: app.json sets the name StashtagAI and the bundle ID and package ai.stashtag.app. eas.json has these profiles:
    • development (iOS simulator)
    • development-device
    • preview
    • production
  • Auth: Supabase email sign-in by magic link, with a 6-digit code fallback that works when iOS opens the link in a different browser. Keys come from EXPO_PUBLIC_SUPABASE_URL and EXPO_PUBLIC_SUPABASE_ANON_KEY. No keys are committed.
  • Migration (supabase/migrations/20261106000000_init_schema.sql):
    • Tables: links, categories (a kind enum of eats|trips|recipes|do), lists and items, plus tags text[] columns.
    • RLS keeps each user to their own rows. Clients can only insert links as pending and cannot update them.
    • A links.url check constraint enforces https and the exact host allowlist.
    • Column names and upsert conflict targets match what process-link already writes (HAN-6).
  • Link intake (src/lib/link-filter.ts):
    • The URL is parsed and its host is matched exactly against the allowlist. Substring checks are never used.
    • Only posts, reels and videos are accepted. Tracking query strings are stripped.
    • 22 unit tests cover the attack cases, including instagram.com.evil.com, evil.com/?u=instagram.com, userinfo (user@host), ports, a trailing dot, punycode and non-https schemes.
  • Lists: browse Category > List > Items, grouped by kind. Sample data shows until the user has processed links.
  • Theme: all colours come from src/constants/theme.ts, accessed through useTheme(), so HAN-10 can restyle the app in one place.
  • README and CI: the README covers setup, env vars and how to run each platform. CI runs typecheck, lint and tests.

Verification

  • npm run typecheck, npm run lint and npm test all pass (22 of 22 tests).
  • expo export bundles successfully for web, iOS and Android.
  • I applied the migration in Postgres (PGlite) with a stub of Supabase's auth schema and checked 23 RLS and constraint cases:
    • Rejected as expected: the lookalike host, the query smuggle, userinfo, http, a client inserting a done row, an insert for another user, a duplicate link, a client update, and attaching a list to another user's category.
    • A second user sees zero of the first user's rows.
    • The service-role upserts on process-link's conflict targets work.
  • I ran the web build in headless Chromium at 390×844 with Supabase stubbed: sign-in, a rejected lookalike link, a saved reel (inserted as pending with a clean URL), then Lists > Restaurants > Denver.

Not yet run: the real iOS simulator. This Linux host has no Xcode. Run npm run ios on macOS, or eas build --profile development --platform ios.

Board setup

  1. Run supabase link --project-ref qzaijqrkriuhlqbwmyto, then supabase db push.
  2. In Supabase Auth, add these redirect URLs: stashtag://auth/callback and your web origins.
  3. Optional: add {{ .Token }} to the magic-link email template.
  4. Run eas init to attach the EAS project ID.

🤖 Generated with Claude Code

- Expo SDK 58 + Expo Router + TypeScript; iOS-first, Android and web build
- app.json (StashtagAI, ai.stashtag.app) and eas.json dev/preview/production profiles
- Supabase client with email magic-link + one-time-code auth
- Migration: links, categories (kind eats|trips|recipes|do), lists, items,
  tags arrays, RLS per user, https/host allowlist check on links.url
- Link intake with exact-host Instagram/TikTok allowlist (unit-tested)
- Lists browser: Category > List > Items with sample data until processing lands
- README, CI (typecheck, lint, test)

Co-Authored-By: Paperclip <noreply@paperclip.ing>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The Supabase magic-link email carries no code unless the template is
edited, so the board could not finish signing in on the iOS build.
Password sign-in/sign-up is now the default; the magic link stays as
an alternative.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant