Tutorial Next JS 14 Pemula: Bikin Web  Jual Template CV Sederhana

Pada artikel ini, kita akan belajar membuat website sederhana untuk jualan template CV menggunakan Next.js versi 14, khususnya dengan fitur app router. Bayangkan kamu adalah seorang pengusaha yang menjual berbagai template CV untuk membantu orang-orang melamar pekerjaan dengan desain yang menarik.

Website ini akan menampilkan katalog template CV yang dapat diunduh oleh pengguna, namun kita akan bekerja dengan dummy data terlebih dahulu untuk memudahkan proses pengembangan.

Website yang akan kita buat ini adalah langkah awal bagi para developer pemula yang ingin memahami alur kerja Next.js dengan struktur data yang baik. Dalam proyek ini, kita akan fokus pada bagaimana mengatur data template CV, menampilkannya dengan baik, dan mengelola navigasi menggunakan app router dari Next.js.

Bayangkan struktur web ini seperti toko kecil yang menjual berbagai barang, dalam hal ini template CV. Setiap template memiliki informasi seperti nama, deskripsi, harga, dan kategori. Nah, dengan Next.js app router, kita bisa dengan mudah membuat halaman-halaman yang menampilkan daftar template, detail template, dan bahkan halaman checkout (meskipun untuk latihan kali ini, kita tidak akan menyertakan fungsionalitas transaksi sebenarnya).

Cara Membuat Next.js Project Baru dengan App Router

Untuk memulai membuat website jual template CV sederhana, hal pertama yang harus kita lakukan adalah membuat Next.js project baru. Dalam tutorial ini, kita akan menggunakan Next.js 14 yang sudah dilengkapi dengan fitur app router. Berikut adalah langkah-langkah untuk membuat proyek baru beserta contoh koding lengkapnya.

Pertama, kamu perlu memastikan bahwa Node.js sudah terinstal di komputermu. Setelah itu, kamu bisa membuka terminal atau command prompt dan jalankan perintah berikut untuk menginstal Next.js secara global:

npx create-next-app@latest my-cv-template-store

Perintah ini akan membuat folder proyek baru bernama my-cv-template-store dengan Next.js 14. Setelah proses instalasi selesai, masuk ke folder proyek tersebut dengan menjalankan:

cd my-cv-template-store

Untuk memastikan bahwa proyek sudah menggunakan app router, pastikan bahwa struktur folder yang dibuat otomatis oleh Next.js berisi folder app di dalam root proyek. Folder inilah yang berfungsi sebagai pengatur rute halaman-halaman dalam aplikasi.

Selanjutnya, jalankan server pengembangan untuk melihat hasil proyek awal:

npm run dev

Jika kamu membuka browser dan masuk ke http://localhost:3000, kamu akan melihat halaman awal default dari Next.js.

Penjelasan Struktur Folder dan File pada Next.js App Router Project

Setelah kita berhasil membuat Next.js project dengan app router, sekarang mari kita bahas struktur folder dan file yang dihasilkan.

  • Folder app: Folder ini adalah inti dari aplikasi yang menggunakan app router. Semua file dan folder di dalamnya akan menjadi halaman-halaman website berdasarkan struktur folder tersebut. Misalnya, jika ada folder bernama app/templates, maka halaman yang diakses melalui http://localhost:3000/templates akan memuat konten dari folder tersebut.
  • File layout.js: File ini adalah template utama yang akan membungkus semua halaman dalam aplikasi. Kamu bisa menganggapnya seperti kerangka dasar dari setiap halaman, seperti header dan footer yang muncul di semua halaman.
  • File page.js: File ini berfungsi untuk menampilkan konten pada halaman tertentu. Jika kamu membuat file page.js di dalam folder app, maka file ini akan ditampilkan di halaman utama http://localhost:3000/. Setiap folder dalam app bisa memiliki file page.js yang bertanggung jawab atas konten spesifik di rutenya masing-masing.
  • Folder public: Di sinilah kamu bisa menyimpan file-file statis seperti gambar, ikon, atau berkas lainnya yang dapat diakses langsung oleh browser tanpa harus melalui proses render server.
  • Folder styles: Folder ini berisi file CSS yang mengatur tampilan antarmuka aplikasi. Kamu bisa mengatur gaya global di sini atau mengimpor gaya ke dalam komponen tertentu.
  • File next.config.js: File konfigurasi untuk Next.js. Di sini kamu bisa mengatur berbagai konfigurasi seperti optimisasi gambar, jalur URL kustom, dan lainnya sesuai kebutuhan proyekmu.

