Minggu, 13 September 2026

Buku Monograf

 


\



Machine Learning dan Python

 













Apps Script

 












Codex

 
















Supabase

 





















Website Data Mahasiswa - Supabase

 





Saya seorang lecture web programming. Buatkan studi kasus sederhana full stack dengan backend menggunakan supabase. Terangkan step by step


“Planning Website — Sistem Data Mahasiswa Full Stack + Supabase” dalam format siap ditempel ke Word/Google Docs, mencakup:

  1. Project Overview
  2. Problem Statement
  3. Project Objectives
  4. Target User
  5. Functional Requirements
  6. Non-Functional Requirements
  7. User Flow
  8. Information Architecture
  9. Site Map
  10. UI/UX Planning
  11. Database Design / ERD
  12. Supabase Architecture
  13. API & CRUD Specification
  14. Security & RLS
  15. Folder Structure
  16. Technology Stack
  17. Development Roadmap
  18. Testing Plan
  19. Deployment Plan
  20. Assignment/Rubric untuk mahasiswa

Studi Kasus: Sistem Data Mahasiswa

Kita akan membuat aplikasi sederhana CRUD Data Mahasiswa menggunakan:

  • Frontend: HTML + CSS + JavaScript
  • Backend/Database: Supabase
  • API: Supabase JavaScript Client
  • Authentication: belum digunakan pada tahap awal
  • Deployment: dapat dilanjutkan ke GitHub Pages/Netlify/Vercel

Aplikasi memungkinkan pengguna:

Tambah → Tampilkan → Edit → Hapus → Cari data mahasiswa

1. Tujuan Pembelajaran

Setelah menyelesaikan studi kasus ini, mahasiswa memahami alur:

                 FULL STACK WEB
                      │
          ┌───────────┴───────────┐
          │                       │
       FRONTEND                BACKEND
          │                       │
   HTML + CSS + JS            SUPABASE
          │                       │
          └───────────┬───────────┘
                      │
                   DATABASE
                      │
                PostgreSQL

Mahasiswa belajar bahwa:

HTML
 ↓
User Interface

CSS
 ↓
Presentation

JavaScript
 ↓
Application Logic

Supabase
 ↓
Backend Service + API

PostgreSQL
 ↓
Data Persistence

Jadi mahasiswa tidak hanya belajar membuat website statis, tetapi memahami bagaimana website berkomunikasi dengan database.


2. Studi Kasus

Sistem Data Mahasiswa

Misalkan sebuah program studi ingin mempunyai aplikasi sederhana untuk mengelola data mahasiswa.

Data yang disimpan:

FieldContoh
ID1
NIM2401001
NamaBudi Santoso
Program StudiInformatika
Angkatan2024
Emailbudi@email.com

Fitur:

========================================
       SISTEM DATA MAHASISWA
========================================

[ + Tambah Mahasiswa ]

----------------------------------------
NIM       Nama          Prodi
----------------------------------------
2401001   Budi          Informatika
2401002   Siti          Sistem Informasi
2401003   Andi          Informatika

[Edit] [Hapus]

----------------------------------------

Cari mahasiswa: [____________]

3. Arsitektur Aplikasi

Arsitektur sederhananya:

┌─────────────────────────────┐
│           USER              │
└──────────────┬──────────────┘
               │
               ▼
┌─────────────────────────────┐
│         FRONTEND            │
│                             │
│ HTML                         │
│ CSS                          │
│ JavaScript                   │
└──────────────┬──────────────┘
               │
               │ HTTPS / API
               ▼
┌─────────────────────────────┐
│          SUPABASE           │
│                             │
│  API                         │
│  Authentication              │
│  Database                    │
│  Storage                     │
└──────────────┬──────────────┘
               │
               ▼
┌─────────────────────────────┐
│       PostgreSQL            │
│                             │
│       mahasiswa             │
│       ├── id                │
│       ├── nim               │
│       ├── nama              │
│       ├── prodi             │
│       ├── angkatan          │
│       └── email             │
└─────────────────────────────┘

Hal penting untuk mahasiswa:

Frontend tidak langsung mengakses PostgreSQL.

