Quick Start

Build your first feature with AppLighter in minutes. Learn how to create screens, fetch data with Vibecode DB, and use AI tools for rapid development.

Project Structure

Here's an overview of the AppLighter starter template:

code/
├── app/                              # Expo Router pages
│   ├── _layout.tsx                   # Root layout with auth state
│   ├── index.tsx                     # Entry point (redirect logic)
│   ├── (auth)/                       # Public auth routes
│   │   ├── signin.tsx                # Sign in screen
│   │   └── signup.tsx                # Sign up screen
│   └── (app)/                        # Protected routes (tab navigation)
│       ├── home.tsx                  # Home / Tasks screen
│       └── profile.tsx               # Profile screen

├── components/                       # Reusable UI components
│   ├── index.ts                      # Barrel exports
│   ├── ThemeProvider.tsx             # Theme context
│   ├── ThemeToggle.tsx               # Dark/light toggle
│   └── ThemedView.tsx                # Theme-aware container

├── src/                              # Business logic
│   ├── db/                           # Database layer
│   │   ├── client.ts                 # Vibecode DB client
│   │   ├── schema.ts                 # TypeScript types
│   │   └── seeds/                    # Mock data
│   ├── hooks/                        # useAuth, useOffline
│   ├── providers/                    # AppProviders, ThemeProvider
│   └── lib/                          # Utilities
│       └── queryClient.ts            # TanStack Query config

├── pocketbase/                       # PocketBase backend config
│   ├── command-scripts/              # DB push & seed scripts
│   └── pb_migrations/                # Migration files

├── supabase/                         # Supabase backend config
│   ├── migrations/                   # SQL migration files
│   ├── seed/                         # Seed data scripts
│   └── types/                        # Generated TypeScript types

├── .claude/                          # Claude AI configuration
│   ├── skills/                       # 16 domain-specific skills
│   ├── commands/                     # Slash commands
│   ├── agents/                       # AI agents
│   └── docs/                         # Architecture & API reference

├── theme.ts                          # Theme color tokens
├── global.css                        # Tailwind base styles
├── tailwind.config.js                # NativeWind config
├── claude.md                         # Project context for AI
├── rapidnative.json                  # RapidNative project config
├── .env                              # Environment variables
└── package.json                      # Dependencies

Creating a New Screen

With Expo Router, creating new screens is file-based. Add a new file to the app/ directory:

// app/(app)/settings.tsx
import { View, Text, ScrollView } from 'react-native'
import { SafeAreaView } from 'react-native-safe-area-context'
 
export default function SettingsScreen() {
  return (
    <SafeAreaView className="flex-1 bg-background" edges={['top']}>
      <ScrollView className="flex-1 px-4">
        <Text className="text-2xl font-bold text-foreground mt-4">Settings</Text>
      </ScrollView>
    </SafeAreaView>
  )
}

Fetching Data with Vibecode DB

Use the Vibecode client to fetch data from your backend:

import { vibecode } from '@/src/db/client'
 
// Fetch all items (chain order: from → filters → order → limit → select)
const { data, error } = await vibecode
  .from('posts')
  .order('created_at', { ascending: false })
  .limit(50)
  .select('*')
 
if (error) throw error
 
// Fetch with filters
const { data: userPosts } = await vibecode
  .from('posts')
  .eq('user_id', userId)
  .order('created_at', { ascending: false })
  .limit(50)
  .select('*')

Using TanStack Query

Wrap database calls with TanStack Query for caching and offline support:

import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'
import { vibecode } from '@/src/db/client'
 
export default function HomeScreen() {
  const queryClient = useQueryClient()
 
  const { data: posts, isLoading } = useQuery({
    queryKey: ['posts'],
    queryFn: async () => {
      const { data, error } = await vibecode
        .from('posts')
        .order('created_at', { ascending: false })
        .limit(50)
        .select('*')
      if (error) throw error
      return data ?? []
    },
  })
 
  // ... render posts
}