HR platform for Indonesia's largest labor supply company — attendance, overtime, leave, and payslip for field workers nationwide.
PT PKSS (Prima Karya Sarana Sejahtera) is a labor supply company under BRI Group, managing thousands of outsourced workers across Indonesia. Before this platform, their entire HR operation — attendance, overtime, leave, payroll integration — ran on spreadsheets, WhatsApp messages, and a third-party app they didn't own. The goal: build a system they fully controlled, that could grow with them. What started as a 3-month mobile app became a 3-year product — rebuilt, scaled, and automated across three major versions.
PKSS had 50,000+ outsourced field workers across Indonesia already using GreatDay to manage attendance, overtime, and time off. The platform worked but PKSS didn't own it. Every feature was a subscription, every data point lived in someone else's system. The goal of Prima Super App wasn't to digitize a manual process. It was to replace a dependency, build an in-house HR platform so PKSS could stop subscribing to GreatDay and take full ownership of their workforce data. Starting with an initial rollout of 10,000 workers.
Two things directly affected payroll accuracy and both were broken:
Indonesian labor law defines overtime into categories — LB1, LB2, LL1, LL2 & LL3 — each with different pay multipliers depending on the day type. Manual calculation meant different results depending on who did the math.
A failed clock-in meant missing pay. Their previous app (GreatDay) handled this, so it was a non-negotiable expectation coming in.
The initial design was logical: workers select their overtime category (LB1, LB2, LL1, LL2 & LL3) when submitting a request. The categories are defined by law, the client understood them, and the design was approved.
Then we hit UAT. Field workers didn't know what LB or LL meant. They knew they worked late on a Tuesday. They knew it was a national holiday. But mapping lived experience to a labor law category before submitting a form was friction that served the system, not the person using it. A change request came in: this isn't working.
Flip the input model from category-first to time-first.
Rather than asking workers to understand labor law, the new form asks three things: start time, end time, and day type (Workday / Weekend / National Holiday). The system calculates the correct LB/LL category automatically. The worker never sees the categories but the admin still gets exactly the same structured output they always needed.
Same output. Simpler input. The client approved the first version because it made systemic sense. Field workers showed us it didn't work in practice. That gap between logically correct and actually usable is exactly the problem design is supposed to catch.
Workers who missed a clock-in needed a correction flow. The obvious risk: an open correction feature becomes a fraud vector — workers claiming presence they didn't have.
The instinct was to solve this inside the system: GPS verification, photo evidence, manager confirmation in-app. But building a verification layer without the right data infrastructure would have bloated V1's scope and pushed the deadline.
Keep the app purely administrative. Let the human relationship handle verification.
The app doesn't verify whether the absence was legitimate. That trust layer lives in the supervisor-worker relationship, which already existed. The app just makes the agreement official. This kept scope tight, matched how PKSS supervisors already operated, and created accountability without adding complexity the team wasn't ready to support.
Delivered across iOS and Android in 3 months, for 10,000 field workers. PKSS was proud of what shipped, despite a tight timeline with piloting, go-live, and maintenance still ahead, they had built their first in-house HR tool and were confident it could fully replace GreatDay. The late-stage overtime redesign added time, but it shipped a product field workers could actually use. And the architecture built here — approval flows, role hierarchy, data structure — became the exact foundation V2 would expand into a platform serving multiple companies.
















Stakeholder approval isn't user validation. The overtime input was approved, built, and delivered before field workers showed it didn't work. Approval reflects intent — usability reflects reality. Both need to be tested.
Scope discipline is a design decision. The attendance correction could have become a complex verification system. Keeping it administrative wasn't a compromise — it was the right call for where the product was at. Knowing when not to add complexity is as important as knowing how to solve it.
Design for the mental model, not the data model. LB1 and LB2 made sense to the system. Field workers think in hours and day types. The gap between those two is exactly where design adds value.
V1 proved the concept. PKSS had their HR system across mobile and web, and it worked. The next ask changed everything: make it available to their client companies, each with their own branding, their own org structure, and their own workers. One requirement "white label" became the foundation for a complete rethink of how the platform was built. Both platforms grew as a direct result. New modules emerged from client needs. The login screen itself changed. By the end of V2: 17 mobile menus, 19 web menus — up from 13 and 14 in V1.
Making one app work for one company is a solved problem. Making it work for many companies each with different org structures, different approval chains, different branding is an architecture problem that surfaces as a UX problem. The key challenges V2 introduced:
Each company has its own structure: branches, clients, work units. That needs to be configured before anyone can use the app.
An approval chain that works for a 3-layer hierarchy breaks for one with 6 layers.
Some workers have fixed shifts. Others have schedules that change week to week.
The first challenge of white label wasn't branding — it was onboarding. Before a company could use the platform, someone needed to configure their entire org structure: company, branches, clients, office branches, work units, and finally workers. Six layers. Wrong order meant broken data relationships across the entire system. The initial instinct was a single long form. The problem: admins don't think in data hierarchy. They think in "my company has branches, and each branch has clients."
Container-first: create the shell before filling the details.
Branch and client sit at the same level, not nested inside each other. This was a deliberate decision: one client can serve multiple branches without duplicating data. Putting client inside branch would have meant creating the same client record repeatedly for every branch that works with it. The hierarchy enforces itself through the UI — you can't add an office branch without a branch, you can't add a work unit without an office branch. Data relationships are always correct by the time setup is complete.
Once the org structure existed as structured data, it became something that could do more than just organize permissions. The first thing it unlocked: automatic org chart generation. The same data admins input during setup renders as a visual hierarchy. No extra work — the org chart is a live read-out of the structure that already exists.
The second and more complex implication was rethinking approval logic. In V1, approval was simple: one approver, one decision. In V2, org structure meant multiple approvers in a chain. The question: if an overtime request goes to 3 approvers, what does "approved" mean? The first answer was OR logic — any one approver can approve. Simple, but it let a manager approve something their director hadn't seen.
Switch to AND logic: every approver in the chain must approve.
AND logic introduced a state that didn't exist before: "Diterima Sebagian" (Partially Approved). A request where some approvers said yes but others hadn't — or said no — lives in a visible middle state. Workers see exactly where in the chain their request is sitting, not just "pending."




