Skip to content

SyntaxFear/shipyard

Repository files navigation

Vancore - Van Life Community App

Vancore Logo

A trusted van-life community app that combines nomadic dating, activity-based friendships, and a premium builder-help platform with verified access to keep it safe and intentional.

Built for Shipyard: Creator Contest 2026 by RevenueCat
Quin Gable's Brief

Quin Gable TikTok Shipyard 2026 RevenueCat


About Shipyard

This app was built as part of Shipyard: Creator Contest 2026 — a 4-week app-building competition organized by RevenueCat where developers collaborate with content creators to build, launch, and monetize MVP apps.

The Brief: Quin Gable

Quin Gable is a TikTok creator with 1.2M+ followers and 30M+ likes who documents solo van life adventures with her cats Atlas and Otto, featuring hiking and travel content.

"Dating and making friends on the road is hard when you're always moving—and van life is a tight, protective community."

Quin's Vision: A van-life app with nomadic dating, activity-based friend finding, and a paid 'builder help' section for van projects, with invite-only or verified access to keep it safe and intentional.

Competition Details

Detail Value
Prize Pool $140,000
Duration 4 weeks (Jan 15 - Feb 12, 2026)
Requirements Mobile app (iOS/Android), RevenueCat integration
Distribution TestFlight (iOS) / Play Internal Testing (Android)

Table of Contents


Overview

Vancore is a social networking mobile application designed specifically for the van-life community, built to address the unique challenges of making connections while living life on the road.

"Dating and making friends on the road is hard when you're always moving—and van life is a tight, protective community." — Quin Gable

The app serves as a trusted platform connecting nomads, travelers, and van enthusiasts through:

  • Swipe-Based Matching: Find romantic connections or platonic friendships with other van-lifers
  • Activity Coordination: Create and join micro-events/activities with nearby community members
  • Builder Help Q&A: A premium community knowledge base for van build assistance
  • Verified Access: Identity verification to keep the community safe and intentional

The Problem We Solve

Van life is an incredible lifestyle, but it comes with unique social challenges:

  • Constant Movement: Traditional dating apps and social networks don't account for nomadic lifestyles
  • Trust & Safety: The van life community is tight-knit and protective — strangers need to be vetted
  • Finding Your Tribe: Meeting like-minded people who understand the lifestyle is difficult
  • Builder Knowledge: Van builds are complex, and finding reliable advice is scattered across forums

Vancore brings the van life community together in one trusted space.

Target Users

  • People living the van-life or nomadic lifestyle
  • Digital nomads and remote workers
  • Van builders (planning, building, or upgrading their rigs)
  • Travelers seeking community connections on the road
  • Quin Gable's 1.2M+ TikTok community

App Identity

