React Native Expo Event Management

1

Part 1: Pengenalan & Arsitektur

2

Part 2: Instalasi di Mac, Windows, Ubuntu

3

Part 3: Project Setup

4

Part 4: Autentikasi Admin

5

Part 5: Manajemen Event

6

Part 6: QR Scanner Kehadiran

7

Part 7: Polish & Deploy

Artikel ini tersedia dalam Bahasa Inggris

šŸ‡¬šŸ‡§ Read in English

21 Januari 2026

šŸ‡®šŸ‡© Bahasa Indonesia

React Native Expo Event Management Part 3: Project Setup

Membuat project Expo baru dengan TypeScript, install dependencies, konfigurasi NativeWind, dan setup struktur folder untuk aplikasi event management.

6 min read


šŸ“– Overview

Di bagian ini, kita akan membuat project Expo baru dan melakukan konfigurasi awal termasuk routing, styling, dan folder structure.

šŸš€ Step 1: Create Expo Project

# Create new Expo project dengan TypeScript template
npx create-expo-app@latest lampung-dev-mobile --template tabs

# Masuk ke folder project
cd lampung-dev-mobile

Template tabs sudah menyertakan:

  • TypeScript configuration
  • Expo Router (file-based routing)
  • Tab navigation contoh
  • Basic folder structure

šŸ“¦ Step 2: Install Dependencies

# Core dependencies
npm install axios zustand

# Expo packages
npx expo install expo-secure-store expo-camera

# Styling (NativeWind - Tailwind untuk React Native)
npm install nativewind
npm install --save-dev [email protected]

# Icons
npm install lucide-react-native
npm install react-native-svg

Penjelasan Dependencies

PackageFungsi
axiosHTTP client untuk API calls
zustandState management ringan
expo-secure-storePenyimpanan token yang aman
expo-cameraAkses kamera untuk QR scan
nativewindTailwind CSS untuk React Native
lucide-react-nativeIcon library

šŸŽØ Step 3: Konfigurasi NativeWind (Tailwind CSS)

A. Initialize Tailwind

npx tailwindcss init

B. Edit tailwind.config.js

// tailwind.config.js
/** @type {import('tailwindcss').Config} */
module.exports = {
  content: [
    "./app/**/*.{js,jsx,ts,tsx}",
    "./components/**/*.{js,jsx,ts,tsx}"
  ],
  presets: [require("nativewind/preset")],
  theme: {
    extend: {
      colors: {
        primary: '#f0880a',    // Warna brand LampungDev
        secondary: '#1a1a1a',  // Dark mode background
      },
    },
  },
  plugins: [],
}

C. Buat global.css

/* global.css */
@tailwind base;
@tailwind components;
@tailwind utilities;

D. Edit babel.config.js

// babel.config.js
module.exports = function (api) {
  api.cache(true);
  return {
    presets: [
      ["babel-preset-expo", { jsxImportSource: "nativewind" }],
      "nativewind/babel",
    ],
  };
};

E. Buat nativewind-env.d.ts

// nativewind-env.d.ts
/// <reference types="nativewind/types" />

F. Edit metro.config.js

// metro.config.js
const { getDefaultConfig } = require("expo/metro-config");
const { withNativeWind } = require('nativewind/metro');

const config = getDefaultConfig(__dirname);

module.exports = withNativeWind(config, { input: './global.css' });

šŸ“‚ Step 4: Buat Folder Structure

# Buat folders yang dibutuhkan
mkdir -p services store components constants utils

Struktur akhir:

lampung-dev-mobile/ ā”œā”€ā”€ app/ # Screens (Expo Router) │ ā”œā”€ā”€ (tabs)/ # Tab navigation │ ā”œā”€ā”€ event/ # Event screens │ ā”œā”€ā”€ login.tsx # Login screen │ └── _layout.tsx # Root layout │ ā”œā”€ā”€ components/ # Komponen reusable ā”œā”€ā”€ services/ # API services ā”œā”€ā”€ store/ # State management ā”œā”€ā”€ constants/ # App constants ā”œā”€ā”€ utils/ # Utilities └── assets/ # Images, fonts