Frontend berkomunikasi dengan layanan Supabase menggunakan API/client library.


4. Step 1 — Membuat Project Supabase

Buka:

Supabase

Kemudian:

Login
  ↓
Dashboard
  ↓
New Project
  ↓
Nama project:
web-programming-mahasiswa
  ↓
Buat project

Setelah project selesai dibuat, kita memperoleh:

Project URL
+
Publishable/Anon Key

Contohnya:

const SUPABASE_URL = "https://xxxxxxxx.supabase.co";

const SUPABASE_KEY = "YOUR_PUBLISHABLE_KEY";

Catatan untuk mahasiswa: jangan memasukkan secret/service-role key ke frontend. Untuk aplikasi browser, gunakan key publik yang memang dirancang untuk client-side access dan atur keamanan melalui Row Level Security (RLS).


5. Step 2 — Membuat Database

Di Supabase buka:

SQL Editor

Kemudian buat tabel:

create table mahasiswa (
    id bigint generated by default as identity primary key,
    nim varchar(20) not null unique,
    nama varchar(100) not null,
    prodi varchar(100) not null,
    angkatan integer not null,
    email varchar(100),
    created_at timestamptz default now()
);

Struktur database:

mahasiswa
│
├── id
├── nim
├── nama
├── prodi
├── angkatan
├── email
└── created_at

6. Step 3 — Memasukkan Data Awal

Masukkan beberapa data:

insert into mahasiswa
(nim, nama, prodi, angkatan, email)
values
('2401001', 'Budi Santoso', 'Informatika', 2024, 'budi@email.com'),
('2401002', 'Siti Aminah', 'Sistem Informasi', 2024, 'siti@email.com'),
('2401003', 'Andi Wijaya', 'Informatika', 2024, 'andi@email.com');

Sekarang database kita mempunyai data.


7. Step 4 — Memahami CRUD

Ini bagian yang sangat bagus untuk pembelajaran.

CRUD:

C = CREATE
R = READ
U = UPDATE
D = DELETE

Hubungannya dengan database:

CREATE
   ↓
INSERT

READ
   ↓
SELECT

UPDATE
   ↓
UPDATE

DELETE
   ↓
DELETE

Dalam aplikasi:

Form
 │
 ▼
JavaScript
 │
 ▼
Supabase Client
 │
 ▼
Supabase API
 │
 ▼
PostgreSQL

8. Step 5 — Membuat Struktur Project

Buat folder:

sistem-mahasiswa/
│
├── index.html
├── style.css
└── app.js

Sangat sederhana.

Untuk tahap pertama saya justru menyarankan jangan menggunakan React/Vue/Next.js terlebih dahulu.

Tujuannya supaya mahasiswa memahami:

Apa sebenarnya yang terjadi di balik framework.


9. Step 6 — Membuat HTML

File:

index.html

Isi:

<!DOCTYPE html>
<html lang="id">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">

    <title>Sistem Data Mahasiswa</title>

    <link rel="stylesheet" href="style.css">
</head>

<body>

    <div class="container">

        <h1>Sistem Data Mahasiswa</h1>

        <form id="mahasiswaForm">

            <input type="hidden" id="id">

            <input
                type="text"
                id="nim"
                placeholder="NIM"
                required
            >

            <input
                type="text"
                id="nama"
                placeholder="Nama Mahasiswa"
                required
            >

            <input
                type="text"
                id="prodi"
                placeholder="Program Studi"
                required
            >

            <input
                type="number"
                id="angkatan"
                placeholder="Angkatan"
                required
            >

            <input
                type="email"
                id="email"
                placeholder="Email"
            >

            <button type="submit">
                Simpan
            </button>

            <button type="button" id="btnBatal">
                Batal
            </button>

        </form>

        <hr>

        <input
            type="text"
            id="search"
            placeholder="Cari mahasiswa..."
        >

        <table>

            <thead>
                <tr>
                    <th>NIM</th>
                    <th>Nama</th>
                    <th>Prodi</th>
                    <th>Angkatan</th>
                    <th>Email</th>
                    <th>Aksi</th>
                </tr>
            </thead>

            <tbody id="dataMahasiswa">
            </tbody>

        </table>

    </div>

    <script src="https://cdn.jsdelivr.net/npm/@supabase/supabase-js@2"></script>
    <script src="app.js"></script>

