<?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: XuXin</title>
    <description>The latest articles on DEV Community by XuXin (@zn070515).</description>
    <link>https://dev.to/zn070515</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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4239463%2F73319a79-ca2f-4b9c-8667-01b0d3c61a0e.jpg</url>
      <title>DEV Community: XuXin</title>
      <link>https://dev.to/zn070515</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/zn070515"/>
    <language>en</language>
    <item>
      <title>I Built ArtFlow to Tame the Chaos Behind Live Events</title>
      <dc:creator>XuXin</dc:creator>
      <pubDate>Wed, 11 Nov 2026 16:22:16 +0000</pubDate>
      <link>https://dev.to/zn070515/i-built-artflow-to-tame-the-chaos-behind-live-events-13i6</link>
      <guid>https://dev.to/zn070515/i-built-artflow-to-tame-the-chaos-behind-live-events-13i6</guid>
      <description>&lt;p&gt;A live event can look effortless from the audience. Behind the scenes, it can be a maze of spreadsheets, chat groups, forms, uploaded files, scoring sheets, and last-minute decisions.&lt;/p&gt;

&lt;p&gt;ArtFlow started from that gap. Its first real-world context was organizing university arts events, including a singing competition and stage performances. The goal was never just another voting page or a prettier registration form. It was to make the &lt;strong&gt;entire event workflow consistent, recoverable, and explainable&lt;/strong&gt;—especially when things change minutes before going live.&lt;/p&gt;

&lt;p&gt;I'm sharing the project while its v2 architecture is actively evolving, both to explain the engineering decisions and to hear from people who have built or run similar systems.&lt;/p&gt;

&lt;h2&gt;
  
  
  The problem isn't one missing tool
&lt;/h2&gt;

&lt;p&gt;For a competition, you might already have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a form for registration;&lt;/li&gt;
&lt;li&gt;a spreadsheet for contestants and scores;&lt;/li&gt;
&lt;li&gt;chat messages for missing materials and urgent updates;&lt;/li&gt;
&lt;li&gt;a separate voting link for the audience;&lt;/li&gt;
&lt;li&gt;manually assembled results and archives.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each part works on its own. The failure happens &lt;strong&gt;between&lt;/strong&gt; them. Is the lineup finalized? Has the judging round been locked? Can a corrected score overwrite an already confirmed result? Is a rehearsal vote accidentally mixed into the real tally? What should staff see when a connection drops?&lt;/p&gt;

&lt;p&gt;These aren't just UI questions. They are questions about authority, state, and recovery.&lt;/p&gt;

&lt;h2&gt;
  
  
  From a competition app to a composable EventOps platform
&lt;/h2&gt;

&lt;p&gt;ArtFlow v1 was a Django-based system built around an actual event workflow. After that experience, I started rebuilding the product as &lt;strong&gt;ArtFlow v2 / ArtFlow-Plus&lt;/strong&gt;: a composable operations platform for competitions and complex events.&lt;/p&gt;

&lt;p&gt;The intended user-facing product has four surfaces:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Studio&lt;/strong&gt; — define the event, its rules, forms, roles, and workflows.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ops&lt;/strong&gt; — prepare the real people, materials, reviews, and operational tasks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Live&lt;/strong&gt; — operate the event, control scoring/voting, and handle on-site changes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Portal&lt;/strong&gt; — give participants, judges, staff, and audiences appropriate views and actions.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These aren't four unrelated applications. They share an &lt;strong&gt;Activity Engine&lt;/strong&gt; and reusable &lt;strong&gt;capabilities&lt;/strong&gt; such as registration, materials, competition, voting, ticketing, publishing, grouping, tasks, and archive.&lt;/p&gt;

&lt;p&gt;Different event shapes are composed from capabilities and default definitions. The repository currently includes packs for singer competitions, stage-show collection, review awards, and voting-oriented workflows. Tests cover distinct event journeys on the same core instead of duplicating a separate engine for each format.&lt;/p&gt;

&lt;h2&gt;
  
  
  Correctness before a flashy live dashboard
&lt;/h2&gt;

