<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Rahman Nugar</title>
    <description>The latest articles on DEV Community by Rahman Nugar (@rahmannugar).</description>
    <link>https://dev.to/rahmannugar</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3408076%2F1bb7d54a-d698-4106-ba89-095779ea601a.JPG</url>
      <title>DEV Community: Rahman Nugar</title>
      <link>https://dev.to/rahmannugar</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/rahmannugar"/>
    <language>en</language>
    <item>
      <title>Owlyn: Building a Multimodal Agent Ecosystem for Live Technical Interviews and Real-Time Assistance #GeminiLiveAgentChallenge</title>
      <dc:creator>Rahman Nugar</dc:creator>
      <pubDate>Mon, 16 Mar 2026 17:48:40 +0000</pubDate>
      <link>https://dev.to/rahmannugar/owlyn-building-a-multimodal-agent-ecosystem-for-live-technical-interviews-and-real-time-assistance-15hg</link>
      <guid>https://dev.to/rahmannugar/owlyn-building-a-multimodal-agent-ecosystem-for-live-technical-interviews-and-real-time-assistance-15hg</guid>
      <description>&lt;p&gt;The current landscape of technical hiring is bottlenecked by a fundamental scalability problem. Organizations receiving hundreds of applications per role find it impossible to conduct live, high-quality interviews for every candidate, often resorting to cold, non-immersive recordings or static tests. These traditional "AI interviews" are neither live nor engaging—they strip away the conversational nuance that defines a great engineer and leave both the company and the candidate with a fragmented view of technical potential.&lt;/p&gt;

&lt;p&gt;We built &lt;strong&gt;Owlyn&lt;/strong&gt; to solve this gap using real-time multimodal intelligence. Instead of a static AI assessment, Owlyn operates as an autonomous agent ecosystem capable of seeing, hearing, and reasoning about a candidate’s live workspace. By leveraging the Gemini Live API, Owlyn conducts real-time technical interviews and provides a persistent assistant mode that can see, hear, and interact with sub-second latency. Every interaction is synchronized with live transcripts, ensuring the system is both high-fidelity and accessible across every workflow.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://youtu.be/D8g6On2PBhM?si=jiWdYYfitfzeh1Nl" rel="noopener noreferrer"&gt;Watch the Owlyn Demo on YouTube&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This piece of content was written by me, &lt;strong&gt;Abdulrahmon Adenuga&lt;/strong&gt; (&lt;a class="mentioned-user" href="https://dev.to/rahmannugar"&gt;@rahmannugar&lt;/a&gt;), along with &lt;strong&gt;Akeem Adetunji&lt;/strong&gt; and &lt;strong&gt;Mosimiloluwa Adebisi&lt;/strong&gt; and created for the purposes of entering the Google &lt;strong&gt;#GeminiLiveAgentChallenge&lt;/strong&gt; hackathon. It covers how we built Owlyn using Google AI models and Google Cloud.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;The Core Objectives&lt;/li&gt;
&lt;li&gt;System Architecture&lt;/li&gt;
&lt;li&gt;The Multi-Agent Protocol&lt;/li&gt;
&lt;li&gt;Live Workflows: Interview, Monitoring, and Assistant&lt;/li&gt;
&lt;li&gt;Recruitment Management: Dashboards and Talent Pools&lt;/li&gt;
&lt;li&gt;Real-Time Multimodal Pipelines&lt;/li&gt;
&lt;li&gt;Security: The Sentinel Mode&lt;/li&gt;
&lt;li&gt;Engineering Decisions&lt;/li&gt;
&lt;li&gt;Closing Thoughts and Future Roadmap&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  1. The Core Objectives
&lt;/h2&gt;

&lt;p&gt;Existing AI interview tools often fail because they are built as wrappers around static LLMs, leading to two major deal-breakers: &lt;strong&gt;hallucination&lt;/strong&gt; and &lt;strong&gt;latency&lt;/strong&gt;. If an AI takes 5 seconds to respond, the conversation is dead. If it "guesses" what your code does instead of analyzing its logic, it loses all technical authority.&lt;/p&gt;

&lt;p&gt;To solve this, we defined four design pillars for Owlyn:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Zero-Latency&lt;/strong&gt;: Using Gemini Live to achieve sub-second response times, this eliminates the "awkward silence" typical of LLM-based bots, ensuring the conversation maintains the natural momentum of a real-world technical discussion.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Multimodal Reasoning&lt;/strong&gt;: The agent must do more than listen; it must "see" the workspace. By streaming the screen feed, the agent can react to a candidate's cursor movements or a logic error in a whiteboard diagram.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Inclusive Accessibility&lt;/strong&gt;: Building a system that is accessible to everyone. This means supporting multiple spoken languages and providing live transcripts for candidates with hearing disabilities, ensuring that automation doesn't come at the cost of inclusion.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  2. System Architecture
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6v2ato3amrknj0we5bg1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6v2ato3amrknj0we5bg1.png" alt="System Architecture I" width="800" height="1200"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fggoh8mhp3ja1wkpq0wal.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fggoh8mhp3ja1wkpq0wal.jpg" alt="System Architecture II" width="800" height="628"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Owlyn is designed as a distributed, real-time multimodal system composed of four major layers:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Electron Client Layer&lt;/li&gt;
&lt;li&gt;Backend Orchestration Layer&lt;/li&gt;
&lt;li&gt;Worker Agent Layer&lt;/li&gt;
&lt;li&gt;Infrastructure &amp;amp; AI Layer&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This separation allows the system to maintain sub-second conversational latency, while supporting multiple AI agents analyzing different signals simultaneously.&lt;/p&gt;

&lt;h3&gt;
  
  
  2.1 Electron Client Layer
&lt;/h3&gt;

&lt;p&gt;The client application is built with Electron + React, which allows Owlyn to access system-level capabilities that are unavailable in the browser.&lt;/p&gt;

&lt;p&gt;The Electron frontend is responsible for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Capturing camera, microphone, and screen feeds&lt;/li&gt;
&lt;li&gt;Rendering the Monaco coding workspace&lt;/li&gt;
&lt;li&gt;Streaming audio/video via WebRTC&lt;/li&gt;
&lt;li&gt;Sending application events to the backend via HTTPS REST&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The client communicates with the backend in two ways:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;HTTPS / REST&lt;/strong&gt;&lt;br&gt;
Used for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Authentication&lt;/li&gt;
&lt;li&gt;Session creation&lt;/li&gt;
&lt;li&gt;Interview configuration&lt;/li&gt;
&lt;li&gt;transcript synchronization&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;LiveKit WebRTC&lt;/strong&gt;&lt;br&gt;
Used for low-latency real-time streams:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;microphone audio&lt;/li&gt;
&lt;li&gt;webcam video&lt;/li&gt;
&lt;li&gt;workspace signals&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These streams are routed to the backend orchestration layer and AI agents.&lt;/p&gt;

&lt;h3&gt;
  
  
  2.2 Backend Orchestration Layer
&lt;/h3&gt;

&lt;p&gt;The backend is built using Spring Boot and acts as the central orchestrator of the entire system.&lt;/p&gt;

&lt;p&gt;Rather than allowing each AI agent to independently connect to the client, all signals pass through the backend first. This ensures:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;consistent session state&lt;/li&gt;
&lt;li&gt;controlled AI communication&lt;/li&gt;
&lt;li&gt;centralized logging and monitoring&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The backend exposes two internal interfaces:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;REST API&lt;/strong&gt;&lt;br&gt;
Handles standard application workflows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;interview creation&lt;/li&gt;
&lt;li&gt;candidate session management&lt;/li&gt;
&lt;li&gt;transcript storage&lt;/li&gt;
&lt;li&gt;session metadata&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Internal API&lt;/strong&gt;&lt;br&gt;
Used for agent-to-agent communication and system orchestration.&lt;br&gt;
This internal API connects to the Assessor Agent, which performs post-interview analysis and scoring.&lt;/p&gt;

&lt;h3&gt;
  
  
  2.3 Worker Agent Layer
&lt;/h3&gt;

&lt;p&gt;Owlyn runs several specialized Python worker agents responsible for processing multimodal signals during a session.&lt;br&gt;
These agents operate independently from the core backend to keep real-time processing lightweight.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;LiveKit Agent&lt;/strong&gt;&lt;br&gt;
The LiveKit Agent connects to the LiveKit WebRTC stream and manages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;real-time voice conversation&lt;/li&gt;
&lt;li&gt;audio streaming to Gemini Live&lt;/li&gt;
&lt;li&gt;returning AI responses to the candidate&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This forms the primary conversational loop of the interview.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Proctor Sentinel&lt;/strong&gt;&lt;br&gt;
The Integrity Sentinel monitors the webcam feed to ensure the session remains secure.&lt;br&gt;
Using Gemini Vision, it detects:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;unauthorized devices&lt;/li&gt;
&lt;li&gt;additional people in frame&lt;/li&gt;
&lt;li&gt;suspicious behavior&lt;/li&gt;
&lt;li&gt;environmental anomalies&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Any violation is immediately flagged and logged.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Workspace Sentinel&lt;/strong&gt;&lt;br&gt;
The Workspace Sentinel observes the candidate’s coding environment, including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Monaco editor&lt;/li&gt;
&lt;li&gt;whiteboard interactions&lt;/li&gt;
&lt;li&gt;cursor behavior&lt;/li&gt;
&lt;li&gt;code structure&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It continuously analyzes implementation logic and forwards observations to the Interviewer agent so the conversation can react to the candidate’s code in real time.&lt;/p&gt;

&lt;h3&gt;
  
  
  2.4 Infrastructure and AI Layer
&lt;/h3&gt;

&lt;p&gt;The final layer provides the persistent infrastructure and AI services that power the system.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Dockerized PostgreSQL &amp;amp; Redis&lt;/strong&gt;&lt;br&gt;
We utilize &lt;strong&gt;Docker&lt;/strong&gt; to containerize our data layer, ensuring a consistent and isolated environment for both PostgreSQL and Redis. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;PostgreSQL&lt;/strong&gt;: Handles durable storage for interview sessions, transcripts, reports, and user data. It is accessed through the Spring Boot backend via JPA.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Redis&lt;/strong&gt;: Stores live session state (transcript buffers, agent context, security flags) for sub-millisecond updates during live conversations.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note on Backend Deployment&lt;/strong&gt;: The Owlyn backend (orchestration layer and worker agents) is hosted on &lt;strong&gt;Google Cloud Virtual Machines (VMs)&lt;/strong&gt;. This provides the stable, high-performance environment necessary for sub-second multimodal processing and session management.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;LiveKit Server&lt;/strong&gt;&lt;br&gt;
LiveKit acts as the real-time media server for Owlyn.&lt;br&gt;
It manages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;WebRTC signaling&lt;/li&gt;
&lt;li&gt;audio/video transport&lt;/li&gt;
&lt;li&gt;stream synchronization&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This allows voice conversations to occur with sub-second latency, which is critical for maintaining natural dialogue.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Gemini AI&lt;/strong&gt;&lt;br&gt;
Owlyn integrates multiple Gemini models for specialized reasoning tasks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Gemini Live API → real-time voice conversation&lt;/li&gt;
&lt;li&gt;Gemini 3.1 Pro → deeper reasoning and evaluation&lt;/li&gt;
&lt;li&gt;Gemini 3 Flash → lightweight real-time inference&lt;/li&gt;
&lt;li&gt;Gemini Vision → visual analysis of the workspace and webcam
Each model powers a different agent in the system.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2.5 Cross-System Communication Flow
&lt;/h3&gt;

&lt;p&gt;During a live interview session, the system operates as a continuous pipeline:&lt;/p&gt;

&lt;p&gt;The Electron client streams audio/video via LiveKit.&lt;/p&gt;

&lt;p&gt;The Spring Boot backend orchestrates session state.&lt;/p&gt;

&lt;p&gt;Python agents process multimodal signals in parallel.&lt;/p&gt;

&lt;p&gt;Signals are routed to Gemini AI models for reasoning.&lt;/p&gt;

&lt;p&gt;Results are returned through LiveKit to the candidate in real time.&lt;/p&gt;

&lt;p&gt;Redis stores live context while PostgreSQL stores persistent records.&lt;/p&gt;

&lt;p&gt;This architecture allows Owlyn to maintain low latency, contextual awareness, and modular AI reasoning, enabling the system to behave less like a scripted bot and more like a real technical interviewer.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. The Multi-Agent Protocol
&lt;/h2&gt;

&lt;p&gt;Owlyn is built on a &lt;strong&gt;decoupled multi-agent architecture&lt;/strong&gt;. We designed the system from the ground up using specialized Gemini instances for distinct tasks; voice interaction, workspace vision, and real-time code analysis rather than relying on a single monolithic agent. This ensures that the interviewer remains grounded by the candidate's actual workspace signals while maintaining sub-second conversational latency.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;Orchestrator&lt;/strong&gt; is our server. Since Gemini agents can't directly talk to each other without a shared context, the Orchestrator acts as the central router. It receives video and audio via WebRTC, pipes them to the correct Gemini model, and then relays &lt;strong&gt;context&lt;/strong&gt; between the different agents. This ensures the interviewer can react to a failing test case or a specific logic choice in real-time.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Agent 1: The Question Generator (Gemini 3 Flash Preview)&lt;/strong&gt;: This agent runs during the interview creation phase on the management dashboard. It analyzes the job role and requirement details to draft specific technical challenges and coding tasks. This ensures the interviewer (Agent 2) has a tailored set of objectives ready before the candidate even starts the session.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Agent 2: The Interviewer (Gemini Live)&lt;/strong&gt;: This is the conversational agent the candidate hears. It handles the voice loop with sub-second latency, maintaining a natural dialogue flow throughout the session.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Agent 3: The Sentinels (Gemini 3.1 Flash Lite)&lt;/strong&gt;: These are the specialized "eyes" and "ears" of the system.

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Integrity Sentinel&lt;/strong&gt;: Processes the video feed to monitor session security and detect unauthorized activity.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Workspace Sentinel&lt;/strong&gt;: Observes the Monaco editor and whiteboard. It analyzes the implementation logic in real-time, providing deep structural insights to the interviewer.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Agent 4: The Technical Assessor (Gemini 3)&lt;/strong&gt;: Once the interview ends, this agent takes the full transcript and the logic reasoning logs to generate a structured JSON report. It looks purely at the data to give an unbiased score.
&lt;/li&gt;

&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;graph LR
    %% Phase 1: Setup
    subgraph Setup ["1. Pre-Interview Setup"]
        Start(Job Role) --&amp;gt; A1[Agent 1: Question Generator]
        A1 -- "Drafts" --&amp;gt; Tasks(Technical Tasks)
    end

    %% Phase 2: Live
    subgraph Interaction ["2. Live Interaction"]
        Candidate((Candidate)) &amp;lt;--&amp;gt; |LiveKit WebRTC| Orch[Spring Boot Orchestrator]
        Orch &amp;lt;--&amp;gt; A2[Agent 2: Gemini Live Interviewer]
        Orch &amp;lt;--&amp;gt; A3[Agent 3: Workspace Sentinels]
        A3 -- "Visual &amp;amp; Code Feed" --&amp;gt; A2
    end

    %% Phase 3: Reporting
    subgraph Evaluation ["3. Final Scoring"]
        Interaction -- "Session Logs" --&amp;gt; Data(Transcripts &amp;amp; Context)
        Data --&amp;gt; A4[Agent 4: Technical Assessor]
        A4 -- "Report" --&amp;gt; Result(Unbiased Score)
    end

    %% Logic Flow
    Tasks -.-&amp;gt; A2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This "Agent-to-Agent" handoff is what makes Owlyn feel smart. When Agent 3 identifies a logic error in your code, it tells Agent 2: &lt;em&gt;"Hey, their solution might have a performance issue."&lt;/em&gt; Agent 2 then asks the candidate: &lt;em&gt;"I noticed your current approach might have some performance challenges. Can you walk me through your time complexity?"&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Persona Customization: Defining the Interviewer
&lt;/h3&gt;

&lt;p&gt;We built a &lt;strong&gt;Persona Engine&lt;/strong&gt; to move away from a "one-size-fits-all" agent ecosystem. Recruiters can configure their agents' behavior through several technical levers in the management dashboard:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Linguistic Localization&lt;/strong&gt;: The spoken language can be set per session, supporting &lt;strong&gt;English, German, Spanish, French&lt;/strong&gt;, and several other locales for a global candidate pool.&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Behavioral Scalars&lt;/strong&gt;: Instead of basic prompts, we use weighted scores for &lt;strong&gt;Empathy&lt;/strong&gt;, &lt;strong&gt;Analytical Depth&lt;/strong&gt;, and &lt;strong&gt;Directness&lt;/strong&gt;. These values are injected into the agent's core instructions to shift the tone from a supportive guide to a rigorous technical evaluator.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Document-Based Knowledge&lt;/strong&gt;: Recruiters can upload PDFs or DOCX files—such as internal engineering rubrics or company values—which the system parses and uses to inform the agent's specific technical knowledge during the session.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  4. Live Workflows: Interview, Monitoring, and Assistant
&lt;/h2&gt;

&lt;p&gt;We didn't just stop at an interview screen. We built four distinct ways to use Owlyn. Across all modes, we prioritized accessibility through &lt;strong&gt;Live Transcripts&lt;/strong&gt;. For developers with hearing disabilities or those in noisy environments, Owlyn provides a threaded, real-time transcript of every word the agent says. This ensures the system remains inclusive and that the agent's logic can be read and reviewed as it happens.&lt;/p&gt;

&lt;h3&gt;
  
  
  A. The Interview Workspace
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyy0pegydrgcb551hv310.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyy0pegydrgcb551hv310.png" alt="Interview workspace" width="800" height="520"&gt;&lt;/a&gt;&lt;br&gt;
This is the core experience. The candidate has a professional-grade workspace with the &lt;strong&gt;Monaco Editor&lt;/strong&gt;, a canvas-based &lt;strong&gt;Whiteboard&lt;/strong&gt;, and a &lt;strong&gt;Notes&lt;/strong&gt; app. Everything is synced in real-time.&lt;/p&gt;

&lt;h3&gt;
  
  
  Support for Multiple Programming Languages
&lt;/h3&gt;

&lt;p&gt;We engineered the workspace to be language-agnostic. By utilizing &lt;strong&gt;Monaco Editor&lt;/strong&gt; (the engine behind VS Code), Owlyn provides a native coding experience for over 20+ languages, including &lt;strong&gt;Typescript, Python, Go, Java, and C++&lt;/strong&gt;. The Workspace Sentinel (Agent 3) is specifically tuned to understand the idiomatic nuances of these languages, ensuring that whether a candidate is writing a high-performance Go routine or a clean React component, the evaluation remains context-aware and accurate.&lt;/p&gt;

&lt;h3&gt;
  
  
  B. Monitoring Mode
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftcyslvvkqu7vrxnk3f0k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftcyslvvkqu7vrxnk3f0k.png" alt="Monitoring Mode" width="800" height="520"&gt;&lt;/a&gt;&lt;br&gt;
For organizations, visibility is just as important as the evaluation itself. We built a &lt;strong&gt;Monitoring Dashboard&lt;/strong&gt; that serves as a real-time command center for recruitment teams. &lt;/p&gt;

&lt;p&gt;Hiring managers can join any active session as a "Silent Observer," gaining a comprehensive view of the candidate’s performance without interfering with the natural flow of the interview. The dashboard provides a live, rolling transcript, a synchronized audio waveform to visualize the conversation's cadence, and an instant alert system. If our sentinels detect a security anomaly—such as the presence of a mobile device or an unauthorized person in the frame—a flag is immediately raised on the recruiter's screen, allowing for instant intervention if necessary.&lt;/p&gt;

&lt;h3&gt;
  
  
  C. Assistant Mode
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fogeys7w2fghtracc9u2i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fogeys7w2fghtracc9u2i.png" alt="Assistant Mode" width="800" height="520"&gt;&lt;/a&gt;&lt;br&gt;
Assistant Mode transforms Owlyn into a persistent multimodal companion for everyday development. Beyond the interview, this mode operates as a &lt;strong&gt;floating widget&lt;/strong&gt; that lives alongside your IDE and terminal. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Environmental Context&lt;/strong&gt;: The agent utilizes screen-share vision and your microphone to stay synchronized with your active tasks. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Voice-First Interaction&lt;/strong&gt;: Leveraging the &lt;strong&gt;LiveKit&lt;/strong&gt; protocol for sub-second responses, it acts as a senior pair-programmer you can talk to in real-time.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ambient Assistance&lt;/strong&gt;: Whether you're debugging a complex stack trace or architecting a new service, the Assistant provides contextual insights based on exactly what it sees on your screen.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  D. Practice Mode
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fddwney9f2237g19ytd9s.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fddwney9f2237g19ytd9s.png" alt="Practice Mode" width="800" height="520"&gt;&lt;/a&gt;&lt;br&gt;
Before entering a real technical interview session, candidates need a way to test their technical skills and get comfortable with the interview environment. We built &lt;strong&gt;Practice Mode&lt;/strong&gt; as a standalone version of the workspace where users define their own parameters:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Customizable Sessions&lt;/strong&gt;: Users input a specific topic (e.g., "React Performance" or "Distributed Systems") and set a difficulty and timer. The agent then dynamically generates a technical session based on those constraints.
--&lt;strong&gt;Multi Language Support&lt;/strong&gt;: Users can select their preferred language from the list of supported languages. This instructs the AI agent to communicate with the candidate in their preferred language.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Protocol Parity&lt;/strong&gt;: It uses the same multi-agent orchestration, audio/video streaming, and code analysis as the Enterprise mode. This ensures the candidate is getting the real experience in a private environment.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  5. Recruitment Management: Dashboards and Talent Pools
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7ju8rfr46yzszv4ior88.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7ju8rfr46yzszv4ior88.png" alt="Dashboard" width="800" height="520"&gt;&lt;/a&gt;&lt;br&gt;
Technical hiring is about more than just one interview; it is about managing many candidates effectively across an entire company. We built a management system to help teams handle their hiring process from start to finish:&lt;/p&gt;