This made the system honest. Instead of a black-box "pending," workers see progress. Instead of one approval being enough, the full chain is respected regardless of how many layers a company has.
V2 introduced work scheduling. Not all workers have the same kind of schedule and that difference required two entirely different design approaches. Shift Tetap (Fixed Shift): a permanent, recurring schedule — admin sets it once and it applies going forward. Shift Outsourcing (Variable Shift): a schedule that changes — different shifts on different dates depending on deployment. Admin uploads an Excel file, one row per worker per date, and the system processes it.
Different input models for fundamentally different work patterns.


Beyond setup, the shifts had a direct UX consequence: the attendance button became shift-aware. In V1, this already worked but only because all workers had fixed shifts. The system always knew their schedule, so the home screen could reflect the right state automatically: clock in before shift, clock out after, done for the day.

V2 introduced a problem. Shift Outsourcing requires admins to upload schedules — but during early rollout and implementation, not all workers had schedules assigned yet. A strict shift-gated system would have blocked them from clocking in entirely.
If a worker has no assigned schedule, let them self-select their shift instead of blocking them.


When a worker has no scheduled shift for the day, the app surfaces a shift selection screen showing all available shifts in their work unit. The worker picks the one that matches their actual hours, then proceeds to clock in normally. This kept the system honest: workers with assigned schedules clock in within their shift window automatically. Workers without a schedule still clock in — they just manually confirm which shift they're on. No one gets blocked because an admin hasn't uploaded their schedule yet.
V1 established the time-based input model. V2 improved how overtime moved through the system after submission. Before: overtime requests were batched and reviewed monthly. A request submitted on the 3rd might not be approved until month-end. After: daily approval. Each request is reviewed as it's submitted. Admins can also proactively assign overtime to workers, not just receive submissions. Two additional guardrails: no back-date — overtime can't be submitted for a date that's already passed — and admin-assigned overtime, for planned overtime, admins create a pre-approved record before the shift.
Workers Flow



Admin Flow



This was refinement, not redesign. The input model from V1 stayed. The approval cycle became faster and more accountable — shaped by how the V1 system was actually being used.
With multiple companies and a 6-layer hierarchy, every table in the platform had to answer: whose data should this person see? A Super Admin sees everything. A branch manager sees their branch. A client admin sees only their client's work units. Same data, different lens.
Auto-scope filters to the user's access level. Don't start at the top.

Rather than showing the full hierarchy and hiding what's irrelevant, filters default to the user's own access level. A branch manager opens an attendance report and immediately sees their branch — no extra filtering needed. The pattern was applied consistently across all 19 web menus, so the experience of "what I see = what I'm responsible for" felt natural throughout.
V2 transformed a single-company HR tool into a multi-tenant platform. The Admin Maker gave PKSS's clients the ability to self-onboard their org structure without IT support. The org chart became a bonus deliverable — not in the original scope, but immediately valued by clients. AND approval logic gave workers visibility into where their requests actually stood. The platform was now ready to serve not just PKSS's own operations, but their entire client network — each under their own branding, each with their own structure, all running on the same foundation.


















