HOSTING CEPATDOMAIN MURAHSSL GRATISSUPPORT 24/7UPTIME 99.9%SERVER INDONESIAHOSTING CEPATDOMAIN MURAHSSL GRATISSUPPORT 24/7UPTIME 99.9%SERVER INDONESIA
Web Development

Cara Membuat Website dengan Remix: Full-Stack React Framework 2026

Tim HostingEkspres|26 Mei 2026|14 menit baca
cara membuat website dengan remixremix framework tutorialremix run indonesiafull stack react frameworkremix js pemularemix hostingweb development fullstack
Cara Membuat Website dengan Remix: Full-Stack React Framework 2026

Pendahuluan: Mengapa Belajar Cara Membuat Website dengan Remix?

Cara membuat website dengan Remix adalah topik yang semakin relevan bagi developer React yang ingin membangun aplikasi web full-stack yang cepat, tangguh, dan berperforma tinggi. Remix adalah full-stack web framework berbasis React yang dibangun di atas Web Standards - artinya Remix memanfaatkan API browser dan server yang sudah ada, bukan menciptakan abstraksi baru.

Apa yang membuat Remix spesial? Remix memiliki filosofi yang terinspirasi dari model web lama yang terbukti bekerja: form HTML yang benar-benar berfungsi, URL sebagai sumber kebenaran state, dan response HTTP yang dimanfaatkan sepenuhnya. Dikombinasikan dengan React, hasilnya adalah aplikasi web yang terasa snappy, resilient bahkan saat JavaScript gagal, dan mudah di-cache.

Remix juga memiliki sistem nested routing yang powerful: setiap segmen URL dapat memiliki layout, data loader, dan action handler sendiri-sendiri. Ini membuat kode lebih terstruktur dan data fetching lebih efisien karena data dimuat secara paralel. Dalam panduan ini, Anda akan belajar cara membuat website dengan Remix dari nol hingga siap deploy ke hosting.

Remix vs Next.js: Kapan Memilih Remix?

Kedua framework sama-sama populer untuk React full-stack, tetapi memiliki filosofi berbeda:

cara membuat website dengan remix
Ilustrasi cara membuat website dengan remix
  • Remix unggul dalam form handling, mutation (create/update/delete data), resilience (progressive enhancement), dan aplikasi yang banyak berinteraksi dengan server
  • Next.js lebih unggul untuk Static Site Generation (SSG) skala besar, ekosistem yang lebih matang, dan integrasi dengan platform Vercel
  • Remix lebih dekat ke Web Standards - skill yang dipelajari langsung berlaku di vanilla web
  • Remix cocok untuk aplikasi CRUD, dashboard, e-commerce, dan aplikasi enterprise

Prasyarat Sebelum Belajar Remix

Remix adalah framework yang dibangun di atas React, jadi prasyarat utamanya adalah:

  • HTML dasar - terutama form, method GET/POST, dan atribut action
  • CSS dasar - selector, box model, flexbox, dan responsiveness
  • JavaScript ES6+ - async/await, module, destructuring, dan array methods
  • React dasar - komponen, props, state (useState), dan hooks dasar
  • HTTP dasar - request, response, headers, dan status codes

Langkah 1: Menyiapkan Environment dan Membuat Proyek Remix

Install Node.js

Remix memerlukan Node.js versi 18 atau lebih baru. Unduh dari nodejs.org dan verifikasi instalasi:

node --version   # harus v18+
npm --version

Membuat Proyek Remix Baru

Gunakan perintah resmi untuk membuat proyek baru:

npx create-remix@latest nama-website-anda
cd nama-website-anda
npm run dev

Wizard akan menanyakan beberapa pilihan. Rekomendasi untuk pemula:

  • Template: Remix App Server (default)
  • TypeScript: Yes (sangat direkomendasikan)

Buka browser di http://localhost:3000.

Struktur Folder Proyek Remix

