EG
Resume

basically, this project is legit cool. 😎

System Architecture — E-RUPS Platform
REST APILaravel ReverbORMEmbedPub/SubReact SPACORELaravel APICOREWebSocketSERVICEPostgreSQLDATABASEZoom SDKSERVICERedis QueueDATABASE
CORESERVICEDATABASEDATA FLOW

The Problem

Shareholder meetings (RUPS) in Indonesia traditionally required physical presence. For a company like Sinartama Gunita (Share Registrar), this meant:

  • Investors flying in from across Indonesia
  • Meeting venues, catering, logistics costs
  • Limited participation due to travel constraints
  • Slow decision-making process

Then 2020 happened and everyone realized: wait, meetings can be online right? 🤯

What is E-RUPS?

Electronic RUPS (Rapatan Umum Pemegang Saham) - basically shareholders can attend meetings, vote, and ask questions online. No more flying to Jakarta for a 30-min meeting.

The Tech Stack

Frontend:

  • React + Vite (fast builds, great DX)
  • WebSocket for real-time features
  • Zod for validation
  • Tailwind + custom UI

Backend:

  • Laravel (their existing stack)
  • Laravel Reverb (WebSocket server)
  • PostgreSQL for data

Integrations:

  • Zoom SDK (embedded meeting experience)

Key Features Built

1. Live Meeting Rooms

// Real-time participant list
const [participants, setParticipants] = useState([]);

useEffect(() => {
  const ws = new WebSocket(`${WS_URL}/meeting/${meetingId}`);

  ws.onmessage = (event) => {
    const data = JSON.parse(event.data);
    if (data.type === 'USER_JOINED') {
      setParticipants(prev => [...prev, data.user]);
    }
  };

  return () => ws.close();
}, [meetingId]);

2. Voting System

  • Real-time vote count updates
  • Yes/No/Abstain options
  • Animated vote bars
  • Result announcement after closing

3. Q&A Module

  • Participants submit questions
  • Moderator approves/rejects
  • Questions visible to all
  • Answered during live session

4. Multi-Role Access Control

type UserRole = 'issuer' | 'investor' | 'bae' | 'intermediary';

const rolePermissions = {
  issuer: ['create_meeting', 'start_voting', 'close_meeting'],
  investor: ['join_meeting', 'vote', 'ask_question'],
  bae: ['moderate_qna', 'view_reports'],
  intermediary: ['register_attendee', 'view_attendance']
};

5. Zoom Integration

Embedded Zoom meetings within the app - participants don't need separate Zoom app. One click, you're in the meeting.

Technical Challenges

Handling 300 Concurrent Users

WebSocket connections can get heavy. solved by:

  • Redis for pub/sub
  • Connection pooling
  • Efficient re-renders with React.memo

Data Integrity

Financial meetings need:

  • Immutable vote records
  • Timestamp accuracy
  • Audit trail for every action
  • Frontend + backend validation

Parallel Development

Worked with 3 backend devs + 2 QA. API contracts were essential. if you skip API docs in a team this size, you're gonna have a bad time. 😅

The Flow

1. Issuer creates meeting → sets agenda, date, participants
2. System sends email/SMS invites
3. Participants register → verify identity
4. Day of meeting → join via Zoom embedded SDK
5. Real-time Q&A → submit questions
6. Voting → live results
7. Meeting ends → minutes auto-generated
8. All records → audit trail complete

Results

  • ✅ 300+ concurrent users supported
  • ✅ Zero downtime during live meetings
  • ✅ Real-time everything (voting, Q&A, chat)
  • ✅ Mobile-responsive (important for older shareholders)
  • ✅ Audit trail for compliance

What I Learned

  1. WebSocket at scale - it's different when 300 people are hitting it simultaneously
  2. Role-based systems - complex but essential for enterprise
  3. Financial data - validation is everything, trust nothing from frontend
  4. Integration testing - Zoom SDK + WebSocket + backend = fun times debugging 😵

this project made me realize: enterprise software doesn't have to be boring. it's actually solving real problems for real people.

Related Articles