Property Value
App Name Vancore
Bundle ID com.vanlife.community
URL Scheme vanlife://
Primary Color Green (#16a34a)
Built For Shipyard 2026
Creator Quin Gable

Features

🔄 Match - Discovery & Connections

The heart of the app - a swipe-based discovery system for finding friends and romantic connections.

  • Swipe Cards: Tinder-style card interface with smooth gesture animations
  • Two Modes: Switch between "Friends" and "Dating" discovery modes
  • Actions: Like, Pass, and Super Like other profiles
  • Mutual Matching: Get notified when both users like each other
  • Location-Based: Filter profiles by distance from your current location
  • Second Chance: Revisit profiles you previously passed on
  • Interest Filtering: Find people with similar interests
  • Prefetch Optimization: Images preloaded for smooth scrolling

📅 Activities - Events & Meetups

Coordinate meetups and activities with the van-life community.

  • Create Activities: Host hiking trips, coworking sessions, campfire hangouts, and more
  • Categories:
    • 🥾 Hiking
    • 🧗 Climbing
    • 🏄 Surfing
    • ⛺ Camping
    • 💻 Coworking
    • 🎉 Social
    • 📸 Photography
    • 🎵 Music
    • 🍕 Food
    • 💪 Fitness
  • Join/Leave: RSVP to activities with attendee limits
  • Status Tracking: See upcoming, in-progress, and ended activities
  • Comments: Discuss activities with other attendees
  • Edit & Delete: Manage your own activities
  • Distance Sorting: Find activities near you

💬 Messages - Real-Time Chat

Connect with your matches through real-time messaging.

  • Real-Time Chat: Powered by Supabase Realtime subscriptions
  • Typing Indicators: See when the other person is typing
  • Message Types: Text, images, voice messages, and location sharing
  • Unread Counts: Badge indicators for unread messages
  • Block & Report: Safety features for unwanted contacts
  • Archive & Mute: Organize your conversations
  • Message Requests: Control who can message you

🔧 Builder Help - Q&A Platform

A premium community-driven knowledge base for van build assistance.

  • Topics:
    • ⚡ Electrical Systems
    • ☀️ Solar Setup
    • 🚿 Plumbing
    • 🌡️ HVAC & Ventilation
    • 🧱 Insulation
    • 🛠️ Carpentry & Framing
    • 🚐 Mechanical & Maintenance
    • 📡 Off-Grid Tech
    • 🎨 Interior Design
    • 💰 Budgeting
  • Ask Questions: Premium feature to post detailed questions
  • Answer & Reply: Help others with your expertise
  • Voting System: Upvote/downvote answers
  • Accepted Answers: Mark the best answer
  • View Counts: Track question engagement
  • Image Attachments: Share photos of your build

👤 Profile

Showcase your van-life journey and personality.

  • Photo Gallery: Multiple photos organized in albums
  • Photo Likes: See who liked your photos
  • Primary Photo: Set your main profile picture
  • Vanlife Details:
    • Rig Type (Van, Bus, RV, Truck Camper, etc.)
    • Travel Pace (Full-time, Part-time, Weekender)
    • Current Location
  • Interests: Display your hobbies and passions
  • Bio: Tell your story
  • Verification Badge: Show you're a verified member

⚙️ Settings

Comprehensive controls for privacy and preferences.

  • Privacy Settings:
    • Show/hide age, location, online status
    • Control profile visibility
    • Manage who can message you
  • Notification Preferences: Customize push and in-app notifications
  • Blocked Users: Manage your block list
  • Identity Verification: Request verification for trust
  • Help & Feedback: Contact support
  • Account Management: Delete account option

🔐 Authentication

Secure and flexible sign-in options.

  • Email/Password: Traditional authentication with email verification
  • Apple Sign-In: Native iOS authentication
  • Google Sign-In: OAuth integration
  • Password Reset: Self-service password recovery

🎨 Onboarding

Guided profile setup for new users.

  1. Basics: Name and age
  2. Vanlife Details: Rig type and travel pace
  3. Interests: Select your hobbies (multi-select)
  4. Preferences: Choose discovery mode (Friends/Dating/Both)
  5. Photo: Upload your profile picture

Tech Stack

Core Framework

Technology Version Purpose
React Native 0.83.1 Cross-platform mobile framework
Expo SDK 55 Development platform and native APIs
React 19.2.0 UI library
TypeScript 5.3.3 Type safety

Navigation

Technology Purpose
Expo Router 55 File-based routing with typed routes
NativeTabs Native tab bar implementation

Backend Services

Service Purpose
Supabase Backend-as-a-Service
- Auth Authentication (Email, Apple, Google)
- Database PostgreSQL with Row Level Security
- Realtime WebSocket subscriptions
- Storage File uploads (avatars, photos, attachments)
- Edge Functions Serverless functions

State Management

Technology Purpose
Zustand 5.0.2 Lightweight state management

Payments

Technology Purpose
RevenueCat Subscription management
react-native-purchases RevenueCat SDK

UI & Animation

Library Purpose
React Native Reanimated 4.2.1 High-performance animations
React Native Gesture Handler 2.30.0 Touch gestures
Expo Linear Gradient Gradient backgrounds
Expo Glass Effect iOS blur effects
Expo Symbols SF Symbols icons
@shopify/flash-list Performant lists
Zeego Native context menus

Media

Library Purpose
Expo Image Optimized image component
Expo Image Picker Photo/video selection
Expo Video Video playback
Expo Audio Audio recording/playback

Other Libraries

Library Purpose
date-fns Date formatting
@renegades/react-native-tickle Haptic feedback
react-native-keyboard-controller Keyboard handling
expo-secure-store Secure credential storage
expo-notifications Push notifications
expo-location Location services
expo-maps Map components

Getting Started

Prerequisites

  • Node.js 18+
  • npm or yarn
  • Expo CLI (npm install -g expo-cli)
  • Supabase account
  • iOS Simulator / Android Emulator or physical device
  • Xcode (for iOS development)
  • Android Studio (for Android development)

Installation

1. Clone the Repository

git clone <repository-url>
cd vanlife-app

2. Install Dependencies

npm install

3. Configure Supabase

  1. Create a new project at supabase.com
  2. Run the database migrations from supabase/migrations/ in order
  3. Enable Auth providers:
    • Email (with email verification)
    • Apple (configure with your Apple Developer credentials)
    • Google (configure with your Google Cloud credentials)
  4. Create storage buckets:
    • avatars (public)
    • photos (public)
    • attachments (public)

4. Configure RevenueCat (Optional - for premium features)

  1. Create a RevenueCat account at revenuecat.com
  2. Set up your app and products
  3. Create entitlements (e.g., "Builder Help Plus")
  4. Add your API keys to environment variables

5. Environment Variables

Copy the example environment file:

cp .env.example .env

Fill in your values (see Environment Variables section).

6. Run the App

# Start Expo development server
npx expo start

# Run on iOS Simulator
npx expo run:ios

# Run on Android Emulator
npx expo run:android

# Run with development build
npx expo start --dev-client

Project Structure

vanlife-app/
├── app/                              # Expo Router screens (file-based routing)
│   ├── _layout.tsx                   # Root layout with providers
│   ├── +not-found.tsx                # 404 screen
│   │
│   ├── (auth)/                       # Auth group (unauthenticated users)
│   │   ├── _layout.tsx               # Auth layout
│   │   ├── welcome.tsx               # Welcome/landing screen
│   │   ├── sign-in.tsx               # Sign in screen
│   │   ├── sign-up.tsx               # Sign up screen
│   │   ├── forgot-password.tsx       # Password reset
│   │   └── onboarding.tsx            # Profile setup wizard
│   │
│   ├── (tabs)/                       # Main tab navigator
│   │   ├── _layout.tsx               # Tab bar configuration
│   │   ├── match/                    # Discovery/matching
│   │   │   └── index.tsx
│   │   ├── activities/               # Activities list
│   │   │   └── index.tsx
│   │   ├── messages/                 # Conversations list
│   │   │   └── index.tsx
│   │   └── builder/                  # Q&A forum
│   │       └── index.tsx
│   │
│   ├── profile/                      # Profile screens
│   │   ├── [id].tsx                  # View profile
│   │   ├── edit.tsx                  # Edit profile
│   │   └── photos.tsx                # Manage photos
│   │
│   ├── activities/                   # Activity detail screens
│   │   ├── [id].tsx                  # Activity details
│   │   ├── create.tsx                # Create activity
│   │   └── edit.tsx                  # Edit activity
│   │
│   ├── messages/                     # Chat screens
│   │   └── [id].tsx                  # Chat conversation
│   │
│   ├── builder/                      # Builder help screens
│   │   ├── [id].tsx                  # Question details
│   │   └── ask.tsx                   # Ask question
│   │
│   ├── settings/                     # Settings screens
│   │   ├── index.tsx                 # Settings menu
│   │   ├── privacy.tsx               # Privacy settings
│   │   ├── notifications.tsx         # Notification preferences
│   │   ├── blocked.tsx               # Blocked users
│   │   ├── verification.tsx          # Identity verification
│   │   └── help.tsx                  # Help & feedback
│   │
│   └── subscription.tsx              # Premium subscription paywall
│
├── components/                       # Reusable components
│   ├── ui/                           # Base UI components
│   │   ├── Button.tsx
│   │   ├── Input.tsx
│   │   ├── Card.tsx
│   │   ├── Avatar.tsx
│   │   ├── Badge.tsx
│   │   ├── Chip.tsx
│   │   ├── EmptyState.tsx
│   │   ├── LoadingSpinner.tsx
│   │   ├── BottomSheet.tsx
│   │   ├── CircularCarousel.tsx
│   │   ├── ScaleCarousel.tsx
│   │   ├── ParallaxCarousel.tsx
│   │   ├── GlassProgressBar.tsx
│   │   ├── SafeGlassView.tsx
│   │   └── ...
│   │
│   ├── match/                        # Match/discovery components
│   │   ├── CardStack.tsx             # Swipeable card stack
│   │   ├── SwipeableCard.tsx         # Individual swipe card
│   │   ├── ProfileCard.tsx           # Profile display
│   │   ├── ActionButton.tsx          # Like/Pass buttons
│   │   ├── MatchModal.tsx            # Match celebration
│   │   ├── ModeToggle.tsx            # Friends/Dating toggle
│   │   └── EndOfStack.tsx            # Empty state
│   │
│   ├── builder/                      # Builder help components
│   │   ├── AnswerCard.tsx            # Answer display
│   │   ├── ReplyItem.tsx             # Nested replies
│   │   └── AnswerActions.tsx         # Vote/accept actions
│   │
│   ├── messages/                     # Messaging components
│   │   ├── MessageBubble.tsx
│   │   ├── ChatInput.tsx
│   │   └── ConversationItem.tsx
│   │
│   ├── onboarding/                   # Onboarding step components
│   │   ├── BasicsStepNew.tsx
│   │   ├── VanlifeStepNew.tsx
│   │   ├── InterestsStepNew.tsx
│   │   ├── PreferencesStepNew.tsx
│   │   └── PhotoStepNew.tsx
│   │
│   ├── notifications/                # Notification components
│   │   └── NotificationToast.tsx
│   │
│   └── molecules/                    # Compound components
│       └── ...
│
├── store/                            # Zustand state stores
│   ├── authStore.ts                  # Authentication state
│   ├── discoveryStore.ts             # Match/discovery state
│   ├── discoveryLocationStore.ts     # Discovery location state
│   ├── messagesStore.ts              # Chat/messaging state
│   ├── activitiesStore.ts            # Activities state
│   ├── builderStore.ts               # Builder Q&A state
│   ├── profileStore.ts               # Profile state
│   ├── settingsStore.ts              # Settings state
│   ├── locationStore.ts              # User location state
│   ├── notificationsStore.ts         # In-app notifications
│   ├── purchasesStore.ts             # RevenueCat subscriptions
│   └── pushNotificationsStore.ts     # Push notification tokens
│
├── types/                            # TypeScript type definitions
│   └── database.ts                   # Supabase database types
│
├── constants/                        # App constants
│   ├── theme.ts                      # Colors, spacing, typography
│   └── topics.ts                     # Builder help topics
│
├── lib/                              # Library utilities
│   ├── supabase/
│   │   └── client.ts                 # Supabase client initialization
│   └── haptics/
│       └── index.ts                  # Haptic feedback system
│
├── hooks/                            # Custom React hooks
│   ├── useTheme.tsx                  # Theme context and hook
│   └── useLocationTracking.ts        # Location permissions
│
├── supabase/                         # Supabase configuration
│   ├── functions/                    # Edge functions
│   └── migrations/                   # Database migrations
│
├── scripts/                          # Utility scripts
│   └── ...
│
├── assets/                           # Static assets
│   ├── images/                       # App icons, splash screens
│   └── fonts/                        # Custom fonts
│
├── app.json                          # Expo app configuration
├── eas.json                          # EAS Build configuration
├── package.json                      # Dependencies
├── tsconfig.json                     # TypeScript configuration
└── .env.example                      # Environment variables template

App Architecture

Navigation Flow

┌─────────────────────────────────────────────────────────────┐
│                      Root Layout                            │
│                   (_layout.tsx)                             │
│                                                             │
│  ┌─────────────────────────────────────────────────────┐   │
│  │                Auth Check                            │   │
│  │                                                      │   │
│  │   Not Authenticated?  ──────►  (auth) Group          │   │
│  │                                 ├── welcome          │   │
│  │                                 ├── sign-in          │   │
│  │                                 ├── sign-up          │   │
│  │                                 ├── forgot-password  │   │
│  │                                 └── onboarding       │   │
│  │                                                      │   │
│  │   Authenticated?  ──────────►  (tabs) Group          │   │
│  │                                 ├── match            │   │
│  │                                 ├── activities       │   │
│  │                                 ├── messages         │   │
│  │                                 └── builder          │   │
│  └─────────────────────────────────────────────────────┘   │
│                                                             │
│  Modal Screens (accessible from anywhere):                  │
│  ├── profile/[id]                                           │
│  ├── profile/edit                                           │
│  ├── activities/[id]                                        │
│  ├── activities/create                                      │
│  ├── messages/[id]                                          │
│  ├── builder/[id]                                           │
│  ├── builder/ask                                            │
│  ├── settings/*                                             │
│  └── subscription (modal presentation)                      │
└─────────────────────────────────────────────────────────────┘

Data Flow

┌──────────────┐     ┌──────────────┐     ┌──────────────┐
│   Component  │────►│ Zustand Store│────►│   Supabase   │
│              │◄────│              │◄────│              │
└──────────────┘     └──────────────┘     └──────────────┘
                            │
                            ▼
                     ┌──────────────┐
                     │   Realtime   │
                     │ Subscriptions│
                     └──────────────┘

Database Schema

Core Tables

profiles

User profile information including vanlife-specific details.

Column Type Description
id uuid Primary key (references auth.users)
full_name text Display name
bio text Profile bio
avatar_url text Profile picture URL
date_of_birth date Birthday
gender text Gender identity
rig_type text Vehicle type (van, bus, RV, etc.)
travel_pace text Full-time, part-time, weekender
latitude float Current latitude
longitude float Current longitude
location_name text Location display name
discovery_mode text friends, dating, or both
is_verified boolean Verification status
is_online boolean Online status
last_online timestamp Last activity
created_at timestamp Account creation

photos

User photo gallery.

Column Type Description
id uuid Primary key
user_id uuid Owner
url text Image URL
album_id uuid Album reference
is_primary boolean Main profile photo
sort_order int Display order
created_at timestamp Upload date

swipes

Discovery likes and passes.

Column Type Description
id uuid Primary key
swiper_id uuid User who swiped
swiped_id uuid User who was swiped on
direction text like, pass, super_like
mode text friends or dating
created_at timestamp Swipe time

matches

Mutual matches between users.

Column Type Description
id uuid Primary key
user1_id uuid First user
user2_id uuid Second user
mode text friends or dating
created_at timestamp Match time

chats

Conversation metadata.

Column Type Description
id uuid Primary key
match_id uuid Associated match
last_message_at timestamp Last activity
created_at timestamp Chat creation

messages

Chat messages.

Column Type Description
id uuid Primary key
chat_id uuid Conversation
sender_id uuid Message author
content text Message text
message_type text text, image, voice, location, system
attachment_url text Media URL
is_read boolean Read status
created_at timestamp Send time

activities

Events and meetups.

Column Type Description
id uuid Primary key
creator_id uuid Event host
title text Activity name
description text Details
category text Activity type
location_name text Venue
latitude float Location lat
longitude float Location lng
start_time timestamp Event start
end_time timestamp Event end
max_attendees int Capacity
is_public boolean Visibility
created_at timestamp Creation date

builder_questions

Q&A questions.

Column Type Description
id uuid Primary key
author_id uuid Question author
topic_id uuid Category
title text Question title
body text Question details
view_count int Views
is_answered boolean Has accepted answer
created_at timestamp Post date

builder_answers

Q&A answers and replies.

Column Type Description
id uuid Primary key
question_id uuid Parent question
parent_id uuid Parent answer (for replies)
author_id uuid Answer author
body text Answer content
is_accepted boolean Accepted answer
vote_count int Net votes
created_at timestamp Post date

Database Functions

Function Purpose
get_discovery_profiles Complex profile discovery with filtering
get_second_chance_profiles Retrieve previously passed profiles
increment_question_views Track question views
update_user_online_status Presence management
use_invite_code Referral system

Authentication

Supported Methods

Email/Password

// Sign up
await supabase.auth.signUp({
  email: 'user@example.com',
  password: 'securepassword',
});

// Sign in
await supabase.auth.signInWithPassword({
  email: 'user@example.com',
  password: 'securepassword',
});

Apple Sign-In

const credential = await AppleAuthentication.signInAsync({
  requestedScopes: [
    AppleAuthentication.AppleAuthenticationScope.FULL_NAME,
    AppleAuthentication.AppleAuthenticationScope.EMAIL,
  ],
});

await supabase.auth.signInWithIdToken({
  provider: 'apple',
  token: credential.identityToken,
});

Google Sign-In

await GoogleSignin.hasPlayServices();
const userInfo = await GoogleSignin.signIn();

await supabase.auth.signInWithIdToken({
  provider: 'google',
  token: userInfo.idToken,
});

Auth Flow

  1. Unauthenticated: User sees Welcome screen
  2. Sign In/Up: User authenticates via chosen method
  3. Profile Check: If full_name is missing, redirect to Onboarding
  4. Onboarding: 5-step profile creation wizard
  5. Authenticated: User accesses main tab navigator

Key Components

UI Components (/components/ui/)

Component Description
Button Primary/secondary/ghost buttons with loading states
Input Text inputs with validation and error states
Card Elevated/flat card containers
Avatar User avatars with verification badges
Badge Category and status badges
Chip Selectable tag chips for filters
EmptyState Illustrated empty state placeholders
LoadingSpinner Activity indicators
BottomSheet Modal bottom sheets
CircularCarousel Circular image carousel
ParallaxCarousel Parallax scrolling carousel
GlassProgressBar iOS glass-effect progress indicator
SafeGlassView Cross-platform blur effect wrapper

Match Components (/components/match/)

Component Description
CardStack Manages stack of swipeable profile cards
SwipeableCard Individual card with pan gesture handling
ProfileCard Profile information display
ActionButton Like/Pass/Super Like action buttons
MatchModal Celebration modal for mutual matches
ModeToggle Friends/Dating mode switcher
EndOfStack Empty state when no profiles available
CardSkeleton Loading skeleton for cards

State Management

The app uses Zustand for state management with domain-specific stores:

Store Overview

Store Purpose Key State
authStore Authentication user, session, profile, isLoading
discoveryStore Matching profiles, currentIndex, matches, mode
discoveryLocationStore Discovery location coordinates, locationName, radius
messagesStore Messaging conversations, messages, typing
activitiesStore Activities activities, selectedActivity, filters
builderStore Q&A questions, answers, topics, filters
profileStore Profile viewing profile, photos, isLoading
settingsStore Settings privacy, notifications, blocked
locationStore User location coordinates, permissions
purchasesStore Subscriptions offerings, entitlements, isPremium
notificationsStore In-app notifications notifications, unreadCount
pushNotificationsStore Push tokens expoPushToken, permission

Example Store Usage

// Using a store in a component
import { useDiscoveryStore } from '@/store/discoveryStore';

function MatchScreen() {
  const { profiles, currentIndex, like, pass, loadProfiles } = useDiscoveryStore();

  useEffect(() => {
    loadProfiles();
  }, []);

  const handleLike = () => {
    like(profiles[currentIndex].id);
  };

  // ...
}

Theming

Theme Configuration

The app uses a centralized theme system defined in constants/theme.ts:

export const Colors = {
  light: {
    primary: '#16a34a',      // Green
    background: '#ffffff',
    surface: '#f5f5f5',
    text: '#1a1a1a',
    textSecondary: '#666666',
    border: '#e5e5e5',
    error: '#ef4444',
    success: '#22c55e',
    warning: '#f59e0b',
  },
  dark: {
    primary: '#22c55e',
    background: '#0a0a0a',
    surface: '#1a1a1a',
    text: '#ffffff',
    textSecondary: '#a3a3a3',
    border: '#333333',
    error: '#f87171',
    success: '#4ade80',
    warning: '#fbbf24',
  },
};

export const Spacing = {
  xs: 4,
  sm: 8,
  md: 16,
  lg: 24,
  xl: 32,
  xxl: 48,
};

export const FontSizes = {
  xs: 12,
  sm: 14,
  md: 16,
  lg: 18,
  xl: 24,
  xxl: 32,
};

export const BorderRadius = {
  sm: 4,
  md: 8,
  lg: 12,
  xl: 16,
  full: 9999,
};

Using Theme

import { useTheme } from '@/hooks/useTheme';

function MyComponent() {
  const { colors, isDark } = useTheme();

  return (
    <View style={{ backgroundColor: colors.background }}>
      <Text style={{ color: colors.text }}>Hello</Text>
    </View>
  );
}

Theme Modes

  • Light Mode: Default light theme
  • Dark Mode: Dark theme for low-light conditions
  • System: Follows device system preference

Haptic Feedback

The app uses @renegades/react-native-tickle for comprehensive haptic feedback:

Available Patterns

Pattern Usage
light Subtle taps, toggles
medium Button presses
heavy Important actions
success Successful operations
warning Warnings
error Errors
selection Selection changes

Usage

import { useHaptics } from '@/lib/haptics';

function MyComponent() {
  const { trigger } = useHaptics();

  const handlePress = () => {
    trigger('medium');
    // ... action
  };

  return <Button onPress={handlePress}>Press Me</Button>;
}

Premium Features

Subscription Plans

Managed through RevenueCat:

Plan Duration Features
Weekly 7 days Builder Help Plus
Monthly 30 days Builder Help Plus
Quarterly 90 days Builder Help Plus
Yearly 365 days Builder Help Plus (best value)

Builder Help Plus Features

  • Ask Questions: Post detailed questions to the community
  • Priority Support: Featured question placement
  • No Ads: Ad-free experience (future feature)

Checking Premium Status

import { usePurchasesStore } from '@/store/purchasesStore';

function PremiumFeature() {
  const { isPremium } = usePurchasesStore();

  if (!isPremium) {
    return <UpgradePrompt />;
  }

  return <PremiumContent />;
}

Environment Variables

Create a .env file with the following variables:

# Supabase Configuration (Required)
EXPO_PUBLIC_SUPABASE_URL=https://your-project.supabase.co
EXPO_PUBLIC_SUPABASE_ANON_KEY=your-anon-key

# RevenueCat (Required for premium features)
EXPO_PUBLIC_REVENUECAT_API_KEY_IOS=your-ios-key
EXPO_PUBLIC_REVENUECAT_API_KEY_ANDROID=your-android-key

# Google Sign-In (Required for Google auth)
EXPO_PUBLIC_GOOGLE_WEB_CLIENT_ID=your-web-client-id
EXPO_PUBLIC_GOOGLE_IOS_CLIENT_ID=your-ios-client-id

# Apple Sign-In (configured in app.json)
# Uses native Expo Apple Authentication

# Optional
EXPO_PUBLIC_APP_ENV=development  # development | staging | production

Scripts

Development

# Start development server
npm start

# Start with cache cleared
npm start -- --clear

# Run on iOS
npm run ios

# Run on Android
npm run android

# Run type checking
npm run typecheck

# Run linting
npm run lint

Building

# Build for iOS (EAS)
eas build --platform ios

# Build for Android (EAS)
eas build --platform android

# Build for both platforms
eas build --platform all

Database

# Generate TypeScript types from Supabase
supabase gen types typescript --project-id your-project-id > types/database.ts

# Run migrations locally
supabase db push

# Reset local database
supabase db reset

Contributing

We welcome contributions! Please follow these steps:

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

Code Style

  • Use TypeScript for all new code
  • Follow existing patterns and conventions
  • Add types for all props and state
  • Use functional components with hooks
  • Keep components small and focused

Commit Messages

Follow conventional commits:

  • feat: New features
  • fix: Bug fixes
  • docs: Documentation changes
  • style: Code style changes
  • refactor: Code refactoring
  • test: Test additions/changes
  • chore: Maintenance tasks

License

MIT License - see LICENSE file for details.


Acknowledgments

  • Quin Gable — For the inspiring brief and vision for this app
  • RevenueCat — For organizing Shipyard and providing subscription infrastructure
  • Shipyard 2026 — For the opportunity to build something meaningful
  • Expo — For the amazing React Native development platform
  • Supabase — For the backend infrastructure

Built with ❤️ for the van-life community

Shipyard 2026Quin GableRevenueCat

About

nomad

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors