All work

Arontel · Telecom Operations Platform

Not a dashboard.
Not a CRUD app.

A control surface for live call routing — every node I rendered was a real telecom decision.

Production Enterprise
60%
Faster rendering
<300ms
Interaction latency
12k+
Nodes in production
0
Downtime incidents
Vue 3NuxtTypeScriptPiniaUnoCSSSupabase

The system, not the screen

One engineer.
Full frontend ownership.

AronTel is a VoIP SaaS platform — IVR automation, PBX, conferencing, and analytics for enterprise clients. When an operator changes a node, they change what a live caller hears right now.

I joined as the sole frontend engineer. Two founders, one designer who later left — and full ownership of every frontend decision from architecture to production delivery.

Where the UI was failing the operators

The problem wasn't missing features.
It was missing constraints.

IVR trees contained 4,000–12,000 nodes in production. Naive rendering caused freezes. State mutations cascaded re-renders across the entire tree. Operators had no visibility into what was live versus inactive. Destructive actions had no confirmation layer.

Before
  • UI froze beyond 4k nodes
  • Deep nested components, re-render cascades
  • 600–700ms interaction latency
  • No node state visibility
  • Destructive actions without confirmation
  • Feature-first, no state normalization
After
  • Smooth at 12k+ nodes — virtual scroll + flat Pinia store
  • Computed hierarchies, no cascade on mutation
  • 250–300ms interaction latency
  • State-driven UI — what you see = what is live
  • PIN-gated destructive actions
  • Domain-separated component architecture

Three decisions that changed the system

Not what I built.
Why I built it that way.

Virtual scrolling over pagination

Performance

Pagination would force operators to click through pages to find nodes, destroying the hierarchical sense of an IVR call tree. Operators need to see the structure. Virtual scrolling kept the full tree visible while only rendering nodes in the viewport. Combined with a flat Pinia store, latency dropped from 600ms to under 300ms.

Flat normalized store over nested reactive trees

Architecture

The original state stored nodes as deeply nested Vue reactive objects. Any mutation triggered a re-render cascade across the entire tree. Switching to a flat ID-keyed Pinia store with computed hierarchies meant one node update caused one re-render — not 12,000.

State-driven UI — operators cannot fix what they cannot see

UX

Operators had no signal for which nodes were live, which had audio, which were broken. I built a full state-mapping system: active green, disabled muted, unconfigured amber, error red. Audio had four visual states. The UI became a real-time mirror of system state. Destructive actions required confirmation. Mistakes became structurally hard to make.

"After the designer left, I owned UX decisions and frontend delivery simultaneously. Requirements came in as business logic — I turned them into component architecture the same day."

Designed for operators, not designers

Six patterns. One shared principle:
operators under pressure make mistakes.

Progressive disclosure

Node summary visible first, deep config on expand. Operators scan hundreds of rows — cognitive load matters.

Gated destructive actions

Delete and override required PIN confirmation. A wrong delete changes live call routing for real callers.

Role-based visibility

Admin controls hidden from operator role. Multi-tenant isolation built into the component layer, not just route guards.

Optimistic UI

Instant visual feedback, background sync. Errors rolled back cleanly without jarring the operator mid-workflow.

Empty state guidance

No audio → upload CTA. No nodes → create prompt. Operators always knew their next action. Never a blank screen.

Error containment

Errors in one node scoped to that node. They did not cascade to siblings or collapse the tree.

What I owned end to end

Five modules.
One shared component system.

Full ownership of architecture, UX decisions, and production delivery. No handoff layer — requirements came in, shipped components went out.

IVR Node Trees

01 · Core system

12k+ node trees with virtual rendering, flat Pinia state, and full state-driven UI. The system everything else depended on.

File Manager

02 · Audio pipeline

Audio file management, TTS generation, upload and playback for node audio. Four visual states per file.

Conferences

03 · Real-time

Real-time participant management, raised hands, mute controls, and session recordings.

Dashboards

04 · Analytics

Live analytics and system health for telecom operators. Real-time metrics across the platform.

User Management

05 · Multi-tenant

Multi-tenant admin panel and role-based access control. Tenant isolation built into the component layer.

Want the full architecture?

Let's talk systems, decisions, and what it took to ship this.

Partial work shown — this is a live production system used by enterprise telecom clients. UI details are intentionally limited.

"I don't just build interfaces.
I build systems that stay fast, usable, and reliable at scale."