Profil Agensi Digital
Landing page satu halaman (single-page) yang berfungsi ganda sebagai company profile agensi digital. Halaman menampilkan hero yang meyakinkan, daftar layanan, showcase portfolio, testimoni klien, dan form kontak yang langsung mengirim lead ke email tim. Fokus MVP adalah konversi pengunjung menjadi lead berkualitas dengan halaman yang cepat, responsif, dan mudah dipercaya — tanpa CMS atau backend berat.
Landing Page & Company Profile Agensi Digital
Landing page satu halaman (single-page) yang berfungsi ganda sebagai company profile agensi digital. Halaman menampilkan hero yang meyakinkan, daftar layanan, showcase portfolio, testimoni klien, dan form kontak yang langsung mengirim lead ke email tim. Fokus MVP adalah konversi pengunjung menjadi lead berkualitas dengan halaman yang cepat, responsif, dan mudah dipercaya — tanpa CMS atau backend berat.
Problem
Agensi digital sering kehilangan calon klien karena tidak punya kehadiran online yang meyakinkan dan mudah dihubungi. Prospek yang datang dari referral, iklan, atau pencarian butuh cara cepat untuk menilai kredibilitas (layanan apa saja, hasil kerja sebelumnya, apa kata klien) dan menghubungi tim tanpa harus menelepon. Tanpa satu halaman terpusat yang rapi, prospek pergi ke kompetitor. Produk ini menyediakan landing page yang menjual sekaligus company profile ringkas, dengan jalur konversi jelas: lihat layanan & portfolio → baca testimoni → isi form kontak → tim menerima lead lewat email.
Goals
- Menyajikan value proposition agensi dalam 5 detik pertama lewat hero yang jelas dan satu CTA utama.
- Menampilkan daftar layanan, portfolio, dan testimoni secara terstruktur sehingga prospek bisa menilai kredibilitas tanpa keluar halaman.
- Menyediakan form kontak yang mengirim lead langsung ke email tim dengan validasi dan proteksi spam dasar.
- Memastikan halaman responsif penuh (mobile-first), cepat (Lighthouse Performance & SEO >= 90 di desktop), dan aksesibel.
- Konten (layanan, portfolio, testimoni, info kontak) dikelola lewat file data terstruktur sehingga mudah diperbarui developer tanpa menyentuh markup.
Non-Goals
- CMS atau panel admin untuk mengedit konten dari browser (MVP: konten via file data di repo).
- Blog, halaman artikel, atau sistem konten dinamis.
- Multi-bahasa / i18n (MVP: satu bahasa, default Bahasa Indonesia).
- Autentikasi, login klien, atau area member.
- Penyimpanan lead ke database dan dashboard analitik lead (MVP: lead dikirim via email; arsip DB ditunda).
- Integrasi CRM, live chat, booking/kalender, atau pembayaran online.
- Dark mode / theme switcher dan animasi kompleks di luar micro-interaction ringan.
Target Users
- Calon klien bisnis (UMKM & brand menengah) — Ingin cepat memahami layanan agensi, melihat bukti hasil kerja (portfolio) dan testimoni, lalu menghubungi tim dengan sekali isi form. Sering membuka dari HP dan tidak sabar menunggu halaman lambat.
- Decision maker / marketing manager — Menilai kredibilitas dan kecocokan agensi sebelum meneruskan ke atasan; butuh informasi layanan yang jelas, studi kasus, dan cara kontak yang profesional.
- Pemilik / tim agensi (pengelola situs) — Menerima notifikasi lead lengkap (nama, email, pesan) di email secepatnya untuk follow-up, serta bisa memperbarui daftar layanan/portfolio/testimoni dengan mudah lewat file data.
User Stories
- must-haveSebagai calon klien, saya ingin langsung memahami apa yang ditawarkan agensi dan melihat satu tombol aksi jelas di bagian hero, agar saya bisa memutuskan dalam hitungan detik apakah agensi ini relevan untuk kebutuhan saya.
- must-haveSebagai calon klien, saya ingin melihat daftar layanan yang ditawarkan beserta deskripsi singkatnya, agar saya tahu apakah agensi menangani kebutuhan spesifik saya (misalnya branding, web, atau iklan).
- must-haveSebagai calon klien, saya ingin melihat portfolio hasil kerja sebelumnya dalam bentuk visual, agar saya bisa menilai kualitas dan gaya kerja agensi sebelum menghubungi.
- should-haveSebagai calon klien, saya ingin membaca testimoni dari klien lain, agar saya merasa lebih yakin dan percaya untuk melanjutkan kontak.
- must-haveSebagai calon klien, saya ingin mengisi form kontak singkat (nama, email, pesan) dan mendapat konfirmasi terkirim, agar saya bisa menghubungi agensi tanpa harus menelepon atau menulis email manual.
- must-haveSebagai pemilik agensi, saya ingin menerima setiap lead dari form langsung di email tim dengan detail lengkap, agar saya bisa merespons calon klien dengan cepat sebelum mereka pindah ke kompetitor.
- must-haveSebagai pengunjung yang membuka dari HP, saya ingin seluruh halaman tampil rapi dan mudah dinavigasi di layar kecil, agar saya nyaman menjelajah dan mengisi form tanpa harus zoom atau scroll horizontal.
Features
Hero Section
Bagian paling atas dengan headline value proposition, subheadline pendukung, satu CTA utama (scroll ke form kontak / anchor #kontak), dan visual/latar pendukung. Mengkomunikasikan siapa agensi dan apa manfaatnya dalam sekali pandang.
- Menampilkan headline, subheadline, dan minimal satu tombol CTA yang mengarah ke section kontak (#kontak) via smooth scroll.
- Konten hero (headline, subheadline, teks & target CTA) dibaca dari file data content/site.ts, bukan di-hardcode di JSX.
- Tampil tanpa scroll horizontal dan seluruh teks terbaca pada viewport 375px, 768px, dan 1280px.
- Teks kontras memenuhi WCAG AA (rasio >= 4.5:1) di atas latar/visual yang dipakai.
Daftar Layanan
Section grid berisi kartu-kartu layanan agensi (misalnya Branding, Web Development, Social Media, Ads). Setiap kartu punya ikon/label, judul layanan, dan deskripsi singkat.
- Merender seluruh item dari array content/services.ts (minimal 3, mendukung hingga 8 tanpa perubahan markup).
- Setiap kartu menampilkan judul dan deskripsi; grid responsif (1 kolom di mobile, 2 di tablet, 3+ di desktop).
- Menamb/mengurangi layanan cukup dengan mengubah file data tanpa menyentuh komponen React.
- Section punya id="layanan" agar bisa dituju dari navigasi.
Portfolio / Showcase
Galeri visual hasil kerja sebelumnya. Setiap item menampilkan gambar, judul proyek, kategori/klien, dan deskripsi singkat opsional.
- Merender item dari content/portfolio.ts (minimal 3 item) dalam layout grid responsif.
- Semua gambar memakai next/image dengan atribut alt deskriptif dan lazy-loading; tidak ada layout shift (CLS) yang terlihat saat load.
- Grid tampil rapi tanpa overflow horizontal di viewport 375px dan 1280px.
- Section punya id="portfolio" untuk navigasi anchor.
Testimoni Klien
Section berisi kutipan testimoni dari klien beserta nama, jabatan/perusahaan, dan foto/inisial opsional. Membangun kepercayaan.
- Merender minimal 3 testimoni dari content/testimonials.ts (kutipan, nama, perusahaan/jabatan).
- Layout responsif (kartu bertumpuk di mobile, grid/carousel sederhana di desktop) tanpa scroll horizontal tak disengaja.
- Jika foto klien tidak tersedia, komponen menampilkan fallback inisial tanpa error.
- Section punya id="testimoni" untuk navigasi anchor.
Form Kontak
Form dengan field Nama, Email, dan Pesan (opsional: nomor telepon/nama perusahaan) yang mengirim data ke backend route, lalu backend meneruskan lead ke email tim. Termasuk validasi client + server dan proteksi spam dasar (honeypot).
- Field wajib (Nama, Email, Pesan) tervalidasi di client dan server memakai skema Zod yang sama; email diverifikasi formatnya.
- Submit valid mengirim POST ke /api/contact yang mengirim email ke alamat tim via Resend dan mengembalikan status 200; UI menampilkan pesan sukses.
- Submit gagal (validasi/error server) menampilkan pesan error yang jelas per-field atau global, tombol submit menampilkan state loading dan tidak bisa diklik ganda.
- Terdapat field honeypot tersembunyi; submission yang mengisinya ditolak diam-diam (di-drop tanpa mengirim email).
- Form bisa dioperasikan penuh via keyboard, setiap input punya <label> terkait, dan section punya id="kontak".
Navigasi & Footer
Navbar sticky dengan anchor ke section (Layanan, Portfolio, Testimoni, Kontak) plus logo/nama agensi, dan footer berisi info kontak, sosial media, dan copyright. Navbar mobile memakai menu hamburger.
- Navbar menampilkan link ke #layanan, #portfolio, #testimoni, #kontak dan smooth-scroll ke section yang benar.
- Di viewport < 768px navbar berubah menjadi menu hamburger yang bisa dibuka/tutup dan dioperasikan via keyboard.
- Footer menampilkan nama agensi, email/telepon, tautan sosial media, dan tahun copyright dinamis (tahun berjalan).
- Data kontak & sosial media dibaca dari content/site.ts.
Responsif, Aksesibilitas & SEO/Performa
Kualitas non-fungsional lintas halaman: layout mobile-first, meta tags & Open Graph, favicon, sitemap sederhana, dan performa. Menjadi acuan definition of done rilis.
- Skor Lighthouse (desktop) untuk Performance >= 90, SEO >= 90, dan Accessibility >= 90 pada halaman utama.
- Metadata Next.js terisi: <title>, meta description, Open Graph (og:title, og:description, og:image) dan favicon tersedia.
- Tidak ada horizontal scroll pada viewport 320px–1440px; seluruh gambar responsif (max-width 100%).
- Semua interaksi utama (navigasi, CTA, form) bisa dijalankan dengan keyboard dan tidak ada error di console browser.
Tech Stack
Pilihan pragmatis dan populer agar mudah dieksekusi AI coding agent: satu framework fullstack (Next.js) menghindari backend terpisah. Gunakan next/image untuk optimasi gambar, next/font untuk font. Hindari dependency berat; tambahkan react-hook-form (opsional) untuk manajemen form. Semua secret lewat .env.local, jangan commit.
Tasks (siap kirim ke AI agent)
Membuat proyek Next.js (App Router) dengan TypeScript dan Tailwind CSS, struktur folder dasar, dan konfigurasi environment.
Lihat isi perintah
Inisialisasi proyek baru bernama 'profil-agensi-digital' menggunakan `npx create-next-app@latest` dengan opsi: TypeScript, ESLint, Tailwind CSS, App Router, dan direktori `src/` TIDAK dipakai (root langsung `app/`). Setelah scaffold: (1) buat struktur folder `components/`, `content/`, `lib/` di root. (2) Bersihkan `app/page.tsx` menjadi halaman kosong dengan satu <main>. (3) Set `app/globals.css` hanya berisi directive Tailwind. (4) Buat `.env.local.example` berisi kunci placeholder: RESEND_API_KEY, CONTACT_TO_EMAIL, CONTACT_FROM_EMAIL. (5) Update `app/layout.tsx` untuk memuat font via next/font (Inter) dan set metadata dasar (title, description). Definition of done: `npm run dev` berjalan tanpa error, halaman kosong tampil di localhost:3000, `npm run build` sukses, dan tidak ada warning TypeScript.
Membangun kerangka tampilan global: tokens warna via Tailwind, komponen Navbar sticky (dengan menu mobile), Footer, dan komponen Section pembungkus yang konsisten.
Lihat isi perintah
Buat design system minimal dan layout global. (1) Di `tailwind.config.ts`, definisikan palet brand (primary, secondary, neutral) dan skala spacing/typography konsisten. (2) Buat `components/Section.tsx`: pembungkus <section> dengan prop `id`, `className`, dan `children`, menerapkan padding vertikal & max-width container konsisten. (3) Buat `components/Navbar.tsx`: sticky top, menampilkan nama/logo agensi + link anchor ke #layanan, #portfolio, #testimoni, #kontak; di viewport < 768px berubah jadi menu hamburger yang dapat dibuka/tutup (state React) dan dioperasikan via keyboard (tombol punya aria-expanded). (4) Buat `components/Footer.tsx`: nama agensi, email, telepon, tautan sosial media, dan copyright dengan tahun berjalan (new Date().getFullYear()). (5) Pasang Navbar & Footer di `app/layout.tsx`. Ambil nama/kontak/sosial dari `content/site.ts` (buat file ini jika belum ada, lihat T3). Definition of done: navbar & footer tampil di semua halaman, menu mobile berfungsi, smooth-scroll anchor aktif (scroll-behavior smooth), tidak ada horizontal scroll di 375px, dan build sukses.
Membuat file data TypeScript bertipe kuat sebagai satu sumber kebenaran konten agar section tinggal me-render tanpa hardcode.
Lihat isi perintah
Buat file data konten berikut di folder `content/` dengan tipe TypeScript eksplisit (export type + export const). (1) `content/site.ts`: objek berisi { agencyName, tagline, hero: { headline, subheadline, ctaLabel, ctaHref }, contact: { email, phone, address }, socials: {label, href}[] }. (2) `content/services.ts`: array Service[] dengan { id, title, description, icon? } minimal 4 contoh layanan agensi digital (Branding, Web Development, Social Media Management, Digital Ads). (3) `content/portfolio.ts`: array PortfolioItem[] dengan { id, title, category, imageUrl, description? } minimal 3 item; imageUrl arahkan ke gambar placeholder di `public/portfolio/`. (4) `content/testimonials.ts`: array Testimonial[] dengan { id, quote, name, role, company, avatarUrl? } minimal 3 item. Sertakan gambar/placeholder di `public/` (boleh gambar dummy). Definition of done: semua file mengekspor tipe dan data, `npm run build` lolos type-check, dan tidak ada `any`.Membangun section hero dengan headline, subheadline, CTA utama ke #kontak, dan visual pendukung, dibaca dari content/site.ts.
Lihat isi perintah
Buat `components/Hero.tsx` dan render di `app/page.tsx` sebagai section paling atas. Ambil data dari `content/site.ts` (hero.headline, hero.subheadline, hero.ctaLabel, hero.ctaHref). Layout: headline besar (font-bold, responsif via clamp/Tailwind text sizes), subheadline, dan satu tombol CTA (link anchor) yang mengarah ke #kontak dengan smooth scroll. Tambahkan visual pendukung (gambar/ilustrasi via next/image atau gradient background) tanpa mengorbankan kontras teks (WCAG AA >= 4.5:1). Gunakan komponen `Section` sebagai pembungkus. Definition of done: hero responsif di 375px/768px/1280px tanpa overflow horizontal, teks terbaca, klik CTA scroll ke section kontak, dan konten murni dari file data (tidak ada string hero yang di-hardcode di JSX).
Grid kartu layanan yang me-render dari content/services.ts, responsif dan mudah diperluas.
Lihat isi perintah
Buat `components/Services.tsx` dan `components/ServiceCard.tsx`, lalu render di `app/page.tsx` di bawah Hero dengan id="layanan". Services.tsx melakukan map atas array dari `content/services.ts` dan merender ServiceCard untuk tiap item (judul + deskripsi + ikon opsional). Grid responsif: 1 kolom < 640px, 2 kolom di md, 3 kolom di lg (Tailwind grid). Pastikan menambah/menghapus item di file data langsung tercermin tanpa mengubah komponen. Definition of done: minimal 4 kartu tampil, grid rapi tanpa overflow di 375px & 1280px, section id="layanan" bisa dituju dari navbar, dan build lolos.
Galeri visual portfolio dengan next/image, alt deskriptif, dan grid responsif dari content/portfolio.ts.
Lihat isi perintah
Buat `components/Portfolio.tsx` dan `components/PortfolioCard.tsx`, render di `app/page.tsx` dengan id="portfolio". Map atas `content/portfolio.ts`; tiap kartu menampilkan gambar (WAJIB next/image dengan width/height atau fill + sizes, alt deskriptif dari data), judul proyek, dan kategori/klien. Grid responsif (1 kolom mobile, 2-3 kolom desktop). Tambahkan hover state ringan (scale/overlay) opsional. Pastikan tidak ada Cumulative Layout Shift saat gambar load (tetapkan aspect-ratio). Definition of done: minimal 3 item tampil dengan gambar teroptimasi & alt, tanpa overflow horizontal di 375px, tanpa CLS terlihat, section id="portfolio" bisa dituju, build lolos.
Menampilkan kutipan testimoni klien dengan nama, jabatan/perusahaan, dan fallback avatar inisial dari content/testimonials.ts.
Lihat isi perintah
Buat `components/Testimonials.tsx` dan `components/TestimonialCard.tsx`, render di `app/page.tsx` dengan id="testimoni". Map atas `content/testimonials.ts`; tiap kartu menampilkan quote, nama, role, dan company. Jika avatarUrl ada, tampilkan via next/image; jika tidak, tampilkan fallback inisial dari nama (lingkaran dengan huruf pertama). Layout: kartu bertumpuk di mobile, grid 2-3 kolom di desktop (carousel opsional, tidak wajib). Definition of done: minimal 3 testimoni tampil, fallback inisial berfungsi tanpa error saat avatar kosong, responsif tanpa overflow horizontal, section id="testimoni" bisa dituju, build lolos.
Membangun komponen form kontak dengan field wajib, validasi client, state loading/sukses/error, honeypot, dan aksesibilitas.
Lihat isi perintah
Buat `components/ContactForm.tsx` (Client Component, 'use client') dan render di `app/page.tsx` dengan pembungkus Section id="kontak". Field: Nama (wajib), Email (wajib, format email), Pesan (wajib, min 10 karakter); opsional Perusahaan & Telepon. Buat skema validasi di `lib/validation.ts` menggunakan Zod (export contactSchema) yang akan dipakai bersama backend (T9). Validasi di client sebelum submit; tampilkan pesan error per-field. Tambahkan input honeypot tersembunyi (mis. field 'website' disembunyikan via CSS, bukan type=hidden) untuk anti-spam. Setiap input punya <label htmlFor> terkait; form bisa disubmit via keyboard. Kelola state: idle | submitting | success | error. Saat submitting, tombol disabled + tampilkan loading (cegah double submit). Saat sukses, tampilkan pesan konfirmasi & reset form; saat error tampilkan pesan global. Submit lewat fetch POST ke /api/contact (endpoint dibuat di T9) mengirim JSON. Definition of done: validasi client berjalan, honeypot ada, state transitions benar, tidak ada error console, dan form dapat dioperasikan penuh via keyboard.
Endpoint API yang memvalidasi payload di server, menolak spam honeypot, dan mengirim email lead ke tim via Resend.
Lihat isi perintah
Buat Route Handler `app/api/contact/route.ts` dengan handler POST. Langkah: (1) Parse JSON body dan validasi ulang di server memakai `contactSchema` dari `lib/validation.ts` (Zod) — kembalikan 400 dengan detail error jika invalid. (2) Jika field honeypot terisi, kembalikan 200 diam-diam TANPA mengirim email (drop). (3) Kirim email ke `process.env.CONTACT_TO_EMAIL` dari `process.env.CONTACT_FROM_EMAIL` memakai Resend SDK (`npm i resend`, `RESEND_API_KEY`), isi email berisi Nama, Email, Perusahaan/Telepon (jika ada), dan Pesan, dengan reply-to di-set ke email pengirim. (4) Kembalikan 200 saat sukses, 500 saat gagal kirim (tanpa membocorkan detail internal). Tangani error dengan try/catch dan log ke server. Update `.env.local.example` bila perlu. Tambahkan rate-limit sederhana opsional (mis. batasi per IP di memori) jika mudah. Definition of done: submit dari ContactForm valid menghasilkan email diterima di CONTACT_TO_EMAIL, payload invalid mengembalikan 400, honeypot terisi tidak mengirim email tetapi tetap 200, dan tidak ada secret yang ter-commit.
Finalisasi metadata/SEO, favicon, Open Graph, audit responsif & Lighthouse, lalu deploy ke Vercel dengan environment variable.
Lihat isi perintah
Finalisasi kualitas & rilis. (1) Lengkapi metadata di `app/layout.tsx` (dan/atau `app/page.tsx`) memakai Metadata API Next.js: title, description, keywords, openGraph (title, description, images), dan twitter card. Tambahkan favicon di `app/icon` / `public` dan satu gambar `public/og.png` untuk Open Graph. (2) Tambahkan `app/sitemap.ts` dan `app/robots.ts` sederhana. (3) Audit responsif manual di 320px, 375px, 768px, 1280px — pastikan tidak ada horizontal scroll dan gambar max-width 100%. (4) Jalankan Lighthouse (desktop) dan perbaiki hingga Performance >= 90, SEO >= 90, Accessibility >= 90 (perbaiki alt, kontras, label, heading order). (5) Pastikan tidak ada error/warning di console browser. (6) Buat `README.md` ringkas berisi cara setup, daftar env var (RESEND_API_KEY, CONTACT_TO_EMAIL, CONTACT_FROM_EMAIL), dan cara update konten. (7) Deploy ke Vercel: hubungkan repo, set environment variables di dashboard, verifikasi form kontak bekerja di production. Definition of done: skor Lighthouse memenuhi target, metadata & OG terpasang (cek via view-source), form kontak production mengirim email, dan URL produksi live.
Risks
- Deliverabilitas email: Resend memerlukan verifikasi domain (SPF/DKIM) agar email lead tidak masuk spam. Jika domain belum diverifikasi, notifikasi lead bisa hilang.
- Spam form: honeypot saja mungkin tidak cukup untuk bot canggih; mungkin perlu tambahan (rate limit atau CAPTCHA) di fase lanjut.
- Ketersediaan konten nyata: portfolio, testimoni, dan copy hero yang meyakinkan bergantung pada aset & materi dari agensi; placeholder bisa menurunkan kredibilitas jika belum diganti sebelum rilis.
- Performa gambar: portfolio dengan gambar besar bisa menurunkan skor Lighthouse jika tidak dioptimasi (wajib next/image + ukuran tepat).
- Tanpa database di MVP, lead hanya ada di email; jika email gagal terkirim dan tidak ada arsip, lead bisa hilang tanpa jejak.
Open Questions
- Alamat email tujuan lead (CONTACT_TO_EMAIL) dan domain pengirim yang akan diverifikasi di Resend — pakai domain apa?
- Apakah butuh field tambahan di form (mis. anggaran, jenis layanan yang diminati) untuk kualifikasi lead lebih baik?
- Berapa banyak item portfolio & testimoni awal yang tersedia, dan apakah ada aset gambar/logo brand resmi?
- Apakah perlu integrasi analitik (mis. Google Analytics / Vercel Analytics) sejak MVP untuk mengukur konversi?
- Apakah nantinya perlu arsip lead ke database/CRM, dan jika ya kapan (menentukan apakah backend perlu disiapkan lebih awal)?
- Palet warna, font, dan panduan brand agensi — apakah sudah ada brand guideline yang harus diikuti?