</body>
</html>

10. Step 7 — Membuat CSS

File:

style.css
body {
    font-family: Arial, sans-serif;
    background: #f4f6f8;
    margin: 0;
    padding: 30px;
}

.container {
    max-width: 1000px;
    margin: auto;
    background: white;
    padding: 30px;
    border-radius: 10px;
}

h1 {
    margin-bottom: 25px;
}

form {
    display: grid;
    gap: 10px;
}

input {
    padding: 10px;
    border: 1px solid #ddd;
    border-radius: 5px;
}

button {
    padding: 10px;
    border: none;
    border-radius: 5px;
    cursor: pointer;
}

table {
    width: 100%;
    margin-top: 20px;
    border-collapse: collapse;
}

th,
td {
    padding: 10px;
    border-bottom: 1px solid #ddd;
    text-align: left;
}

11. Step 8 — Menghubungkan JavaScript dengan Supabase

Sekarang bagian yang paling penting.

File:

app.js

Pertama:

const SUPABASE_URL =
    "https://YOUR_PROJECT.supabase.co";

const SUPABASE_KEY =
    "YOUR_PUBLISHABLE_KEY";

const supabaseClient =
    supabase.createClient(
        SUPABASE_URL,
        SUPABASE_KEY
    );

Perhatikan:

Frontend
   │
   ▼
createClient()
   │
   ▼
Supabase

12. Step 9 — READ Data

Buat fungsi:

async function loadMahasiswa() {

    const { data, error } =
        await supabaseClient
            .from("mahasiswa")
            .select("*")
            .order("id", { ascending: false });

    if (error) {
        console.error(error);
        return;
    }

    displayMahasiswa(data);
}

Kemudian tampilkan:

function displayMahasiswa(data) {

    const tbody =
        document.getElementById("dataMahasiswa");

    tbody.innerHTML = "";

    data.forEach(mahasiswa => {

        const row = document.createElement("tr");

        row.innerHTML = `
            <td>${mahasiswa.nim}</td>
            <td>${mahasiswa.nama}</td>
            <td>${mahasiswa.prodi}</td>
            <td>${mahasiswa.angkatan}</td>
            <td>${mahasiswa.email ?? ""}</td>

            <td>
                <button onclick="editMahasiswa(${mahasiswa.id})">
                    Edit
                </button>

                <button onclick="deleteMahasiswa(${mahasiswa.id})">
                    Hapus
                </button>
            </td>
        `;

        tbody.appendChild(row);
    });
}

Kemudian jalankan saat halaman dibuka:

loadMahasiswa();

13. Apa yang Terjadi?

Ketika browser menjalankan:

supabaseClient
    .from("mahasiswa")
    .select("*");

secara konsep:

Browser
   │
   │ SELECT mahasiswa
   ▼
Supabase API
   │
   ▼
PostgreSQL
   │
   │ data
   ▼
Supabase API
   │
   ▼
JavaScript
   │
   ▼
HTML Table

Ini adalah momen penting untuk menjelaskan kepada mahasiswa:

Database berada di server/cloud, sedangkan HTML berada di browser.


14. Step 10 — CREATE Data

Ketika form disubmit:

document
    .getElementById("mahasiswaForm")
    .addEventListener("submit", async function(e) {

        e.preventDefault();

        const id =
            document.getElementById("id").value;

        const mahasiswa = {

            nim:
                document.getElementById("nim").value,

            nama:
                document.getElementById("nama").value,

            prodi:
                document.getElementById("prodi").value,

            angkatan:
                Number(
                    document.getElementById("angkatan").value
                ),

            email:
                document.getElementById("email").value
        };

        if (id) {

            await updateMahasiswa(id, mahasiswa);

        } else {

            await createMahasiswa(mahasiswa);

        }

        resetForm();

        loadMahasiswa();
    });

Fungsi CREATE:

async function createMahasiswa(mahasiswa) {

    const { error } =
        await supabaseClient
            .from("mahasiswa")
            .insert(mahasiswa);

    if (error) {

        alert(error.message);

        return;
    }

    alert("Data berhasil ditambahkan");
}

