console.log('')

Halo Dunia

Blog /
10 menit dibaca

Sebenarnya saya juga sedih dan sepakat dan merasa relevan dengan twit atau komentar-komentar netizen di akun Instagram para selebritas blunder atau kata-kata mengsedih yang muncul di video Tiktok joget canggung ala Mas dan Mbak mahalentur yang menyatakan akhir-akhir ini kian hari hidup terasa kian berat.

Apalagi kalau turut menyimak tagar #PercumaLaporPolisi yang tiap-tiap cuitannya akan mengingatkan kita pada pecahan-pecahan puisi di buku Cinta yang Marah. Oksimoron paling sedap tahun ini: dipaksa sehat di negara yang sakit.

Apakah kalian membaca Tokyo Revengers? Kadang-kadang ada hari ketika saya entah kenapa lebih menyukai Bonten daripada Touman, berpikir mungkin semuanya akan terasa lebih menyenangkan dan bisa dikendalikan andai hidup semudah bacotan Sano Manjiro. Impulsivitas gelap. Fyuh.

Tetapi hidup terlalu singkat untuk diratapi, bukan?

Toh, lagi pula, tampaknya kita juga sudah terbiasa dengan pola wasweswos ndumel di Twitter akibat melihat kelakuan para badut intoleran yang hendak menghancurkan peradaban, tetapi sesaat kemudian lanjut ngikik terpingkal-pingkal di muka derita orang lain karena ada Mas dan Mbak idola kita yang gemar menuliskan berbagai humor gelap siap retweet mereka setiap waktu.

Maka halo, apa kabar? Apa yang kalian lakukan di sela-sela kepayahan bertahan hidup?

Untuk upaya menghibur diri sendiri, saya membuat blog baru ala Do It Yourself; blog yang dirakit dari nol, termasuk pembuatan desain, perencanaan fitur, dan penulisan kode.

“Kenapa?” kamu mungkin bertanya. “Kenapa repot-repot bikin sendiri kalau ada banyak platform siap pakai?”

Ya benar, Medium bersih dan mudah digunakan, saya tahu. Karyakarsa bahkan bisa jadi ladang duit. Tetapi cuma di blog bikinan sendiri kita bisa bebas ugal-ugalan, seperti membuat dan menyisipkan tombol berikut di tengah-tengah tulisan:

Blog pribadi adalah satu-satunya wadah yang bisa diatur dan didekorasi seenak jidat. Kita bisa memilih bentuk, warna, gaya, fitur—hampir apa pun. Batasannya cuma ketidaktahuan kita untuk memperluasnya.

Saya sangat senang dengan hasil akhir dari blog ini. Baik dari segi desain maupun teknologi, ini adalah apa yang saya sebut sebagai beginilah semestinya sebuah blog dibuat. Ini adalah apa yang saya idam-idamkan sejak lama.

Perubahan yang paling mencolok mungkin gayanya. Berbeda dengan pola desain saya selama bertahun-tahun ngeblog yang selalu dominan hitam putih, sekarang blog saya tampil dengan lebih “berani” dan warna-warni. Bernuansa pop punk ala 90-an.

Berikut tangkapan layar desain blog terakhir saya sebelum ini:

Tampilan beranda desain blog lama
Tampilan beranda desain blog lama
Tampilan konten desain blog lama
Tampilan pos desain blog lama

Jadi bagaimana blog ini dibuat? Tumpukan apa saja yang saya pilih? Mari kita bedah.

Secara teknis, blog ini cuma aplikasi React kecil bertenaga MDX yang ditata dengan styled-jsx, yang kemudian dikompilasi oleh Next.js (dan ya bukan Gatsby).

Next.js: Kerangka Kerja yang Menyenangkan

Jawabannya mudah saja. Alasan utama kenapa saya memilih Next.js adalah karena ia kerangka kerja yang paling mendekati kebutuhan saya. Atau setidaknya, yang paling mudah untuk mencapai tujuan.

Saya selalu menghargai petani yang paham mana tanah yang subur dan mana yang tidak, bagaimana cara mengusir hama, apa yang harus dilakukan saat pancaroba, dan seterusnya dan sebagainya. Atau tukang kayu yang tahu kenapa bahan A lebih cocok untuk membuat meja dan bukan pintu, kenapa bahan B lebih bagus dicampur cairan C tetapi tidak dengan D.

Sama seperti mereka, saya juga ingin menghargai diri sendiri. Dimulai dengan hal-hal kecil seperti memilih alat-alat yang benar-benar saya tahu dan pahami. Karena yang lebih penting daripada tahu kapan dan kenapa harus menggunakan alat yang mana adalah tahu kapan harus tidak menggunakan alat-alat tersebut.

Saya memilih Next.js karena terutama butuh API berbasis rutenya. API Routes Next.js bisa menjalankan rute dinamis, sangat membantu untuk membuat API dengan jalur yang berubah-ubah seperti kebutuhan saya yang ingin membuat fitur realtime pageview untuk pos blog.

pages/api/views/[slug].js
import db from 'lib/database'