&lt;h3&gt;
  
  
  The Recruitment Dashboard
&lt;/h3&gt;

&lt;p&gt;This is the main control center where hiring teams manage their daily work. It shows what is happening in the company right now:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Track Candidates in Real-Time&lt;/strong&gt;: Managers can see which candidates are waiting in the lobby, which interviews are currently live, and which ones are finished. This helps teams stay organized during busy hiring seasons.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Role-Based Customization&lt;/strong&gt;: Recruiters can set different rules for different positions. You can choose the language the AI speaks and set how strict it should be. For example, you can make the AI a helpful guide for a junior developer or a very rigorous judge for a senior lead. You can also upload specific coding tasks for each role.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Human Decision Making (Hire or Decline)&lt;/strong&gt;: While the AI handles the interview, the final choice always belongs to a human. After the interview, a recruiter reviews the technical report and uses the &lt;strong&gt;Hire or Decline&lt;/strong&gt; buttons to make a final evaluation. This ensures that a real person always has the last word.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Team Collaboration
&lt;/h3&gt;

&lt;p&gt;Hiring is a team sport. We added features to help engineering leads and recruiters work together:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Team Management&lt;/strong&gt;: Organizations can invite multiple team members to the dashboard. This allows different people to review the same candidate report and share their feedback.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Shared Feedback&lt;/strong&gt;: Recruiters can leave notes on a candidate's profile for other team members to see. This helps build a complete picture of the candidate’s performance from different perspectives.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Analysis and Reporting
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwkoa4jmbydn7jv8gux96.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwkoa4jmbydn7jv8gux96.png" alt="Analysis" width="800" height="520"&gt;&lt;/a&gt;&lt;br&gt;
Once an interview is over, the AI generates a detailed technical report. This report is the primary tool recruiters use to make their hiring decisions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Technical Radar Charts&lt;/strong&gt;: The system visualizes candidate skills (like Problem Solving, Communication, and Code Quality) on a radar chart. This makes it easy to see at a glance where a candidate is strongest.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Full Transcripts and Code History&lt;/strong&gt;: Recruiters can read every word said during the interview and see exactly how the candidate's code evolved over time.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Automated Summary&lt;/strong&gt;: The AI provides a short summary of the candidate's performance, highlighting both their strengths and their mistakes.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  The Talent Pool
&lt;/h3&gt;

&lt;p&gt;The Talent Pool is a central library where all candidate results are kept. It helps teams find the best talent faster:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Compare Skills Side-by-Side&lt;/strong&gt;: The system takes the AI's technical scores and puts them in a simple table. This lets recruiters filter candidates by their score or role, making it easy to see who performed best across hundreds of sessions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Talent Analytics&lt;/strong&gt;: The dashboard shows overall stats for your hiring pipeline, such as the total number of candidates, the percentage of high-potential profiles, and the average score for a specific role.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Exporting for Teams&lt;/strong&gt;: Recruiters can export lists of elite candidates to share with other departments, ensuring that top talent is never lost in the system.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Unbiased Ranking&lt;/strong&gt;: Because the AI scores everyone using the same technical rules, the Talent Pool gives teams an objective way to rank people based on their actual coding ability.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  6. Real-Time Multimodal Pipelines
&lt;/h2&gt;

&lt;p&gt;Capturing human interaction for an autonomous agent is technically demanding. We had to solve for two main things: data shape and latency.&lt;/p&gt;

&lt;p&gt;For the &lt;strong&gt;Video Feed&lt;/strong&gt;, we stream 1 frame per second. We found this to be the "sweet spot" for Gemini’s Vision capabilities—it’s enough to detect a phone or a change in gaze without destroying the candidate's upload bandwidth.&lt;/p&gt;

&lt;p&gt;For &lt;strong&gt;Audio&lt;/strong&gt;, we use 16kHz mono PCM. This is streamed up to our Java server, which then pipes it directly into the Gemini Live API via the &lt;strong&gt;Google ADK&lt;/strong&gt;. We spent a lot of time on the &lt;code&gt;audio.service.ts&lt;/code&gt; to ensure that audio chunks are small enough for low latency but large enough to maintain quality.&lt;/p&gt;

&lt;h2&gt;
  
  
  7. Security: The Sentinel Mode
&lt;/h2&gt;

&lt;p&gt;Integrity is non-negotiable for professional assessments. We implemented what we call &lt;strong&gt;Sentinel Mode&lt;/strong&gt; to protect the session:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;OS-Level Lockdown&lt;/strong&gt;: We use Electron's &lt;code&gt;globalShortcut&lt;/code&gt; to block navigation and &lt;code&gt;win.setContentProtection(true)&lt;/code&gt; to make the screen appear black to recording software like OBS.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Environmental Breach Detection&lt;/strong&gt;: We listen for "blur" events. If the candidate switches windows, it’s logged as a breach, and the agent verbally warns them to focus.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Vision-Based Security Monitoring&lt;/strong&gt;: Since Gemini is looking at the 1fps feed, it natively detects unauthorized objects (phones, tablets) or external participants in the room.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  8. Engineering Decisions
&lt;/h2&gt;

&lt;p&gt;Every engineering project is a series of trade-offs.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Latency vs. Accuracy&lt;/strong&gt;: We chose 1fps for the vision feed over a smoother 10fps. While less "fluid," it ensures that candidates on a standard home connection can participate without lag or video fragmentation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Centralized Session Orchestration&lt;/strong&gt;: We chose to coordinate multiple agents through our Spring Boot backend rather than having the client manage separate peer-to-peer connections with 4+ different Gemini models. While this centralization adds architectural complexity, it was essential for maintaining a unified state across the Interviewer, Workspace Sentinel, and Integrity Sentinel.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;In-Context Logic Verification&lt;/strong&gt;: We leveraged Gemini’s specialized reasoning models to verify logic in real-time. This avoided the overhead of a formal execution sandbox while allowing the agent to provide feedback on implementation details as they unfold.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Memory-First State Management&lt;/strong&gt;: We use Redis for all active session data (transcripts, flags, editor state). This sacrifices the "safety" of persistent disk writes for the sub-millisecond updates required in a live, voice-driven environment.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  9. Closing Thoughts and Future Roadmap
&lt;/h2&gt;

&lt;p&gt;Building Owlyn for the &lt;strong&gt;#GeminiLiveAgentChallenge&lt;/strong&gt; allowed us to move beyond traditional AI interviews by creating a truly live and immersive workspace. By synchronizing voice and vision, we’ve enabled both high-fidelity technical assessments and a persistent assistant mode for everyday development. We see this multimodal synergy as the new standard for how technical talent is discovered, validated, and empowered in a high-stakes engineering world.&lt;/p&gt;

&lt;p&gt;Looking forward, we’re expanding the Owlyn ecosystem with the following roadmap:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Team-Based Mode&lt;/strong&gt;: Moving beyond silent monitoring to allow recruiters to "jump in" to the live session at any point. This enables a hybrid workflow where a human interviewer can take over the lead from the AI for a final, high-fidelity cultural evaluation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deeper ATS Integration&lt;/strong&gt;: One-click exports to tools like Greenhouse or Lever to automate the hiring funnel.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Collaborative Whiteboarding&lt;/strong&gt;: Support for real-time collaboration between the agent and candidate on the same whiteboard canvas.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Building this for the &lt;strong&gt;#GeminiLiveAgentChallenge&lt;/strong&gt; has been an incredible experience, and we’re just getting started. 🦉&lt;/p&gt;

&lt;h3&gt;
  
  
  The Owlyn Team
&lt;/h3&gt;

&lt;h3&gt;
  
  
  Code Repository
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Frontend&lt;/strong&gt;: &lt;a href="https://github.com/A-Simie/Owlyn" rel="noopener noreferrer"&gt;https://github.com/A-Simie/Owlyn&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Backend&lt;/strong&gt;: &lt;a href="https://github.com/Akeem1955/OwlynBackend" rel="noopener noreferrer"&gt;https://github.com/Akeem1955/OwlynBackend&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Contributor&lt;/th&gt;
&lt;th&gt;GitHub Profile&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Mosimiloluwa Adebisi&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href="https://github.com/A-Simie" rel="noopener noreferrer"&gt;@A-Simie&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Akeem Adetunji&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href="https://github.com/Akeem1955" rel="noopener noreferrer"&gt;@akeem&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Adenuga Abdulrahmon&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href="https://github.com/Rahmannugar" rel="noopener noreferrer"&gt;@Rahmannugar&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

</description>
      <category>geminiliveagentchallenge</category>
      <category>googleaichallenge</category>
      <category>googlecloud</category>
      <category>gemini</category>
    </item>
    <item>
      <title>Designing a Flight Search Engine: Architecture, Caching, and Trade-offs</title>
      <dc:creator>Rahman Nugar</dc:creator>
      <pubDate>Tue, 20 Jan 2026 08:31:38 +0000</pubDate>
      <link>https://dev.to/rahmannugar/designing-a-flight-search-engine-architecture-caching-and-trade-offs-2jbn</link>
      <guid>https://dev.to/rahmannugar/designing-a-flight-search-engine-architecture-caching-and-trade-offs-2jbn</guid>
      <description>&lt;p&gt;I was recently asked to design and build a flight search engine using the Amadeus API as part of a frontend assessment. While the visible requirement was to surface flight results and price trends through a user-facing interface, I chose to approach the problem as a complete system rather than a UI-only task.&lt;/p&gt;