Cara Membuat File Data Dummy untuk Kategori di Folder data

Untuk mengatur kategori template CV di proyek kita, kita bisa membuat file data dummy yang berisi 5 kategori beserta informasi seperti nama kategori, ikon, dan slug. Data ini nantinya bisa digunakan untuk ditampilkan di halaman web kita.

Pertama, buatlah folder baru bernama data di dalam direktori proyek Next.js kamu. Folder ini akan digunakan untuk menyimpan file data dummy. Setelah folder data dibuat, tambahkan file categories.js di dalamnya.

Isi file categories.js dengan data dummy dalam format JavaScript object seperti berikut:

const categories = [
  {
    id: 1,
    name: "Professional",
    icon: "💼",
    slug: "professional",
  },
  {
    id: 2,
    name: "Creative",
    icon: "🎨",
    slug: "creative",
  },
  {
    id: 3,
    name: "Modern",
    icon: "📊",
    slug: "modern",
  },
  {
    id: 4,
    name: "Simple",
    icon: "✏️",
    slug: "simple",
  },
  {
    id: 5,
    name: "Classic",
    icon: "🖋️",
    slug: "classic",
  },
];

export default categories;

Cara Membuat File Data Dummy untuk Penulis di Folder data

Untuk menambahkan informasi tentang penulis template CV di proyek Next.js kita, kita bisa membuat file data dummy berisi informasi tentang 5 penulis. Setiap penulis akan memiliki nama, foto, pekerjaan, dan slug untuk URL. Langkah pertama adalah membuat file di folder data yang sudah dibuat sebelumnya.

Buat file baru bernama authors.js di dalam folder data. File ini akan menyimpan data penulis dalam bentuk array objek. Berikut adalah contoh lengkap kodenya:

const authors = [
  {
    id: 1,
    name: "Alice Johnson",
    photo: "/images/alice.jpg",
    occupation: "Graphic Designer",
    slug: "alice-johnson",
  },
  {
    id: 2,
    name: "Bob Smith",
    photo: "/images/bob.jpg",
    occupation: "Content Writer",
    slug: "bob-smith",
  },
  {
    id: 3,
    name: "Charlie Davis",
    photo: "/images/charlie.jpg",
    occupation: "UX/UI Designer",
    slug: "charlie-davis",
  },
  {
    id: 4,
    name: "Dana Lee",
    photo: "/images/dana.jpg",
    occupation: "Marketing Specialist",
    slug: "dana-lee",
  },
  {
    id: 5,
    name: "Evan Miller",
    photo: "/images/evan.jpg",
    occupation: "Web Developer",
    slug: "evan-miller",
  },
];

export default authors;

Cara Membuat File Data Dummy untuk Template CV di Folder data

Untuk menambahkan informasi tentang template CV yang akan dijual di website kita, kita bisa membuat file data dummy yang berisi informasi tentang template CV, seperti nama, thumbnail, deskripsi, id penulis, id kategori, slug, harga, dan rating. Data ini akan digunakan untuk menampilkan template CV di halaman web kita.

Buat file baru bernama templates.js di dalam folder data. Berikut adalah contoh lengkap kodingnya:

const templates = [
  {
    id: 1,
    name: "Modern CV Template",
    thumbnail: "/images/modern-cv.jpg",
    about: "Desain CV modern yang cocok untuk berbagai profesi.",
    author_id: 1,
    category_id: 3,
    slug: "modern-cv-template",
    price: 15,
    rating: 4.8,
  },
  {
    id: 2,
    name: "Creative CV Template",
    thumbnail: "/images/creative-cv.jpg",
    about: "Template CV dengan desain kreatif untuk pekerjaan di bidang seni.",
    author_id: 2,
    category_id: 2,
    slug: "creative-cv-template",
    price: 20,
    rating: 4.5,
  },
  {
    id: 3,
    name: "Professional CV Template",
    thumbnail: "/images/professional-cv.jpg",
    about: "Desain CV profesional yang ideal untuk melamar posisi formal.",
    author_id: 3,
    category_id: 1,
    slug: "professional-cv-template",
    price: 25,
    rating: 4.9,
  },
  {
    id: 4,
    name: "Simple CV Template",
    thumbnail: "/images/simple-cv.jpg",
    about: "Desain CV sederhana dan minimalis.",
    author_id: 4,
    category_id: 4,
    slug: "simple-cv-template",
    price: 10,
    rating: 4.6,
  },
  {
    id: 5,
    name: "Classic CV Template",
    thumbnail: "/images/classic-cv.jpg",
    about: "Template CV dengan desain klasik yang tetap relevan.",
    author_id: 5,
    category_id: 5,
    slug: "classic-cv-template",
    price: 18,
    rating: 4.7,
  },
];

export default templates;

Penjelasan setiap properti dalam objek templates:

  • name: Nama dari template CV, seperti "Modern CV Template" atau "Creative CV Template".
  • thumbnail: Lokasi gambar thumbnail yang mewakili tampilan dari template CV, misalnya /images/modern-cv.jpg.
  • about: Deskripsi singkat mengenai template CV tersebut, misalnya apa keunggulannya atau siapa yang cocok menggunakannya.
  • author_id: ID yang menghubungkan template ini dengan penulisnya, diambil dari data penulis yang sudah dibuat di file authors.js.
  • category_id: ID yang menghubungkan template ini dengan kategori, diambil dari data kategori yang sudah dibuat di file categories.js.
  • slug: String yang URL-friendly untuk digunakan sebagai bagian dari rute halaman.
  • price: Harga dari template CV tersebut, dalam format angka.
  • rating: Rating dari template berdasarkan ulasan pengguna, juga dalam format angka.

File ini bisa di-import ke komponen yang menampilkan daftar template CV di halaman utama atau halaman detail. Dengan menggunakan data dummy, kita dapat dengan mudah mengelola tampilan konten sebelum data asli tersedia.

Cara Membuat File Types untuk Data Dummy

Untuk menjaga konsistensi struktur data dalam aplikasi Next.js yang kita buat, terutama ketika menggunakan TypeScript, kita perlu mendefinisikan tipe data untuk setiap data dummy yang telah kita buat. Dengan membuat file types, kita bisa mengatur tipe data yang digunakan oleh template CV, penulis, dan kategori. Ini akan memudahkan pengembangan dan mencegah kesalahan penggunaan data.

Buatlah file baru bernama types.ts di dalam folder data atau folder lain yang kamu gunakan untuk tipe data. Berikut adalah contoh lengkap kodingnya untuk seluruh data dummy yang telah kita buat sebelumnya.

export interface Category {
  id: number;
  name: string;
  icon: string;
  slug: string;
}

export interface Author {
  id: number;
  name: string;
  photo: string;
  occupation: string;
  slug: string;
}

export interface TemplateCV {
  id: number;
  name: string;
  thumbnail: string;
  about: string;
  author_id: number;
  category_id: number;
  slug: string;
  price: number;
  rating: number;
}

Penjelasan untuk setiap tipe data di atas:

  • Category: Mendefinisikan struktur data untuk kategori template CV, termasuk properti id (nomor unik), name (nama kategori), icon (ikon yang mewakili kategori), dan slug (teks URL-friendly).
  • Author: Mendefinisikan struktur data untuk penulis template CV, dengan properti id (nomor unik), name (nama penulis), photo (URL foto penulis), occupation (pekerjaan penulis), dan slug (teks URL-friendly).
  • TemplateCV: Mendefinisikan struktur data untuk template CV, dengan properti seperti id (nomor unik), name (nama template), thumbnail (gambar representasi template), about (deskripsi template), author_id (ID penulis terkait), category_id (ID kategori terkait), slug (teks URL-friendly), price (harga template), dan rating (rating dari pengguna).

Dengan mendefinisikan tipe-tipe ini, kamu bisa memastikan bahwa data yang digunakan dalam komponen-komponen Next.js akan sesuai dengan struktur yang diharapkan. TypeScript akan membantu memberikan peringatan ketika ada ketidaksesuaian data, sehingga aplikasi menjadi lebih aman dan mudah dipelihara.

Cara Mapping Data dan Membuat Tabs Sederhana di Komponen Home

Untuk menampilkan data templateCV, category, dan author di komponen Home, kita bisa melakukan mapping data dari file dummy yang sudah dibuat. Selain itu, kita akan menggunakan state di React untuk membuat tabs sederhana yang memungkinkan pengguna memilih template berdasarkan kategori atau penulis.

Pertama, pastikan kamu sudah mengimpor data dari file dummy ke dalam komponen Home. Berikut adalah contoh lengkap kodingnya:

"use client"
import { useState } from "react";
import categories from "../data/categories";
import authors from "../data/authors";
import templates from "../data/templates";

const Home = () => {
  const [activeTab, setActiveTab] = useState("category");

  const filterByCategory = (categoryId: number) => {
    return templates.filter((template) => template.category_id === categoryId);
  };

  const filterByAuthor = (authorId: number) => {
    return templates.filter((template) => template.author_id === authorId);
  };

  return (
    <div>
      {/* Tabs */}
      <div className="tabs">
        <button onClick={() => setActiveTab("category")}>By Category</button>
        <button onClick={() => setActiveTab("author")}>By Author</button>
      </div>

      {/* Content based on active tab */}
      {activeTab === "category" ? (
        <div>
          <h3>Templates by Category</h3>
          {categories.map((category) => (
            <div key={category.id}>
              <h4>{category.name}</h4>
              <div className="template-list">
                {filterByCategory(category.id).map((template) => (
                  <div key={template.id} className="template-item">
                    <img src={template.thumbnail} alt={template.name} />
                    <h5>{template.name}</h5>
                    <p>{template.about}</p>
                    <p>Price: ${template.price}</p>
                    <p>Rating: {template.rating}</p>
                  </div>
                ))}
              </div>
            </div>
          ))}
        </div>
      ) : (
        <div>
          <h3>Templates by Author</h3>
          {authors.map((author) => (
            <div key={author.id}>
              <h4>{author.name} - {author.occupation}</h4>
              <div className="template-list">
                {filterByAuthor(author.id).map((template) => (
                  <div key={template.id} className="template-item">
                    <img src={template.thumbnail} alt={template.name} />
                    <h5>{template.name}</h5>
                    <p>{template.about}</p>
                    <p>Price: ${template.price}</p>
                    <p>Rating: {template.rating}</p>
                  </div>
                ))}
              </div>
            </div>
          ))}
        </div>
      )}
    </div>
  );
};

export default Home;