nama-website-anda/
├── app/
│   ├── routes/              ← sistem routing berbasis file
│   │   ├── _index.tsx       ← halaman beranda (/)
│   │   ├── tentang.tsx      ← halaman /tentang
│   │   ├── blog._index.tsx  ← halaman /blog
│   │   └── blog.$slug.tsx   ← halaman /blog/:slug (dinamis)
│   ├── components/          ← komponen reusable
│   ├── utils/               ← helper functions
│   ├── root.tsx             ← root layout (html, head, body)
│   └── entry.client.tsx     ← entry point browser
├── public/                  ← aset statis
├── remix.config.js
├── tsconfig.json
└── package.json

Langkah 2: Memahami Root Layout

File app/root.tsx adalah layout paling atas yang membungkus semua halaman. Di sinilah Anda mendefinisikan struktur HTML dasar, global CSS, dan meta tags default.

// app/root.tsx
import {
  Links,
  Meta,
  Outlet,
  Scripts,
  ScrollRestoration,
  LiveReload,
} from "@remix-run/react";
import type { LinksFunction } from "@remix-run/node";
import stylesheet from "~/app.css";

export const links: LinksFunction = () => [
  { rel: "stylesheet", href: stylesheet },
];

export default function App() {
  return (
    <html lang="id">
      <head>
        <meta charSet="utf-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1" />
        <Meta />
        <Links />
      </head>
      <body>
        <header>
          <nav>
            <a href="/">Beranda</a>
            <a href="/produk">Produk</a>
            <a href="/blog">Blog</a>
            <a href="/kontak">Kontak</a>
          </nav>
        </header>
        <main>
          <Outlet />
        </main>
        <footer>
          <p>© {new Date().getFullYear()} Website Saya</p>
        </footer>
        <ScrollRestoration />
        <Scripts />
        <LiveReload />
      </body>
    </html>
  );
}

Langkah 3: Loader - Mengambil Data di Server

Salah satu konsep paling penting di Remix adalah loader: fungsi yang berjalan di server sebelum halaman dirender dan menyediakan data untuk komponen. Loader tidak pernah dikirim ke browser - hanya datanya yang dikirim.

Contoh Loader Sederhana

// app/routes/blog._index.tsx
import { json } from "@remix-run/node";
import { useLoaderData, Link } from "@remix-run/react";
import type { LoaderFunctionArgs, MetaFunction } from "@remix-run/node";

interface Artikel {
  id: number;
  slug: string;
  judul: string;
  ringkasan: string;
  tanggal: string;
}

export const meta: MetaFunction = () => [
  { title: "Blog | Website Saya" },
  { name: "description", content: "Artikel dan tutorial web development terbaru." },
];

export async function loader({ request }: LoaderFunctionArgs) {
  // Di sini Anda bisa query database, fetch API eksternal, dll.
  const artikelList: Artikel[] = [
    { id: 1, slug: "cara-memilih-hosting", judul: "Cara Memilih Hosting Terbaik", ringkasan: "@@P3@@...", tanggal: "2026-05-30" },
    { id: 2, slug: "apa-itu-ssl", judul: "Apa itu SSL dan Mengapa Penting?", ringkasan: "SSL melindungi...", tanggal: "2026-05-25" },
  ];
  return json({ artikelList });
}

export default function BlogIndex() {
  const { artikelList } = useLoaderData<typeof loader>();

  return (
    <div>
      <h1>Artikel Terbaru</h1>
      <ul>
        {artikelList.map((artikel) => (
          <li key={artikel.id}>
            <Link to={artikel.slug}>
              <h2>{artikel.judul}</h2>
              <p>{artikel.ringkasan}</p>
              <time>{artikel.tanggal}</time>
            </Link>
          </li>
        ))}
      </ul>
    </div>
  );
}

Loader dengan Parameter URL Dinamis

// app/routes/blog.$slug.tsx
import { json } from "@remix-run/node";
import { useLoaderData } from "@remix-run/react";
import type { LoaderFunctionArgs, MetaFunction } from "@remix-run/node";

export async function loader({ params }: LoaderFunctionArgs) {
  const { slug } = params;
  // Ambil artikel berdasarkan slug dari database
  const artikel = await getArtikelBySlug(slug!);
  if (!artikel) {
    throw new Response("Artikel tidak ditemukan", { status: 404 });
  }
  return json({ artikel });
}

export const meta: MetaFunction<typeof loader> = ({ data }) => [
  { title: data?.artikel.judul ?? "Artikel" },
  { name: "description", content: data?.artikel.ringkasan },
];