&lt;p&gt;To reflect how flight search products are built in practice, I introduced a server layer responsible for integrating a rate-limited external API, defining a stable internal data contract, and implementing a caching strategy that keeps latency low under repeated queries.&lt;/p&gt;

&lt;p&gt;The system uses global, deterministic caching keyed by search parameters rather than per-user caching. This allows identical searches to share cached results, reducing redundant upstream requests while keeping response times consistent across the application.&lt;/p&gt;

&lt;p&gt;This article documents the system design of Flight33, part of an ongoing series of applications I build under the “33” naming convention. You can view the live application available at &lt;a href="https://flyt33.vercel.app" rel="noopener noreferrer"&gt;Flight33&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. System Architecture&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;2. System Boundaries and Constraints&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;3. Data Flow and Responsibilities&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;4. Global Caching Strategy&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;5. Data Normalization and Contracts&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;6. Code Structure and Separation of Concerns&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;7. Client Responsibilities and State Management&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;8. Booking Flow Integration&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;9. Trade-offs and Limitations&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;10. Closing Thoughts&lt;/strong&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  1. System Architecture
&lt;/h2&gt;

&lt;p&gt;Flight33 is structured as a two-tier system with a clear separation between the client application and a server layer that mediates all access to external flight data.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;client&lt;/strong&gt; is responsible for user interaction, search input, filtering, and presentation.&lt;br&gt;
The &lt;strong&gt;server&lt;/strong&gt; layer handles integration with the Amadeus API, response shaping, caching, and enforcement of system constraints.&lt;/p&gt;

&lt;p&gt;The client does not communicate directly with the Amadeus API. All search requests are routed through the server layer, which acts as the single integration point for external flight data.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User
 ↓
Web Client (Next.js)
 ↓
Flight33 API
 ↓
Redis Cache
 ↓
Amadeus API
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With this abstraction, Rate limits, response inconsistencies, and caching behavior are handled once, in a controlled environment, rather than being distributed across the client. As a result, the client remains predictable and focused on delivering a responsive search experience.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. System Boundaries and Constraints
&lt;/h2&gt;

&lt;p&gt;The design of Flight33 is driven primarily by the constraints imposed by the Amadeus API and the expectations of a responsive search experience.&lt;/p&gt;

&lt;p&gt;The Amadeus API is rate-limited, exhibits variable latency, and returns responses whose structure can vary depending on query shape. Treating it as a direct dependency of the client would couple user experience to these constraints and make system behavior harder to control.&lt;/p&gt;

&lt;p&gt;To avoid this, all interaction with Amadeus is isolated behind the server layer. This establishes a clear boundary where external variability is handled explicitly, rather than leaking into the client through retries, conditional logic, or UI workarounds.&lt;/p&gt;

&lt;p&gt;Within this boundary, the system enforces a small set of invariants:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;External API access is centralized and controlled&lt;/li&gt;
&lt;li&gt;Identical searches resolve deterministically&lt;/li&gt;
&lt;li&gt;Cached data is shared globally rather than scoped to individual users&lt;/li&gt;
&lt;li&gt;The client interacts only with normalized, stable data structures&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  3. Data Flow and Responsibilities
&lt;/h2&gt;

&lt;p&gt;A flight search in Flight33 follows a deliberately constrained flow designed to minimize external API usage while keeping client interactions responsive.&lt;/p&gt;

&lt;p&gt;A search begins when the client submits a set of parameters, including origin, destination, dates, and passenger configuration. These parameters are forwarded to the server layer as a single search request.&lt;/p&gt;

&lt;p&gt;On receipt, the server layer performs three sequential steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Cache resolution&lt;br&gt;
A deterministic cache key is generated from the full search payload. If a matching entry exists, the cached result is returned immediately.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;External fetch&lt;br&gt;
If no cached result is found, the server fetches data from the Amadeus API using the validated search parameters.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Response shaping&lt;br&gt;
The raw response is normalized into a stable internal structure before being returned to the client and written to cache.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Once the client receives the search results, no further network requests are required for filtering or pagination. All subsequent interaction operates on the in-memory dataset provided by the initial response.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Global Caching Strategy
&lt;/h2&gt;

&lt;p&gt;Caching is central to how Flight33 controls latency and external API usage.&lt;/p&gt;

&lt;p&gt;Search results are cached globally, not per user. A deterministic cache key is derived from the complete search payload, ensuring that identical searches resolve to the same cached entry regardless of who initiates them. This allows repeated queries to benefit from shared cache state rather than fragmenting cache usage across sessions.&lt;/p&gt;

&lt;p&gt;The cache itself is backed by an in-memory data store(Redis) running alongside the server layer. Cached entries are written with a short time-to-live to balance freshness with performance, allowing the system to serve repeat searches quickly while avoiding long-lived stale data.&lt;/p&gt;

&lt;p&gt;Because caching is handled within the server layer, the client remains unaware of whether a response was served from cache or fetched upstream. This keeps client behavior consistent while allowing cache policies to evolve independently.&lt;/p&gt;

&lt;p&gt;During development and deployment, the cache service runs alongside the server layer using Docker, allowing cache behavior to be tested under the same assumptions used in production. This avoids environment-specific logic and keeps cache semantics consistent across local and deployed setups.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Data Normalization and Contracts
&lt;/h2&gt;

&lt;p&gt;Responses from the Amadeus API are not consumed directly by the client. The raw payload contains deeply nested structures, optional fields, and variations that depend on the search parameters.&lt;/p&gt;

&lt;p&gt;Before any data is returned, responses are transformed into a normalized internal format. This step extracts only the fields required for search results, pricing, and filtering, and maps them into a predictable structure.&lt;/p&gt;

&lt;p&gt;This normalization step serves two purposes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It isolates the client from upstream response variability&lt;/li&gt;
&lt;li&gt;It establishes a stable contract that the rest of the system can rely on&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As a result, changes in the external API surface do not propagate directly to the client, and frontend logic does not need to defensively handle inconsistent data shapes.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Code Structure and Separation of Concerns
&lt;/h2&gt;

&lt;p&gt;The server layer is structured around explicit responsibilities rather than generic layers or framework conventions.&lt;/p&gt;

&lt;p&gt;Search handling is composed of three distinct concerns:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Request coordination: receiving search input, validating parameters, and managing the request lifecycle&lt;/li&gt;
&lt;li&gt;Search execution: resolving cached results, invoking the external flight data provider when required, and aggregating responses&lt;/li&gt;
&lt;li&gt;Data transformation: converting provider-specific payloads into a stable internal data contract&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Caching logic is treated as a first-class concern rather than an implementation detail. Cache key generation, read/write behavior, and expiry policies are centralized and invoked explicitly as part of the search flow, rather than being hidden behind decorators or middleware.&lt;/p&gt;

&lt;p&gt;External integrations, including the Amadeus client and the cache client, are isolated behind well-defined interfaces. This prevents upstream changes or integration-specific behavior from leaking into search logic or request handling.&lt;/p&gt;

&lt;h2&gt;
  
  
  7. Client Responsibilities and State Management
&lt;/h2&gt;

&lt;p&gt;The client is intentionally limited to interaction and presentation concerns.&lt;/p&gt;

&lt;p&gt;Its responsibilities include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Collecting and validating search input&lt;/li&gt;
&lt;li&gt;Triggering search execution&lt;/li&gt;
&lt;li&gt;Rendering search results&lt;/li&gt;
&lt;li&gt;Managing UI state such as loading, errors, filtering, and pagination&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Once search results are returned, the client does not issue additional requests when filters change. All filtering and sorting operations are applied to the in-memory dataset returned by the initial search.&lt;/p&gt;

&lt;p&gt;This approach ensures fast feedback during interaction while keeping network usage predictable and minimal.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvkci5ovq7agfuj35gc2q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvkci5ovq7agfuj35gc2q.png" alt="Flight 33 Search Results" width="800" height="383"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  8. Booking Flow Integration
&lt;/h2&gt;

&lt;p&gt;Flight33 does not attempt to handle bookings directly.&lt;/p&gt;

&lt;p&gt;Each search result exposes a booking action that redirects users to an external booking platform with the relevant search parameters pre-filled. This allows users to continue the booking process without the system managing reservations, payments, or ticketing flows.&lt;/p&gt;

&lt;p&gt;This decision keeps the system focused on search and comparison while delegating transactional complexity to a platform designed for it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frv0z1low90rc1yb8wdhf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frv0z1low90rc1yb8wdhf.png" alt="Flight 33 Booking Interface" width="800" height="373"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  9. Trade-offs and Limitations
&lt;/h2&gt;

&lt;p&gt;This design makes several deliberate trade-offs.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Search result sets are expected to remain within a manageable size&lt;/li&gt;
&lt;li&gt;Client-side filtering assumes sufficient browser memory&lt;/li&gt;
&lt;li&gt;Cached results tolerate short-lived staleness&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If result volume or traffic patterns increased significantly, filtering and pagination would need to move server-side and be sent via every request, also the cache policies would need to be revisited.&lt;/p&gt;

&lt;h2&gt;
  
  
  10. Closing Thoughts
&lt;/h2&gt;

&lt;p&gt;Flight33 was approached as a system design problem rather than a UI exercise.&lt;/p&gt;

&lt;p&gt;By introducing a server layer to control external API access, define stable data contracts, and apply deterministic caching, the client remains predictable and responsive without compensating for upstream uncertainty.&lt;/p&gt;

&lt;p&gt;Flight33 demonstrates that even a simple search-driven application lives or dies by how external data is handled. By centralizing API access, caching identical searches globally, and returning a stable dataset for client-side interaction, the system keeps both performance and behavior predictable.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>redis</category>
      <category>docker</category>
      <category>nextjs</category>
    </item>
    <item>
      <title>Suite 33: A business management platform for SMEs.</title>
      <dc:creator>Rahman Nugar</dc:creator>
      <pubDate>Thu, 27 Nov 2025 01:26:49 +0000</pubDate>
      <link>https://dev.to/rahmannugar/suite-33-a-business-management-platform-for-smes-1gdl</link>
      <guid>https://dev.to/rahmannugar/suite-33-a-business-management-platform-for-smes-1gdl</guid>
      <description>&lt;p&gt;Running a small or medium sized business is difficult enough when operations are structured. Small and medium sized enterprises often rely on manual processes to run their operations. Sales are recorded on paper, inventory is tracked informally, payroll is handled in notebooks, and staff performance is evaluated without any structured system. These gaps often create delays, inaccuracies which is detrimental to business growth.&lt;/p&gt;

&lt;p&gt;Suite33 was created to close those gaps. It is a business management platform designed specifically for SMEs. The goal is simple. Build a digital system that reflects how small businesses already work, while making their day to day operations cleaner, faster and easier to track.&lt;/p&gt;

