Chairul Akmal
Software Engineer
mail@chairulakmal.comMobile (JP)Tokyo, JPAvailable immediatelyLinkedInGitHubSummary
Full-stack TypeScript engineer in Tokyo. Software engineer at Blossom Finance, a US fintech, then JavaScript instructor at Hacktiv8. Building and deploying independently since September 2025: Next.js and Nuxt in front, Rails or Node.js behind, bilingual EN/JA interfaces that stay reachable by keyboard and screen reader. Nuxt and Ghost.org contributor, Tohoku University graduate.
Portfolio
A job tracker for people who apply to many companies at once. Each application is one card, and the card moves from applied to interview to offer. Next.js 16 front end, Rails 8 API. The board asks the API which moves are legal instead of keeping its own copy of the rules, so a plain Ruby module on the server is the only place they live. When two devices edit one card, optimistic locking returns 409 Conflict: the drag snaps back with a message, and a per-card menu offers the same moves to a keyboard or a screen reader. The JWT never reaches the browser, because a route handler keeps it in an httpOnly cookie and every API call runs on the server. Installs on a phone as a web app, with an Android share target and Web Push. Japanese wraps at 文節 boundaries rather than mid-word, through word-break: auto-phrase where the browser supports it and BudouX on the server where it does not. CI fails the build on a hardcoded state name or a missing English or Japanese key.
A study app for the JLPT, the Japanese language exam. It schedules each word for the day the learner is about to forget it, using the FSRS spaced-repetition algorithm, and all four study modes read that one queue. The corpus is 8,000+ words and 200+ grammar patterns. Example sentences are generated once by Claude Haiku and cached in Postgres, so no request reaches an AI model while a learner studies. The interface holds a WCAG AA accessibility floor: ARIA live regions announce each answer, focus moves on every session change, and one shared hook routes the keyboard shortcuts. The 90 KB word list is a cached client fetch, not a React Server Components payload repeated on every visit.
A support desk shared by several client companies. Customers file tickets, staff answer them, and no company can see another company's data. Next.js 16 Server Actions do the work, so there is no separate API layer. Ticket status is a state machine with a minimum role on every edge, and each transition writes the ticket update and its audit row in one Prisma transaction, so a ticket cannot change state without a recorded reason. The service layer applies the per-company filter on every query, and that same filter is why a customer never sees an internal comment. Status controls update the screen at once with useOptimistic and roll back when the action fails. Ticket lists paginate by cursor: a server component renders page one, then the client appends. Attachments compress to WebP in a canvas before upload, and the code probes encoder support first because Safari falls back to PNG without saying so. 234 Vitest tests and a Playwright suite covering five roles.
Experience
Built and shipped the three apps above, front end and back end. On the server that means schema design, authentication, background jobs and Playwright tests. In the browser, it means an accessible interface in both English and Japanese, delivered as an installable web app. Passed JLPT N3.
Studied Japanese full-time on a planned career break and passed JLPT N4. Moved to Tokyo in Aug 2025.
Designed and shipped a collaborative publishing platform in TypeScript. Writers work in markdown, and ownership of each piece is recorded on Base, an Ethereum layer-2 network. Next.js, NestJS, Wagmi.
Taught the full-stack JavaScript curriculum (React, Vue, Node.js, PostgreSQL, MongoDB, Docker) to several cohorts of junior developers. Mentored students one-on-one and ran live code reviews. Marked capstone projects on architecture, testing and delivery.
Wrote the developer onboarding documentation for Penumbra, a shielded cryptocurrency built on zero-knowledge proofs. The guides take an outside contributor from nothing to a running node and a working wallet API call. Set the content structure and the style rules for the developer portal. Drafted the community guidelines and the moderation policy for the technical Discord. Short-term contract.
Built the user onboarding, survey and feedback flows in full-stack JavaScript for the Blossom Microsukuk™ investment platform, then set up its Docker and GitHub Actions CI/CD pipelines. Worked through pull request review on a regulated, remote-first fintech team.
Education
Certifications and Competitions
Built an AI agent that decides how a user can pay for a purchase, across 250 requests.
Technical Skills
Languages
Open Source
A desktop viewer for agent plans and just-cloned READMEs, written in Rust. It re-renders on save and keeps scroll position, with no server and no port. Raw HTML is escaped rather than executed, and property tests push thousands of generated inputs through the escaper to prove it. Published on crates.io and the Snap Store, with a .deb and a tarball per release.
- PR #17831: removed the Bluebird dependency and refactored to native JS Promises.
- Issue #17627: fixed Nodemailer delivery from IPv6-only hosts.