export default function BlogDetail() {
  const { artikel } = useLoaderData<typeof loader>();
  return (
    <article>
      <h1>{artikel.judul}</h1>
      <div dangerouslySetInnerHTML={{ __html: artikel.isi }} />
    </article>
  );
}

Langkah 4: Action - Memproses Form di Server

Action adalah fungsi server yang menangani HTTP POST, PUT, PATCH, dan DELETE. Ini adalah cara Remix menangani mutasi data - jauh lebih sederhana dan lebih web-native daripada pendekatan API endpoint terpisah.

Contoh Form Kontak dengan Action

// app/routes/kontak.tsx
import { json, redirect } from "@remix-run/node";
import { Form, useActionData, useNavigation } from "@remix-run/react";
import type { ActionFunctionArgs, MetaFunction } from "@remix-run/node";

export const meta: MetaFunction = () => [
  { title: "Kontak Kami | Website Saya" },
];

export async function action({ request }: ActionFunctionArgs) {
  const formData = await request.formData();
  const nama = formData.get("nama") as string;
  const email = formData.get("email") as string;
  const pesan = formData.get("pesan") as string;

  // Validasi input
  const errors: Record<string, string> = {};
  if (!nama || nama.length < 2) errors.nama = "Nama minimal 2 karakter";
  if (!email || !email.includes("@")) errors.email = "Email tidak valid";
  if (!pesan || pesan.length < 10) errors.pesan = "Pesan minimal 10 karakter";

  if (Object.keys(errors).length > 0) {
    return json({ errors, values: { nama, email, pesan } }, { status: 400 });
  }

  // Kirim email atau simpan ke database
  await kirimEmail({ nama, email, pesan });

  return redirect("/kontak?terkirim=true");
}

export default function Kontak() {
  const actionData = useActionData<typeof action>();
  const navigation = useNavigation();
  const isSubmitting = navigation.state === "submitting";

  return (
    <div>
      <h1>Hubungi Kami</h1>
      <Form method="post">
        <div>
          <label htmlFor="nama">Nama</label>
          <input
            id="nama"
            name="nama"
            type="text"
            defaultValue={actionData?.values?.nama}
          />
          {actionData?.errors?.nama && (
            <p style={{ color: "red" }}>{actionData.errors.nama}</p>
          )}
        </div>
        <div>
          <label htmlFor="email">Email</label>
          <input
            id="email"
            name="email"
            type="email"
            defaultValue={actionData?.values?.email}
          />
          {actionData?.errors?.email && (
            <p style={{ color: "red" }}>{actionData.errors.email}</p>
          )}
        </div>
        <div>
          <label htmlFor="pesan">Pesan</label>
          <textarea id="pesan" name="pesan" rows={5} defaultValue={actionData?.values?.pesan} />
          {actionData?.errors?.pesan && (
            <p style={{ color: "red" }}>{actionData.errors.pesan}</p>
          )}
        </div>
        <button type="submit" disabled={isSubmitting}>
          {isSubmitting ? "Mengirim..." : "Kirim Pesan"}
        </button>
      </Form>
    </div>
  );
}
cara membuat website dengan remix
Ilustrasi cara membuat website dengan remix

Langkah 5: Nested Routing dan Layout Bersarang

Nested routing adalah salah satu fitur terkuat Remix. Setiap route dapat memiliki layout sendiri, dan layout induk merender outlet untuk menampilkan route anak.

# Struktur file untuk nested routing
app/routes/
├── _index.tsx                 → /
├── dashboard.tsx              → layout /dashboard
├── dashboard._index.tsx       → /dashboard
├── dashboard.statistik.tsx    → /dashboard/statistik
├── dashboard.produk._index.tsx → /dashboard/produk
└── dashboard.produk.$id.tsx   → /dashboard/produk/:id
// app/routes/dashboard.tsx - layout untuk semua halaman /dashboard
import { Outlet, NavLink } from "@remix-run/react";

