Context

Xnapper is a commercial screenshot tool that expanded into image and video editing. As a Software Developer on the team, I owned features across the interface, application state, processing, persistence and service integrations — not a single layer of the stack.

The technical difficulty came from moving beyond static screenshot editing into frame-accurate video workflows that had to stay reliable and maintainable across different runtime environments, without sacrificing performance.

My end-to-end scope

Frontend and product experience

Built editing interfaces with React and Next.js: timeline, clip manipulation, playback and export controls.

Application state and logic

Modeled editor state, undo/redo history and session/preset persistence, connecting interface behavior to the product's different workflows.

Processing

Implemented video processing with Node.js, FFmpeg and WebAssembly, coordinating files, playback, progress and output generation.

Backend and data

Designed and shipped a serverless licensing service that enforced per-device business rules and persisted activation state in Redis.

React / Next.js UI
Editor state & logic
Node.js processing (FFmpeg / WASM)
Serverless backend service
Upstash Redis persistence

The product needed to move beyond static screenshot editing and support reliable video workflows without sacrificing performance, maintainability or consistency across environments.

What I Built

The Electron application uses the Xnapper web app

Video editing pipeline

Built this capability end to end: from timeline interactions and state modeling to frame extraction, processing and final export.

  • Designed the interface and interactions for timeline, clips and playhead.
  • Modeled editing state, clip normalization and undo/redo history.
  • Built frame-accurate playback and seeking.
  • Implemented processing and export with FFmpeg/WASM.
  • Integrated progress, cancellation, error handling and final file generation.

Authentication & integrations

  • Implemented the Google OAuth authentication flow for both the web app and the desktop application.
  • Hardened session handling and renewal to keep product flows authenticated.

Backend licensing service

Designed and shipped a serverless backend to validate commercial licenses and control how many devices could be associated with each user.

  • Built the validation endpoint with Node.js and Express, deployed as a serverless function.
  • Modeled licenses and active devices on top of Upstash Redis.
  • Enforced per-device seat limit rules.
  • Implemented idempotent activation to avoid duplicate records on repeated validation calls.
  • Handled soft-delete device removal without losing activation history.

Product state & architecture

  • Export Strategy abstraction
  • Undo/redo history based on the Memento pattern
  • Session and preset persistence
  • Cross-runtime behavior consistency

Reliability & security

  • Safer file and path handling
  • Reduced local-server attack surface
  • Removal of unsafe process integrations
  • Automated tests for critical paths

Decisions

Demuxer-based frame extraction

Native video seeking wasn't reliable on variable-frame-rate footage — a seek could land on the wrong frame, breaking frame-accurate editing.

Extracted frames through a demuxer instead of relying on native seek, giving the editor a consistent, frame-accurate source regardless of a clip's original encoding.

Export strategies

Supporting multiple export targets was spreading conditional logic across the codebase, making every new export option riskier to add.

Introduced a shared export strategy interface so each target implements the same contract, keeping the branching logic in one place instead of scattered conditionals.

Idempotent activation model

The client could validate the same license repeatedly, and an already-active device shouldn't duplicate its record or consume more than one available seat.

Designed activation as an idempotent operation: if the device was already active, the service returned success without duplicating the record. Deactivations were modeled with soft-delete to preserve history without consuming an available seat.

Outcome

  • Expanded the product from screenshot-focused workflows into video editing.
  • Shipped the work through multiple production releases.
  • Improved maintainability of export and persistence flows.
  • Reduced important security and reliability risks.
  • Supported a product used by approximately 20,000 users.

Stack

  • TypeScript
  • React
  • Next.js
  • Node.js
  • Electron
  • FFmpeg / WebAssembly
  • WebGL
  • Zustand / Jotai
  • Redis / Upstash
  • Jest / Vitest
See my resumeGet in touchBack to portfolio