Portfolio

ZenFlow Charts – Interactive Dashboards

A minimalist online flowchart maker that grew past 1.6M users and won Product Hunt #1 Product of the Day. Customized the mxGraph engine and rebuilt PNG export (GD to ImageMagick) to hold quality at any size.

ZenFlow Charts – Interactive Dashboards

The product

Zen Flowchart is a minimalist online flowchart and diagram maker, built around one stubborn idea: keep the simplest tool feeling simple, even at scale. Marketers, teachers, students, and product teams open a blank canvas and build flowcharts, mind maps, org charts, and whiteboards with one-click nodes, smart connectors, and drag-and-drop editing. No setup, no clutter. The product grew past 1.6 million users and won Product Hunt #1 Product of the Day, and reviews consistently single out the clean editing experience as the reason people stay.

My role

I worked as a full-stack developer across multiple contracts with the founder during the growth phase, from 2018 to 2020. I owned the backend application end to end and the frontend logic the whole editor runs on: the diagram engine, the persistence layer that stores every chart, the server-side image and export pipeline, authentication, and the Stripe billing that powers the paid tier. The brief was always the same. Add capability without adding weight, so the product that won people over by being simple stayed that way.

Architecture

The application is a custom PHP backend on a lightweight front-controller MVC framework rather than a heavyweight framework. The design is deliberately layered so each concern stays in its own place as features grow:

  • Front-controller routing. A single entry point resolves each request to a module and an action, then dispatches to the matching controller. Adding a feature means adding a module, not threading logic through a monolith. Clean separation of the HTTP layer from everything below it.
  • Active-record domain layer. Each entity (documents, version history, subscribers, projects, billing, redemption codes) is a domain class extending a shared data-access base. Controllers stay thin and talk to these models; SQL and persistence details live behind the model, never in the request handler. SOLID single-responsibility and dependency inversion in practice, not on a slide.
  • Autoloaded classes and traits. Domain classes and shared traits load on demand through registered autoloaders, so the codebase stays modular and additive instead of a tangle of includes.
  • Separation of rendering from storage. The diagram itself is stored as a portable model, and image generation is a separate pipeline that reads that model. Editing, persistence, and rasterization are three independent stages, which is what let me rebuild the export engine without touching how charts are saved.
  • Templating and delivery. Server-rendered views go through a modern templating engine with compiled caching and HTML compression, so pages stay light over the wire.

The engineering challenge

The hard part of a flowchart tool is not drawing boxes on a screen. It is this: a diagram is a graph of nodes and edges with positions, sizes, colors, fonts, arrow directions, and styling, and the application has to store all of that faithfully, let the user reopen and edit it pixel-for-pixel later, and also turn it into a high-quality downloadable image on demand. So every chart is persisted as a structured model that captures the full node-and-edge graph with all of its attributes, which is what makes re-editing exact. Generating an image from that model is the part that quietly stores and computes a lot: the server has to parse the graph, lay it out, and rasterize it into a crisp file at any size.

The original export pipeline used PHP’s GD library, and it degraded badly as diagrams got larger. Text blurred, edges got rough, and big charts came out looking nothing like what the user designed. For a product whose entire promise is a clean look, that was an existential bug, not a cosmetic one.

What I built

  • Customized the open-source mxGraph editing engine from the ground up so one-click node creation, smart connectors, and drag-and-drop stayed instant as diagrams grew
  • A persistence layer that stores each chart as a complete node-and-edge graph model, preserving every attribute so charts reopen and re-edit exactly as the user left them
  • A from-scratch server-side image renderer that parses the stored graph model, draws every node, edge, arrowhead, and word-wrapped multi-line label, corrects negative coordinate bounds, scales the canvas, crops to content, and adds a clean border before output
  • Rebuilt the export pipeline from GD onto ImageMagick (Imagick), rendering the parsed model to a server-side image that held its quality at any resolution. That single change turned a recurring complaint into a selling point
  • Export to multiple formats, plus version history with auto-save, trash and restore, and document and folder management for organizing many charts
  • Publish and unpublish for shareable, embeddable charts, with obfuscated public links so internal record IDs are never exposed
  • Authentication with email and password and Sign in with Google, CSRF protection, and per-action login and permission checks on every operation
  • Stripe-powered subscription billing with free and pro tiers, webhook handling for subscription state, and a redemption-code system for lifetime-deal campaigns

Engineering practices

Persistence is parameterized and gated: every save and load runs behind authentication, an ownership and permission check, and a CSRF token, so one account can never read or write another’s charts. Sessions are namespaced to the app and the public-facing identifiers are hashed rather than raw database IDs, which keeps the surface clean. Configuration lives in environment variables, not in code, so credentials never sit in the repository. Server-side analytics are sent through the Google Analytics Measurement Protocol so product events are captured reliably rather than depending on the browser. The editor ships with multi-language resource files, and the careful version-history and auto-save design means a user’s work is recoverable rather than lost on a bad edit.

Stack

PHP on a custom front-controller MVC framework, MySQL for chart and account persistence, and modern JavaScript with a heavily customized mxGraph editor on the frontend. Server-side image generation runs on ImageMagick (Imagick), replacing the original GD pipeline. Supporting pieces: AWS S3 for asset storage, Stripe for subscription billing and webhooks, Google OAuth for social login, SendGrid and PHPMailer for transactional email, Hashids for obfuscated public links, and a Twig templating layer with compiled caching and HTML compression.

Outcome

Rendering and export quality that kept “the simplest tool” feeling simple at scale. The GD-to-ImageMagick rebuild fixed the export quality that users had complained about and made crisp, any-size downloads a reason to upgrade. The product grew past 1.6 million users and won Product Hunt #1 Product of the Day, with reviews that keep pointing to the editing experience as the reason people stay. The same separation of storage from rendering that solved the export problem is exactly the kind of clean foundation an AI-assisted diagramming roadmap would build on, generating and restyling charts from the structured graph model the application already stores.