export default function DashboardLayout() {
  return (
    <div style={{ display: "flex" }}>
      <aside>
        <nav>
          <NavLink to="/dashboard">Ringkasan</NavLink>
          <NavLink to="/dashboard/statistik">Statistik</NavLink>
          <NavLink to="/dashboard/produk">Produk</NavLink>
        </nav>
      </aside>
      <div style={{ flex: 1, padding: "1rem" }}>
        <Outlet />   {/* konten halaman anak dirender di sini */}
      </div>
    </div>
  );
}

Langkah 6: Autentikasi dengan Session

Remix menyediakan utilitas session berbasis cookie yang aman dan mudah digunakan:

// app/utils/session.server.ts
import { createCookieSessionStorage, redirect } from "@remix-run/node";

const sessionStorage = createCookieSessionStorage({
  cookie: {
    name: "__session",
    httpOnly: true,
    secure: process.env.NODE_ENV === "production",
    sameSite: "lax",
    secrets: [process.env.SESSION_SECRET!],
    maxAge: 60 * 60 * 24 * 7, // 7 hari
  },
});

export async function getSession(request: Request) {
  return sessionStorage.getSession(request.headers.get("Cookie"));
}

export async function createUserSession(userId: string, redirectTo: string) {
  const session = await sessionStorage.getSession();
  session.set("userId", userId);
  return redirect(redirectTo, {
    headers: { "Set-Cookie": await sessionStorage.commitSession(session) },
  });
}

export async function requireUserId(request: Request) {
  const session = await getSession(request);
  const userId = session.get("userId");
  if (!userId) throw redirect("/login");
  return userId;
}

Langkah 7: Menggunakan Database dengan Prisma

Remix bekerja sangat baik dengan Prisma ORM. Berikut contoh setup dasar:

npm install @prisma/client
npm install -D prisma
npx prisma init
# prisma/schema.prisma
generator client {
  provider = "prisma-client-js"
}

datasource db {
  provider = "mysql"
  url      = env("DATABASE_URL")
}

model Artikel {
  id        Int      @id @default(autoincrement())
  slug      String   @unique
  judul     String
  isi       String   @db.LongText
  tanggal   DateTime @default(now())
  diterbitkan Boolean @default(false)
}
// app/utils/db.server.ts
import { PrismaClient } from "@prisma/client";

let db: PrismaClient;

declare global {
  var __db: PrismaClient | undefined;
}

if (process.env.NODE_ENV === "production") {
  db = new PrismaClient();
} else {
  if (!global.__db) global.__db = new PrismaClient();
  db = global.__db;
}

export { db };
// Penggunaan di loader
import { db } from "~/utils/db.server";

export async function loader() {
  const artikelList = await db.artikel.findMany({
    where: { diterbitkan: true },
    orderBy: { tanggal: "desc" },
    select: { id: true, slug: true, judul: true, tanggal: true },
  });
  return json({ artikelList });
}

Langkah 8: Error Handling dengan Error Boundary

Remix memiliki sistem error handling yang elegan menggunakan ErrorBoundary yang bisa didefinisikan per-route:

// app/routes/blog.$slug.tsx
export function ErrorBoundary() {
  const error = useRouteError();

  if (isRouteErrorResponse(error) && error.status === 404) {
    return (
      <div>
        <h2>Artikel Tidak Ditemukan</h2>
        <p>Maaf, artikel yang Anda cari tidak ada atau sudah dihapus.</p>
        <a href="/blog">Kembali ke Blog</a>
      </div>
    );
  }

  return (
    <div>
      <h2>Terjadi Kesalahan</h2>
      <p>Maaf, terjadi kesalahan saat memuat halaman ini. Silakan coba lagi.</p>
    </div>
  );
}

Langkah 9: Build dan Deploy Website Remix

Remix adalah server-side rendered framework, sehingga memerlukan Node.js environment untuk production.

Build untuk Production

npm run build

Perintah ini menghasilkan dua output:

  • build/server/ - kode yang berjalan di server
  • build/client/ - aset yang dikirim ke browser

Deploy ke VPS dengan Node.js

# Di VPS
git clone https://github.com/username/nama-website-anda.git
cd nama-website-anda
npm install
npm run build

# Jalankan dengan PM2 untuk production
npm install -g pm2
pm2 start build/server/index.js --name "website-saya"
pm2 save
pm2 startup

Konfigurasi Nginx sebagai Reverse Proxy

