Skip to main content

Authentication

The kit uses Supabase for authentication. By default, it uses anonymous authentication — which is the recommended approach for apps with paywalls and onboarding flows.

Why Anonymous Auth is the Default

Most successful subscription apps follow this pattern:
App Launch → Onboarding → Paywall → Main App
With anonymous auth, users:
  • Don’t see a login screen before they understand your app’s value
  • Can complete onboarding and see the paywall without friction
  • Get a seamless experience that maximizes conversion
Anonymous users are real users. They have a unique ID, can make purchases, and their data persists. The only difference is they didn’t enter an email/password.

When to Use Anonymous Auth

Use CaseRecommendation
Subscription app with paywall✅ Anonymous (default)
Content/media app✅ Anonymous
Social app requiring profiles❌ Use email/social auth
App with user-generated content❌ Use email/social auth
Enterprise/B2B app❌ Use email/social auth

Authentication Options

The kit supports multiple auth methods. Enable them in config/app.config.ts:
auth: {
  mode: 'anonymous', // or 'required'
  providers: {
    email: false,  // Email + Password
    apple: false,  // Sign in with Apple
    google: false, // Google OAuth
  },
}

Available Methods

App Store Requirement: If you use Google OAuth (or any third-party social login), you must also offer Apple Sign In. See the Apple Sign In guide for details and other important App Store guidelines.

How It Works

Anonymous Auth

When the app launches, it automatically creates an anonymous user:
// This happens automatically in auth-context.tsx
const { data } = await supabase.auth.signInAnonymously();
The user gets a unique ID that persists across sessions. They can make purchases, save data, and use the app normally.

Switching to Other Auth Methods

If you need users to sign in, set auth.mode to 'required':
// config/app.config.ts
auth: {
  mode: 'required',
  providers: {
    email: true,
    apple: true,
  },
}
Then use the pre-built auth screens:
// Navigate to login
router.push('/auth/login');

// Or signup
router.push('/auth/signup');

Key Files

FilePurpose
lib/supabase.tsSupabase client configuration
lib/auth.tsAuth utility functions (email, Apple, Google)
contexts/auth-context.tsxAuth state provider
config/app.config.tsAuth configuration
components/auth/Reusable auth UI components
app/auth/Full auth screens (login, signup, forgot-password)

Using Auth in Your App

Get Current User

import { useAuth } from '@/contexts/auth-context';

function MyComponent() {
  const { user, isLoading } = useAuth();
  
  if (isLoading) return <LoadingSpinner />;
  
  return <Text>User ID: {user?.id}</Text>;
}

Check if Anonymous

import { isAnonymousUser } from '@/lib/auth';

const isAnon = isAnonymousUser(user);
// true if user signed in anonymously

Sign Out

const { signOut } = useAuth();

await signOut();
// User is now signed out, will create new anonymous user on next launch

UI Components

The kit includes ready-to-use auth components:

Forms

import { LoginForm, SignupForm, ForgotPasswordForm } from '@/components/auth';

// Login form with email/password
<LoginForm 
  onSuccess={() => router.replace('/(main)')}
  onForgotPassword={() => router.push('/auth/forgot-password')}
  onSignUp={() => router.push('/auth/signup')}
/>

// Signup form
<SignupForm 
  onSuccess={() => Alert.alert('Check your email')}
  onLogin={() => router.push('/auth/login')}
/>

Social Buttons

import { SocialAuthButtons } from '@/components/auth';

<SocialAuthButtons
  showApple={true}
  showGoogle={true}
  onSuccess={() => router.replace('/(main)')}
  onError={(err) => Alert.alert('Error', err.message)}
/>

Divider

import { AuthDivider } from '@/components/auth';

<SocialAuthButtons />
<AuthDivider text="or sign in with email" />
<LoginForm />

Account Linking (Coming Soon)

In a future update, anonymous users will be able to “upgrade” their account by linking an email or social provider — without losing their data or purchases.

Next Steps