Episode ini membedah arsitektur Remix: routing berbasis filesystem dengan nested routes, loader dan action sebagai server-side data handler, alur server rendering versus client hydration, serta komponen utama project seperti vite.config, app/routes, dan request lifecycle.

Di episode 1 kalian memahami filosofi Remix. Sekarang saatnya membuka kap mesin dan melihat bagaimana Remix bekerja di balik layar. Episode 2 adalah peta arsitektur: dari file sampai request, dari server sampai browser.
Konsep inti yang akan kalian pegang adalah satu: setiap request HTTP yang masuk melewati satu alur yang bisa diprediksi. Remix melihat request, mencocokkan URL dengan route di filesystem, memanggil loader untuk mengambil data, me-render HTML di server, lalu mengirim hasilnya ke browser untuk di-hydrate. Memahami alur ini akan membuat konsep lain — caching, error boundary, streaming — terasa alami.
Mengapa episode ini penting? Karena hampir semua keputusan desain Remix bisa dijelaskan lewat arsitektur. Kalau kalian tahu apa yang terjadi saat browser meminta sebuah URL, kalian sudah menguasai setengah dari seluruh series ini.
Remix memetakan file di folder app/routes langsung menjadi URL. File _index.tsx menjadi halaman /, about.tsx menjadi /about, dan folder menghasilkan hierarki. Konvensi ini membuat struktur aplikasi bisa dibaca langsung dari struktur folder, tanpa konfigurasi routing terpusat.
app/routes/_index.tsx -> / halaman beranda
app/routes/about.tsx -> /about
app/routes/posts._index.tsx -> /posts
app/routes/posts.$id.tsx -> /posts/123 id adalah paramsKalian tidak menulis config route manual seperti di React Router klasik. File di app/routes langsung menjadi URL tanpa konfigurasi tambahan.
Keistimewaan Remix adalah nested routes: setiap file route bisa diekspor menjadi komponen default, dan route induk di-render oleh komponen Outlet dari route anak. Hasilnya, layout bersarang mengikuti struktur URL. Bagian yang sama di beberapa halaman cukup ditulis sekali di route induk.
import { Outlet, NavLink } from "@remix-run/react";
export default function LayoutBlog() {
return (
<div>
<nav>
<NavLink to="/posts">Semua Posting</NavLink>
</nav>
<Outlet />
</div>
);
}Outlet di atas adalah tempat route anak di-render. Saat navigasi terjadi, hanya bagian route yang berubah yang me-render ulang, bukan seluruh halaman — ini sumber kecepatan Remix.
Fungsi loader adalah tempat membaca data di server. Ia dipanggil setiap kali route diminta, dan hasilnya dikirim ke komponen lewat useLoaderData. Karena berjalan di server, loader bisa mengakses database, secret, dan API eksternal dengan aman.
import { useLoaderData } from "@remix-run/react";
export async function loader({ params }) {
const post = await getPost(params.id);
return post;
}
export default function DetailPost() {
const post = useLoaderData();
return <article>{post.judul}</article>;
}Loader menerima context seperti params, request, dan context, lalu mengembalikan data. Data inilah yang dipakai komponen untuk me-render HTML di server.
Jika loader membaca, maka action menulis. Action dipanggil saat form dikirim via POST, PUT, PATCH, atau DELETE. Setelah action selesai, Remix me-refresh loader route sehingga data yang ditampilkan selalu terkini. Pola dua fungsi ini menggantikan seluruh lapisan API terpisah di aplikasi SPA.
Saat browser meminta URL, Remix mencocokkan route, memanggil semua loader yang relevan, me-render HTML lengkap di server, dan mengirimnya bersama data serialized. Browser menampilkan halaman segera, lalu menjalankan JavaScript untuk hydration — menghubungkan event handler dan state React pada HTML yang sudah ada.
URL masuk -> match route -> jalankan loader -> render HTML di server
-> kirim HTML + data -> browser render -> hydrate dengan ReactAlur ini berjalan untuk navigasi pertama maupun navigasi berikutnya, hanya saja navigasi berikutnya dijalankan via fetch internal dan ditangani secara progresif oleh client.
Remix tidak menyediakan server sendiri. Ia memakai adapter untuk berjalan di berbagai platform: @remix-run/node untuk Node.js, @remix-run/cloudflare-pages untuk Cloudflare, @remix-run/vercel untuk Vercel, dan seterusnya. Build menghasilkan aset statis dan server bundle yang dideploy sesuai platform target. Detail adaptor akan dibahas mendalam di episode 20.
Sebuah project Remix modern (v3, berbasis Vite) memiliki struktur sebagai berikut:
nama-aplikasi/
app/
routes/ <- file route, satu file satu URL
entry.client.tsx <- titik masuk browser
entry.server.tsx <- titik masuk server
root.tsx <- root layout, tempat Outlet teratas
public/ <- aset statis
vite.config.ts <- konfigurasi build (menggantikan remix.config.js)
tsconfig.jsonDi Remix v2, konfigurasi utama berada di remix.config.js; sejak v3 konfigurasi pindah ke vite.config.ts. Ini perubahan yang penting saat kalian membaca tutorial lama — tutorial yang menyebut remix.config.js biasanya ditulis untuk versi sebelum v3.
Setiap route bisa mengekspor fungsi khusus: meta untuk tag di <head>, headers untuk header HTTP respons, serta ErrorBoundary dan CatchBoundary untuk menangani error. Kombinasi ekspor inilah yang disebut route module — satu file berisi UI, data, meta, dan perilaku error dari satu URL.
Episode 2 memperlihatkan arsitektur Remix secara utuh: filesystem routing dengan nested layout, loader dan action sebagai pasangan baca-tulis di server, alur render di server lalu hydration di client, serta struktur project modern berbasis Vite. Semua konsep berikutnya akan memakai peta ini sebagai titik acuan.
Inti yang harus dibawa pulang:
Di episode 3 selanjutnya kita akan langsung praktik: memulai proyek Remix dengan npx create-remix@latest, memahami struktur folder yang dihasilkan, menjalankan dev server dengan hot reload, serta mengonfigurasi TypeScript, ESLint, dan Prettier. Siapkan terminal kalian, karena kita akan membangun project pertama.