Chuyển đến nội dung chính

Lesson 16: Vibe Coding for Mobile & Cross-Platform

Develop mobile applications using Vibe Coding. React Native and Flutter workflows. UI generation, navigation, API integration. Platform-specific code. Testing mobile apps. Deploy to App Store and Google Play.

💻 Programming — Lesson 16 Lesson 16: Vibe Coding for Mobile & Cross-Platform

Vibe Coding with GitHub Copilot: From Basics to Advanced

Part 5: Vibe Coding in action — Building real projects

xdev.asia

1. Vibe Coding on Mobile — How is it different from the Web?

Mobile development has its own characteristics that Vibe Coding needs to adapt to:

Characteristics Web Mobile
Layout CSS Flexbox/Grid Platform-specific layout
Navigation URL-based routing Stack/Tab navigation
Testing Browser → instant feedback Emulator/Device → slower
Native APIs Limitations Camera, GPS, Sensors, Push
Performance DOM rendering Native rendering
Deploy Vercel/Netlify App Store review process

2. React Native with Vibe Coding

2.1. Setup project

// Prompt:
Create a React Native project with Expo for the Task Management app.
Include:
- TypeScript
- React Navigation (stack + bottom tabs)
- React Query for API calls
- AsyncStorage for local state
- Expo secure-store for auth tokens
- NativeWind (TailwindCSS for React Native)

2.2. Shared types with Backend

// Prompt:
I have a backend with these API responses (paste TypeScript types).
Generate React Native API client and hooks that match these types exactly.
Reuse the same Zod schemas from the web frontend.
// src/hooks/useTasks.ts
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
import { api } from '../lib/api';
import type { Task, CreateTaskInput } from '../types';

export function useTasks(projectId: string) {
  return useQuery({
    queryKey: ['tasks', projectId],
    queryFn: () => api.get<Task[]>(`/tasks?projectId=${projectId}`),
  });
}

export function useCreateTask() {
  const queryClient = useQueryClient();

  return useMutation({
    mutationFn: (data: CreateTaskInput) => api.post('/tasks', data),
    onSuccess: (_, variables) => {
      queryClient.invalidateQueries({
        queryKey: ['tasks', variables.projectId],
      });
    },
  });
}

2.3. Mobile-specific UI

// Prompt:
Create a task list screen for React Native with:
- Pull to refresh
- Infinite scroll pagination
- Swipe to complete/delete
- FAB (floating action button) to add tasks
- Priority color indicators
- Use NativeWind for styling
// src/screens/TaskListScreen.tsx
import { FlatList, RefreshControl, View, Text, Pressable } from 'react-native';
import { Swipeable } from 'react-native-gesture-handler';
import { useTasks } from '../hooks/useTasks';

export function TaskListScreen({ route }) {
  const { projectId } = route.params;
  const { data, isLoading, refetch } = useTasks(projectId);

  const priorityColors = {
    LOW: 'bg-green-500',
    MEDIUM: 'bg-yellow-500',
    HIGH: 'bg-orange-500',
    URGENT: 'bg-red-500',
  };

  const renderTask = ({ item: task }) => (
    <Swipeable
      renderRightActions={() => (
        <Pressable className="bg-green-500 justify-center px-6"
          onPress={() => completeTask(task.id)}>
          <Text className="text-white font-bold">Done</Text>
        </Pressable>
      )}>
      <View className="bg-white p-4 border-b border-gray-100 flex-row items-center">
        <View className={`w-3 h-3 rounded-full mr-3 ${priorityColors[task.priority]}`} />
        <View className="flex-1">
          <Text className="font-semibold text-gray-900">{task.title}</Text>
          <Text className="text-gray-500 text-sm">{task.assignee?.name}</Text>
        </View>
      </View>
    </Swipeable>
  );

  return (
    <View className="flex-1 bg-gray-50">
      <FlatList
        data={data}
        renderItem={renderTask}
        refreshControl={
          <RefreshControl refreshing={isLoading} onRefresh={refetch} />
        }
      />
    </View>
  );
}

