release: banuacoder v1.0.0#1
Merged
Merged
Conversation
Sets up Astro 6 static site with @astrojs/mdx, @astrojs/sitemap, @tailwindcss/vite 4.2.4, i18n routing (id default, en fallback), and all required dependencies locked with pnpm.
Defines portfolio, services, blog, authors, testimonials, and pages collections with full Zod v4 schemas. Uses reference() for author and portfolio cross-references. Creates empty collection dirs with .gitkeep for git tracking.
Adds clients.ts (4 clients with tier classification) and founder-experience.ts (GoTo Financial, Reku, Stockbit/Bibit, Ulearna) as typed static data. Creates src/assets/clients/ and src/assets/companies/ dirs for SVG logo files.
Replaces Astro template README with project-specific docs covering stack, commands, git-flow branch model, and Beads issue tracking. Gitignore already includes package-lock.json, docs/, and .codegraph/.
- Replace placeholder lime accent with brand colors from official logo: primary deep blue (#12398C) and cyan accent (#1D9CD4) - Add neutral-first usage rule: ink/paper dominate, blues used as accent only - Drop logo lockup variants (horizontal, vertical, icon, swoosh, stamp) into src/assets/brand/ for use in nav, footer, favicon, and OG images
M1: Foundation — Astro 5 scaffold, i18n, content collections, design tokens. - Archive legacy Laravel codebase - Scaffold Astro 6 + Tailwind v4 + MDX with pnpm - Configure i18n routing (id default, en fallback) - Add Zod schemas for 6 content collections - Add base layout, design tokens, self-hosted fonts (Geist/Inter/JetBrains Mono) - Add static data stubs for clients and founder experience - Adopt official brand colors (#12398C primary, #1D9CD4 accent) - Drop logo assets into src/assets/brand/
Hand-coded BC monogram SVG from stamp reference — blue rounded-square background, white B letterform, cyan C letterform and bracket accent. Works at any scale; replaces Astro default favicon.svg.
Add spacing-section-y clamp, container-max, prose-max, radius scale, shadow-subtle/elevated tokens, duration-quick/base, and fluid fs-12 through fs-84 type scale. Add dark mode shadow overrides and prefers-reduced-motion global rule.
Add inline FOUC-prevention script (reads localStorage.theme before first paint), hreflang alternate links (id/en/x-default), theme-color meta for light/dark, OpenGraph basics, and head/body slots. Fix /en route conflict by removing src/pages/en/index.astro (let i18n fallback handle it). Add sitemap filter to exclude /dev/ pages.
Nav: sticky, scroll-blur, logo lockup, desktop links with cyan underline reveal, lang switcher, theme toggle, hamburger trigger. MobileDrawer: slide-in panel, focus trap, Esc/backdrop/link close, ARIA dialog. Footer: 3-col grid with brand, sitemap, socials. Container: max-w wrapper. Logo: horizontal/icon/vertical variants with inline SVG support.
SectionHeader: eyebrow // label, bracketed numeral marker, display title, optional description. Prose: 68ch max-width MDX wrapper with editorial rhythm, JetBrains Mono code blocks, pull quotes, cyan link underlines. MonoLabel: small uppercase mono eyebrow with // or > prefix variants.
Button: primary/secondary/ghost variants, md/lg sizes, renders <a> or <button>. Card: base primitive with subtle shadow, hover lift, padding variants. Tag: pill for bucket/tech labels with 4 color variants.
…rocess step) Hero: dot-grid backdrop, asymmetric layout, dual CTAs, media slot, cyan hairline divider. DotGridBackdrop: CSS radial-gradient with JS parallax respecting prefers-reduced-motion. TrustStrip: 4 mono micro-claims with hairline separators. CTA: default and inverted blue variant. ProcessStep: numbered vertical timeline with connector hairlines.
ServiceCard: icon + title (cyan underline on hover) + tagline + 3-bullet preview + learn-more link. CaseStudyCard: cover image with hover scale, bucket Tag, client/year meta, 2-line-clamped summary, impact stat, and data-bucket attribute for BucketFilter. Testimonial: pull-quote style with cyan opening quote mark, author/role/company, optional avatar.
FounderCard: compact (home) and full (/founder) variants with photo placeholder, name/role, headline, narrative, credibility bullets, selected experience, and social links. FounderExperienceStrip: keyboard-accessible tooltip row showing context for each employer from founder-experience.ts.
ClientLogoRow imports from clients.ts and renders each client as a grayscale-on-default, color-on-hover pill. Named-text fallback (mono uppercase company name) renders when SVG logo files are not yet available, so the component works pre-art-delivery.
…cket filter, device frame) LangSwitcher: navigates between /en/... and /... paths via Astro.currentLocale. ThemeToggle: sun/moon button, persists theme in localStorage. BucketFilter: segmented control filtering data-bucket elements with URL hash for shareable views. DeviceFrame: pure-CSS phone/tablet/desktop chrome with blurred NDA modifier. All use vanilla TS in Astro script tags.
Renders every component at /dev/components/ with realistic copy from the brief. Excluded from sitemap via filter. Noindex/nofollow robots meta in head slot. Theme toggle at top for side-by-side light/dark review.
Logo component now renders the official light variant by default and swaps to the white-on-transparent variants (PNG4 horizontal, PNG6 vertical) when html.dark is set. The inline SVG icon also adapts: in dark mode, the deep-blue plate becomes transparent and the B letter switches to paper for contrast.
Extract 6 per-variant SVGs from the 1080x1080 master artboard using viewBox-cropping: horizontal-light, horizontal-dark, vertical-light, vertical-dark, icon (currentColor B + cyan swoosh, no plate), app-icon (deep-blue rounded-square plate), and favicon. Background rects dropped for transparent-bg variants.
Replace hand-coded inline SVG paths with imports from the extracted src/assets/brand/svg/ files. Add 'app-icon' variant and 'theme' prop (auto/light/dark). Remove deprecated 'inline' prop. Update Nav and Footer to drop the removed inline prop usage.
Add @custom-variant dark to global.css so Tailwind v4 dark: utilities activate on html.dark class (JS toggle) instead of only responding to prefers-color-scheme media query. This fixes invisible headlines and icons when OS is dark but the page is force-toggled to light mode. Also update dev page logo labels and remove stale inline prop usage.
The previous SVG rewrite replaced all logo variants. Reverted: horizontal and vertical lockups go back to PNG-based theme swap (already correct and proven). Only the inline-icon path now uses the proper extracted SVG paths instead of the broken hand-coded ones. - Logo.astro: use PNGs for horizontal/vertical with theme swap, single PNG for icon, inline=true icon variant uses extracted SVG with currentColor for theme adaptation - Remove redundant horizontal/vertical SVG variants - Keep banuacoder-icon.svg (inline source), banuacoder-app-icon.svg, banuacoder-favicon.svg
The master SVG uses fill-rule:evenodd at the svg level, which my extracted variants did not preserve. Without it, the BC paths fill solid instead of rendering as the intended outlined letterforms with hollow counterforms — making the C in particular look broken at display sizes. Apply fill-rule="evenodd" to: - src/assets/brand/svg/banuacoder-icon.svg - src/assets/brand/svg/banuacoder-app-icon.svg - The inline icon SVG in Logo.astro
Previously the icon variant rendered as a static blue PNG in both light and dark mode — wrong in dark mode where the icon should be white-on-dark. Now the icon variant always inlines the extracted SVG and uses currentColor for the B+C letterforms, with a CSS variable swap: deep blue (--bnc-primary) in light mode, paper (--bnc-paper) in dark mode. The cyan swoosh stays cyan in both. Drop the unused inline prop and the iconPng import.
The previous design ran two independent cycle timers with an offset, which
meant the front phone could be showing PICO Sulteng while the back phone
was showing Carwa — visually pairing two unrelated apps in a single
moment of the hero.
Restructured to one shared cycle group:
- Both .hero-shot stacks tagged data-hero-cycle-group='hero-products'.
- animations.ts now advances every slot in the group on the same tick,
using a single global index. Each slot's slides are indexed mod its
own length so different slot sizes still stay in sync.
- Each product now has a paired (front, back) screenshot:
PICO Sulteng : front=dashboard, back=peta sebaran
Sikerja : front=jobs list, back=filter pencarian
SIAP Donggala : front=home dashboard, back=profil pegawai
Detexi : front=detail rujukan, back=verifikasi token
- Removed the data-hero-cycle-offset attribute and the legacy
data-hero-cycle hook.
Result: at every tick both phones reference the same product, so the
hero reads as a coherent product spotlight rather than a random slot
machine.
When the cycle attribute was renamed to data-hero-cycle-group for the synced front+back grouping, the CSS rules that absolute-position the non-first slides on top of each other still referenced the old data-hero-cycle attribute. As a result every slide rendered in normal flow and all 4 phone screenshots stacked vertically below the visible phone — the chip label changed but the image never did. Updated both index.astro and en/index.astro selectors to [data-hero-cycle-group] so the stack collapses to one visible image again and the auto-cycle crossfade works.
…E Komdigi badge Hero carousel now cycles through 5 Banua Coder products: PICO Sulteng → Sikerja → SIAP Donggala → Detexi → Carwa The two phones still pair the same product on every tick. Sikerja pair updated per owner request: - Front: Beranda (home dashboard with hero carousel + service icons + Berita Pemprov cards) — sourced from ~/Pictures/Sikerja - Back: Lowongan list (jobs feed with search + popular + available) Carwa added back into the hero rotation: - Front: clean CarWa home/auction screen (mild design annotations remain — these are screenshots from design review handoff, but the only available shots; visible CarWa branding makes the product identifiable). - Back: 'Auctions Ending Today' featured-cards screen. - Sourced from ~/Pictures/Carwa (Pictures/Carwa/SCR-20241015-lvzl-4 + lvzl-5). Footer: added Komdigi PSE registration badge: - Site-wide footer now carries a centered badge linking to https://pse.komdigi.go.id/pse with the Komdigi logo (downloaded to /public/badges/komdigi.png) + the registration number 015494.01/DJAI.PSE/09/2024 (mirrors the badge already used on the Ayana Web product, which is registered under the same entity).
…only behind text or near edge
Previous tuning had the fade-blur tween running for 0.22 of timeline
on entrance AND exit. Cell lifespan was 0.26, so the logo was
blurry for 84% of its life and clear for only ~0.04 in between —
in practice the blur dominated.
Two adjustments:
1. Blur is split into two CSS variables stacked additively:
--cell-fade-blur (timeline-driven entrance/exit dolly blur)
--cell-overlap-blur (ticker-driven extra blur ONLY while the
logo's centre sits inside the headline rect,
1px margin per spec)
CSS:
filter: blur(calc(fade-blur + overlap-blur))
grayscale(fade-gray)
So a logo can be sharp during travel AND auto-blur the moment it
passes behind the centred 'Klien dan partner kami' text.
2. Shortened the entrance/exit fade-blur duration from 0.22 → 0.08
(and matching position drift exit-padding from +0.22 → +0.08).
Now: 0–8% lifespan = fade in, 8–92% = clear cruising, 92–100%
= fade out. Logos read clean for most of their on-screen time and
only blur when (a) approaching a viewport edge or (b) overlapping
the headline.
Down from 16 slots (with caretaker, bps, ulearna, pemprov-sulteng, klinikgo, detexi appearing twice) to 10 slots — one per unique brand. Stagger widened from 0.04 to 0.07 so all 10 logos get clear airtime across the scrubbed timeline (last logo enters at 0.63, exits 0.89). Order: Ulearna → Pemprov Sulteng → Caretaker → BPS → Pemkab Gowa → Detexi → KlinikGo → Pemkab Donggala → Brantas Inti Utama → Pemprov Sulsel
… cycle to repeating pattern - ClientLogoCycle: restored 16-slot repeating pattern per owner request (caretaker, bps, ulearna, pemprov-sulteng, klinikgo, detexi each appear twice). Duplicates will be swapped for new logos as more partner brands are added. - Services preview: 2 cards now slide in from opposite sides with a 3D rotation-Y depth tilt — Build & Engineer drifts in from the left tilted away (-25deg), Brand & Grow from the right (+25deg). Triggered at 'top 82%' on the grid, once. - Public Sector module: bullets cascade from the left with 0.08s stagger, plus each arrow span pops in via back.out scale + rotation so the list reads as proof points being checked off in sequence. - Wired data attrs in both id + en home pages: data-tell-services / data-tell-services-card, data-tell-public-bullets / data-tell-public-bullet.
Splits the featured testimonial quote into individual word-spans (via createElement to avoid innerHTML), then fades each word up with y:14 → y:0 + opacity 0 → 1 on a 0.025s stagger. After the words finish, the figcaption (author + company line) eases up with its own tween. Reads as the quote being spoken rather than dumped in as a block of text. Markup-side: data-tell-testimonial on the wrapper section in both id + en home pages.
…nce strip, final CTA About: - The "founded 2019 / based in Sulteng" mono decoration card now has its own entrance distinct from the surrounding section reveal — slides in from x:60 with a slight scale-up, easing on power3.out. Founder strip: - The horizontal row of past-employer logos (GoTo Financial, Reku, Stockbit/Bibit, Ulearna) cascades in with y:20 + scale 0.9 + back.out pop, 0.07s stagger. Reads as the credentials being laid out one by one rather than dumped together. Final CTA: - Headline scales up from 0.92 + y:20 with power3.out for a punchy arrival. - Sub line eases up 0.2s after. - Buttons stagger in at 0.35s with back.out overshoot — the call to action visibly assembles itself as the user scrolls in. Wired data attrs in: src/components/sections/CTA.astro (data-tell-cta, data-tell-cta-headline, data-tell-cta-sub, data-tell-cta-actions), and id + en home pages (data-tell-about-decor, data-tell-founder-experience).
…e reduction)
Loading screen:
- Inline overlay in BaseLayout.astro renders before any external CSS
loads. Shows the BC monogram pulsing + a brand-colour shimmer bar.
- Inline JS hides it on window.load (with a 4s safety cap), then
removes it from DOM so it can't trap focus.
- Light/dark backgrounds keyed off :root.dark.
- Reduced-motion: stops both keyframes.
Image optimization:
Source PNG → WebP (q 82 -m 6), originals removed:
sikerja/screenshots: 4.2M → 624K (-85%)
detexi/screenshots: 2.0M → 464K (-77%)
siap-donggala/screenshots: 5.1M → 236K (-95%)
carwa/screenshots (clean-{1,2}): 3.0M → 592K (-80%)
founder/work-product (Reku 1–6): 4.9M → 756K (-85%)
Total: 19.2M → 2.7M sources committed (~16.5MB cut from repo).
Updated all imports/.png→.webp in:
- index.astro / en/index.astro (hero stack)
- founder.astro / en/founder.astro (Reku marquee + BC product mix)
- portfolio/{sikerja,detexi,siap-donggala}/index.{id,en}.mdx (gallery)
Astro's <Image> still re-encodes downstream variants for responsive
sizes, but smaller sources mean faster cold builds AND faster dev
serving (which streams the source as-is for unoptimised paths).
…ideos
New portfolio entry showcasing Banua Coder's Flutter performance
engagement on Masjid Sejuta Pemuda — a Muslim youth community consumer
app inherited from a previous "vibecoded" contractor.
Narrative across 4 acts of the case study:
1. Diagnosis with Performance Overlay + Rebuild Rainbow — 62.8ms max
frame time, whole-tree rebuild every second.
2. Iteration 1: const audit fixes jank but rebuild scope unchanged.
3. Iteration 2: encapsulate sections — narrows rebuild but countdown
still spreads to siblings.
4. Iteration 3: custom text-rotator + countdown widgets from scratch
with isolated state — final state shows only the countdown digit
rebuilding, frame time ~16ms.
Videos:
- 5 source .mov clips (~82MB) compressed via ffmpeg to web mp4
(libx264, crf 26, scaled to 540px, audio stripped). Total now ~2.4MB.
- Posters generated as first-frame jpg.
- Stored in /public/portfolio/msp/ for direct static URL serving.
- Embedded in MDX via raw <video> tags with controls + muted +
playsinline + preload=metadata.
Other:
- Added MSP to src/data/clients.ts (no logo file yet — text-only entry,
tier standard).
- bucket: consumer, year: 2025, featured: true.
Story arc reads as engineering process documentation (audit -> diagnose
-> iterate -> prove with same tooling) rather than 'we made it faster'
marketing copy.
…o/msp Previous commit landed video assets at src/content/portfolio/msp-performance-audit/videos/public/portfolio/msp/ because the shell pwd had drifted into that nested folder during the ffmpeg + mv pipeline. The MDX <video src="/portfolio/msp/..."> tags expect them at public/portfolio/msp/. Renamed all 10 files (5 mp4 + 5 poster jpg) to the right location.
Root causes: 1. <MobileDrawer /> component was never rendered anywhere — the hamburger button in Nav.astro had aria-controls="mobile-drawer" pointing at an element that didn't exist in the DOM. Adding the drawer right under Nav so the hamburger has something to open. 2. The drawer sits at right:0 with translate-x-full to hide off-screen right. Without overflow-x containment on body, that translate pushed document width 273px past the viewport edge — visible as a horizontal scroll on mobile (375px viewport, 456px doc width). Added overflow-x: clip on html, body in global.css base layer. `clip` (vs hidden) keeps fixed-position descendants painting correctly while still containing layout. Verified via Playwright at 375x812: - doc width = win width = 375px (was 456 → 375) - hamburger click: drawer slides in (left 102, right 375), backdrop opacity 1, body overflow hidden, aria-expanded=true.
Loading screen + favicon: - BaseLayout page-loader now renders the canonical Banua Coder icon SVG (cyan swoosh + B + C silhouette) instead of the hand-crafted monogram. - Bumped size from 64 → 72px and added a dark-mode override that swaps the body letterform fill from #12398C to #f7f7f4 so it's still readable on the ink background. - Favicon was already pointing at the canonical brand SVG (no change needed there — verified cmp identical to src/assets/brand/svg/ banuacoder-favicon.svg). Indonesian copywriting pass — main pain point was tech jargon mixed into copy aimed at general business owners and government decision-makers. Fixed: home.id.mdx - 'Engineering-led delivery' → 'Dibangun dengan disiplin engineering' / 'dikerjakan dengan standar engineering' (used as plain Indonesian rather than English jargon). - 'product thinking, engineering discipline, MVP' tech tower in About rewritten as plain Indonesian. - Services taglines: 'membership experience' → 'sistem keanggotaan'; 'attendance system / approval workflow / admin panel' → Indonesian equivalents on the deliverables list; 'discovery / MVP / modernization / maintenance' likewise. - Why-tiles: 'Eksekusi berbasis engineering' → 'Dibangun untuk bertahan lama'; 'Delivery yang low-risk' → 'Proses jelas, risiko terkendali'. - Process steps fully renamed to Indonesian (Pemetaan Awal, Penyusunan Solusi, Desain & Validasi, Pengerjaan, Pengujian & Peluncuran, Pendampingan & Pengembangan) — was a mix of English headers + ID bodies. - Founder narrative: 'platform engineering / engineering depth / product thinking' replaced with plain Indonesian descriptions. - 'Discovery Call' CTA → 'Diskusi Pemetaan'. - 'consumer-facing / case study / vendor eksekusi' fragments cleaned up. Founder page (id + en) prior-work section: - 'UI yang sudah kami kirim' → 'Karya terpilih' (the specific phrase the owner flagged as awkward). - 'UI we've shipped' → 'Selected work' on /en/founder/. Build green: 73 pages.
Two related issues stacked on top of each other: 1. The mobile media query was hiding .hero-shot-back via display:none (and the hero-chip with it), so phone users only saw a single phone. 2. The same media query tried to centre the lone front phone with `transform: translateX(50%)`, but the GSAP parallax tween on .hero-shot writes its own transform on every scroll tick, clobbering the centring rule. Net effect: a single phone parked left-of-centre. Fix: - Mobile CSS now keeps both phones visible — front 220px wide pinned to the right (right: 4%, top: 12px), back 150px wide tucked left (left: -4%, top: 60px). Chip label stays at bottom-left. Stage grew to 360x420 to fit both. Desktop tilts (-2deg / -9deg) inherit through. - Hero parallax scrub in animations.ts is now gated to viewports ≥641px so it can't fight the small-screen layout. Mobile readers get a static dual-phone composition; desktop keeps the parallax. Verified on a 375x812 viewport: front phone (SIAP Donggala home) is right-aligned, back phone (profile screen) is offset to the left, both visible at once, chip label '// SIAP Donggala' renders below.
Pinned client-logo cycle, hero auto-carousel, scroll storytelling across sections, founder UI marquee, MSP performance audit case study, mobile fixes, copy audit, page loader, image/video optimisation.
- BaseLayout: re-apply theme to incoming <html> on astro:before-swap - ThemeToggle: delegate click on document so listener survives swaps
…e doesn't shift logos
- deploy.yml: trigger on tag v*.*.* push (was: branches: main) - release-prepare.yml: open release PR + bump package.json + grouped changelog - release-finalize.yml: tag + CHANGELOG.md + GitHub Release + back-merge PR
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Release: banuacoder v1.0.0
Changelog
✨ Features
🐛 Bug Fixes
⚡ Performance
♻️ Refactor
📝 Docs
👷 CI
🧹 Chore
💄 Style
📌 Other
When merged,
release-finalize.ymlwill:v1.0.0and trigger deployCHANGELOG.mdonmaindevelopChecklist