Workshop Next.js UDINUS
1. Hasil Akhir Workshop
Paham alur kerja Next.js App Router.
Bisa membaca dan memodifikasi tiap file utama project.
Bisa menjalankan project di lokal dengan NPM.
Bisa build dan deploy ke Vercel.
2. Prasyarat Instalasi
2.1 Tool yang wajib ada
Node.js 20+ (disarankan 20 LTS).
NPM (otomatis ikut saat instal Node.js).
Git.
VS Code.
2.2 Cek versi tool
node -v
npm -v
git --version3. Membuat dan Menjalankan Project
3.1 Create project
npx create-next-app@latest belajar-next-udinus3.2 Masuk ke project dan install package
cd belajar-next-udinus
npm install3.3 Jalankan local development
npm run devBuka http://localhost:3000.
4. Struktur Folder Project
app/
globals.css
layout.tsx
page.tsx
components/
navbar.tsx
footer.tsx
section/
hero.tsx
skills.tsx
education.tsx
contact.tsx
project/
page.tsx
ui/
button.tsx
card.tsx
public/
images/5. Penjelasan Konsep Dasar Next.js
5.1 app/layout.tsx
Ini adalah layout global. Navbar dan Footer ditempatkan di sini supaya otomatis muncul di semua halaman.
5.2 app/page.tsx
Ini adalah halaman Home. File ini hanya menyusun section agar kode lebih bersih.
5.3 app/project/page.tsx
Ini route tambahan untuk halaman Project di URL /project.
6. Full Kode Tiap File Utama (Sesuai Project)
6.1 app/layout.tsx
import type { Metadata } from "next";
import { Geist, Geist_Mono } from "next/font/google";
import "./globals.css";
import Navbar from "./components/navbar";
import Footer from "./components/footer";
const geistSans = Geist({
variable: "--font-geist-sans",
subsets: ["latin"],
});
const geistMono = Geist_Mono({
variable: "--font-geist-mono",
subsets: ["latin"],
});
export const metadata: Metadata = {
title: "{Nama Kalian}",
description: "Website Portofolio {Nama Kalian}",
};
export default function RootLayout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
return (
<html
lang="en"
className={`${geistSans.variable} ${geistMono.variable} h-full antialiased`}
>
<body className="min-h-full flex flex-col items-center px-5">
<Navbar />
<div className="w-full max-w-xl py-20 min-h-screen">{children}</div>
<Footer />
</body>
</html>
);
}6.2 app/page.tsx
import Hero from "./section/hero";
import Skills from "./section/skills";
import Education from "./section/education";
import Contact from "./section/contact";
export default function Home() {
return (
<>
<Hero />
<Skills />
<Education />
<Contact />
</>
);
}6.3 app/components/navbar.tsx
import Link from "next/link";
export default function Navbar() {
return (
<div className="h-14 w-full border-b border-zinc-800 flex px-5 items-center justify-between fixed bg-background">
<Link href="/">
<h1 className="text-lg font-semibold tracking-tight">
{Nama Kalian}
</h1>
</Link>
<div className="flex gap-x-5">
<Link href="/" className="hover:underline">
Home
</Link>
<Link href="/project" className="hover:underline">
Project
</Link>
</div>
</div>
);
}6.4 app/components/footer.tsx
export default function Footer() {
return (
<div className="h-14 w-full border-t border-zinc-800 flex px-5 items-center justify-center">
<h1>Made With 💖 By {Nama Kalian}</h1>
</div>
);
}6.5 app/section/hero.tsx
import Image from "next/image";
export default function Hero() {
return (
<div className="flex flex-col items-center mt-10">
<div className="w-44 h-44 rounded-full overflow-hidden">
<Image
src="/images/face.jpg"
alt="face"
width={200}
height={200}
className="w-full h-full object-cover object-center"
/>
</div>
<h1 className="text-xl sm:text-3xl font-bold mt-5 tracking-tighter">
👋{Nama Kalian}🚀
</h1>
<p className="text-center w-full max-w-md mt-5">
Lorem ipsum dolor sit amet consectetur adipisicing elit. Ut, doloribus?
Ab temporibus explicabo saepe perspiciatis, eligendi quod minus error
ullam tempora quas accusantium itaque placeat mollitia, nemo magni, quam
voluptas!
</p>
</div>
);
}6.6 app/section/skills.tsx
export default function Skills() {
return (
<div className="mt-20">
<h1 className="font-semibold text-xl">⭐Skills</h1>
<div className="flex flex-wrap mt-5 gap-3">
<div className="rounded-lg bg-zinc-800 p-2 text-sm font-semibold">
HTML
</div>
<div className="rounded-lg bg-zinc-800 p-2 text-sm font-semibold">
CSS
</div>
<div className="rounded-lg bg-zinc-800 p-2 text-sm font-semibold">
Tailwind
</div>
<div className="rounded-lg bg-zinc-800 p-2 text-sm font-semibold">
Next.js
</div>
</div>
</div>
);
}6.7 app/section/education.tsx
export default function Education() {
return (
<div className="mt-20">
<h1 className="font-bold text-xl">🎓Education</h1>
<div className="mt-5">
<h1 className="font-bold">
✨Universitas Diponegoro - Teknik Komputer
</h1>
<p className="mt-3">
Lorem, ipsum dolor sit amet consectetur adipisicing elit. Similique,
nisi voluptatibus nostrum nihil mollitia quae dolor debitis, quidem
consectetur totam illum repellendus dolorum aliquid? Deserunt
repellendus illum ut optio modi?
</p>
</div>
<div className="mt-5">
<h1 className="font-bold">✨SMAN 2 Semarang</h1>
<p className="mt-3">
Lorem, ipsum dolor sit amet consectetur adipisicing elit. Similique,
nisi voluptatibus nostrum nihil mollitia quae dolor debitis, quidem
consectetur totam illum repellendus dolorum aliquid? Deserunt
repellendus illum ut optio modi?
</p>
</div>
</div>
);
}6.8 app/section/contact.tsx
import Button from "../ui/button";
import Link from "next/link";
export default function Contact() {
return (
<div className="mt-20">
<h1 className="font-bold text-xl">📞Contact</h1>
<div className="flex flex-wrap gap-3 mt-5">
<Link
href="https://www.linkedin.com/in/pramudya-diagusta/"
target="_blank"
>
<Button>Linkedin</Button>
</Link>
<Button>Github</Button>
<Button>Instagram</Button>
<Button>Email</Button>
</div>
</div>
);
}6.9 app/ui/button.tsx
export default function Button({ children }: any) {
return (
<button className="bg-white p-2 rounded-xl cursor-pointer text-black hover:bg-zinc-300 font-bold">
{children}
</button>
);
}6.10 app/ui/card.tsx
import Image from "next/image";
import Button from "./button";
import Link from "next/link";
export default function Card({
title,
image,
description,
website,
github,
}: any) {
return (
<div className="bg-zinc-900 rounded-xl p-4 space-y-4">
<h1 className="font-bold">{title}</h1>
<div className="aspect-video w-full rounded overflow-hidden">
<Image
src={image}
alt="face"
width={200}
height={200}
className="w-full h-full object-cover object-center"
/>
</div>
<p className="text-sm">{description}</p>
<div className="space-x-2">
<Link href={website}>
<Button>Website</Button>
</Link>
<Link href={github}>
<Button>Github</Button>
</Link>
</div>
</div>
);
}6.11 app/project/page.tsx
import Card from "../ui/card";
export default function Page() {
return (
<div>
<h1 className="font-semibold text-xl">🚀Projects</h1>
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4 mt-5">
<Card
title="Project 1"
image="/images/project.png"
description="Lorem ipsum dolor sit amet consectetur adipisicing elit. Cumque, veritatis!"
website="/"
github="/"
/>
<Card
title="Project 2"
image="/images/project.png"
description="Lorem ipsum dolor sit amet consectetur adipisicing elit. Cumque, veritatis!"
website="/"
github="/"
/>
<Card
title="Project 3"
image="/images/project.png"
description="Lorem ipsum dolor sit amet consectetur adipisicing elit. Cumque, veritatis!"
website="/"
github="/"
/>
</div>
</div>
);
}6.12 app/globals.css
@import "tailwindcss";
:root {
--background: #ffffff;
--foreground: #171717;
}
@theme inline {
--color-background: var(--background);
--color-foreground: var(--foreground);
--font-sans: var(--font-geist-sans);
--font-mono: var(--font-geist-mono);
}
@media (prefers-color-scheme: dark) {
:root {
--background: #0a0a0a;
--foreground: #ededed;
}
}
body {
background: var(--background);
color: var(--foreground);
font-family: Arial, Helvetica, sans-serif;
}7. Menjalankan Project, Lint, dan Build
7.1 Development
npm run dev7.2 Lint
npm run lint7.3 Build production
npm run build7.4 Jalankan build di lokal
npm run start8. Deployment ke Vercel
Pastikan di pc/laptop sudah terinstall Git. Jika belum bisa install di
https://git-scm.com/install/windows
Dan jika belum memiliki akun github bisa register disini:
8.1 Push ke GitHub
git config --global user.name "username_github"
git config --global user.email "emailkamu@example.com"
git init
git add .
git commit -m "Initial commit: portfolio nextjs"
git branch -M main
git remote add origin https://github.com/USERNAME/NAMA-REPO.git
git push -u origin main8.2 Deploy lewat dashboard Vercel
Login/Register ke Vercel dengan akun GitHub.

Pilih Add New Project.

Import repository project.

Klik Deploy.