export default async function handler(req, res) {
  if (req.method === 'POST') {
    const ref = db.ref('views').child(req.query.slug)
    const { snapshot } = await ref.transaction((currentViews) => {
      if (currentViews === null) {
        return 1
      }
      return currentViews + 1
    })

    return res.status(200).json({
      total: snapshot.val(),
    })
  }

  if (req.method === 'GET') {
    const snapshot = await db.ref('views').child(req.query.slug).once('value')
    const views = snapshot.val()

    return res.status(200).json({ total: views })
  }
}

Catatan: saat merakit blog ini, enam bulan lalu, Gatsby belum mendukung API rute dinamis. Sekarang ada dukungannya di Gatsby 4, rilis 26 Oktober 2021.

Apa fungsi tayangan waktu nyata? Untuk tahu berapa banyak tulisan saya dibaca. Saya tidak menggunakan Google Analytics karena selain isu privasi pengguna, fiturnya terlalu mewah. Lagi pun GA lebih cocok untuk model Bisnis ke Bisnis ketimbang individu.

Untuk analisis web saya menggunakan Splitbee. Ini gratis, sederhana, dan aman dari isu privasi. Tetapi ada satu batasan: paket gratisnya cuma bisa menyimpan data sejauh enam bulan terakhir. Jadi saya membuat basis data cadangan di Firebase Realtime Database.

Selain untuk cadangan, tayangan waktu nyata buatan ini juga berguna sebagai pusat data, jaga-jaga kalau di lain hari saya ingin mencopot Splitbee dan memasang alat analisis lain tanpa khawatir kehilangan data utama.

Pertimbangan lain kenapa saya memilih Next.js adalah karena alat ini digunakan oleh banyak perusahaan ternama seperti Netflix, Uber, Nike, Hashnode, Notion, Apple. Bahkan situs dokumentasi resmi React yang baru sedang dalam proses migrasi ke Next.js.

CSS-in-JS: Pengatur Lembar Gaya

Jadi begini, kalau kita pereteli, blog ini dirakit dengan sistem blok komponen mandiri yang beberapa bloknya tidak digunakan berulang-ulang secara brutal, tetapi bisa tiba-tiba muncul di sembarang tempat di sembarang laman.

Saya membagi blok komponen menjadi dua: parsial dan tempelan. Parsial adalah blok yang membentuk inti antarmuka (Header, Navigation, Footer). Blok-blok parsial digabung ke dalam satu blok komponen induk yang saya sebut Layout. Nah, di Layout, sebagai komponen induk, saya bisa bebas menyisipkan blok-blok tempelan (Breadcrumb, Social Share).

Kerangka desain

Artinya, jika blok tombol berbagi ke media sosial hanya digunakan di laman pos tunggal, lembar gaya yang mengatur tata letak tombol berbagi tidak harus ada di laman Profil, Kontak, Proyek, apalagi Beranda. Setiap laman HTML hanya boleh merujuk fail CSS yang dibutuhkan.

Dan di sinilah kekuatan pustaka CSS-in-JS masuk. CSS-in-JS adalah cara menulis lembar gaya di dalam fail JavaScript secara langsung. Dengan cara ini, tiap-tiap gaya akan melekat pada selector di tempat di mana gaya diterapkan, dan dengan sendirinya tidak akan bentrok dengan selector di tempat lain. Setiap komponen punya CSS-nya sendiri.

Sebagai contoh, beginilah cara saya mengatur komponen CodeBlock:

import highlight from 'styles/highlight'

function CodeBlock({ children }) {
  return (
    <pre className={children.props.className}>
      {children}
      <style jsx global>
        {highlight}
      </style>
    </pre>
  )
}

Lembar gaya highlight.js (saat diurai akan diubah menjadi highlight.css) hanya akan muncul di laman yang ada kode <pre> di HTML-nya. Kalau saya membuat tulisan yang tidak menggunakan CodeBlock, gaya highlight.js tidak akan dipanggil. (Hal ini bisa dicapai dengan memanfaatkan fitur Dynamic Import dari Next.js.)

Alasan lain kenapa saya memilih CSS-in-JS adalah saya menikmati cara ini:

components/test/styles.js
export const color = {
  black: '#222222',
  white: '#ffffff',
}

export const font = {
  mono: 'Consolas, Menlo, monospace',
}

Yang kemudian bisa digunakan seperti ini:

components/test/index.js
import { color, font } from './styles'

function TestComponent() {
  return (
    <>
      <marquee>Yihaaa!</marquee>
      <style jsx>{`
        marquee {
          color: ${color.black};
          font-family: ${font.mono};
        }
      `}</style>
    </>
  )
}

Fantastis.

Untuk pertanyaan kenapa styled-jsx dan bukan styled-components atau emotion yang dipilih, jawabannya karena styled-jsx adalah pustaka built-in Next.js, yang berarti ia terintegrasi dengan baik dan memiliki dukungan penuh dengan kompiler Next.js.

Trivia: saya sejujurnya lebih suka Linaria karena ia tanpa runtime, tetapi blog saya jadi meledak berkali-kali barangkali karena Linaria ada konflik dengan konfigurasi Babel dan webpack 5 dari Next.js.