15. Step 11 — UPDATE Data

async function updateMahasiswa(id, mahasiswa) {

    const { error } =
        await supabaseClient
            .from("mahasiswa")
            .update(mahasiswa)
            .eq("id", id);

    if (error) {

        alert(error.message);

        return;
    }

    alert("Data berhasil diperbarui");
}

Konsep SQL-nya:

UPDATE mahasiswa
SET
    nama = 'Budi Baru'
WHERE id = 1;

16. Step 12 — Edit Data

async function editMahasiswa(id) {

    const { data, error } =
        await supabaseClient
            .from("mahasiswa")
            .select("*")
            .eq("id", id)
            .single();

    if (error) {

        alert(error.message);

        return;
    }

    document.getElementById("id").value =
        data.id;

    document.getElementById("nim").value =
        data.nim;

    document.getElementById("nama").value =
        data.nama;

    document.getElementById("prodi").value =
        data.prodi;

    document.getElementById("angkatan").value =
        data.angkatan;

    document.getElementById("email").value =
        data.email || "";
}

Alurnya:

Klik EDIT
   ↓
Ambil ID
   ↓
SELECT database
   ↓
Data kembali
   ↓
Isi form
   ↓
User mengubah data
   ↓
UPDATE

17. Step 13 — DELETE

async function deleteMahasiswa(id) {

    const yakin =
        confirm("Hapus data mahasiswa?");

    if (!yakin) return;

    const { error } =
        await supabaseClient
            .from("mahasiswa")
            .delete()
            .eq("id", id);

    if (error) {

        alert(error.message);

        return;
    }

    alert("Data berhasil dihapus");

    loadMahasiswa();
}

Konsepnya:

User
 ↓
Klik Hapus
 ↓
Konfirmasi
 ↓
DELETE
 ↓
Supabase
 ↓
PostgreSQL
 ↓
Refresh data

18. Step 14 — Reset Form

function resetForm() {

    document
        .getElementById("mahasiswaForm")
        .reset();

    document
        .getElementById("id")
        .value = "";
}

Tombol batal:

document
    .getElementById("btnBatal")
    .addEventListener("click", resetForm);

19. Step 15 — Search

Tambahkan:

document
    .getElementById("search")
    .addEventListener("input", async function() {

        const keyword = this.value;

        const { data, error } =
            await supabaseClient
                .from("mahasiswa")
                .select("*")
                .or(
                    `nim.ilike.%${keyword}%,nama.ilike.%${keyword}%`
                );

        if (error) {

            console.error(error);

            return;
        }

        displayMahasiswa(data);
    });

Sekarang aplikasi sudah mempunyai:

CREATE
  ✓

READ
  ✓

UPDATE
  ✓

DELETE
  ✓

SEARCH
  ✓

20. Step 16 — Keamanan dengan RLS

Ini bagian penting untuk materi full stack.

Jangan mengajarkan mahasiswa bahwa:

"Kalau API key ada di JavaScript berarti database aman."

Bukan begitu.

Keamanan database Supabase menggunakan antara lain:

Authentication
       +
Row Level Security
       +
Database Policies

Aktifkan RLS pada tabel:

alter table mahasiswa
enable row level security;

Untuk tahap praktikum awal, jika aplikasinya memang sengaja dibuat sebagai aplikasi publik, policy dapat dibuat sesuai kebutuhan pembelajaran.

Contoh policy untuk membaca data:

create policy "Public can read mahasiswa"
on mahasiswa
for select
to anon
using (true);

Namun untuk operasi insert, update, dan delete, jangan otomatis membuka akses publik pada aplikasi nyata. Untuk praktik yang lebih aman, tahap berikutnya adalah menambahkan authentication dan policy berdasarkan user/role.


21. Full Code app.js

Setelah semua langkah digabung:

const SUPABASE_URL =
    "https://YOUR_PROJECT.supabase.co";

const SUPABASE_KEY =
    "YOUR_PUBLISHABLE_KEY";

const supabaseClient =
    supabase.createClient(
        SUPABASE_URL,
        SUPABASE_KEY
    );