Data architecture is a UX problem. The multi-tenant setup wasn't just a backend task — how admins configured their org structure affected every feature downstream. Getting the setup flow right meant getting everything else right.
Clean data models generate features for free. The org chart wasn't in the original scope. It emerged because the structure data was already there. When the underlying model is solid, features cost almost nothing to add.
The correct answer isn't always the simpler one. OR approval logic is easier to build and easier to explain. AND approval logic is what actual approval chains require. Designing for correctness meant adding complexity — and a new UI state — that the simpler version didn't need.
Three years of running the platform. 53,000 users across multiple companies. By V3, PKSS didn't need more features, they needed the platform to close the gaps that field use had exposed. Two pain points remained: finding the right replacement worker fast when someone was absent, and workers having no way to record their actual attendance during overtime hours.
Two operational gaps remained after V1 and V2.
When a worker was absent, the RO (field supervisor) had to search for a replacement themselves — checking who was qualified, who was available, who hadn't exceeded their deployment limit. No system supported this. It all happened over phone calls.
Overtime requests existed, but there was no clock-in/clock-out specifically for overtime hours. Workers were submitting requests after the fact without a real-time record of when they actually started and finished.
Context: PGS (Petugas Pengganti Sementara) are temporary workers deployed when a permanent worker is absent. Before V3, the RO handled this entirely through phone calls and manual records — there was no system support at all. The design problem had two parts: finding the right person, and managing how many days they'd already worked.
Finding the right reliever
A single RO might have access to a large pool of potential reliever workers. Calling through them manually was slow and error-prone. The system needed to surface the right candidates quickly.
Filter-first: let ROs narrow the pool by qualification, location, and category before selecting.


Rather than presenting a flat list of everyone available, the assignment screen opens with filters: job qualification, geographic location, and deployment category. The RO narrows the list, picks the right person, and the system generates the assignment automatically — including a formal Surat Tugas (assignment letter) sent directly to the reliever.
Managing the 21-day quota
Indonesian labor regulations cap external reliever deployment at 21 working days per month. Before V3, tracking this was manual — and it was easy to exceed the limit without realizing it until it was too late.
Visual quota tracking with progressive warnings, not just a hard block.



Progressive warnings matter here. A hard block at exactly 21 days creates operational emergencies — an RO with no reliever and no time to find one. Surfacing the threshold early gives time to plan before it becomes a problem.
Completion flow
When the reliever finishes their assignment and clocks out, they input a WhatsApp number in the app. This triggers the performance evaluation and task acceptance process — keeping the post-assignment workflow inside the system rather than jumping back to manual channels.

This is where the overtime story which started in V1 completes.
The challenge: adding overtime attendance without disrupting the existing attendance and overtime submission systems.
Add overtime clock-in as a parallel default state, and separate the act of recording attendance from the act of submitting a formal request.

When a worker has no active regular schedule or has already completed their shift, the home screen shows two attendance buttons simultaneously: Absen Masuk for regular attendance and Absen Lembur for overtime. The worker can clock in for overtime directly from the home screen without touching the existing regular attendance flow. But the result isn't a finalized overtime submission. It becomes a Draft.

Why Draft, not automatic submission? In the field, workers often start overtime before their SPL (Surat Perintah Lembur — overtime authorization letter) is ready. Requiring SPL at clock-in time would block workers from recording attendance in the moment. Making it auto-submit without SPL would create unverifiable requests in the approval queue. Draft solves both: the attendance is recorded the moment it happens, and the formal submission — with SPL — happens whenever the worker is ready. The two steps are decoupled without either being skipped.
The real-time record is immediately visible to admins. The Daily Attendance view gains a dedicated Hadir Lembur tab — showing every worker currently clocked in for overtime, with photo and location data for both clock-in and clock-out.

The overtime arc is now complete: from asking workers to understand labor law categories, to letting them clock in naturally and handle the paperwork separately.
V3 closed the gaps that three years of field use had revealed. ROs could assign replacement workers in minutes instead of through phone calls. Workers could record overtime attendance in the moment without waiting until after the fact, and without needing an SPL ready at the start. The Draft state gave them the flexibility to clock in first, submit formally later. The three-version arc tells a complete story: a product that started by replacing a third-party dependency, scaled to serve an entire company network, and matured by listening to what field use actually required — not just what the system assumed it would.



Features get better when data accumulates. Auto overtime wasn't possible in V1 — there wasn't enough reliable data yet. Two years of attendance records and approved schedules made it straightforward by V3. Some features need time to be earned.
Progressive warnings outperform hard blocks. Blocking at exactly 21 days creates emergencies. Warning at 19 gives time to respond. How you design a constraint matters as much as the constraint itself.
Good design compounds. The overtime fix in V1 unlocked better approval in V2. Better approval in V2 made auto-calculation possible in V3. Every design decision that reduced friction created headroom for the next one.
V1 replaced a third-party HR app PKSS didn't own. V2 turned it into a platform that could serve their entire client network. V3 automated what three years of field use had revealed. Every version's fix created the headroom the next one needed.
Designer spec sheet