šŸ”§ Step 5: Konfigurasi app.json

Edit file app.json:

{
  "expo": {
    "name": "Lampung Dev",
    "slug": "lampung-dev",
    "version": "1.0.0",
    "orientation": "portrait",
    "icon": "./assets/images/icon.png",
    "scheme": "lampungdev",
    "userInterfaceStyle": "automatic",
    "splash": {
      "image": "./assets/images/splash-icon.png",
      "resizeMode": "contain",
      "backgroundColor": "#1a1a1a"
    },
    "ios": {
      "supportsTablet": true,
      "bundleIdentifier": "org.lampungdev.mobile"
    },
    "android": {
      "adaptiveIcon": {
        "foregroundImage": "./assets/images/adaptive-icon.png",
        "backgroundColor": "#1a1a1a"
      },
      "package": "org.lampungdev.mobile",
      "permissions": ["CAMERA"]
    },
    "plugins": [
      "expo-router",
      [
        "expo-camera",
        {
          "cameraPermission": "Izinkan aplikasi mengakses kamera untuk scan QR"
        }
      ]
    ]
  }
}

🌐 Step 6: Setup API Service

A. Buat Base API

File: services/api.ts

import axios from 'axios';
import * as SecureStore from 'expo-secure-store';

// Development: Gunakan IP lokal kamu
// Production: Gunakan domain API
export const BASE_URL = __DEV__ 
  ? 'http://192.168.1.100:3000'  // Ganti dengan IP kamu
  : 'https://lampungdev.org';

export const API_BASE_URL = `${BASE_URL}/api`;

export const api = axios.create({
  baseURL: API_BASE_URL,
  headers: {
    'Content-Type': 'application/json',
  },
  timeout: 10000, // 10 seconds timeout
});

// Request interceptor - tambahkan auth token
api.interceptors.request.use(async (config) => {
  try {
    const token = await SecureStore.getItemAsync('auth_token');
    if (token) {
      config.headers.Authorization = `Bearer ${token}`;
    }
  } catch (error) {
    console.error('Error getting token:', error);
  }
  return config;
});

// Response interceptor - handle errors
api.interceptors.response.use(
  (response) => response,
  async (error) => {
    if (error.response?.status === 401) {
      // Token expired - clear auth
      await SecureStore.deleteItemAsync('auth_token');
      await SecureStore.deleteItemAsync('auth_user');
      // Redirect ke login ditangani oleh store
    }
    return Promise.reject(error);
  }
);

B. Buat Auth Service

File: services/auth.ts

import { api } from './api';

interface LoginResponse {
  success: boolean;
  data?: {
    token: string;
    user: {
      id: string;
      name: string;
      email: string;
      role: string;
      picture?: string;
    };
  };
  error?: string;
}

export const loginAdmin = async (
  email: string, 
  password: string
): Promise<LoginResponse> => {
  const response = await api.post('/admin/auth', { email, password });
  return response.data;
};

C. Buat Events Service

File: services/events.ts

import { api } from './api';

export interface Event {
  id: string;
  title: string;
  description: string;
  date: string;
  location: string;
  imageUrl?: string;
  registrationCount: number;
  attendanceCount: number;
}

export interface EventsResponse {
  success: boolean;
  data: {
    events: Event[];
    pagination: {
      page: number;
      limit: number;
      total: number;
      totalPages: number;
    };
  };
}

export const getAdminEvents = async (
  page = 1, 
  limit = 20
): Promise<EventsResponse> => {
  const response = await api.get('/admin/events', {
    params: { page, limit }
  });
  return response.data;
};

export const getEventDetail = async (id: string) => {
  const response = await api.get(`/admin/events/${id}`);
  return response.data;
};

D. Buat Attendance Service

File: services/attendance.ts

import { api } from './api';

interface AttendanceResponse {
  success: boolean;
  message?: string;
  data?: {
    registration: {
      id: string;
      name: string;
      email: string;
      checkedInAt: string;
    };
  };
  error?: string;
}