&lt;p&gt;Live Link - &lt;a href="https://suite33.vercel.app" rel="noopener noreferrer"&gt;Suite33&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. Why Suite33 Was Built&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;2. Understanding the Challenges SMEs Face&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;3. Designing the Suite33 Experience&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;4. Getting Started: Onboarding and Setup&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;5. The Modules That Shape Suite33&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;6. Business Security and Roles&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;7. Lessons Learned While Building Suite33&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;8. Closing Thoughts&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Why Suite33 Was Built
&lt;/h2&gt;

&lt;p&gt;Suite33 did not begin as a random idea. It came from firsthand experience.&lt;br&gt;
Recently, I was consulting with a business and I quickly noticed they ran their entire business activities with unorganized records. The business owner had no central view of how the business was performing. Decisions were made from instinct instead of data. It became clear that these businesses needed structure, hence Suite33.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Understanding the Challenges SMEs Face
&lt;/h2&gt;

&lt;p&gt;Before writing a line of code, it was important to understand the real problems facing several SMEs in Nigeria.&lt;/p&gt;

&lt;p&gt;After a thorough case study, I was able to draft out some of the most common issues:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Sales records disappear easily because they are written in notebooks or loose sheets.&lt;/li&gt;
&lt;li&gt;Inventory is uncertain, making it difficult to know what is available at any moment.&lt;/li&gt;
&lt;li&gt;Payroll takes too long, especially when each staff salary is calculated manually.&lt;/li&gt;
&lt;li&gt;Staff performance is subjective, with no historical score or monthly evaluation.&lt;/li&gt;
&lt;li&gt;Financial insights are unclear, since there is no unified view of revenue, spending and profit.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  3. Designing the Suite33 Experience
&lt;/h2&gt;

&lt;p&gt;I modelled Suite33 around clarity and structure. Instead of building a complex enterprise style system, the goal was to create something simple enough for daily use but powerful enough to rely on.&lt;/p&gt;

&lt;p&gt;Every screen, every form and every action follows three principles:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Keep the workflow familiar&lt;/strong&gt;&lt;br&gt;
If a business is used to notebooks, Suite33 should feel like a digital extension of that, not a replacement that forces new habits.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Reduce cognitive load&lt;/strong&gt;&lt;br&gt;
No cluttered screens, no confusing menus. Businesses should be able to understand their data at a glance.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Centralize everything&lt;/strong&gt;&lt;br&gt;
Sales, expenses, inventory, payroll, staff and KPIs should all be centralized in a single dashboard application.&lt;/p&gt;

&lt;p&gt;This approach ensured that Suite33 could serve small teams without overwhelming them.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Getting Started: Onboarding and Setup
&lt;/h2&gt;

&lt;p&gt;The onboarding flow guides the business into the platform step by step.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Business Setup&lt;/strong&gt;&lt;br&gt;
Users begin by providing the essential details:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Business name&lt;/li&gt;
&lt;li&gt;Industry&lt;/li&gt;
&lt;li&gt;Location&lt;/li&gt;
&lt;li&gt;Optional Business logo&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This immediately personalizes the workspace and prepares the environment for operations.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa80n623nikqhnq2gv68q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa80n623nikqhnq2gv68q.png" alt="Business Onboarding Image" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Inviting Staff&lt;/strong&gt;&lt;br&gt;
Admins can invite up to 10 staff members per month.&lt;br&gt;
This limit is intentional. It encourages businesses to gradually set up their team and ensures the system remains manageable during early adoption.&lt;br&gt;
Staff receive an email and join the business with their own login. Their roles determine what they can access in the platform.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyca75ueklokrdhbbokeo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyca75ueklokrdhbbokeo.png" alt="Staff Invite Image" width="800" height="449"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Editing Profile&lt;/strong&gt;&lt;br&gt;
Every user can update their personal information. This includes updating name, avatar.&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fijikzr8qfmbpv8nf6sab.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fijikzr8qfmbpv8nf6sab.png" alt=" " width="800" height="449"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjlfohgjl4pxvni5xbbmu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjlfohgjl4pxvni5xbbmu.png" alt=" " width="800" height="449"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  5. The Modules That Shape Suite33
&lt;/h2&gt;

&lt;p&gt;Suite33 contains several core modules, each responsible for one part of the business operation. They are connected behind the scenes, which allows the dashboard to generate a complete view of business performance.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sales Management&lt;/strong&gt;&lt;br&gt;
The sales module makes it easy for businesses to record daily sales and monitor revenue trends over time.&lt;br&gt;
With the ability to track monthly progress, visualize data export results and gain insights, SMEs finally gain clarity about how their business is performing. This transforms guesswork into informed decisions.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0p14bzcrczhyx7ax1vz1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0p14bzcrczhyx7ax1vz1.png" alt="Sales Image" width="800" height="451"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh99nmpqk54ln5xjzl6tv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh99nmpqk54ln5xjzl6tv.png" alt="Sales Image" width="800" height="449"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Expenditures&lt;/strong&gt;&lt;br&gt;
For a business to truly understand its profit margins, it must first understand spending.&lt;br&gt;
Suite33 allows businesses to log every expense, categorize it and review spending patterns throughout the year. Every expenditure feeds directly into the dashboard’s profit and loss calculation.&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkwcbpx3zdjwkcij436t4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkwcbpx3zdjwkcij436t4.png" alt="Expenditures Image" width="800" height="449"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7cv4gykr2chowmgqi9gp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7cv4gykr2chowmgqi9gp.png" alt="Expenditures Image" width="800" height="424"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Inventory Management&lt;/strong&gt;&lt;br&gt;
Inventory issues are one of the biggest pain points for SMEs. Suite33 simplifies this process with a clean, structured layout.&lt;/p&gt;

&lt;p&gt;Businesses can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create categories&lt;/li&gt;
&lt;li&gt;Add new inventory items&lt;/li&gt;
&lt;li&gt;Track quantities&lt;/li&gt;
&lt;li&gt;Edit details as stock changes&lt;/li&gt;
&lt;li&gt;Export inventory lists&lt;/li&gt;
&lt;li&gt;View low stock&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The system prevents accidental deletion of categories that still contain items, protecting the integrity of the data.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5uyw1xfmuazgd9ipyz7x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5uyw1xfmuazgd9ipyz7x.png" alt="Inventory Image" width="800" height="450"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F94pq2fnq67jyriuvuuqf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F94pq2fnq67jyriuvuuqf.png" alt="Inventory Image" width="800" height="449"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Payroll&lt;/strong&gt;&lt;br&gt;
Payroll is often the most repetitive and time consuming task for SMEs. Suite33 introduces a monthly payroll batch system that automates most of the work.&lt;/p&gt;

&lt;p&gt;Each month:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The admin generates a batch.&lt;/li&gt;
&lt;li&gt;Staff salaries are automatically included.&lt;/li&gt;
&lt;li&gt;Admin can update staff salaries and mark each staff as paid or unpaid.&lt;/li&gt;
&lt;li&gt;When the batch is complete, it can be locked to prevent accidental changes.&lt;/li&gt;
&lt;li&gt;Staff can view their payslip privately.&lt;/li&gt;
&lt;li&gt;Admins can export the payroll to Excel or CSV.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs77deqvf3ddeuobsbrwp.JPG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs77deqvf3ddeuobsbrwp.JPG" alt="Payroll Image" width="800" height="350"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9oytfn73dk70oy1do5ak.JPG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9oytfn73dk70oy1do5ak.JPG" alt="Payroll Image" width="800" height="333"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fukuf5llopu685r4kptat.JPG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fukuf5llopu685r4kptat.JPG" alt="Payroll Image" width="800" height="341"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Staff Management&lt;/strong&gt;&lt;br&gt;
Staff records are organized in one place. Admins can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add new staff&lt;/li&gt;
&lt;li&gt;Remove staff&lt;/li&gt;
&lt;li&gt;Edit roles&lt;/li&gt;
&lt;li&gt;Assign departments&lt;/li&gt;
&lt;li&gt;Staff only see information relevant to them.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiwxgpqgj1ftnmqn6i106.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiwxgpqgj1ftnmqn6i106.png" alt="Organization Management Image" width="800" height="449"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv0xy5vr0jnmxuu5s0mgp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv0xy5vr0jnmxuu5s0mgp.png" alt="Organization Management Image" width="800" height="449"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;KPI Tracking&lt;br&gt;
Performance evaluation becomes simpler with monthly KPI scoring.&lt;br&gt;
Instead of relying on memory or last minute judgments, businesses can maintain a consistent record of how each staff performs throughout the year.&lt;br&gt;
KPI scores help guide promotions, reviews and improvements.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm20hsrypc46a9bi098oy.JPG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm20hsrypc46a9bi098oy.JPG" alt="KPI Image" width="800" height="346"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyu9yxy0rsirhnb53cqiv.JPG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyu9yxy0rsirhnb53cqiv.JPG" alt="KPI Image" width="800" height="347"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frhpedbfcznc56zy84xmw.JPG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frhpedbfcznc56zy84xmw.JPG" alt="KPI Image" width="800" height="335"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Dashboard Overview&lt;/strong&gt;&lt;br&gt;
The dashboard is the heart of Suite33.&lt;br&gt;
It brings together data from every module to give the business a complete operational overview.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb54607pmeppobyll11e1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb54607pmeppobyll11e1.png" alt="Dashboard Overview Image" width="800" height="449"&gt;&lt;/a&gt;&lt;br&gt;
The dashboard displays:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Sales summary&lt;/li&gt;
&lt;li&gt;Expenditures summary&lt;/li&gt;
&lt;li&gt;Staff count&lt;/li&gt;
&lt;li&gt;Inventory count&lt;/li&gt;
&lt;li&gt;Payroll status&lt;/li&gt;
&lt;li&gt;Profit and loss table&lt;/li&gt;
&lt;li&gt;Business identity
This allows business owners to view their financial and operational health at a glance.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  6. Business Security and Roles
&lt;/h2&gt;

&lt;p&gt;Suite33 is structured around three access levels:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Admin&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Full access to all operations and business management.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Sub Admin(Assistant Admin)&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Support role with management access but limited payroll visibility.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Staff&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Restricted access with visibility limited to personal payslips and details.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This structure ensures privacy, accountability and security on all fronts.&lt;/p&gt;

&lt;h2&gt;
  
  
  8. Lessons Learned While Building Suite33
&lt;/h2&gt;