// =============================
// READ
// =============================

async function loadMahasiswa() {

    const { data, error } =
        await supabaseClient
            .from("mahasiswa")
            .select("*")
            .order("id", { ascending: false });

    if (error) {

        console.error(error);

        return;
    }

    displayMahasiswa(data);
}


// =============================
// DISPLAY
// =============================

function displayMahasiswa(data) {

    const tbody =
        document.getElementById("dataMahasiswa");

    tbody.innerHTML = "";

    data.forEach(mahasiswa => {

        const row =
            document.createElement("tr");

        row.innerHTML = `
            <td>${mahasiswa.nim}</td>
            <td>${mahasiswa.nama}</td>
            <td>${mahasiswa.prodi}</td>
            <td>${mahasiswa.angkatan}</td>
            <td>${mahasiswa.email ?? ""}</td>

            <td>

                <button
                    onclick="editMahasiswa(${mahasiswa.id})">
                    Edit
                </button>

                <button
                    onclick="deleteMahasiswa(${mahasiswa.id})">
                    Hapus
                </button>

            </td>
        `;

        tbody.appendChild(row);
    });
}


// =============================
// CREATE / UPDATE
// =============================

document
    .getElementById("mahasiswaForm")
    .addEventListener("submit", async function(e) {

        e.preventDefault();

        const id =
            document.getElementById("id").value;

        const mahasiswa = {

            nim:
                document.getElementById("nim").value,

            nama:
                document.getElementById("nama").value,

            prodi:
                document.getElementById("prodi").value,

            angkatan:
                Number(
                    document.getElementById("angkatan").value
                ),

            email:
                document.getElementById("email").value
        };


        if (id) {

            await updateMahasiswa(
                id,
                mahasiswa
            );

        } else {

            await createMahasiswa(
                mahasiswa
            );
        }


        resetForm();

        loadMahasiswa();
    });


// =============================
// CREATE
// =============================

async function createMahasiswa(mahasiswa) {

    const { error } =
        await supabaseClient
            .from("mahasiswa")
            .insert(mahasiswa);

    if (error) {

        alert(error.message);

        return;
    }

    alert("Data berhasil ditambahkan");
}


// =============================
// UPDATE
// =============================

async function updateMahasiswa(
    id,
    mahasiswa
) {

    const { error } =
        await supabaseClient
            .from("mahasiswa")
            .update(mahasiswa)
            .eq("id", id);

    if (error) {

        alert(error.message);

        return;
    }

    alert("Data berhasil diperbarui");
}


// =============================
// EDIT
// =============================

async function editMahasiswa(id) {

    const { data, error } =
        await supabaseClient
            .from("mahasiswa")
            .select("*")
            .eq("id", id)
            .single();

    if (error) {

        alert(error.message);

        return;
    }


    document.getElementById("id").value =
        data.id;

    document.getElementById("nim").value =
        data.nim;

    document.getElementById("nama").value =
        data.nama;

    document.getElementById("prodi").value =
        data.prodi;

    document.getElementById("angkatan").value =
        data.angkatan;

    document.getElementById("email").value =
        data.email || "";
}


// =============================
// DELETE
// =============================

async function deleteMahasiswa(id) {

    if (!confirm("Hapus data mahasiswa?"))
        return;


    const { error } =
        await supabaseClient
            .from("mahasiswa")
            .delete()
            .eq("id", id);


    if (error) {

        alert(error.message);

        return;
    }


    alert("Data berhasil dihapus");

    loadMahasiswa();
}


// =============================
// SEARCH
// =============================

document
    .getElementById("search")
    .addEventListener(
        "input",
        async function() {

            const keyword = this.value;


            const { data, error } =
                await supabaseClient
                    .from("mahasiswa")
                    .select("*")
                    .or(
                        `nim.ilike.%${keyword}%,nama.ilike.%${keyword}%`
                    );


            if (error) {

                console.error(error);

                return;
            }


            displayMahasiswa(data);
        }
    );


// =============================
// RESET
// =============================

function resetForm() {

    document
        .getElementById("mahasiswaForm")
        .reset();

    document
        .getElementById("id")
        .value = "";
}