export const recordAttendance = async (
  eventId: string, 
  uniqueCode: string
): Promise<AttendanceResponse> => {
  const response = await api.post('/attendance', { eventId, uniqueCode });
  return response.data;
};

E. Buat Index Export

File: services/index.ts

export * from './api';
export * from './auth';
export * from './events';
export * from './attendance';

šŸŽÆ Step 7: Setup Constants

File: constants/Colors.ts

const tintColorLight = '#f0880a';
const tintColorDark = '#f0880a';

export const Colors = {
  light: {
    text: '#11181C',
    background: '#fff',
    tint: tintColorLight,
    icon: '#687076',
    tabIconDefault: '#687076',
    tabIconSelected: tintColorLight,
    card: '#f5f5f5',
    border: '#e0e0e0',
  },
  dark: {
    text: '#ECEDEE',
    background: '#151718',
    tint: tintColorDark,
    icon: '#9BA1A6',
    tabIconDefault: '#9BA1A6',
    tabIconSelected: tintColorDark,
    card: '#1a1a1a',
    border: '#2a2a2a',
  },
};

šŸ“± Step 8: Run Development

# Start Expo development server
npm start

# Atau dengan platform specific
npm run android
npm run ios

Testing di Device

  1. Install Expo Go app di smartphone
  2. Scan QR code dari terminal
  3. Pastikan HP dan komputer di jaringan WiFi yang sama

Mencari IP Address

# macOS/Linux
ifconfig | grep "inet "

# Windows
ipconfig

Update BASE_URL di services/api.ts dengan IP kamu.

āœ… Project Structure Check

Setelah setup selesai, struktur project harusnya seperti ini:

lampung-dev-mobile/ ā”œā”€ā”€ app/ │ ā”œā”€ā”€ (tabs)/ │ │ ā”œā”€ā”€ index.tsx │ │ ā”œā”€ā”€ scanner.tsx # Akan dibuat nanti │ │ └── account.tsx # Akan dibuat nanti │ ā”œā”€ā”€ event/ │ │ └── [id].tsx # Akan dibuat nanti │ ā”œā”€ā”€ login.tsx # Akan dibuat nanti │ ā”œā”€ā”€ _layout.tsx │ └── +not-found.tsx ā”œā”€ā”€ components/ ā”œā”€ā”€ services/ │ ā”œā”€ā”€ api.ts āœ… │ ā”œā”€ā”€ auth.ts āœ… │ ā”œā”€ā”€ events.ts āœ… │ ā”œā”€ā”€ attendance.ts āœ… │ └── index.ts āœ… ā”œā”€ā”€ store/ ā”œā”€ā”€ constants/ │ └── Colors.ts āœ… ā”œā”€ā”€ utils/ ā”œā”€ā”€ assets/ ā”œā”€ā”€ app.json āœ… ā”œā”€ā”€ babel.config.js āœ… ā”œā”€ā”€ metro.config.js āœ… ā”œā”€ā”€ tailwind.config.js āœ… ā”œā”€ā”€ global.css āœ… ā”œā”€ā”€ nativewind-env.d.ts āœ… └── package.json

āœ… Checklist

  • Project dibuat dengan create-expo-app
  • Dependencies terinstall (axios, zustand, nativewind)
  • NativeWind terkonfigurasi
  • Folder structure dibuat
  • API services di-setup
  • Constants terkonfigurasi
  • App running di Expo Go

šŸš€ Selanjutnya

Di Part 4, kita akan membuat sistem autentikasi termasuk login screen, state management dengan Zustand, dan token storage dengan SecureStore.


← Part 2: Instalasi | Part 4: Autentikasi Admin →


Series ini dibuat untuk mendukung materi Casual Meetup #15 di LampungDev.

Lanjut Membaca

Previous article thumbnail

← Artikel Sebelumnya

React Native Expo Event Management Part 2: Instalasi di Mac, Windows, Ubuntu

Artikel Selanjutnya →

React Native Expo Event Management Part 4: Autentikasi Admin

Next article thumbnail