Penjelasan koding:

  • useState: Kita menggunakan useState untuk menyimpan status tab aktif. Ada dua tab: By Category dan By Author. State activeTab akan menentukan data mana yang ditampilkan, apakah berdasarkan kategori atau penulis.
  • filterByCategory dan filterByAuthor: Dua fungsi ini digunakan untuk menyaring templateCV berdasarkan category_id atau author_id, sesuai tab yang aktif.
  • Mapping Data: Kita melakukan mapping terhadap data categories dan authors, kemudian untuk setiap kategori atau penulis, kita menampilkan template-template yang sesuai dengan menggunakan fungsi penyaringan tadi.
  • Tabs: Ada dua tombol yang mengatur tab aktif. Saat pengguna mengklik tombol "By Category", tab akan berubah dan menampilkan template berdasarkan kategori. Demikian juga dengan "By Author".

Cara Membuat Komponen Category, Author, dan TemplateCV

Untuk membuat struktur kode yang lebih terorganisir di dalam aplikasi Next.js 14, kita bisa memecah tampilan data menjadi beberapa komponen terpisah: Category, Author, dan TemplateCV. Ini akan memudahkan dalam pengelolaan dan pemeliharaan kode.

Langkah 1: Membuat Komponen Category

Buat file komponen Category.js di folder components. Komponen ini akan bertanggung jawab untuk menampilkan data kategori:

// components/Category.js
const Category = ({ category, templates }) => {
  return (
    <div>
      <h4>{category.name}</h4>
      <div className="template-list">
        {templates.map((template) => (
          <div key={template.id} className="template-item">
            <img src={template.thumbnail} alt={template.name} />
            <h5>{template.name}</h5>
            <p>{template.about}</p>
            <p>Price: ${template.price}</p>
            <p>Rating: {template.rating}</p>
          </div>
        ))}
      </div>
    </div>
  );
};

export default Category;

Langkah 2: Membuat Komponen Author

Buat file komponen Author.js di folder components. Komponen ini akan menampilkan daftar template yang ditulis oleh penulis tertentu:

// components/Author.js
const Author = ({ author, templates }) => {
  return (
    <div>
      <h4>{author.name} - {author.occupation}</h4>
      <div className="template-list">
        {templates.map((template) => (
          <div key={template.id} className="template-item">
            <img src={template.thumbnail} alt={template.name} />
            <h5>{template.name}</h5>
            <p>{template.about}</p>
            <p>Price: ${template.price}</p>
            <p>Rating: {template.rating}</p>
          </div>
        ))}
      </div>
    </div>
  );
};

export default Author;

Langkah 3: Membuat Komponen TemplateCV

Buat file komponen TemplateCV.js di folder components. Komponen ini akan menangani tampilan untuk satu template CV. Meskipun kita sudah menampilkannya di dalam komponen Category dan Author, kita bisa membuat komponen ini terpisah jika nantinya perlu digunakan secara independen.

// components/TemplateCV.js
const TemplateCV = ({ template }) => {
  return (
    <div className="template-item">
      <img src={template.thumbnail} alt={template.name} />
      <h5>{template.name}</h5>
      <p>{template.about}</p>
      <p>Price: ${template.price}</p>
      <p>Rating: {template.rating}</p>
    </div>
  );
};

export default TemplateCV;

Langkah 4: Mapping dan Menggunakan Komponen-Komponen Tersebut di Komponen Home

Sekarang kita akan mengimpor komponen Category dan Author ke dalam komponen Home, lalu melakukan mapping data menggunakan komponen-komponen tersebut.

"use client";

import { useState } from "react";
import categories from "../data/categories";
import authors from "../data/authors";
import templates from "../data/templates";
import Category from "../components/Category";
import Author from "../components/Author";

export default function Home() {
  const [activeTab, setActiveTab] = useState("category");

  const filterByCategory = (categoryId) => {
    return templates.filter((template) => template.category_id === categoryId);
  };

  const filterByAuthor = (authorId) => {
    return templates.filter((template) => template.author_id === authorId);
  };

  return (
    <div>
      {/* Tabs */}
      <div className="tabs">
        <button onClick={() => setActiveTab("category")}>By Category</button>
        <button onClick={() => setActiveTab("author")}>By Author</button>
      </div>

      {/* Content based on active tab */}
      {activeTab === "category" ? (
        <div>
          <h3>Templates by Category</h3>
          {categories.map((category) => (
            <Category
              key={category.id}
              category={category}
              templates={filterByCategory(category.id)}
            />
          ))}
        </div>
      ) : (
        <div>
          <h3>Templates by Author</h3>
          {authors.map((author) => (
            <Author
              key={author.id}
              author={author}
              templates={filterByAuthor(author.id)}
            />
          ))}
        </div>
      )}
    </div>
  );
}