MDX: Mesin Kompiler

MDX adalah sihir yang membantu para pengembang menembus batas wajar dalam menulis konten. Ini adalah alat yang membantu saya melakukan hal-hal yang tadinya tidak mungkin, seperti membuat dan menyematkan tombol konfeti di atas tadi. Faktanya, seluruh hal di luar data di dalam konten blog ini dibuat dengan MDX.

Di Next.js, orang biasanya akan memakai salah satu dari dua pilihan berikut ketika ingin memasang MDX di aplikasinya:

  • @next/mdx: plugin resmi Next.js
  • next-mdx-remote: plugin dari HashiCorp

Saya tidak puas dengan keduanya karena tidak bisa mencapai kasus penggunaan saya. Jadi saya mencari kompiler lain dan menemukan mdx-bundler buatan Kent. C. Dodds.

Melebihi ekspektasi, mdx-bundler ternyata punya fitur di atas rata-rata, mendukung impor komponen sekali pakai, dan ia merupakan mesin yang agnostik terhadap kerangka kerja. Yah, siapa tahu dua tahun ke depan ada alat lain yang lebih sakti dari Next.js, saya bisa migrasi tanpa sakit kepala.

Plus, mdx-bundler tidak peduli dengan di/dari mana konten berasal. Fail lokal atau API jarak jauh, keduanya sama aman. Jadi kalau, katakanlah, sewaktu-waktu saya ingin memindahkan seluruh konten blog ini ke Headless CMS yang bisa menghasilkan node Markdown (misalnya GraphCMS), saya tidak perlu mengedit banyak hal.

Masih tentang cara menulis konten, guna menolong diri sendiri, saya juga memakai remark-directive sebagai pintasan sintaks dalam menulis.

// daripada menulis seperti ini
<div className="caption">Text</div>

// saya bisa menulisnya seperti ini
:div[Text]{.caption}

Jauh lebih ringkas pun terasa lebih Markdown. Dan meskipun saya lebih suka memakai JSX untuk memanggil komponen MDX, sintaks directives juga bisa digunakan kalau mau.

:youtube{#9_gkpYORQLU}

Hasil:

Bagian Belakang: Hal-Hal di Balik Layar

Sebagaimana aplikasi Jamstack pada umumnya, seluruh data dan kode sumber blog ini saya simpan di GitHub. Saya masih nyaman dengan alur menulis Markdown di Visual Studio Code dan mengunggahnya ke GitHub lewat terminal.

Saya suka bagaimana semua roda di sekitar blog ini bisa bergerak hanya dengan tiga baris perintah:

git add .
git commit -m "add new post"
git push origin main

Ada semacam kesenangan tak terjelaskan ketika mengetik tiga perintah di atas dan melihat utas proses berjalan, tanpa perlu membuka peramban. Ya, saya memasang VSCode Vercel (blog ini dihos di Vercel), jadi saya bisa memantau proses deployment secara langsung di Visual Studio Code.

VSCode Vercel

Sulit untuk menyangkal Next.js dan Vercel adalah salah satu kombinasi terbaik di ekosistem Jamstack. AWS Lambda sebagai penangan fungsi tanpa server ditambah Node.js 14 sebagai default runtime, Vercel memberikan pengalaman pengembangan yang sangat amat ajaib. Membuat API untuk formulir kontak jadi semudah ini:

import { SMPTClient } from 'emailjs'

export default async function handler(req, res) {
  const email = new SMPTClient({
    port: 587,
    tls: true,
    host: process.env.EMAIL_HOST,
    user: process.env.EMAIL_USER,
    password: process.env.EMAIL_PASSWORD,
  })

  email.send(
    {
      from: process.env.EMAIL_USER,
      to: 'Gigip <gigip@gipsterya.com>',
      subject: `New message from ${req.body.name}`,
      text: `${req.body.message}
       
      ${req.body.name},
      <${req.body.email}>
      `,
    },
    (error, message) => {
      console.log(error, message)
      res.send('success')
    }
  )
}

Tidak butuh layanan pihak ketiga, tidak ada batasan berapa banyak surel yang bisa saya terima. Mantap jiwa.

Saya sangat kagum dengan betapa mudahnya mengonfigurasi hal-hal di luar urusan frontend di Next.js. Bukan cuma API, saya juga bisa membuat:

Apa berikutnya?

Belum tahu. Mungkin milis? Saya lebih suka berdiskusi via surel ketimbang Twitter karena bisa menulis lebih panjang. Yang jelas, ke depannya, blog ini akan saya isi dengan konten-konten sejenis (bahasan seputar improvisasi, bukan tutorial), atau hal-hal lainnya yang menurut saya cukup menarik untuk dibahas.

Akhir kata, merakit platform blog sendiri dari awal adalah kegiatan yang menantang dan menyenangkan. Jika ada hal-hal yang ingin kamu tanyakan atau sampaikan, sila gunakan formulir kontak. Jika ada hal-hal yang menurutmu bermanfaat dari tulisan ini, boleh bantu bagikan ke media sosial. Terima kasih!