document
    .getElementById("btnBatal")
    .addEventListener(
        "click",
        resetForm
    );


// =============================
// INITIAL LOAD
// =============================

loadMahasiswa();

22. Cara Menjalankan

Struktur akhirnya:

sistem-mahasiswa/
│
├── index.html
├── style.css
└── app.js

Kemudian buka:

index.html

Browser:

index.html
    │
    ├── style.css
    │
    ├── Supabase JS
    │
    └── app.js
            │
            ▼
        Supabase
            │
            ▼
        PostgreSQL

23. Peta Konsep Pembelajaran

Saya sarankan menjelaskan kepada mahasiswa menggunakan model berikut:

                   WEB APPLICATION
                         │
              ┌──────────┴──────────┐
              │                     │
           FRONTEND              BACKEND
              │                     │
        HTML + CSS + JS          SUPABASE
              │                     │
              │              ┌──────┼──────┐
              │              │      │      │
              │             API    Auth   DB
              │                     │      │
              │                     │      ▼
              │                     │ PostgreSQL
              │                     │
              └─────────────┬───────┘
                            │
                          CRUD
                            │
                ┌───────────┼───────────┐
                │           │           │
              CREATE       READ       UPDATE
                │                       │
                └───────────┬───────────┘
                            │
                          DELETE

24. Pembagian Pertemuan Kuliah

Studi kasus ini dapat dikembangkan menjadi 5 pertemuan praktikum.

Pertemuan 1 — Konsep Full Stack

Materi:

Frontend
Backend
API
Database
HTTP
JSON
CRUD

Output:

Mahasiswa memahami arsitektur aplikasi.


Pertemuan 2 — Supabase Database

Materi:

Project Supabase
PostgreSQL
Table
Column
Primary Key
Insert
Select
RLS

Output:

Mahasiswa mempunyai database mahasiswa.


Pertemuan 3 — Frontend

Materi:

HTML
Form
Table
CSS
DOM
JavaScript
Event

Output:

Interface aplikasi selesai.


Pertemuan 4 — Integrasi Backend

Materi:

Supabase Client
SELECT
INSERT
UPDATE
DELETE

Output:

Frontend terhubung dengan database.


Pertemuan 5 — Pengembangan

Mahasiswa menambahkan:

Search
Validation
Pagination
Loading
Error handling
Authentication
Authorization

25. Level Pengembangan Tugas

Agar cocok untuk mahasiswa, tugas dapat dibuat bertingkat.

Level 1 — Basic

CRUD Mahasiswa

Level 2 — Intermediate

Tambahkan:

Search
Filter Prodi
Filter Angkatan
Sorting
Pagination

Level 3 — Advanced

Tambahkan:

Login
Register
Logout
Profile
Role

Contoh:

ADMIN
  │
  ├── Create
  ├── Read
  ├── Update
  └── Delete

MAHASISWA
  │
  ├── Read
  └── Update Profile

Level 4 — Full Stack Project

Kembangkan menjadi:

                    SISTEM AKADEMIK
                           │
          ┌────────────────┼────────────────┐
          │                │                │
      MAHASISWA          DOSEN            ADMIN
          │                │                │
          ▼                ▼                ▼
       KRS              NILAI           MASTER DATA
          │                │
          └────────────────┘
                   │
                   ▼
                SUPABASE
                   │
                   ▼
              PostgreSQL

26. Mengapa Studi Kasus Ini Bagus untuk Kuliah?

Yang menarik dari kasus ini adalah mahasiswa dapat melihat evolusi teknologi web secara nyata:

LEVEL 1
HTML
│
▼
Static Website

kemudian:

LEVEL 2
HTML + CSS + JS
│
▼
Interactive Website

kemudian:

LEVEL 3
HTML + CSS + JS
        +
Supabase
        │
        ▼
Full Stack Web Application

dan selanjutnya:

LEVEL 4

Frontend
   +
API
   +
Authentication
   +
Authorization
   +
Database
   +
Deployment
   ↓ 

Production Web Application 


Buku Monograf

  \ https://www.youtube.com/watch?v=h0vg1Sikqso