@atourin/ds
v0.3.0
Published
Design system Atourin lintas framework: token desain, CSS chrome (navbar & footer), data tautan, dan ikon. Dipakai bersama oleh marketplace-v3 (Nuxt) dan directory-app (Next).
Readme
@atourin/ds
Design system Atourin yang dipakai bersama dua app beda framework — token desain plus chrome (istilah UI untuk bingkai halaman: navbar & footer).
Namanya ds, bukan chrome, karena tokens.css di sini bukan milik
navbar/footer saja melainkan seluruh sistem; dan bukan atr, karena atr
sudah dipakai sebagai nama schema Supabase bersama.
| App | Framework | Peran |
| --- | --- | --- |
| marketplace-v3 | Nuxt 4 / Vue 3 | pemilik domain, melayani semua path kecuali /explore/** |
| directory-app | Next 16 / React 19 | melayani /explore/** lewat reverse-proxy Nitro |
Status: footer + navbar. Footer sejak 0.1.0, navbar sejak 0.3.0.
Kenapa bukan satu komponen
Komponen Vue dan komponen React tidak bisa berbagi kode render. Yang bisa dibagi lintas framework cuma tiga hal, dan ketiganya itu justru yang menentukan "tampilannya sama":
| Berkas | Isi | Menjamin |
| --- | --- | --- |
| tokens.css | variabel --atr-* | warna, font, radius, bayangan identik |
| container.css | .atr-container + --atr-canvas-* | lebar kanvas & padding tepi identik |
| footer.css | kelas .atr-footer__* | tata letak, jarak, hover, breakpoint identik |
| nav.css | kelas .atr-nav__*, .atr-util__*, .atr-usermenu__*, .atr-drawer__* | navbar, baris utilitas, dropdown profil, drawer mobile identik |
| data.js | daftar tautan + teks ID/EN | isi & wording identik |
| icons.js | markup SVG sebagai string | ikon identik |
Yang tetap ditulis dua kali cuma ±40 baris markup di tiap app — dan markup tidak menentukan tampilan, CSS yang menentukan.
Sumber kebenaran
Berkas di sini turunan, bukan asli. Kalau desain berubah, ubah dulu di folder handoff (READ-ONLY), baru selaraskan ke sini:
- token →
Website & App Revamp Desain System/design-system/atr-tokens.css - kanvas →
Website & App Revamp Desain System/*.jsx(maxWidth: 1376+ padding 32px, 74 pemakaian) - footer →
Website & App Revamp Desain System/site-chrome.jsx(fungsiSiteFooter) - navbar →
Website & App Revamp Desain System/site-chrome.jsx(UtilityBar+TopNav)
Satu penyimpangan sengaja dari handoff: prototipe memberi footer kanvas
sendiri (maxWidth: 1280 + padding 40px) sehingga tepinya tidak segaris
dengan section mana pun. Di sini footer ikut --atr-canvas-* yang sama
dengan .atr-container. Alasan lengkapnya ada di kepala footer.css.
Pemakaian
Muat CSS sekali di level app, sebelum CSS app sendiri.
Nuxt (nuxt.config.ts):
css: [
"@atourin/ds/tokens.css",
"@atourin/ds/container.css",
"@atourin/ds/nav.css",
"@atourin/ds/footer.css",
"~/assets/css/main.css",
],Next (src/app/layout.tsx):
import "@atourin/ds/tokens.css";
import "@atourin/ds/container.css";
import "@atourin/ds/nav.css";
import "@atourin/ds/footer.css";
import "./globals.css";Lalu pakai datanya:
import { FOOTER_COLUMNS, pickLabel, isExternal } from "@atourin/ds/data";
import { ICONS } from "@atourin/ds/icons";Struktur markup yang harus diikuti kedua app ada di komponen masing-masing:
| Chrome | Nuxt | Next |
| --- | --- | --- |
| footer | marketplace-v3/app/components/Section/SectionFooter.vue | directory-app/src/components/layout/SiteFooter.tsx |
| navbar | marketplace-v3/app/components/Nav/NavBar.vue | directory-app/src/components/layout/TopNav.tsx |
Keduanya sengaja dibuat sejajar baris per baris supaya gampang dibandingkan.
Navbar
Sama seperti footer: kelasnya di sini, markup-nya di tiap app. Bedanya navbar punya bagian yang tidak bisa dibagi karena penuh state.
| Milik package | Milik app |
| --- | --- |
| kelas .atr-nav__*, .atr-util__*, .atr-usermenu__*, .atr-drawer__* | posisi (fixed / sticky) |
| daftar menu, tautan utilitas, isi dropdown profil (data.js) | komponen pencarian |
| ikon (icons.js) | sumber status login & aksi logout |
| isActiveNav() — penanda entri aktif | jumlah notifikasi |
| | maskot AI & logo (aset) |
position sengaja tidak diatur package. marketplace-v3 memakai fixed
dan mengukur tingginya lewat ResizeObserver ke --navbar-height; 16 berkas
lain memakai nilai itu untuk offset konten, sticky, dan scroll-spy. Memaksakan
satu nilai dari sini akan menggeser halaman yang tidak ikut digarap. Tingginya
tetap sama di dua app karena isinya sama.
Penanda aktif dihitung dari path, bukan dari nama tab yang dioper manual:
import { NAV_ITEMS, isActiveNav } from "@atourin/ds/data";
NAV_ITEMS.map((item) => ({ ...item, active: isActiveNav(item, route.path) }));match mencocokkan path persis atau anaknya — /product cocok untuk
/product/event, tidak untuk /products. Awalan locale /en dibuang dulu.
Maskot AI tidak ikut package. NAV_AI cuma memberi href; gambarnya milik
app (marketplace dari CMS main_navigation, directory dari
/assets/atr/assistant.png). Kalau entri CMS-nya diganti, navbar dua app
langsung beda di titik itu — periksa saat QA.
Penyimpangan sengaja dari prototipe: baris navbar di sana maxWidth: 1440
sementara baris utilitas 1376 dan footer 1280. Di sini semuanya ikut
--atr-canvas-*. Alasannya sama dengan footer — lihat kepala nav.css.
Aturan href
Kedua app tampil di satu domain. Marketplace melayani semuanya kecuali
/explore/** yang di-proxy ke directory-app (directoryProxyPaths di
marketplace-v3/nuxt.config.ts). Jadi:
/explore/*→ halaman directory-app- path lain → harus ada di
marketplace-v3/app/pages
Halaman directory-app di luar /explore (/market/*, /sdgs, /arti,
/career, /promo, /profile/*) tidak bisa dibuka pengunjung. Jangan
ditaut dari footer.
Distribusi
Diterbitkan ke npm registry publik dengan scope @atourin.
Registry dipilih, bukan dependensi URL git, karena para consumer tersebar di
dua host: marketplace-v3/mapi di GitLab atourin-platform,
directory-app/ai-assistant-app/gateway-app/partner-app di GitHub
tech-atourin. Dependensi git memaksa tiap consumer punya kredensial host
tempat paket ini tinggal — termasuk di Vercel. Registry netral terhadap host.
license: "UNLICENSED" disengaja: paket boleh dipasang siapa saja, tapi tidak
ada pemberian hak untuk memakai ulang isinya.
Memasang di project baru
pnpm add @atourin/ds # atau: npm i @atourin/ds (directory-app pakai npm)Tidak perlu token, .npmrc, atau setelan tambahan di Vercel.
Menerbitkan versi baru
npm login # sekali saja, akun yang memiliki scope @atourin
npm version patch # atau minor / major — menaikkan versi + bikin tag git
npm publish # publishConfig.access sudah "public"
git push --follow-tagsLalu naikkan versinya di consumer (pnpm up @atourin/ds / npm up @atourin/ds).
Patuhi semver. Consumer memakai rentang ^, jadi rilis patch/minor
masuk ke produksi dua app tanpa PR di repo mana pun:
| Perubahan | Naikkan |
| --- | --- |
| perbaikan nilai CSS, typo teks | patch |
| tambah tautan, kelas, atau ikon baru | minor |
| ganti/hapus nama kelas, ubah bentuk data, hapus export | major |
Ganti nama kelas atau bentuk data selalu major — markup di kedua app
mengacu ke nama itu, dan tidak ada compiler yang akan menangkapnya.
Pengembangan lokal
Selama menggarap package dan app bersamaan, arahkan sementara ke folder lokal:
pnpm link ../atourin-ds # marketplace-v3
npm link ../atourin-ds # directory-appJangan commit perubahan package.json hasil link — kembalikan ke versi
registry sebelum push.