server {
  listen 80;
  server_name domainanda.com www.domainanda.com;

  location / {
    proxy_pass http://localhost:3000;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection 'upgrade';
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_cache_bypass $http_upgrade;
  }

  location /build/ {
    root /var/www/nama-website-anda/public;
    expires 1y;
    add_header Cache-Control "public, immutable";
  }
}

Deploy ke Vercel

  1. Pastikan Anda menggunakan adapter Vercel: npm install @remix-run/vercel
  2. Push kode ke GitHub
  3. Hubungkan repository di vercel.com
  4. Vercel otomatis mendeteksi dan mengkonfigurasi Remix
  5. Klik Deploy

FAQ: Cara Membuat Website dengan Remix

Pertanyaan yang Sering Diajukan

Apa perbedaan Remix dan Next.js?

Remix lebih dekat ke Web Standards dan unggul dalam form handling, data mutation, dan progressive enhancement. Next.js unggul dalam SSG dan memiliki ekosistem lebih besar. Remix cocok untuk aplikasi CRUD dan dashboard; Next.js lebih fleksibel untuk berbagai jenis website.

Apakah Remix cocok untuk pemula React?

Remix memerlukan pemahaman dasar React dan konsep HTTP. Jika sudah nyaman dengan React dasar, Remix bisa dipelajari dalam beberapa minggu. Pemula murni disarankan belajar React dasar dulu selama 1-2 bulan.

Apa itu loader dan action di Remix?

Loader adalah fungsi server yang mengambil data sebelum halaman dirender, tersedia via useLoaderData. Action menangani HTTP POST/PUT/DELETE dari form. Keduanya berjalan hanya di server, menjaga logika sensitif tetap aman.

Hosting apa yang cocok untuk Remix?

Remix memerlukan Node.js environment. Gunakan VPS dengan Node.js untuk kontrol penuh, atau platform seperti Vercel dan Fly.io untuk deployment yang mudah. Shared hosting tradisional tidak mendukung Remix karena memerlukan server Node.js yang berjalan terus-menerus.

Apakah Remix bisa digunakan untuk API?

Ya, melalui Resource Routes: buat file route yang hanya mengekspor loader atau action tanpa komponen React. Route tersebut akan berfungsi sebagai API endpoint yang mengembalikan JSON atau format data lainnya.

Apa itu Remix v2 dan perubahan utamanya?

Remix v2 memperkenalkan flat file routing, integrasi Vite, dan persiapan menuju React Router v7 yang akan menggabungkan Remix dan React Router menjadi satu. Untuk proyek baru di 2026, pertimbangkan React Router v7 yang sudah mengintegrasikan semua fitur Remix.

Kesimpulan

Belajar cara membuat website dengan Remix membuka pintu ke paradigma full-stack React yang berbeda: lebih dekat ke Web Standards, lebih sederhana dalam menangani data dan form, dan menghasilkan aplikasi yang lebih resilient. Konsep loader, action, dan nested routing mungkin terasa asing di awal, tetapi begitu dipahami, akan membuat pengembangan aplikasi web terasa jauh lebih terstruktur.

Kelebihan utama Remix dibanding framework lain adalah kesederhanaannya dalam menangani hal-hal yang secara tradisional sulit di React: form submission dengan validasi, mutation data, error handling, dan session management - semuanya menggunakan pola yang jelas dan dapat diprediksi.

Untuk deployment, Remix memerlukan Node.js hosting. VPS adalah pilihan terbaik untuk kontrol penuh dan performa optimal. Pilih VPS dengan spesifikasi yang sesuai dengan traffic website Anda dan pastikan server berada di Indonesia untuk latensi yang rendah bagi pengguna lokal. Dengan setup yang tepat, website Remix Anda akan berjalan cepat, aman, dan dapat di-scale sesuai pertumbuhan bisnis.

Butuh Hosting untuk Website Anda?

Dapatkan hosting cepat, aman, dan terpercaya dengan harga terjangkau. Gratis domain, SSL, dan support 24/7.

Jangan Ketinggalan Promo!

Subscribe newsletter kami dan dapatkan diskon hingga 50% untuk pembelian pertama kamu.

Gratis, tanpa spam. Bisa unsubscribe kapan saja.