&lt;p&gt;Building Suite33 revealed several important insights about SMEs and software design.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. SMEs value simplicity above all else&lt;/strong&gt;&lt;br&gt;
Most small businesses do not need complex systems. They need clarity. They need something that simplifies their existing processes instead of replacing them.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Onboarding is as important as the product&lt;/strong&gt;&lt;br&gt;
Businesses lose interest quickly if the first steps feel overwhelming. Refining onboarding to be quick and human centered made adoption smoother.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Accuracy is everything when dealing with money&lt;/strong&gt;&lt;br&gt;
Payroll and financial modules must leave no room for uncertainty. The smallest error can create distrust. Ensuring reliability at every stage became a priority.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. A business cannot grow without visibility&lt;/strong&gt;&lt;br&gt;
SMEs often operate in the dark. When they finally see their numbers clearly, they make better decisions. Data presentation mattered just as much as data storage.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Scalability is not only about technology&lt;/strong&gt;&lt;br&gt;
It is also about designing workflows that still make sense when the business grows from 5 staff to 50 staff. Features were built to feel predictable, even when usage increases.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;6. Every role needs a different view of the system&lt;/strong&gt;&lt;br&gt;
Admins do not need the same interface as staff, and staff should never see what belongs only to administrators. Clear separation of roles became essential.&lt;/p&gt;

&lt;h2&gt;
  
  
  8. Closing Thoughts
&lt;/h2&gt;

&lt;p&gt;Suite33 is designed to give SMEs a more organized way to run their business. It replaces manual processes with a single system that tracks sales, inventory, expenses, payroll and staff performance in one place.&lt;/p&gt;

&lt;p&gt;The platform does not aim to complicate operations. Instead, it brings the structure small businesses need to work more efficiently and make informed decisions.&lt;/p&gt;

&lt;p&gt;As SMEs continue to grow, Suite33 gives them a dependable foundation to grow on.&lt;/p&gt;

</description>
      <category>businessmanagement</category>
      <category>webdev</category>
      <category>nextjs</category>
      <category>typescript</category>
    </item>
    <item>
      <title>Contemporary State Management and Data Operations in React</title>
      <dc:creator>Rahman Nugar</dc:creator>
      <pubDate>Thu, 16 Oct 2025 13:29:14 +0000</pubDate>
      <link>https://dev.to/rahmannugar/contemporary-state-management-and-data-operations-in-react-3kja</link>
      <guid>https://dev.to/rahmannugar/contemporary-state-management-and-data-operations-in-react-3kja</guid>
      <description>&lt;blockquote&gt;
&lt;h2&gt;
  
  
  Tools evolve, trends change.
&lt;/h2&gt;
&lt;/blockquote&gt;

&lt;p&gt;React introduced developers to a new way of thinking about UI, where components react to data and user interactions in real time. It started as a simple idea: manage state locally and let the UI update automatically. But as applications grew more complex, so did the challenge of handling state that needed to live across many parts of an app.&lt;/p&gt;

&lt;p&gt;Fast forward to &lt;code&gt;currentDate()&lt;/code&gt;, and we’ve come a long way from simple &lt;code&gt;useState&lt;/code&gt; and &lt;code&gt;useEffect&lt;/code&gt; for state management and data fetching respectively. Today, React developers work with &lt;code&gt;Context API&lt;/code&gt;, &lt;code&gt;Zustand&lt;/code&gt;, &lt;code&gt;Redux Toolkit&lt;/code&gt;, for managing state and &lt;code&gt;TanStack Query&lt;/code&gt;, &lt;code&gt;RTK Query&lt;/code&gt;, server side fetching(Nextjs) for querying or mutating data. Each tool solves a slightly different problem, and knowing which one to use for a particular project makes all the difference.&lt;/p&gt;

&lt;p&gt;In this article, we’ll take a detailed look at modern state management, data query and mutation in React. You’ll learn when each tool shines, how they fit together, and how to make the most of them in a modern React app.&lt;/p&gt;

&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Understanding React’s Core State Model&lt;/li&gt;
&lt;li&gt;Context API: The Native Option&lt;/li&gt;
&lt;li&gt;Zustand: Lightweight Yet Scalable&lt;/li&gt;
&lt;li&gt;Redux Toolkit: Predictable and Enterprise-Ready&lt;/li&gt;
&lt;li&gt;useEffect: The Misused Hook&lt;/li&gt;
&lt;li&gt;TanStack Query&lt;/li&gt;
&lt;li&gt;RTK Query&lt;/li&gt;
&lt;li&gt;ServerSide Fetching&lt;/li&gt;
&lt;li&gt;Patterns and Best Practices&lt;/li&gt;
&lt;li&gt;Conclusion&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  1. Understanding React’s Core State Model
&lt;/h2&gt;

&lt;p&gt;Before looking at the aforementioned contemporary tools, it’s worth revisiting the basics.&lt;/p&gt;

&lt;p&gt;React’s design encourages predictable, unidirectional data flow. Each component has its own state, typically managed with hooks like &lt;code&gt;useState&lt;/code&gt; and &lt;code&gt;useReducer&lt;/code&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Usestate&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const [name, setName] = useState("Nugar");
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This works perfectly for local, isolated state such as toggling a modal or tracking form input.&lt;/p&gt;

&lt;p&gt;For more complex scenarios, developers often use useReducer for clearer state transitions:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;UseReducer&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const initialState = { isOpen: false, modalType: null };

function reducer(state, action) {
  switch (action.type) {
    case "OPEN_MODAL": return { isOpen: true, modalType: action.payload };
    case "CLOSE_MODAL": return { isOpen: false, modalType: null };
    default: return state;
  }
}

const [state, dispatch] = useReducer(reducer, initialState);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The problem arises when different components need access to the same data. Manually passing props up and down the tree leads to “prop drilling,” which quickly becomes difficult to maintain. This is where global state solutions step in.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Context API: The Native Option
&lt;/h2&gt;

&lt;p&gt;The Context API is React’s built-in way to share data globally across components without prop drilling. It’s simple, dependency-free, and ideal for small applications or simple global state.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// theme-context.tsx
import { createContext, useContext, useState } from "react";

const ThemeContext = createContext(null);

export const ThemeProvider = ({ children }) =&amp;gt; {
  const [theme, setTheme] = useState("light");
  const toggleTheme = () =&amp;gt; setTheme(t =&amp;gt; (t === "light" ? "dark" : "light"));

  return (
    &amp;lt;ThemeContext.Provider value={{ theme, toggleTheme }}&amp;gt;
      {children}
    &amp;lt;/ThemeContext.Provider&amp;gt;
  );
};

export const useTheme = () =&amp;gt; useContext(ThemeContext);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Then in any component:&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const { theme, toggleTheme } = useTheme();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;When to Use&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Small projects or simple global state&lt;/li&gt;
&lt;li&gt;Shared values like theme, language, or authentication status&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Limitations&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Can trigger re-renders across all consuming components&lt;/li&gt;
&lt;li&gt;Becomes hard to manage as the app grows&lt;/li&gt;
&lt;li&gt;Not ideal for frequent or performance-sensitive updates&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The Context API shines for lightweight scenarios, but once your application grows or requires complex state logic, a dedicated library becomes a better fit.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Zustand: Lightweight Yet Scalable
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;Zustand&lt;/code&gt; has become a favorite among developers for its simplicity and performance. It provides a minimal, intuitive API that lets you create global stores without providers or reducers. I frequently use Zustand nowadays for projects that require global state management due to its simplicity and ease of use.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { create } from "zustand";

const useUserStore = create(set =&amp;gt; ({
  user: null,
  setUser: user =&amp;gt; set({ user }),
  logout: () =&amp;gt; set({ user: null })
}));
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Usage&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const { user, setUser, logout } = useUserStore();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No boilerplate, no extra setup. Zustand uses shallow comparison to prevent unnecessary re-renders, keeping your app fast and efficient.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why Developers Love It&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Minimal API and easy learning curve&lt;/li&gt;
&lt;li&gt;Excellent TypeScript support&lt;/li&gt;
&lt;li&gt;Works great for UI and session state&lt;/li&gt;
&lt;li&gt;Supports persistence, middlewares, and subscriptions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;When to Use&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Small to medium projects that need global state&lt;/li&gt;
&lt;li&gt;Applications with local caching or session management&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  4. Redux Toolkit: Predictable and Enterprise-Ready
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;Redux&lt;/code&gt; has been around for years, and while it used to be associated with boilerplate and verbosity, Redux Toolkit (RTK) changed that. RTK provides structured, opinionated utilities that simplify reducers, actions, and store configuration.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { configureStore, createSlice, PayloadAction } from "@reduxjs/toolkit";

interface AuthState {
  user: { name: string } | null;
}

const initialState: AuthState = { user: null };

const authSlice = createSlice({
  name: "auth",
  initialState,
  reducers: {
    login: (state, action: PayloadAction&amp;lt;{ name: string }&amp;gt;) =&amp;gt; {
      state.user = action.payload;
    },
    logout: state =&amp;gt; {
      state.user = null;
    },
  },
});

export const { login, logout } = authSlice.actions;
export const store = configureStore({ reducer: { auth: authSlice.reducer } });
export type RootState = ReturnType&amp;lt;typeof store.getState&amp;gt;;
export type AppDispatch = typeof store.dispatch;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Usage&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { useSelector, useDispatch } from "react-redux";
import { login, logout, RootState } from "./store";