&lt;p&gt;The most important engineering choices are about preserving meaning under pressure:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. A single authoritative write path.&lt;/strong&gt; Commands produce a receipt, audit information, domain facts, and an outbox record within one transaction. Retries should be explainable, not silently applied twice.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Explicit finality.&lt;/strong&gt; A configured release is immutable. Confirmed results have a controlled publishing path; corrections shouldn't quietly rewrite history.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Rehearsal and formal execution are isolated.&lt;/strong&gt; Event mode affects facts, votes, rankings, events, and projections—not just a visual badge in the UI.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Realtime is a convenience, not the source of truth.&lt;/strong&gt; A WebSocket can signal that something changed. HTTP remains the recovery authority if the realtime connection disappears.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Capabilities have boundaries.&lt;/strong&gt; One capability should not reach into another capability's tables and reinterpret its business facts. Cross-capability behavior goes through explicit contracts.&lt;/p&gt;

&lt;p&gt;This approach is more work than creating an impressive demo page, but it targets the failures that matter during an actual event.&lt;/p&gt;

&lt;h2&gt;
  
  
  Under the hood
&lt;/h2&gt;

&lt;p&gt;The current v2 development baseline uses:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;TypeScript 7 / Node.js 24&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fastify 5&lt;/strong&gt; with TypeBox contracts and OpenAPI&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;React 19&lt;/strong&gt; for the web surfaces&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;PostgreSQL 18&lt;/strong&gt; with Kysely&lt;/li&gt;
&lt;li&gt;a transactional outbox and projection relay&lt;/li&gt;
&lt;li&gt;a single realtime core with WebSocket invalidation signals and HTTP recovery&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The repository also documents architectural decisions, invariants, test gates, event-shape validation, and a roadmap. Those documents are part of how the system is reviewed, not just an afterthought.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is available today—and what isn't
&lt;/h2&gt;

&lt;p&gt;The public repository's &lt;strong&gt;main branch now tracks v2&lt;/strong&gt;, the only active development line. The historical Django 1.x implementation is preserved at tag &lt;strong&gt;v1.0.2&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;v2 has implemented and tested many core journeys. It is &lt;strong&gt;still being developed&lt;/strong&gt;, and the repository explicitly tracks remaining gaps—including some public content/program surfaces, spreadsheet/document exports, and more advanced competition formats. I'm not presenting it as a finished, universally deployable SaaS product or claiming that every planned surface is complete.&lt;/p&gt;

&lt;p&gt;One licensing detail matters: &lt;strong&gt;ArtFlow is source-available, not OSI-licensed open source.&lt;/strong&gt; The project offers PolyForm Noncommercial and PolyForm Internal Use terms, with separate written licensing for uses outside those grants. Please check the actual license before reuse or deployment.&lt;/p&gt;

&lt;h2&gt;
  
  
  I'd love feedback from event operators and builders
&lt;/h2&gt;

&lt;p&gt;If you've helped run competitions, conferences, campus events, festivals, or live productions: &lt;strong&gt;which failure modes did your tools handle badly?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I'm particularly interested in:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;judging and result correction under time pressure;&lt;/li&gt;
&lt;li&gt;last-minute changes to participants or schedules;&lt;/li&gt;
&lt;li&gt;concurrent staff actions and permission boundaries;&lt;/li&gt;
&lt;li&gt;unreliable venue networks and recovery behavior;&lt;/li&gt;
&lt;li&gt;keeping rehearsals from contaminating formal records.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Project and technical documentation: &lt;strong&gt;&lt;a href="https://github.com/Zn070515/ArtFlow" rel="noopener noreferrer"&gt;ArtFlow on GitHub&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Architecture and product scope: &lt;strong&gt;&lt;a href="https://github.com/Zn070515/ArtFlow/blob/main/GOAL.md" rel="noopener noreferrer"&gt;ArtFlow GOAL&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Thanks for reading. I'd be happy to compare notes with anyone solving similar operational problems.&lt;/p&gt;

</description>
      <category>showdev</category>
      <category>architecture</category>
      <category>typescript</category>
      <category>buildinpublic</category>
    </item>
  </channel>
</rss>
