This commit is contained in:
Yovan
2026-11-05 11:55:36 +07:00
commit aed738af00
29 changed files with 1853 additions and 0 deletions
+118
View File
@@ -0,0 +1,118 @@
import Link from "next/link";
import { navLinks } from "../../_data/nav-links";
export default function AboutPage() {
return (
<>
<header className="site-header">
<h1 className="page-title">About Me</h1>
<p className="tagline">Sedikit cerita tentang siapa saya.</p>
<nav className="site-nav">
<ul>
{navLinks.map((link) => (
<li key={link.href}>
<Link href={link.href} className={link.href === "/about" ? "active" : undefined}>
{link.label}
</Link>
</li>
))}
</ul>
</nav>
</header>
<main className="about-wrapper">
<section id="bio">
<h2 className="section-title">Bio</h2>
<p>
Nama saya Yovan Budianto Tanujaya, biasa dipanggil Yovan. Saya lahir
di Surabaya dan sekarang tinggal di Surabaya. Saya sedang belajar
Informatika dan tertarik pada pengembangan web.
</p>
<p>
<span className="inline-block bg-indigo-600 text-white text-sm font-semibold px-3 py-1 rounded-full">
Mahasiswa Informatika
</span>{" "}
<span className="inline-block bg-emerald-600 text-white text-sm font-semibold px-3 py-1 rounded-full">
Web Beginner
</span>
</p>
</section>
<section id="education">
<h2 className="section-title">Pendidikan</h2>
{/* ol dipakai karena urutan jenjang pendidikan itu penting (kronologis) */}
<ol className="list-decimal pl-6">
<li>SDK Santo Yusup Karangpilang (2013 - 2019)</li>
<li>SMPK Angelus Custos 2 (2019 - 2022)</li>
<li>SMA Santo Yusup Karangpilang (2022 - 2025)</li>
<li>S1 Informatika, Universitas Katolik Widya Mandala Surabaya (2025 - sekarang)</li>
</ol>
</section>
<section id="skills">
<h2 className="section-title">Skill</h2>
<h3 className="text-lg font-semibold mb-2">Skill yang sedang saya pelajari</h3>
<table className="w-full border-collapse">
<thead>
<tr className="bg-orange-100">
<th className="border border-stone-400 px-3 py-2 text-left">Skill</th>
<th className="border border-stone-400 px-3 py-2 text-left">Level</th>
<th className="border border-stone-400 px-3 py-2 text-left">Catatan</th>
</tr>
</thead>
<tbody>
<tr>
<td className="border border-stone-400 px-3 py-2">HTML</td>
<td className="border border-stone-400 px-3 py-2">Pemula</td>
<td className="border border-stone-400 px-3 py-2">
Sedang dipelajari di mata kuliah Pemrograman Web
</td>
</tr>
<tr>
<td className="border border-stone-400 px-3 py-2">CSS</td>
<td className="border border-stone-400 px-3 py-2">Pemula</td>
<td className="border border-stone-400 px-3 py-2">
Inline, internal, eksternal, dan Tailwind
</td>
</tr>
<tr>
<td className="border border-stone-400 px-3 py-2">PYTHON</td>
<td className="border border-stone-400 px-3 py-2">Pemula</td>
<td className="border border-stone-400 px-3 py-2">Class OOP</td>
</tr>
</tbody>
</table>
<h3 className="text-lg font-semibold mt-4 mb-2">Sifat yang menggambarkan saya</h3>
{/* ul dipakai karena poin-poin ini tidak punya urutan */}
<ul className="list-disc pl-6">
<li>Rasa ingin tahu yang tinggi</li>
<li>Suka bekerja dalam tim</li>
<li>Sabar</li>
</ul>
</section>
<section id="quote">
<h2 className="section-title">Kutipan Favorit</h2>
{/* inline CSS: prop style pada blockquote ini menjadi atribut style="" di HTML; inline punya prioritas tertinggi sehingga menimpa aturan lain */}
<blockquote
style={{
borderLeft: "6px solid #ea580c",
backgroundColor: "#ffedd5",
margin: 0,
padding: "12px 20px",
fontStyle: "italic",
color: "#7c2d12",
}}
>
&quot;Hiduplah seperti ini hari terahkir mu.&quot;
<footer>Jerinx</footer>
</blockquote>
</section>
</main>
<footer className="site-footer">
<p>&copy; 2026 Yovan Budianto Tanujaya - Web Lanjut, Informatika UKWMS</p>
</footer>
</>
);
}
+51
View File
@@ -0,0 +1,51 @@
import type { Metadata } from "next";
import type { ReactNode } from "react";
import Script from "next/script";
// external CSS: styles.css dimuat sebagai <link rel="stylesheet">; mengatur navbar (.site-nav) dan wadah layout <main> (.about-wrapper)
import "../styles.css";
export const metadata: Metadata = {
title: "About - Yovan",
};
// internal CSS: satu blok <style> di <head>; mengatur background + font body,
// memakai selector class (.section-title) dan id (#education)
const internalCss = `
body {
background-color: #fdf6ec;
font-family: Georgia, "Times New Roman", serif;
color: #292524;
line-height: 1.6;
}
.section-title {
color: #7c2d12;
font-size: 1.5rem;
font-weight: bold;
border-bottom: 2px solid #fdba74;
padding-bottom: 4px;
margin: 0 0 12px;
}
#education {
background-color: #ffffff;
padding: 16px 20px;
border-radius: 8px;
}
`;
export default function AboutLayout({ children }: { children: ReactNode }) {
return (
<html lang="id">
<head>
<style>{internalCss}</style>
</head>
<body>
{/* tailwind CSS: skrip CDN, dipakai untuk badge, tabel skill, dan daftar di halaman ini */}
<Script src="https://cdn.tailwindcss.com" strategy="beforeInteractive" />
{children}
</body>
</html>
);
}
+59
View File
@@ -0,0 +1,59 @@
import Link from "next/link";
import { navLinks } from "../../_data/nav-links";
export default function ContactPage() {
return (
<>
<header className="site-header">
<h1 className="page-title">Contact</h1>
<p className="tagline">Mari terhubung.</p>
<nav className="site-nav">
<ul>
{navLinks.map((link) => (
<li key={link.href}>
<Link href={link.href} className={link.href === "/contact" ? "active" : undefined}>
{link.label}
</Link>
</li>
))}
</ul>
</nav>
</header>
<main className="page-wrapper">
<section className="card">
<h2>Kontak &amp; Media Sosial</h2>
<ul>
<li>
Email: <a href="mailto:yovanbudianto@gmail.com">yovanbudianto@gmail.com</a>
</li>
<li>
Telepon: <a href="tel:+62800000000000">+62 8xx-xxxx-xxxx</a>
</li>
<li>
Instagram:{" "}
<a href="https://www.instagram.com/yovans._?mdxt=djZucGVubnA0b3k2" target="_blank" rel="noopener noreferrer">
@yovans._
</a>
</li>
</ul>
</section>
<section className="card">
<h2>Kampus</h2>
<p>
Program Studi Informatika, Fakultas Teknik,{" "}
<a href="https://www.ukwms.ac.id/" target="_blank" rel="noopener noreferrer">
Universitas Katolik Widya Mandala Surabaya
</a>
, Jl. Kalijudan 37, Surabaya.
</p>
</section>
</main>
<footer className="site-footer">
<p>&copy; 2026 Yovan Budianto Tanujaya - Pemrograman Web, Informatika UKWMS</p>
</footer>
</>
);
}
+21
View File
@@ -0,0 +1,21 @@
import type { Metadata } from "next";
import type { ReactNode } from "react";
// pilihan CSS: external (styles.css).
// alasan: halaman ini hanya teks dan daftar tautan, tampilannya harus sama dengan hobbies.
// external CSS memakai ulang aturan yang sudah ada (navbar, card, footer) tanpa menyalin kode,
// tanpa menambah skrip CDN, dan lebih mudah dirawat daripada inline per elemen.
// tailwind tidak dipilih karena halaman sesederhana ini tidak butuh utility class tambahan.
import "../styles.css";
export const metadata: Metadata = {
title: "Contact - Yovan",
};
export default function ContactLayout({ children }: { children: ReactNode }) {
return (
<html lang="id">
<body className="page-body">{children}</body>
</html>
);
}
+68
View File
@@ -0,0 +1,68 @@
import Link from "next/link";
import { navLinks } from "../../_data/nav-links";
export default function GalleryPage() {
return (
<>
<header className="bg-indigo-900 text-white pt-6 text-center">
<h1 className="text-3xl font-bold mb-1">Gallery</h1>
<p>Potret momen-momen yang saya simpan.</p>
<nav>
<ul className="flex flex-wrap justify-center gap-1 mt-4 list-none p-0">
{navLinks.map((link) => (
<li key={link.href}>
<Link
href={link.href}
className={
link.href === "/gallery"
? "block px-4 py-3 rounded-t-md bg-indigo-600"
: "block px-4 py-3 rounded-t-md hover:bg-indigo-600"
}
>
{link.label}
</Link>
</li>
))}
</ul>
</nav>
</header>
<main className="max-w-5xl mx-auto px-4 py-6">
<section>
<h2 className="text-2xl font-semibold text-indigo-900 mb-4">Koleksi Foto</h2>
{/* grid responsif: 1 kolom di ponsel, 2 di tablet, 3 di layar lebar */}
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6">
<figure className="bg-white rounded-lg shadow overflow-hidden">
<img src="/images/galeri-1.jpg" alt="Saya bersama teman-teman di kampus, berfoto dengan seragam merah" className="w-full h-56 object-cover" />
<figcaption className="p-3 text-sm text-slate-600">Bersama teman-teman di kampus.</figcaption>
</figure>
<figure className="bg-white rounded-lg shadow overflow-hidden">
<img src="/images/galeri-2.jpg" alt="Maskot kucing dan karakter pemegang kue ulang tahun pada poster raksasa di tribun" className="w-full h-56 object-cover" />
<figcaption className="p-3 text-sm text-slate-600">Poster raksasa di tribun pertandingan basket.</figcaption>
</figure>
<figure className="bg-white rounded-lg shadow overflow-hidden">
<img src="/images/galeri-3.jpg" alt="Suasana arena basket dengan poster burung elang raksasa di tribun" className="w-full h-56 object-cover" />
<figcaption className="p-3 text-sm text-slate-600">Suasana arena pertandingan basket.</figcaption>
</figure>
<figure className="bg-white rounded-lg shadow overflow-hidden">
<img src="/images/galeri-4.jpg" alt="Ringkasan rute bersepeda sore 30,53 km di Surabaya dari aplikasi Strava" className="w-full h-56 object-cover" />
<figcaption className="p-3 text-sm text-slate-600">Rute bersepeda sore sejauh 30,53 km.</figcaption>
</figure>
<figure className="bg-white rounded-lg shadow overflow-hidden">
<img src="/images/galeri-5.jpg" alt="Layar hasil pertandingan Clash Squad yang dimenangkan tim saya" className="w-full h-56 object-cover" />
<figcaption className="p-3 text-sm text-slate-600">Kemenangan di game Clash Squad.</figcaption>
</figure>
<figure className="bg-white rounded-lg shadow overflow-hidden">
<img src="/images/galeri-6.jpg" alt="Rangkaian Arduino Smart Parking System dengan layar LCD bertuliskan Welcome dan Slot Left 4, dua sensor inframerah, dan motor servo" className="w-full h-56 object-cover" />
<figcaption className="p-3 text-sm text-slate-600">Proyek Arduino Smart Parking System.</figcaption>
</figure>
</div>
</section>
</main>
<footer className="text-center py-5 text-sm text-slate-500">
<p>&copy; 2026 Yovan Budianto Tanujaya - Web Lanjut, Informatika UKWMS</p>
</footer>
</>
);
}
+19
View File
@@ -0,0 +1,19 @@
import type { Metadata } from "next";
import type { ReactNode } from "react";
import Script from "next/script";
export const metadata: Metadata = {
title: "Gallery - Yovan",
};
export default function GalleryLayout({ children }: { children: ReactNode }) {
return (
<html lang="id">
<body className="bg-slate-100 text-slate-800 leading-relaxed">
{/* tailwind CSS only: satu-satunya skrip di halaman ini adalah CDN Tailwind */}
<Script src="https://cdn.tailwindcss.com" strategy="beforeInteractive" />
{children}
</body>
</html>
);
}
+71
View File
@@ -0,0 +1,71 @@
import Link from "next/link";
import { navLinks } from "../../_data/nav-links";
export default function HobbiesPage() {
return (
<>
<header className="site-header">
<h1 className="page-title">Hobbies</h1>
<p className="tagline">Hal-hal yang saya lakukan di waktu luang.</p>
<nav className="site-nav">
<ul>
{navLinks.map((link) => (
<li key={link.href}>
<Link href={link.href} className={link.href === "/hobbies" ? "active" : undefined}>
{link.label}
</Link>
</li>
))}
</ul>
</nav>
</header>
<main className="page-wrapper">
<section className="card">
<h2>Tiga Hobi Utama</h2>
<div className="hobby-grid">
<article className="hobby-card">
<img src="/images/hobi-bersepeda.jpg" alt="Sepeda balap saya terparkir, dengan ringkasan rute Strava bersepeda sore" />
<h3>Bersepeda</h3>
<p>
Saya suka bersepeda sore keliling Surabaya. Dua rute terakhir saya
menempuh 30,53 km dan 37,79 km.
</p>
</article>
<article className="hobby-card">
<img src="/images/hobi-menggambar.jpg" alt="Gambar digital karakter berhoodie biru memegang cat semprot buatan saya" />
<h3>Menggambar</h3>
<p>Saya suka menggambar karakter kartun dengan aplikasi digital.</p>
</article>
<article className="hobby-card">
<img src="/images/hobi-olahraga.jpg" alt="Tim futsal berbaris merangkul bahu di lapangan dengan suporter di tribun" />
<h3>Olahraga</h3>
<p>Saya suka bermain futsal dan bermain setiap minggu.</p>
</article>
</div>
</section>
<section className="card">
<h2>Lebih Dekat dengan Hobi Saya</h2>
<h3>Perlengkapan yang saya pakai</h3>
<ul>
<li>Sepeda</li>
<li>Sepatu futsal</li>
<li>Ibis Piant X</li>
</ul>
<h3>Cara saya memulai hobi baru</h3>
{/* ol dipakai karena langkah-langkahnya berurutan */}
<ol>
<li>Mencari tahu dasar-dasarnya lewat video dan buku.</li>
<li>Mencoba dengan perlengkapan sederhana.</li>
<li>Berlatih rutin setiap minggu.</li>
</ol>
</section>
</main>
<footer className="site-footer">
<p>&copy; 2026 Yovan Budianto Tanujaya - Web Lanjut, Informatika UKWMS</p>
</footer>
</>
);
}
+17
View File
@@ -0,0 +1,17 @@
import type { Metadata } from "next";
import type { ReactNode } from "react";
// external CSS only: semua gaya halaman ini ada di styles.css
import "../styles.css";
export const metadata: Metadata = {
title: "Hobbies - Yovan",
};
export default function HobbiesLayout({ children }: { children: ReactNode }) {
return (
<html lang="id">
<body className="page-body">{children}</body>
</html>
);
}
+25
View File
@@ -0,0 +1,25 @@
import type { Metadata } from "next";
import type { ReactNode } from "react";
export const metadata: Metadata = {
title: "Home - Yovan",
};
// inline CSS only: layout ini tidak mengimpor file .css dan tidak memuat <style>
export default function HomeLayout({ children }: { children: ReactNode }) {
return (
<html lang="id">
<body
style={{
margin: 0,
fontFamily: "'Segoe UI', Arial, sans-serif",
backgroundColor: "#f1f5f9",
color: "#1e293b",
lineHeight: 1.6,
}}
>
{children}
</body>
</html>
);
}
+111
View File
@@ -0,0 +1,111 @@
import Link from "next/link";
import { navLinks } from "../_data/nav-links";
export default function HomePage() {
return (
<>
<header
style={{
backgroundColor: "#312e81",
color: "#ffffff",
padding: "24px 16px 0",
textAlign: "center",
}}
>
<h1 style={{ margin: "0 0 4px", fontSize: "2rem" }}>Halo, saya Yovan</h1>
<p style={{ margin: 0 }}>
Mahasiswa Informatika yang suka membangun hal-hal kecil di web.
</p>
<nav>
<ul
style={{
listStyle: "none",
margin: "16px 0 0",
padding: 0,
display: "flex",
justifyContent: "center",
flexWrap: "wrap",
gap: 4,
}}
>
{navLinks.map((link) => (
<li key={link.href}>
<Link
href={link.href}
style={{
display: "block",
padding: "12px 16px",
color: "#ffffff",
textDecoration: "none",
borderRadius: "6px 6px 0 0",
// tab aktif (Home) diberi warna latar
backgroundColor: link.href === "/" ? "#4f46e5" : undefined,
}}
>
{link.label}
</Link>
</li>
))}
</ul>
</nav>
</header>
<main style={{ maxWidth: 900, margin: "24px auto", padding: "0 16px" }}>
<section
style={{
display: "flex",
flexWrap: "wrap",
alignItems: "center",
gap: 24,
backgroundColor: "#ffffff",
borderRadius: 10,
padding: 24,
boxShadow: "0 1px 4px rgba(15, 23, 42, 0.12)",
}}
>
<img
src="/images/foto-profil.jpg"
alt="Foto Yovan dari belakang memakai jersey bernomor 4 di lapangan"
width={220}
height={220}
style={{
width: 220,
height: 220,
objectFit: "cover",
borderRadius: "50%",
border: "4px solid #4f46e5",
}}
/>
<div style={{ flex: 1, minWidth: 240 }}>
<h2 style={{ marginTop: 0, color: "#312e81", fontSize: "1.5rem" }}>
Selamat datang di situs pribadi saya
</h2>
<p>
Saya Yovan, mahasiswa semester 3 Program Studi Informatika di
Universitas Katolik Widya Mandala Surabaya. Situs ini saya buat sebagai
Perkenalan Pribadi saya.
</p>
<p>
Silakan jelajahi halaman <strong>About</strong> untuk mengenal saya lebih
jauh, <strong>Hobbies</strong> dan <strong>Gallery</strong> untuk sisi
santai saya, serta <strong>Contact</strong> jika ingin menghubungi saya.
</p>
</div>
</section>
</main>
<footer
style={{
textAlign: "center",
padding: "20px 16px",
color: "#64748b",
fontSize: "0.9rem",
}}
>
<p style={{ margin: 0 }}>
&copy; 2026 Yovan Budianto Tanujaya - Web Lanjut, Informatika UKWMS
</p>
</footer>
</>
);
}
+8
View File
@@ -0,0 +1,8 @@
// data navigasi bersama: dipakai oleh navbar di kelima halaman
export const navLinks = [
{ href: "/", label: "Home" },
{ href: "/about", label: "About" },
{ href: "/hobbies", label: "Hobbies" },
{ href: "/gallery", label: "Gallery" },
{ href: "/contact", label: "Contact" },
];
+141
View File
@@ -0,0 +1,141 @@
/* external stylesheet: shared by hobbies.html, about.html and contact.html */
.page-body {
margin: 0;
font-family: "Segoe UI", Arial, sans-serif;
background-color: #f1f5f9;
color: #1e293b;
line-height: 1.6;
}
/* header + shared navigation bar */
.site-header {
background-color: #312e81;
color: #ffffff;
padding: 24px 16px 0;
text-align: center;
}
.site-header .page-title {
margin: 0 0 4px;
font-size: 2rem;
}
.site-header .tagline {
margin: 0;
}
.site-nav ul {
list-style: none;
margin: 16px 0 0;
padding: 0;
display: flex;
justify-content: center;
flex-wrap: wrap;
gap: 4px;
}
.site-nav a {
display: block;
padding: 12px 16px;
color: #ffffff;
text-decoration: none;
border-radius: 6px 6px 0 0;
}
.site-nav a:hover,
.site-nav a.active {
background-color: #4f46e5;
}
/* layout containers */
.page-wrapper,
.about-wrapper {
max-width: 900px;
margin: 24px auto;
padding: 0 16px;
}
.about-wrapper {
display: flex;
flex-direction: column;
gap: 24px;
}
/* content cards (hobbies + contact) */
.card {
background-color: #ffffff;
border-radius: 10px;
padding: 20px 24px;
margin-bottom: 20px;
box-shadow: 0 1px 4px rgba(15, 23, 42, 0.12);
}
.card h2 {
margin-top: 0;
color: #312e81;
font-size: 1.5rem;
}
.card h3 {
margin: 0 0 6px;
font-size: 1.15rem;
}
.card ul {
list-style: disc;
padding-left: 24px;
}
.card ol {
list-style: decimal;
padding-left: 24px;
}
.card a {
color: #4338ca;
}
/* hobbies grid */
.hobby-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
gap: 16px;
}
.hobby-card img {
display: block;
width: 100%;
height: 180px;
object-fit: cover;
border-radius: 8px;
margin-bottom: 10px;
}
.hobby-card p {
margin: 0;
}
/* tables */
.data-table {
width: 100%;
border-collapse: collapse;
}
.data-table th,
.data-table td {
border: 1px solid #cbd5e1;
padding: 8px 12px;
text-align: left;
}
.data-table th {
background-color: #e0e7ff;
}
.site-footer {
text-align: center;
padding: 20px 16px;
color: #64748b;
font-size: 0.9rem;
}