Penjelasan:

  • Category Component: Komponen Category menerima properti category dan templates. Data ini ditampilkan berdasarkan kategori tertentu, dan template-template yang sesuai ditampilkan menggunakan mapping.
  • Author Component: Komponen Author mirip dengan Category, tetapi menampilkan template berdasarkan penulis yang bersangkutan.
  • TemplateCV Component: Komponen ini bertindak sebagai unit dasar untuk menampilkan satu template CV. Ini dipanggil di dalam komponen Category dan Author melalui mapping.
  • State Management di Home: useState digunakan untuk mengelola tab aktif (category atau author), dan filterByCategory serta filterByAuthor digunakan untuk menyaring data template berdasarkan kategori atau penulis.

Kesimpulan yang Telah Dipelajari:

  1. Modularisasi Komponen: Dalam pengembangan dengan Next.js, membagi tampilan dan logika ke dalam beberapa komponen seperti Category, Author, dan TemplateCV membuat kode lebih terstruktur, mudah dipelihara, dan fleksibel. Modularisasi ini membantu dalam menangani data secara efisien dengan cara yang terorganisir.
  2. Penggunaan "use client": Untuk menggunakan fitur interaktif di Next.js seperti useState, komponen harus ditandai dengan "use client". Ini memastikan bahwa komponen tersebut dijalankan di sisi client, memungkinkan pengelolaan state dan interaksi langsung dengan pengguna, yang tidak bisa dilakukan di server components secara default.
  3. Mapping Data untuk UI Dinamis: Memanfaatkan data dari file dummy dan melakukan mapping dengan komponen individual adalah cara yang efektif untuk merender data secara dinamis di halaman web. Ini memberikan fleksibilitas untuk menampilkan konten berdasarkan kategori, penulis, atau properti lain sesuai dengan kebutuhan aplikasi.

Saran untuk Materi Lain yang Perlu Dipelajari:

  • Server-Side Rendering (SSR) dan Static Site Generation (SSG): Pelajari lebih dalam tentang bagaimana Next.js menggunakan SSR dan SSG untuk meningkatkan performa aplikasi, terutama dalam hal merender data secara efisien.
  • API Routes di Next.js: Belajar tentang bagaimana membangun API di dalam proyek Next.js untuk mengelola data secara dinamis dari backend atau sumber eksternal.
  • State Management Lebih Lanjut: Mempelajari state management lebih dalam, seperti menggunakan Context API atau Redux, bisa membantu dalam menangani data global dalam aplikasi yang lebih kompleks.

Penutup

Dengan mempelajari konsep-konsep di atas, kamu sudah memiliki pondasi yang baik untuk membangun aplikasi web modern menggunakan Next.js. Namun, perjalanan belajar tidak berhenti di sini. Untuk menguasai lebih dalam dan mendapatkan pengalaman nyata dalam proyek, kamu bisa belajar bersama mentor expert di BuildWithAngga.

Di BuildWithAngga, kamu akan mendapatkan akses selamanya ke semua materi pembelajaran, bisa membangun portfolio berkualitas yang siap digunakan untuk melamar pekerjaan, dan juga mendapatkan kesempatan untuk konsultasi langsung dengan mentor yang berpengalaman. Selain itu, ada banyak benefit menarik lainnya yang akan membantumu mempercepat perjalanan karier sebagai developer.

Ayo, terus kembangkan skill-mu dan bergabunglah bersama komunitas belajar yang mendukung di BuildWithAngga!