Every row on this page has a project behind it.
This is not a list of skills. The right-hand column names where the technology runs today, so you can open it and check.
Languages & runtime
Most of it is JavaScript and TypeScript on Node.js. The rest follows the problem rather than preference — Laravel when multi-tenancy is the core of it, Kotlin when the code has to touch hardware.
- JavaScript · Node.js
- The widest use — Telegram bots, APIs, background services. e.g. the Kantinmu Midtrans sync, this site's Lab backend
- TypeScript
- For things meant to last and carrying many models. e.g. MUV, Imago, the thesis reviewer
- PHP · Laravel
- When multi-tenancy and access rules are the problem. e.g. Aksara, across 56 school hubs
- Python
- Data work, migrations, and long-running scripts. e.g. migrating Aksara's 44,909 items
- Dart · Flutter
- Android apps installed on a device. e.g. QR Scanner, QR Generator
- Kotlin (native plugins)
- When the web cannot reach the hardware. e.g. two Sepiring POS plugins — ESC/POS printing over Bluetooth, and native SQLite
Interface
Chosen from what the page has to carry, not from what is fashionable. Plenty of internal tools need no framework at all, and open faster for it.
- Next.js (App Router)
- Apps with authentication, many routes, and server data. e.g. MUV, Office, Imago
- React · Vite
- Single-page apps that are heavy on the client. e.g. PrintMe, Meero, Sepiring POS
- Plain HTML + JavaScript
- Internal tools that must open instantly and rarely change. This site included
- PWA (manifest + service worker)
- So it installs to the home screen and still opens on a poor connection
- Capacitor
- Wrapping a web interface into an Android app that can reach hardware
Databases & storage
Decided by the size of the problem, not by habit. An internal tool with one writer does not need Postgres, and a 56-branch system must not use SQLite.
- PostgreSQL
- For shared writers and complex relations. e.g. Aksara (11,212 bibliography records, 44,909 items), MUV (67-model schema), Sepiring POS
- SQLite · better-sqlite3
- Where it is genuinely single-writer. e.g. Dock, Uang Keluar, this site's Lab backend
- Prisma
- Recorded schema and migrations over PostgreSQL. e.g. MUV, the thesis reviewer
- Drift
- Local storage on an Android device. e.g. QR Scanner
- Google Sheets as an operational store
- When the team must still be able to open and edit the data themselves. e.g. SMM Merchandise Sales (8,367 transaction rows)
- IndexedDB
- Data that deliberately never leaves the browser. e.g. Notepad, Kanva
Integrations already connected
All of these run in production; none are experiments.
- Midtrans
- Payment links, pulling transaction status, and reconciliation. Used in Kantinmu and SMM Merchandise Sales — one audit found Rp198,381,500 that had never reached a report
- Google Sheets API
- Two-way read and write through a service account. e.g. merchsales, ProdForm, Role Dashboard, ReportFinder
- Google Docs API
- Generating documents from templates. e.g. the HR Job Profile Builder
- Telegram Bot API
- Four bots running — reporting, answering questions, and one that can change data
- AI models
- Anthropic, DeepSeek, and self-hosted Ollama — chosen per case on cost, quality, and where the data is allowed to live
- OCR (Tesseract)
- Reading scanned documents. e.g. an internal OCR service
- Web Speech API
- Speech recognition and synthesis in the browser. e.g. English Coach
- Bluetooth Classic · ESC/POS
- Printing to thermal hardware, verified on a physical device. e.g. Sepiring POS
- Cloudflare (DNS & Pages)
- DNS zones and static hosting. This domain included
Servers & operations
All of it runs on one VPS I operate myself — not a platform that can change its pricing overnight, and not a host I don't have root on.
- Reverse proxy & TLS
- Caddy, automatic certificates, separate config per project
- Application processes
- PM2 for Node services, Docker Compose where isolation is needed
- How services are exposed
- Bound to 127.0.0.1; containers mapped as 127.0.0.1:PORT. The only public door is Caddy on 80 and 443
- Releases
- Rebuild the image, rather than copying files into a running container
- Schema changes
- Recorded migration files, not pushing schema directly
- Backups
- Daily dumps to off-server storage, with rotation
- Backup verification
- The dump is restored into a separate temporary database and row counts compared against production until they match
- Monitoring
- An automated check calls every URL and records its response code — this site's portfolio reads that same result
The code, and what happens if I disappear
This gets asked up front least often, and matters most.
- Code ownership
- Agreed in writing at the start, not at the end
- Repository
- Can live in your own git organisation from the first commit
- Documentation
- README, architecture notes, and deploy steps written as part of the work
- Handover
- A session with your team, with enough written down to continue without me
If this arrangement ends, your team has to be able to carry on. If they can't, my work wasn't finished.
Where I am the wrong choice
This list exists so you don't discover it halfway through a project.
- 24/7 operational support with layered SLAs — I'm one person, and that can't be promised.
- Formal compliance certification, ISO audits, or regulatory work requiring an institutional process.
- Deep integration into large enterprise systems needing months of cross-vendor coordination.
- A large team working parallel tracks against the same deadline.
- Work requiring access to sensitive personal data at scale without a clear data-processing agreement.
If your need is on this list, you'll hear it in the first conversation. For some of them I can still help with the front half — shaping it, building the first version, then handing it to the team or vendor better suited to carry it.