export default function App() {
  const user = useSelector((state: RootState) =&amp;gt; state.auth.user);
  const dispatch = useDispatch();

  return user ? (
    &amp;lt;button onClick={() =&amp;gt; dispatch(logout())}&amp;gt;Logout&amp;lt;/button&amp;gt;
  ) : (
    &amp;lt;button onClick={() =&amp;gt; dispatch(login({ name: "Rahman" }))}&amp;gt;Login&amp;lt;/button&amp;gt;
  );
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  5. useEffect: The Misused Hook
&lt;/h2&gt;

&lt;p&gt;Before exploring modern data-fetching solutions, it’s important to talk about &lt;code&gt;useEffect&lt;/code&gt;, a hook that was never designed for fetching or mutating data, yet became the default tool for it in most React apps.&lt;/p&gt;

&lt;p&gt;When React Hooks were introduced, &lt;code&gt;useEffect&lt;/code&gt; filled an essential gap in functional components. It allowed developers to perform side effects; actions that happen outside React’s rendering cycle. These effects include subscribing to events, updating the document title, managing timers, or synchronizing state with browser APIs.&lt;/p&gt;

&lt;p&gt;In simple terms, &lt;code&gt;useEffect&lt;/code&gt; lets your component “reach outside” React’s pure rendering world and interact with the environment.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;useEffect(() =&amp;gt; {
  document.title = `Hello, ${userName}`;
}, [userName]);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is a perfect use case: the effect reacts to changes in &lt;code&gt;userName&lt;/code&gt; and synchronizes the browser title accordingly.&lt;/p&gt;

&lt;p&gt;However, over time, developers began using &lt;code&gt;useEffect&lt;/code&gt; for something it wasn’t built for — data fetching and mutation.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;useEffect(() =&amp;gt; {
  async function loadUser() {
    const res = await fetch("/api/user");
    const data = await res.json();
    setUser(data);
  }
  loadUser();
}, []);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;While this pattern works for small applications, it quickly becomes fragile as your app grows.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why useEffect Is a Poor Fit for Data Operations&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It Easily Re-Triggers Requests&lt;/li&gt;
&lt;li&gt;It Doesn’t Handle Caching or Syncing&lt;/li&gt;
&lt;li&gt;It Causes Race Conditions&lt;/li&gt;
&lt;li&gt;It Adds Manual Overhead&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These problems have even caused real-world incidents. Recently, Cloudflare experienced a large-scale performance issue that stemmed from an application repeatedly firing API calls due to misused React effects. The component’s re-renders multiplied outgoing requests, consuming massive internal bandwidth. The problem wasn’t React, it was a hook used for something beyond its purpose.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2p1phpaz7dh8bexzer5h.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2p1phpaz7dh8bexzer5h.jpg" alt="Cloudflare Blogpost on useEfffect" width="800" height="555"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What &lt;code&gt;useEffect&lt;/code&gt; Was Actually Meant For&lt;/strong&gt;&lt;br&gt;
The React team’s intention for useEffect has always been clear:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Setting up subscriptions or event listeners&lt;/li&gt;
&lt;li&gt;Managing timers, intervals, or animations&lt;/li&gt;
&lt;li&gt;Interacting with browser or third-party APIs&lt;/li&gt;
&lt;li&gt;Cleaning up resources when a component unmounts&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These are side effects, they are interactions that depend on or modify something outside of React’s data flow.&lt;/p&gt;

&lt;p&gt;Fetching data, however, is a data flow operation, not a side effect. It belongs in a layer that manages caching, background refetching, synchronization, and invalidation. That’s far beyond what useEffect was built to handle.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Modern Tools Do It Differently&lt;/strong&gt;&lt;br&gt;
Libraries like React Query, RTK Query, and frameworks like Next.js have redefined how React handles data operations.&lt;/p&gt;

&lt;p&gt;These tools aren’t built on top of &lt;code&gt;useEffect&lt;/code&gt;. Instead, they use dedicated data layers that integrate deeply with React’s rendering engine, concurrent features, and Suspense. They know when to fetch, how to cache, and when to revalidate, all without you manually orchestrating it.&lt;/p&gt;

&lt;p&gt;In modern React, &lt;code&gt;useEffect&lt;/code&gt; should be reserved for what it was meant to do: handling external side effects at the component level. For data fetching, the ecosystem has evolved, and the right tools now exist to handle that responsibility cleanly and efficiently.&lt;/p&gt;
&lt;h2&gt;
  
  
  6. TanStack Query: Data Fetching Made Declarative
&lt;/h2&gt;

&lt;p&gt;TanStack Query formerly known as React Query introduced a fundamental shift in how developers think about server data. Instead of manually managing loading, error, and caching logic, React Query abstracts those concerns behind a declarative API. It treats data as a cache that stays in sync with the server, not as temporary state inside your component.&lt;/p&gt;

&lt;p&gt;TanStack Query revolves around two main concepts:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Queries for reading data (fetching)&lt;/li&gt;
&lt;li&gt;Mutations for writing or updating data (creating, editing, deleting)
Both are managed within a powerful caching layer that automatically keeps your UI in sync with your backend.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Query Example&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { useQuery } from "@tanstack/react-query";

function UserProfile() {
  const { data, isLoading, isError } = useQuery({
    queryKey: ["user"],
    queryFn: async () =&amp;gt; {
      const res = await fetch("/api/user");
      if (!res.ok) throw new Error("Failed to fetch user");
      return res.json();
    },
  });

  if (isLoading) return &amp;lt;p&amp;gt;Loading...&amp;lt;/p&amp;gt;;
  if (isError) return &amp;lt;p&amp;gt;Something went wrong.&amp;lt;/p&amp;gt;;

  return &amp;lt;h2&amp;gt;Welcome back, {data.name}&amp;lt;/h2&amp;gt;;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This hook handles fetching, caching, and background refetching automatically. When the &lt;code&gt;queryKey&lt;/code&gt; changes, React Query knows it’s a different dataset and fetches accordingly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Mutation Example&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { useMutation, useQueryClient } from "@tanstack/react-query";
function UpdateUser() {
  const queryClient = useQueryClient();

  const mutation = useMutation({
    mutationFn: async (user) =&amp;gt; {
      const res = await fetch("/api/user", {
        method: "PUT",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify(user),
      });
      if (!res.ok) throw new Error("Failed to update user");
      return res.json();
    },
    onSuccess: () =&amp;gt; {
      // Automatically refresh user data
      queryClient.invalidateQueries(["user"]);
    },
  });

  const handleUpdate = () =&amp;gt; {
    mutation.mutate({ name: "Rahman Nugar" });
  };

  return (
    &amp;lt;button onClick={handleUpdate} disabled={mutation.isPending}&amp;gt;
      {mutation.isPending ? "Updating..." : "Update Profile"}
    &amp;lt;/button&amp;gt;
  );
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;TanStack Query handles retries, optimistic updates, and cache synchronization under the hood, freeing you from manually tracking loading or error states.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why It Matters&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Queries cache data and refresh it only when needed.&lt;/li&gt;
&lt;li&gt;Mutations update the server and sync local caches automatically.&lt;/li&gt;
&lt;li&gt;Background updates ensure your data stays fresh without blocking UI rendering.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  7. RTK Query: Redux-Powered Data Management
&lt;/h2&gt;

&lt;p&gt;While TanStack Query is a standalone solution, RTK Query extends the Redux Toolkit ecosystem with an integrated data-fetching layer. It’s ideal if you already use Redux for state management but want modern, efficient data handling without extra libraries.&lt;/p&gt;

&lt;p&gt;RTK Query provides similar declarative querying and mutation features but ties them directly into your Redux store.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Setting Up RTK Query&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { createApi, fetchBaseQuery } from "@reduxjs/toolkit/query/react";

export const userApi = createApi({
  reducerPath: "userApi",
  baseQuery: fetchBaseQuery({ baseUrl: "/api" }),
  endpoints: (builder) =&amp;gt; ({
    getUser: builder.query({
      query: () =&amp;gt; "/user",
    }),
    updateUser: builder.mutation({
      query: (user) =&amp;gt; ({
        url: "/user",
        method: "PUT",
        body: user,
      }),
    }),
  }),
});

export const { useGetUserQuery, useUpdateUserMutation } = userApi;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Integrate it into your Redux store:&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { configureStore } from "@reduxjs/toolkit";
import { userApi } from "./userApi";

export const store = configureStore({
  reducer: {
    [userApi.reducerPath]: userApi.reducer,
  },
  middleware: (getDefaultMiddleware) =&amp;gt;
    getDefaultMiddleware().concat(userApi.middleware),
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Using Queries and Mutations&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function User() {
  const { data, isLoading } = useGetUserQuery();
  const [updateUser, { isLoading: isUpdating }] = useUpdateUserMutation();

  if (isLoading) return &amp;lt;p&amp;gt;Loading user...&amp;lt;/p&amp;gt;;

  return (
    &amp;lt;div&amp;gt;
      &amp;lt;h2&amp;gt;{data.name}&amp;lt;/h2&amp;gt;
      &amp;lt;button
        onClick={() =&amp;gt; updateUser({ name: "Rahman Nugar" })}
        disabled={isUpdating}
      &amp;gt;
        {isUpdating ? "Updating..." : "Update"}
      &amp;lt;/button&amp;gt;
    &amp;lt;/div&amp;gt;
  );
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;RTK Query automatically caches responses, invalidates old data after mutations, and deduplicates concurrent requests while keeping data in Redux for predictable debugging and inspection.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;When to Use RTK Query&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You’re already using Redux Toolkit.&lt;/li&gt;
&lt;li&gt;You want a single source of truth for both app and server state.&lt;/li&gt;
&lt;li&gt;You need integrated caching and request lifecycle management.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  8. ServerSide Fetching(Nextjs)
&lt;/h2&gt;

&lt;p&gt;With frameworks like Next.js, data fetching moved beyond the client. Instead of fetching data after rendering, Next.js introduced ways to prefetch data on the server through &lt;code&gt;getServerSideProps&lt;/code&gt;, &lt;code&gt;getStaticProps&lt;/code&gt;, and, more recently, the Server Components model.&lt;/p&gt;

&lt;p&gt;Server fetching shifts the data-fetching responsibility to the server layer, improving performance, SEO, and initial load times.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example with Server Components&lt;/strong&gt;&lt;br&gt;
In the App Router (&lt;code&gt;app/&lt;/code&gt; directory), you can fetch data directly on the server without using useEffect or any client-side hooks:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// app/page.tsx
async function getUser() {
  const res = await fetch("https://api.example.com/user", {
    cache: "no-store",
  });
  return res.json();
}

export default async function Page() {
  const user = await getUser();

  return (
    &amp;lt;section&amp;gt;
      &amp;lt;h1&amp;gt;Welcome, {user.name}&amp;lt;/h1&amp;gt;
    &amp;lt;/section&amp;gt;
  );
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Mutations in Next.js&lt;/strong&gt;&lt;br&gt;
With the new Server Actions, Next.js now supports secure, server-side mutations as well:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"use server";

export async function updateUser(data: { name: string }) {
  await fetch("https://api.example.com/user", {
    method: "PUT",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify(data),
  });
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These actions can be directly called from client components using forms or event handlers, eliminating API route overhead while maintaining security and performance.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;When to Use&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Apps with strong SEO needs or public-facing content&lt;/li&gt;
&lt;li&gt;Projects that rely on fast, server-rendered pages&lt;/li&gt;
&lt;li&gt;Scenarios where data privacy and server security matter&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  9. Patterns and Best Practices
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. Separate UI State from Server State&lt;/strong&gt;&lt;br&gt;
Keep client-side UI logic (like modals or form inputs) separate from server-synced data.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Use useEffect Only for True Side Effects&lt;/strong&gt;&lt;br&gt;
Reserve it for browser interactions, subscriptions, or third-party integrations not data fetching.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Leverage Caching Layers&lt;/strong&gt;&lt;br&gt;
Tools like React Query and RTK Query prevent unnecessary requests and ensure consistent data.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Server-First Approach&lt;/strong&gt;&lt;br&gt;
In frameworks like Next.js, fetch data server-side whenever possible for better performance and SEO.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Handle Mutations with Invalidation&lt;/strong&gt;&lt;br&gt;
Always invalidate or update cached queries after a successful mutation to keep UI and server data aligned.&lt;/p&gt;

&lt;h2&gt;
  
  
  10. Conclusion
&lt;/h2&gt;

&lt;p&gt;State management and data operations are essential parts of building efficient and scalable React applications. While React’s built-in tools like Context and hooks such as useState or useReducer can handle smaller projects, more complex applications often need advanced solutions to manage global state, server state, and API interactions efficiently.&lt;/p&gt;

&lt;p&gt;For state management, libraries such as Redux Toolkit, Zustand provide robust and predictable ways to manage application-wide state. They help keep your logic organized and predictable, especially when multiple components need access to shared data or when actions in one part of the app affect another.&lt;/p&gt;

&lt;p&gt;When it comes to data fetching and mutations, tools like Tanstack Query and RTK Query simplify handling asynchronous operations, caching, and synchronization between the client and server.&lt;/p&gt;

&lt;p&gt;There are, of course, many other tools and technologies that address state management and data operations in React for example, libraries like Jotai, MobX, SWR, or even broader technologies like GraphQL that redefine how the client side communicate with the server side.&lt;/p&gt;

&lt;p&gt;That being said, the tools covered here represent the most widely adopted solutions in modern React development and the ones I’ve personally worked with in real-world projects to deliver consistent, performant, and maintainable applications.&lt;/p&gt;

</description>
      <category>react</category>
      <category>useeffect</category>
      <category>webdev</category>
      <category>redux</category>
    </item>
    <item>
      <title>📆Byte-DatePicker: A Lightweight React Date Picker</title>
      <dc:creator>Rahman Nugar</dc:creator>
      <pubDate>Sun, 03 Aug 2025 00:39:50 +0000</pubDate>
      <link>https://dev.to/rahmannugar/byte-datepicker-a-lightweight-react-date-picker-420d</link>
      <guid>https://dev.to/rahmannugar/byte-datepicker-a-lightweight-react-date-picker-420d</guid>
      <description>&lt;p&gt;Lately, whenever I try to use a date picker in a project, I run into two main issues:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;The default browser  feels outdated, inaccessible, and not intuitive enough for modern UIs.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;External UI libraries often come with bloated bundle sizes and tightly coupled components, making my app unnecessarily heavy.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;While working on a project at my company, I needed a simple, flexible, and lightweight date picker that could be styled easily — and nothing quite fit. So, I built Byte-DatePicker.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;✨ Introducing Byte-DatePicker&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Byte-DatePicker is a reusable React component library tailored for date selection in forms and dashboards. Written in TypeScript, It allows full date selection (day, month, year) and ships with smooth animations, responsive layout, and minimal styling — making it easy to plug into any modern UI.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.npmjs.com/package/byte-datepicker" rel="noopener noreferrer"&gt;🔗 Check it out on npm&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;🧩 Key Features&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;🚀 Small bundle size – No unnecessary dependencies&lt;/p&gt;

&lt;p&gt;📅 Full date selection – Ideal for forms, reports, billing, subscriptions, content scheduling, etc.&lt;/p&gt;

&lt;p&gt;💅 Minimal styling – Easily customizable with your own CSS&lt;/p&gt;

&lt;p&gt;⚛️ React 17, 18, 19 compatible&lt;/p&gt;

&lt;p&gt;🧠 TypeScript support – Strong types and intellisense out of the box&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install byte-datepicker
# or
yarn add byte-datepicker

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then in your component:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import ByteDatePicker from "byte-datepicker";
import "byte-datepicker/dist/index.css";

const App = () =&amp;gt; {
  return (
    &amp;lt;div&amp;gt;
      &amp;lt;h2&amp;gt;Select a Month and Year&amp;lt;/h2&amp;gt;
      &amp;lt;ByteDatePicker onChange={(date) =&amp;gt; console.log(date)} /&amp;gt;
    &amp;lt;/div&amp;gt;
  );
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0gxlasb2vhqb2ynu30up.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0gxlasb2vhqb2ynu30up.gif" alt=" " width="412" height="176"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp5oo1h9vrgt7h1kyhszp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp5oo1h9vrgt7h1kyhszp.png" alt=" " width="800" height="666"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Prop&lt;/th&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Default&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;value&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;`Date&lt;/td&gt;
&lt;td&gt;null`&lt;/td&gt;
&lt;td&gt;&lt;code&gt;null&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;onChange&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;(date: Date) =&amp;gt; void&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;undefined&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Callback when a date is selected&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;minYear&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;number&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;currentYear - 10&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Minimum year selectable&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;maxYear&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;number&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;currentYear + 10&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Maximum year selectable&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;className&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;string&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;""&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Custom class name for styling&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;👨‍💻 Why You Might Use This&lt;/strong&gt;&lt;br&gt;
You want a focused datepicker, without a full UI library.&lt;/p&gt;

&lt;p&gt;You're building something like a resume form, billing cycle selector, or historical filter.&lt;/p&gt;

&lt;p&gt;You want a modern, accessible component with zero styling opinion unless you want to customize it.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;💭 Final Thoughts&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;This is just the first version of byte-datepicker. If you use it and find it helpful (or want more features), I’d love your feedback.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.npmjs.com/package/byte-datepicker" rel="noopener noreferrer"&gt;🔗 See it on npm →&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let me know what you think or feel free to contribute! 👇&lt;/p&gt;

</description>
    </item>
    <item>
      <title>🚀 I finally built my first project on Electron Js: A Draggable Floating Webcam for Creators.</title>
      <dc:creator>Rahman Nugar</dc:creator>
      <pubDate>Sat, 02 Aug 2025 18:37:29 +0000</pubDate>
      <link>https://dev.to/rahmannugar/i-finally-built-my-first-project-on-electron-js-a-draggable-floating-webcam-for-creators-3d1h</link>
      <guid>https://dev.to/rahmannugar/i-finally-built-my-first-project-on-electron-js-a-draggable-floating-webcam-for-creators-3d1h</guid>
      <description>&lt;p&gt;Recently, I started a new job where one of the requirements was working with Electron.js — a framework I hadn’t touched before. Coming from a web development background (React, TypeScript, etc.), the idea of building desktop apps with web technologies felt both exciting and a bit daunting.&lt;/p&gt;

&lt;p&gt;To speed up my learning and get comfortable with Electron’s ecosystem, I decided to build a side project: &lt;em&gt;a floating, draggable webcam overlay for creators.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;🎥Floating Webcam — A Lightweight Camera Overlay App&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;If you’ve ever recorded tutorials, walkthroughs, or gameplay, you know how tedious it can be to position and overlay your webcam footage during post-production. I wanted to eliminate that step entirely.&lt;/p&gt;

&lt;p&gt;So I built Floating Webcam, a minimal desktop tool that lets you keep your webcam feed on top of other windows — no editing needed. Just launch the app, drag the camera feed where you want it, and start your screen recording software.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3m0k3o08zzzuwlj59cgz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3m0k3o08zzzuwlj59cgz.png" alt=" " width="800" height="623"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;No overlays. No clutter. Just record.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;🛠️ What It’s Built With&lt;/strong&gt;&lt;br&gt;
Electron.js – For creating a native-feeling cross-platform desktop app.&lt;/p&gt;

&lt;p&gt;React – To structure the UI and manage component state.&lt;/p&gt;

&lt;p&gt;TypeScript – For better DX and safer code.&lt;/p&gt;

&lt;p&gt;TailwindCSS – For rapid and responsive styling.&lt;/p&gt;

&lt;p&gt;Watch the demo on LinkedIn&lt;br&gt;
&lt;a href="https://www.linkedin.com/feed/update/urn:li:activity:7348222161079144448" rel="noopener noreferrer"&gt;Demo&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can view the full source code and try it yourself on GitHub:&lt;br&gt;
&lt;a href="//github.com/Rahmannugar/floating-webcam"&gt;GitHub&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  &lt;strong&gt;💡 Why I Built It&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;At work, I inherited an old Electron-based project that needed some serious improvements. Rather than dive straight into the legacy code, I figured the best way to understand how Electron works was to build something new and practical from the ground up.&lt;/p&gt;

&lt;p&gt;Floating Webcam became the perfect sandbox — not too simple, not overly complex, and aligned with real-world use cases.&lt;/p&gt;
&lt;h2&gt;
  
  
  &lt;strong&gt;🔍 What I Learned About Electron&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Before this project, my mental model was: "Electron just wraps a web app in a desktop shell."&lt;/p&gt;

&lt;p&gt;But once I got into it, I quickly realized Electron has its own architecture and design considerations.&lt;/p&gt;

&lt;p&gt;Here’s a breakdown of key concepts I picked up:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;🧵 Main vs Renderer Process&lt;/strong&gt;&lt;br&gt;
Electron apps run two types of processes:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Main process – Manages the app’s lifecycle, windows, and system-level interactions.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Renderer process – Runs inside each window (like a browser tab) and handles the UI.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Understanding how they work together — and when to separate logic between them — was a foundational step.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;🔐 Context Isolation + IPC&lt;/strong&gt;&lt;br&gt;
Because of security risks, Electron enforces context isolation between the main and renderer. So if you want to pass data (like media devices, window state, etc.), you need to use IPC (inter-process communication) via the contextBridge API.&lt;/p&gt;

&lt;p&gt;I learned how to expose safe APIs from the main process to the renderer, which allowed React to control Electron-native behavior without direct access to Node.js.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;🎥 Accessing Media Devices&lt;/strong&gt;&lt;br&gt;
Electron gives you access to the same Web APIs you’d use in the browser — like&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;navigator.mediaDevices.getUserMedia.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This meant I could handle webcam streams just as I would in a regular React app — but now within a persistent desktop environment.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;👨‍💻 Final Thoughts&lt;/strong&gt;&lt;br&gt;
Electron can be intimidating at first, especially if you're coming from a web-only background. But once you get the hang of its architecture and build flow, it’s surprisingly powerful.&lt;/p&gt;

&lt;p&gt;If you’ve ever wanted to turn a web app into a desktop app — or need native system access without learning a whole new language — Electron is absolutely worth exploring.&lt;/p&gt;

&lt;p&gt;This project gave me the hands-on experience I needed to start contributing confidently to Electron-based projects at work.&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>electron</category>
      <category>vite</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
