Membangun antarmuka pengguna NativePHP dengan Blade template dan Livewire: rendering di WebView (pre-v4), pola navigasi multi-halaman, form handling Livewire, styling mobile-friendly dengan Tailwind CSS, serta membangun layar list-detail responsif.

Setelah di episode 4 kita mengkonfigurasi identitas aplikasi — app identifier, ikon, splash screen, dan environment bundle — pada episode ini kita masuk ke UI layer: membangun antarmuka pengguna dengan Blade templates, Livewire components, dan Tailwind CSS.
Jika kalian sudah mahir Blade + Livewire untuk web, bagian ini terasa familier. Di NativePHP (pre-v4), UI dirender di dalam WebView bawaan perangkat — Blade templates dikompilasi seperti biasa, Livewire menangani interaksi real-time, dan Tailwind CSS menyediakan styling mobile-friendly. Di v4 SuperNative, komponen Blade yang sama dikonversi ke view SwiftUI/Jetpack Compose — tapi pola dasarnya identik.
Blade template di NativePHP menggunakan syntax yang sama persis dengan web. Bedanya: konteksnya adalah layar perangkat, bukan browser window. Ini berarti kalian perlu memperhatikan ukuran layar, touch targets, dan safe area.
<x-layouts.app>
<div class="min-h-screen bg-gray-50 p-4">
<h1 class="text-2xl font-bold text-gray-900 mb-4">
Halo, NativePHP!
</h1>
<p class="text-gray-600">
Aplikasi ini berjalan di perangkat kalian.
</p>
</div>
</x-layouts.app>Gunakan component Blade (<x-...> syntax) untuk membangun komponen reusable: header, kartu, tombol, form input. Ini memastikan konsistensi UI dan mengurangi duplikasi kode.
Livewire adalah pilihan utama untuk interaksi di NativePHP. Setiap user action (klik, input, swipe) ditangani oleh Livewire component yang mengelola state dan melakukan update secara reaktif:
<?php
namespace App\Livewire;
use Livewire\Component;
use App\Models\Todo;
class TodoList extends Component
{
public $todos = [];
public $newTodo = '';
public function mount()
{
$this->todos = Todo::all()->toArray();
}
public function addTodo()
{
if (empty(trim($this->newTodo))) return;
Todo::create(['title' => $this->newTodo]);
$this->newTodo = '';
$this->todos = Todo::all()->toArray();
}
public function toggleTodo($id)
{
$todo = Todo::find($id);
$todo->completed = !$todo->completed;
$todo->save();
$this->todos = Todo::all()->toArray();
}
public function render()
{
return view('livewire.todo-list');
}
}Di NativePHP, Livewire berjalan di dalam WebView — setiap update state memicu AJAX request ke PHP runtime lokal, yang merespons dengan JSON berisi HTML yang di-apply ke DOM. Semuanya berjalan di perangkat, tanpa koneksi internet.
Aplikasi mobile membutuhkan navigasi yang berbeda dari web. NativePHP menyediakan beberapa pendekatan:
<?php
use Illuminate\Support\Facades\Route;
use App\Livewire\Home;
use App\Livewire\TodoList;
use App\Livewire\TodoDetail;
Route::get('/', Home::class);
Route::get('/todos', TodoList::class);
Route::get('/todos/{id}', TodoDetail::class);Di WebView, navigasi ini bekerja seperti browser biasa — URL berubah, halaman baru dimuat. Untuk pengalaman yang lebih "native", kalian bisa menggunakan JavaScript bridge untuk push/pop navigation stack.
Untuk tab bar (seperti Instagram, Twitter), gabungkan route dengan layout tab:
<x-layouts.tab-bar>
<livewire:home />
<livewire:todo-list />
<livewire:settings />
</x-layouts.tab-bar>Tailwind CSS sangat cocok untuk mobile karena utility-first approach memudahkan responsive design. Gunakan breakpoint sm:, md:, lg: untuk menyesuaikan dengan ukuran layar perangkat:
<div class="grid grid-cols-1 sm:grid-cols-2 gap-4 p-4">
<div class="bg-white rounded-xl shadow-sm p-4">
<h3 class="text-lg font-semibold">Task Hari Ini</h3>
<p class="text-gray-500 mt-2">5 task pending</p>
</div>
<div class="bg-white rounded-xl shadow-sm p-4">
<h3 class="text-lg font-semibold">Selesai</h3>
<p class="text-gray-500 mt-2">12 task completed</p>
</div>
</div>Pastikan touch target minimal 44x44 point sesuai guideline Apple, dan spacing antar elemen cukup lebar untuk navigasi dengan jari.
Bangun aplikasi todo sederhana dengan dua layar — list dan detail — menggunakan Livewire:
<div class="min-h-screen bg-gray-50">
<div class="bg-white shadow-sm p-4">
<h1 class="text-xl font-bold">Todos</h1>
</div>
<form wire:submit="addTodo" class="p-4">
<input
type="text"
wire:model="newTodo"
placeholder="Tambah todo baru..."
class="w-full border rounded-lg p-3"
/>
</form>
<div class="divide-y">
@foreach($todos as $todo)
<a href="/todos/{{ $todo['id'] }}"
class="flex items-center justify-between p-4 bg-white">
<span class="{{ $todo['completed'] ? 'line-through text-gray-400' : '' }}">
{{ $todo['title'] }}
</span>
<button wire:click="toggleTodo({{ $todo['id'] }})">
{{ $todo['completed'] ? '✅' : '⬜' }}
</button>
</a>
@endforeach
</div>
</div>Tip
Di v4 SuperNative, komponen Blade ini akan otomatis dirender sebagai SwiftUI/Jetpack Compose views. Kalian tidak perlu menulis ulang — cukup pastikan Blade templates kalian mengikuti komponen yang didukung oleh NativePHP v4.
Inti yang harus dibawa pulang:
Di episode 6 selanjutnya, kita akan membahas Device APIs: Camera & Media — cara mengakses kamera dan galeri, permission flow iOS/Android, serta membangun fitur foto profil: ambil, crop, simpan lokal, dan upload saat online. Sampai jumpa di episode 6!