Struktur Project — Mading Online (Fullstack SMK RPL)

Dokumen ini memetakan seluruh folder dan file project majalah dinding digital, membedakan yang bawaan vs dibuat sendiri, file bawaan yang perlu diedit, serta alur komunikasi antar bagian.

Cara menjalankan (2 terminal + DB):

LangkahFolder / alatPerintahURL / hasil
DBdatabase/psql … -f schema.sql & seed.sqlDB mading
1backend/npm run devhttp://localhost:5000
2frontend/npm run devhttp://localhost:5173

Legenda

SimbolArti
[B]Bawaan — dari npm create vite, npm init, atau tool instalasi
[BUAT]Dibuat sendiri — untuk kebutuhan latihan Mading Online
[EDIT]File bawaan yang wajib/diperlukan diedit agar project jalan
[OPS]Operasional — dihasilkan otomatis atau isinya dari penggunaan (upload, build)
[DOC]Dokumentasi / materi belajar
[ARSIP]Materi lama (sistem berita) — jangan dipakai sebagai panduan mading saat ini

Tree folder & file (tanpa node_modules dan dist)

Mading Online/                         ← folder project (buka di VS Code / Cursor)
│
├── README.md                           [BUAT][DOC]   setup, akun seed, endpoint ringkas
├── PERENCANAAN.md                      [BUAT][DOC]   fitur, API, keputusan bisnis
├── STRUKTUR.md                         [BUAT][DOC]   ringkasan tree (teks)
├── dbdiagram.md                        [BUAT][DOC]   catatan diagram DB (opsional)
│
├── database/                           [BUAT]        skrip PostgreSQL (bukan MySQL)
│   ├── schema.sql                      [BUAT]        enum + tabel users & posting
│   ├── seed.sql                        [BUAT]        admin, penulis, post contoh
│   └── dbdiagram.sql                   [BUAT][DOC]   referensi diagram
│
├── docs/                               [BUAT][DOC]
│   ├── README.md                       [BUAT][DOC]   petunjuk mana yang aktif / arsip
│   ├── materi-alur-mading-online.html  [BUAT][DOC]   panduan alur coding (aktif)
│   ├── STRUKTUR-PROJECT-mading-online.html [BUAT][DOC] ← file ini
│   ├── materi-alur-backend-news.html   [ARSIP]       portal berita lama
│   └── STRUKTUR-PROJECT-news.html      [ARSIP]       struktur berita lama
│
├── backend/                            [BUAT]        folder utama API (Express + PostgreSQL)
│   ├── server.js                       [BUAT][EDIT]  pintu masuk API — CORS, JSON, static, mount route
│   ├── package.json                    [B][EDIT]     dependensi: express, pg, bcrypt, jwt, multer, cors, dotenv
│   ├── package-lock.json               [B][OPS]
│   ├── .env                            [BUAT][EDIT]  rahasia: PORT, DB_*, JWT_SECRET, FRONTEND_URL
│   ├── .env.example                    [BUAT][DOC]   contoh env (aman di-commit)
│   │
│   ├── config/
│   │   └── db.js                       [BUAT]        pool koneksi PostgreSQL (pg)
│   │
│   ├── routes/
│   │   ├── authRoutes.js               [BUAT]        /api/auth — register, login, /me
│   │   ├── postRoutes.js               [BUAT]        /api/post — publik + CRUD author
│   │   └── adminRoutes.js              [BUAT]        /api/admin — users + post (wajib JWT admin)
│   │
│   ├── controllers/
│   │   ├── authController.js           [BUAT]        register, login, getMe, updateMe
│   │   ├── postController.js           [BUAT]        list/detail publik + CRUD milik author
│   │   ├── adminPostController.js      [BUAT]        CRUD penuh semua posting
│   │   └── adminUserController.js      [BUAT]        list/detail/update/hapus penulis
│   │
│   ├── models/
│   │   ├── userModel.js                [BUAT]        query tabel users
│   │   └── postModel.js                [BUAT]        query tabel posting
│   │
│   ├── middlewares/
│   │   ├── authMiddleware.js           [BUAT]        JWT → loadUser → requireRole
│   │   └── uploadMiddleware.js         [BUAT]        multer → uploads/post/
│   │
│   ├── utils/
│   │   ├── response.js                 [BUAT]        helper JSON sukses/gagal seragam
│   │   ├── helpers.js                  [BUAT]        util validasi / format kecil
│   │   └── fileHelper.js               [BUAT]        hapus file upload saat post dihapus
│   │
│   ├── scripts/                        [BUAT]        skrip bantu (audit API, gen hash, dll.)
│   │   ├── audit-api.js
│   │   └── genhash.js
│   │
│   └── uploads/
│       └── post/                       [BUAT][OPS]   file gambar hasil upload
│
└── frontend/                           [B]           kerangka React + Vite
    ├── index.html                      [B][EDIT]     judul & meta Mading Online
    ├── vite.config.js                  [B][EDIT]     plugin React, port dev
    ├── package.json                    [B][EDIT]     react, react-router-dom, bootstrap
    ├── package-lock.json               [B][OPS]
    ├── eslint.config.js                [B]
    ├── .gitignore                      [B]
    ├── .env                            [BUAT][EDIT]  VITE_API_URL=http://localhost:5000
    ├── .env.example                    [BUAT][DOC]
    │
    ├── public/
    │   ├── favicon.svg                 [B][EDIT]
    │   └── placeholder-image.jpg       [BUAT]        gambar default jika post tanpa foto
    │
    ├── dist/                           [OPS]         hasil npm run build
    │
    └── src/
        ├── main.jsx                    [B][EDIT]     mount React + Bootstrap + App
        ├── App.jsx                     [B][EDIT]     merender AppRoutes
        │
        ├── routes/
        │   └── index.jsx               [BUAT]        semua <Route> publik, author, admin
        │
        ├── services/                   [BUAT]        layer HTTP ke backend
        │   ├── api.js                  [BUAT]        apiFetch, token, imageUrl, setAuth
        │   ├── authService.js          [BUAT]        /api/auth/*
        │   └── postService.js          [BUAT]        /api/post + /api/admin/*
        │
        ├── constants/
        │   └── site.js                 [BUAT]        nama situs, rubrik, teks hardcode
        │
        ├── components/
        │   ├── ConfirmModal.jsx        [BUAT]        dialog konfirmasi hapus
        │   ├── auth/
        │   │   └── ProtectedRoute.jsx  [BUAT]        jaga /dashboard/* sesuai role
        │   ├── layout/
        │   │   ├── PublicLayout.jsx    [BUAT]        header/footer halaman publik
        │   │   └── DashboardLayout.jsx [BUAT]        sidebar + Outlet panel
        │   └── post/
        │       └── PostTable.jsx       [BUAT]        tabel post di dashboard
        │
        └── pages/
            ├── public/
            │   ├── Home.jsx            [BUAT]        /
            │   ├── ListPost.jsx        [BUAT]        /post (?kategori=)
            │   ├── DetailPost.jsx      [BUAT]        /post/:id
            │   ├── Login.jsx           [BUAT]        /login
            │   └── Daftar.jsx          [BUAT]        /daftar
            └── dashboard/
                ├── Profil.jsx          [BUAT]        profil bersama author & admin
                ├── author/
                │   ├── Dashboard.jsx   [BUAT]        daftar post milik sendiri
                │   └── FormPost.jsx    [BUAT]        tulis / edit post
                └── admin/
                    ├── Dashboard.jsx   [BUAT]        ringkasan statistik
                    ├── ListPost.jsx    [BUAT]        kelola semua post
                    ├── DetailPost.jsx  [BUAT]
                    ├── ListUser.jsx    [BUAT]        kelola penulis
                    ├── DetailUser.jsx  [BUAT]
                    └── EditUser.jsx    [BUAT]

Tidak ditulis di tree (bawaan npm):


Ringkasan: bawaan vs buat sendiri

Folder level atas

FolderAsalKeterangan
database/[BUAT]SQL PostgreSQL untuk DB mading
backend/[BUAT]Seluruh isi API dibuat untuk latihan; tidak dari template Vite
frontend/[B] kerangka + [BUAT] isi src/Kerangka dari npm create vite; hampir semua file di src/ buatan latihan
docs/[BUAT][DOC]Materi belajar; bedakan file aktif vs arsip berita
node_modules/[B][OPS]Hasil npm install di masing-masing folder

File bawaan frontend yang perlu diedit

FileYang biasanya diubah
index.htmlJudul halaman, meta
vite.config.jsPlugin React / port jika perlu
package.jsonTambah bootstrap, react-router-dom
.env / .env.exampleVITE_API_URL=http://localhost:5000
src/main.jsxImport Bootstrap + mount App
src/App.jsxMerender AppRoutes
src/routes/index.jsx[BUAT] Semua <Route> Mading Online

File bawaan frontend yang boleh dibiarkan

FileKeterangan
eslint.config.jsAturan lint default
README.md (jika masih default Vite)Opsional diperbarui

File backend — hampir semuanya [BUAT]

Tidak ada scaffold Express otomatis seperti Vite. Yang paling mendekati “bawaan npm”:

FileAsal
package.json[B] dari npm init, lalu [EDIT] dependencies & script dev
package-lock.json[B][OPS]

Semua file .js di config/, routes/, controllers/, models/, middlewares/, utils/ adalah [BUAT].


Alur komunikasi antar folder & file

1. Gambaran besar (dua aplikasi terpisah)

Browser (:5173)                    Browser / Postman (:5000)
     │                                      │
     │  fetch JSON + JWT                      │
     └──────────────────────────────────────►│  backend/server.js
                                             │       │
                                             │       ├─► routes/*.js
                                             │       ├─► middlewares/
                                             │       ├─► controllers/
                                             │       ├─► models/
                                             │       └─► config/db.js → PostgreSQL (mading)
                                             │
     ◄──────────────────────────────────────┘  JSON + file /uploads/...

Frontend tidak memanggil PostgreSQL langsung. Semua data lewat REST API di backend/.


2. Alur request backend (satu kali panggilan API)

HTTP request
    → server.js               (CORS, JSON body, static /uploads)
    → routes/auth|post|admin  (cocokkan path + method)
    → middlewares/            (opsional: JWT, loadUser, role, multer)
    → controllers/            (validasi, aturan bisnis)
    → models/                 (SQL SELECT / INSERT / UPDATE / DELETE)
    → config/db.js            (pool pg)
    → PostgreSQL
    ← JSON { success, message, data? } ke client

Contoh: Penulis update post milik sendiri

FormPost.jsxpostService.updatePost()PUT /api/post/:idpostRoutes.jspostController.updatepostModel → tabel posting.


3. Alur frontend (dari buka halaman sampai tampil data)

index.html
    → main.jsx                 (render React + Bootstrap)
    → App.jsx                  (AppRoutes)
    → routes/index.jsx         (semua <Route>)
    → halaman di pages/        (Home, ListPost, FormPost, …)
    → komponen di components/
    → services/api.js          (fetch + Authorization)
    → authService.js | postService.js
    → backend API

Contoh: Beranda menampilkan post terbaru

Home.jsxgetPosts({ limit })GET /api/postpostController.getAllpostModel → render kartu/list di UI.


4. Autentikasi (login → request berikutnya)

Login.jsx
    → authService.login()  →  POST /api/auth/login
    → authController.login  →  bcrypt + jwt.sign
    → setAuth(token, user)  →  localStorage "token" + "user"

Request berikutnya (dashboard):
    → apiFetch()  →  Header: Authorization: Bearer <token>
    → authMiddleware  →  decode JWT
    → loadUserMiddleware  →  req.user dari DB
    → requireRole("admin" | "author")  (jika dipakai)
    → controller
RolePrefix APIHalaman frontend
PublikGET /api/post, GET /api/post/:id/, /post, /post/:id
Author/api/auth/me, /api/post/mine, CRUD /api/post/dashboard/author/*
Admin/api/admin/users, /api/admin/post/dashboard/admin/*

ProtectedRoute.jsx memblokir dashboard jika belum login atau role salah. Proteksi sesungguhnya tetap di middleware backend.


5. Upload gambar post

FormPost (frontend) — FormData + field "gambar"
    → postService.createPost / updatePost
       atau createPostAdmin / updatePostAdmin
    → POST/PUT multipart /api/post atau /api/admin/post
    → middlewares/uploadMiddleware.js  (multer)
    → uploads/post/<file>
    → controller simpan path ke kolom posting.gambar
    → JSON path: "/uploads/post/..."

Tampil di browser:
    → api.js imageUrl(path)  →  http://localhost:5000/uploads/post/...
    → jika kosong: /placeholder-image.jpg (public frontend)

6. Peta halaman → file utama

URL browserFile halamanAPI utama
/Home.jsxGET /api/post
/postListPost.jsxGET /api/post?kategori=
/post/:idDetailPost.jsxGET /api/post/:id
/login, /daftarLogin.jsx, Daftar.jsxPOST /auth/login, /register
/dashboard/author/*pages/dashboard/author/* + layoutpostService/api/post
/dashboard/admin/*pages/dashboard/admin/* + layout/api/admin/*
.../profilProfil.jsxGET/PUT /api/auth/me

Menu & rubrik hardcode: constants/site.js → layout publik / link filter.


7. Database (PostgreSQL) — hubungan dengan kode

Tabel / enumModelDipakai untuk
users + enum user_roleuserModel.jslogin, register, profil, admin kelola penulis
posting + enum kategori_postingpostModel.jskonten mading (4 rubrik)
users (admin | author) ──menulis──> posting
                         author_id (FK)

Import awal: jalankan schema.sql lalu seed.sql, isi backend/.env.


Urutan belajar file (siswa)

  1. database/schema.sql + seed.sql — pahami tabel & akun lab
  2. backend/server.jsroutes/authRoutes.jsauthController.js
  3. frontend/src/main.jsxApp.jsxroutes/index.jsxpages/public/Home.jsx
  4. frontend/src/services/api.jspostService.js
  5. Login: Login.jsx + ProtectedRoute + JWT di authMiddleware.js
  6. Penulis: Dashboard.jsx + FormPost.jsxpostRoutes.js
  7. Admin: admin/ListPost.jsx + ListUser.jsxadminRoutes.js
  8. Dokumen lanjutan: docs/materi-alur-mading-online.html + PERENCANAAN.md

Catatan project