3. Flutter with Vibe Coding

3.1. Flutter project setup

// Prompt:
Create a Flutter app for Task Management with:
- Clean architecture (presentation, domain, data layers)
- Riverpod for state management
- Go Router for navigation
- Dio for API calls
- Freezed for immutable models
- Material 3 design

3.2. Dart model generation

// Prompt:
Generate Freezed models for these API responses:
- Task (id, title, description, status, priority, dueDate, assignee)
- Project (id, name, description, owner)
- User (id, email, name, avatar)
Include fromJson/toJson serialization.
// lib/models/task.dart
import 'package:freezed_annotation/freezed_annotation.dart';

part 'task.freezed.dart';
part 'task.g.dart';

@freezed
class Task with _$Task {
  const factory Task({
    required String id,
    required String title,
    String? description,
    @Default(TaskStatus.todo) TaskStatus status,
    @Default(Priority.medium) Priority priority,
    DateTime? dueDate,
    User? assignee,
  }) = _Task;

  factory Task.fromJson(Map<String, dynamic> json) => _$TaskFromJson(json);
}

enum TaskStatus {
  @JsonValue('TODO') todo,
  @JsonValue('IN_PROGRESS') inProgress,
  @JsonValue('IN_REVIEW') inReview,
  @JsonValue('DONE') done,
}

enum Priority {
  @JsonValue('LOW') low,
  @JsonValue('MEDIUM') medium,
  @JsonValue('HIGH') high,
  @JsonValue('URGENT') urgent,
}

3.3. Flutter UI with Copilot

// Prompt:
Create a Flutter task board widget with:
- Horizontal scrollable columns (Todo, In Progress, Done)
- Draggable task cards between columns
- Material 3 card design
- Pull to refresh
- Hero animation when opening task detail

4. Platform-Specific Code

// Prompt:
Add push notifications to the mobile app:
- Firebase Cloud Messaging setup
- Handle foreground/background/terminated states  
- Deep link to specific task when notification tapped
- Platform-specific code for iOS (APNs) and Android (FCM)

Copilot understands platform differences and generate appropriate code for each platform.

5. Comparison: React Native vs Flutter for Vibe Coding

Criteria React Native Flutter
AI code quality Good (lots of training data) Good (growing ecosystem)
Code sharing with the web High (shared TypeScript) Low (Private Dart)
Copilot suggestions Very accurate (JS/TS) Accurate (Dart)
Component generation Fast (JSX familiar) Fast (widget tree)
Testing with AI Jest + RTL (familiar) Widget testing (learning curve)
Hot reloads Fast Refresh ✅ Hot Reload ✅

Recommendation: If the team has used React for web → React Native. If you need high performance and custom UI → Flutter.

6. Testing Mobile Apps

// Prompt cho React Native:
Write tests for TaskListScreen:
- Renders task list from API
- Pull to refresh calls refetch
- Swipe right completes task
- Shows loading indicator
- Shows empty state when no tasks
Use @testing-library/react-native
// Prompt cho Flutter:
Write widget tests for TaskBoard:
- Renders columns with correct titles
- Shows tasks in correct columns
- Drag and drop changes task status
- Pull to refresh triggers reload

7. Deploy Mobile Apps

// Prompt:
Create a CI/CD pipeline for the React Native app:
- GitHub Actions workflow
- Build for iOS (using Expo EAS)
- Build for Android (using Expo EAS)
- Auto-submit to TestFlight and Google Play Internal Testing
- Run tests before build

8. Summary

Mobile Tasks Vibe Coding Effectiveness
UI screens ⭐⭐⭐⭐⭐ Very effective
API integration ⭐⭐⭐⭐⭐ Type-safe and fast
Navigation ⭐⭐⭐⭐ Good with familiar patterns
Native APIs ⭐⭐⭐ Need to review platform specifics
Performance tuning ⭐⭐ Need human expertise
App Store submission ⭐⭐⭐ CI/CD setup is good, but needs manual review

Part 6 will focus on quality and professionalism — Code quality, security, technical debt, and working in a team with Vibe Coding.