<?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>Forem: Terry Zhang</title>
    <description>The latest articles on Forem by Terry Zhang (@terryzhang).</description>
    <link>https://forem.com/terryzhang</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%2F997546%2Faca3e5a1-b35e-4e03-ae6b-6115c4f33661.png</url>
      <title>Forem: Terry Zhang</title>
      <link>https://forem.com/terryzhang</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/terryzhang"/>
    <language>en</language>
    <item>
      <title>The Story That Almost Wasn't — How LlamaGen Changed Everything December 4, 2024</title>
      <dc:creator>Terry Zhang</dc:creator>
      <pubDate>Fri, 03 Apr 2026 04:28:47 +0000</pubDate>
      <link>https://forem.com/terryzhang/the-story-that-almost-wasnt-how-llamagen-changed-everything-december-4-2024-3p07</link>
      <guid>https://forem.com/terryzhang/the-story-that-almost-wasnt-how-llamagen-changed-everything-december-4-2024-3p07</guid>
      <description>&lt;p&gt;There is a moment every artist knows.&lt;/p&gt;

&lt;p&gt;You sit down. The canvas is white. The cursor blinks. And somewhere between the story burning in your head and the page in front of you, something seizes up. Not a lack of ideas — you have too many. Not a lack of will. Something more primal: the terror that what you make will be smaller than what you imagine.&lt;/p&gt;

&lt;p&gt;I've spoken to hundreds of comic artists, animators, and game creators over the past few years. The blank page comes up every time. Not as a metaphor. As a real, recurring experience that has stopped real stories from ever being told.&lt;/p&gt;

&lt;p&gt;That conversation is why I built LlamaGen.Ai.&lt;/p&gt;

&lt;p&gt;What the Blank Page Actually Costs&lt;br&gt;
Jenny is a freelance comic artist based in Berlin. Eight years of professional experience in traditional manga-style storytelling. She described her studio before she found us: a small room, a drawing tablet, and the particular kind of paralysis that sets in when you have a story but can't yet see it.&lt;/p&gt;

&lt;p&gt;"I would spend days sketching rough layouts," she told me. "Second-guessing every panel composition before a single line felt committed."&lt;/p&gt;

&lt;p&gt;Her story is not unusual. It is, in fact, the rule.&lt;/p&gt;

&lt;p&gt;The economics of visual storytelling have always been brutal in a way that writing and music are not. A sentence costs nothing to revise. A comic panel — with its composition, lighting, character expression, and sequential logic — can take hours. An anime episode takes hundreds of artists and months of grinding work. The gap between idea and execution is so wide, and so expensive, that most of the world's visual stories simply don't get made.&lt;/p&gt;

&lt;p&gt;Not because they aren't good enough. Because the people who carry them run out of time before they ever begin.&lt;/p&gt;

&lt;p&gt;A Simple Idea, Extraordinarily Hard to Build&lt;br&gt;
When Jenny uploaded her first story to LlamaGen.Ai — a girl discovering a magical garden — eight rendered comic panels appeared within moments. Not placeholder sketches. Panels that captured the wonder she had imagined but struggled to get on paper.&lt;/p&gt;

&lt;p&gt;"It wasn't just about the technology," she said. "It was about transforming that intimidating blank canvas into a springboard."&lt;/p&gt;

&lt;p&gt;That is the sentence I want to put on everything we build.&lt;/p&gt;

&lt;p&gt;The idea behind LlamaGen.Ai is almost embarrassingly simple: a creator should be able to describe what they see in their head, and a machine should render it — panels, characters, storyboards, the full visual architecture of a story — in seconds instead of months.&lt;/p&gt;

&lt;p&gt;Simple to say. Genuinely hard to build well.&lt;/p&gt;

&lt;p&gt;We needed a system that understood sequential art not just as a collection of images, but as a language — with grammar, pacing, the weight of a silent panel, the logic of a face changing across six frames of emotion. We needed character consistency: the same person, recognizable at panel 1 and panel 300, through different lighting and angles and expression. We needed it to understand that a comic page is not a gallery. It is a time machine.&lt;/p&gt;

&lt;p&gt;The Skeptic's Journey&lt;br&gt;
Jenny came to us skeptical. Most artists do. The question is always some version of the same fear: will this make my work less mine?&lt;/p&gt;

&lt;p&gt;What she found — what I hear from creators across twelve countries now — is the opposite. The AI doesn't replace the artist's vision. It amplifies it. The generated panels become a dialogue: the machine offers a perspective, the artist responds, the story emerges from the conversation.&lt;/p&gt;

&lt;p&gt;"Sometimes an unexpected angle would spark an entirely new direction," she said. "Perspectives I hadn't considered. I started exploring artistic territories I might have otherwise overlooked."&lt;/p&gt;

&lt;p&gt;That is not automation. That is collaboration. And it changes the creative process at its root — not by removing the artist, but by eliminating the specific suffering that happened before the artist could begin.&lt;/p&gt;

&lt;p&gt;What We're Actually Building&lt;br&gt;
LlamaGen.Ai is, on the surface, an AI platform for comics, anime, and game creation. But the mission underneath is bigger than the product.&lt;/p&gt;

&lt;p&gt;We want to build a world where every story that deserves to exist gets made. Where the creator in Osaka with the story that should become a series isn't stopped by the cost of a studio. Where the blank page is no longer a barrier, but an invitation.&lt;/p&gt;

&lt;p&gt;The greatest IP in history — the characters and worlds that have become cultural infrastructure — started as someone's drawing on paper. We believe AI unlocks the next generation of that. Not by replacing artists, but by giving every artist an impossibly fast, impossibly patient creative partner.&lt;/p&gt;

&lt;p&gt;Jenny put it better than I could: "Starting with AI-generated panels doesn't limit creativity. It opens up possibilities I never knew existed."&lt;/p&gt;

&lt;p&gt;That's the product. That's the company. That's why I show up every day.&lt;/p&gt;

&lt;p&gt;The blank page was never the enemy. We just finally built something to prove it.&lt;/p&gt;

&lt;p&gt;— Terry&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Why I Started AFFiNE - August 3, 2022</title>
      <dc:creator>Terry Zhang</dc:creator>
      <pubDate>Fri, 03 Apr 2026 04:28:12 +0000</pubDate>
      <link>https://forem.com/terryzhang/why-i-started-affine-august-3-2022-36al</link>
      <guid>https://forem.com/terryzhang/why-i-started-affine-august-3-2022-36al</guid>
      <description>&lt;p&gt;Every great product begins with a question you can't stop asking. Mine was: What if your data truly belonged to you?&lt;/p&gt;

&lt;p&gt;The Spark&lt;br&gt;
I'd spent the better part of two years inside a large engineering team, working on online documentation infrastructure. The codebase was aging. The tooling was borrowed from architectures designed for someone else's constraints. Every time a user lost work to a sync failure, or couldn't access their notes offline, I felt the gap between what we had and what was possible.&lt;/p&gt;

&lt;p&gt;I started building experiments in the margins of my actual job — prototypes of a different kind of editor, one that kept your data on your device first and treated the server as optional rather than essential. A local-first architecture, before I'd even heard that phrase used widely.&lt;/p&gt;

&lt;p&gt;Those experiments consumed my nights. And the more I built, the more convinced I became that the right answer couldn't live inside corporate walls.&lt;/p&gt;

&lt;p&gt;The Leap&lt;br&gt;
So I left. No roadmap approved by a committee, no guaranteed runway — just a conviction that the problem was real, the timing was right, and that the only honest way to build something people could truly trust was to build it in the open.&lt;/p&gt;

&lt;p&gt;That decision was the founding moment of AFFiNE.&lt;/p&gt;

&lt;p&gt;The Vision&lt;br&gt;
AFFiNE is a next-generation knowledge base — a place where planning, organizing, and creating are one continuous flow, not three separate apps that barely talk to each other.&lt;/p&gt;

&lt;p&gt;Privacy-first. Open-source from day one. Built to run on your machine, for real, not as a marketing footnote. The editor and the data layer are both open for anyone to inspect, fork, or contribute to.&lt;/p&gt;

&lt;p&gt;We refused the trade-off that most tools accept quietly: that you must surrender ownership to get great features. That offline means falling behind. That collaboration requires handing your documents to someone else's cloud.&lt;/p&gt;

&lt;p&gt;A Different Philosophy&lt;br&gt;
With AFFiNE, your data stays on your device first. Collaboration happens when you choose to enable it — peer-to-peer, not routed through a platform that has interests of its own.&lt;/p&gt;

&lt;p&gt;We're building the kind of tool I wish had existed when I first started asking these questions. Not because it's technically elegant, though I believe it is, but because it reflects a principle worth fighting for: the tools we use to think should work for us, not the other way around.&lt;/p&gt;

&lt;p&gt;Looking Forward&lt;br&gt;
I started AFFiNE because I believe the software we use to create and collaborate should empower us, not extract from us. We're early. There is a long road ahead.&lt;/p&gt;

&lt;p&gt;But the question that started all of this hasn't changed.&lt;/p&gt;

&lt;p&gt;What if your data truly belonged to you?&lt;/p&gt;

&lt;p&gt;We're building the answer.&lt;/p&gt;

&lt;p&gt;— Terry&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>devjournal</category>
      <category>sideprojects</category>
      <category>startup</category>
    </item>
    <item>
      <title>What I Learned from Watching Google Docs Work — and Why It Changed Everything December 15, 2020</title>
      <dc:creator>Terry Zhang</dc:creator>
      <pubDate>Fri, 03 Apr 2026 04:27:51 +0000</pubDate>
      <link>https://forem.com/terryzhang/what-i-learned-from-watching-google-docs-work-and-why-it-changed-everything-december-15-2020-i77</link>
      <guid>https://forem.com/terryzhang/what-i-learned-from-watching-google-docs-work-and-why-it-changed-everything-december-15-2020-i77</guid>
      <description>&lt;p&gt;I typed a single sentence into Google Docs.&lt;/p&gt;

&lt;p&gt;"Embrace every kind of life" — a phrase from my work in writing, nothing special. Then I did what any curious engineer does at 2 AM with too much coffee: I opened the network tab and watched what happened.&lt;/p&gt;

&lt;p&gt;Thirty-four discrete edit operations flew to the server before the sentence even finished rendering.&lt;/p&gt;

&lt;p&gt;Thirty-four.&lt;/p&gt;

&lt;p&gt;I sat back and stared at that number for a long time. That one moment — watching a handful of characters explode into dozens of atomic network requests — cracked open something I hadn't expected. What I thought was a product question turned into a philosophical one.&lt;/p&gt;

&lt;p&gt;The Protocol Is the Product&lt;br&gt;
Most engineers, when they think about collaborative editing, reach for the algorithm first. OT, CRDTs, conflict resolution — the academic machinery. I made the same mistake.&lt;/p&gt;

&lt;p&gt;The real insight came earlier, at the protocol layer.&lt;/p&gt;

&lt;p&gt;When I traced those requests, what I found wasn't a document being synchronized. It was a stream of commands — each one atomic, composable, and reversible. The operations mapped cleanly into four primitives:&lt;/p&gt;

&lt;p&gt;create — bring a new entity into existence&lt;br&gt;
update — mutate an existing property&lt;br&gt;
delete — remove&lt;br&gt;
tether — bind an entity to a position in the document&lt;br&gt;
That last one surprised me most. Inserting an image isn't a single operation in Google Docs. It's a choreography: first a special placeholder character, then an addEntity call, then a tether to bind the entity to that position. Verbose, yes. But exquisitely trackable, replayable, and mergeable across any number of concurrent editors.&lt;/p&gt;

&lt;p&gt;The protocol wasn't an implementation detail. It was the product.&lt;/p&gt;

&lt;p&gt;A Document Is Not a String&lt;br&gt;
Once I understood the protocol, I started working backwards to the data model — and the comfortable intuition that "a document is a string" collapsed almost immediately.&lt;/p&gt;

&lt;p&gt;The top-level structure of a Google Doc contains: body, documentStyle, lists, namedStyles, revisionId, and more. The body is a sequence of StructuralElement objects. Paragraphs contain ParagraphElement runs. And the index system doesn't count characters — it counts UTF-16 code units, which means a single emoji (a surrogate pair) consumes two index positions.&lt;/p&gt;

&lt;p&gt;These are the kinds of details that sound pedantic until the day you try to build comments, undo/redo, cross-device sync, or tables. Then they become life-or-death decisions. A string-based model will eventually crack. A structured object model keeps evolving.&lt;/p&gt;

&lt;p&gt;The Three-Version Problem&lt;br&gt;
After the protocol and the data model, I hit what I now think of as the true heart of collaborative engineering: version management.&lt;/p&gt;

&lt;p&gt;The problem is simple to state. Every client is constantly producing diffs and pushing them to the server, which broadcasts them to everyone else. But networks are unreliable. So at any given moment, every screen in a collaboration session is showing a slightly different document.&lt;/p&gt;

&lt;p&gt;To prevent this from spiraling into chaos, every command must be stamped with the revision it was based on. And to handle network failures, reconnections, out-of-order arrivals, and concurrent submissions, each client must simultaneously maintain three versions of the document:&lt;/p&gt;

&lt;p&gt;Server version — the last confirmed state from the server&lt;br&gt;
Sent version — changes dispatched but not yet acknowledged&lt;br&gt;
Editor version — local edits not yet sent&lt;br&gt;
When a conflict arrives — when someone else's changes land before yours are acknowledged — the system performs something that feels like git rebase. It replays the incoming changes before your pending queue, applies inverse OT corrections to the unconfirmed operations, and reconciles everything without either party losing their work.&lt;/p&gt;

&lt;p&gt;This is not academic rigor for its own sake. It's the engineering contract that makes collaboration feel effortless, even when the underlying reality is anything but.&lt;/p&gt;

&lt;p&gt;Why This Led Me to Open Source&lt;br&gt;
When I finished filling my Notion with all of this — every protocol detail, every data structure, every version-management edge case — I felt two things at once.&lt;/p&gt;

&lt;p&gt;I was in awe of the engineering. It is genuinely beautiful. Precise, resilient, elegant under pressure.&lt;/p&gt;

&lt;p&gt;And I was troubled.&lt;/p&gt;

&lt;p&gt;Because this kind of capability is extraordinarily expensive to build and maintain. Which means it will naturally concentrate in the hands of a few large platforms. And when your documents live on someone else's server, you don't truly own them — you're renting access to your own thoughts.&lt;/p&gt;

&lt;p&gt;That realization sharpened something I'd been circling for months into a clear commitment:&lt;/p&gt;

&lt;p&gt;Collaboration should be more accessible, not less. And users should truly own their data.&lt;/p&gt;

&lt;p&gt;When those two things become your north star, open source stops being a technical preference and starts being the only honest path. Open source means the capability can be copied and carried forward. Trust can be verified rather than promised. Self-hosting, migration, backup — these become facts, not features on a roadmap.&lt;/p&gt;

&lt;p&gt;That winter, tracing a single network request through Google Docs, I didn't know where any of this was pointing. But every line I wrote in those notes was quietly sharpening one conviction:&lt;/p&gt;

&lt;p&gt;Build it open. Give users their data back. Make the powerful tools available to everyone.&lt;/p&gt;

&lt;p&gt;— Terry&lt;/p&gt;

</description>
    </item>
    <item>
      <title>LlamaGen.ai Comic API – Seeking Feedback from the Community</title>
      <dc:creator>Terry Zhang</dc:creator>
      <pubDate>Fri, 03 Apr 2026 04:15:47 +0000</pubDate>
      <link>https://forem.com/terryzhang/llamagenai-comic-api-seeking-feedback-from-the-community-20po</link>
      <guid>https://forem.com/terryzhang/llamagenai-comic-api-seeking-feedback-from-the-community-20po</guid>
      <description>&lt;p&gt;Hi everyone,&lt;/p&gt;

&lt;p&gt;I'm the founder and CTO of the open-source project AFFiNE (&lt;a href="https://github.com/toeverything/AFFiNE" rel="noopener noreferrer"&gt;https://github.com/toeverything/AFFiNE&lt;/a&gt;), which currently has 66.9K stars on GitHub.&lt;/p&gt;

&lt;p&gt;Recently, I built a new project called &lt;strong&gt;LlamaGen.ai&lt;/strong&gt; — an AI platform for generating comics and manga. As part of it, we’ve created a Comic API specifically for developers.&lt;/p&gt;

&lt;p&gt;I also published the official JavaScript/TypeScript SDK as the npm package &lt;code&gt;comic&lt;/code&gt; (&lt;code&gt;npm i comic&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;The API supports generating multi-panel comics (1–20 panels), character consistency (via reference images or character descriptions), various styles (including 500+ presets and custom styles), and different aspect ratios. It accepts text prompts, and higher plans support image-to-comic, video-to-comic, and document-to-comic workflows.&lt;/p&gt;

&lt;h3&gt;
  
  
  Quick SDK Example
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm i comic
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;LlamaGenClient&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;comic&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;LlamaGenClient&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;apiKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;YOUR_API_KEY&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;comics&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;generate&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;A brave fox warrior fighting a giant robot in a neon cyberpunk city, dramatic manga style, 4 panels&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;panels&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;manga&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;character_consistency&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Right now, I’m actively looking for honest feedback and real experiments from the developer community. I want to know how people might actually use it, what works well, what’s missing, and how it can be improved.&lt;/p&gt;

&lt;p&gt;For more details, API reference, full parameters, and examples, please check: &lt;a href="https://llamagen.ai/comic-api" rel="noopener noreferrer"&gt;https://llamagen.ai/comic-api&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you’re interested in trying the API or SDK, feel free to leave a comment below or send me a message. I’ll happily send you some experience credits to test it out.&lt;/p&gt;

&lt;p&gt;I’d really appreciate any thoughts, use case ideas, prompt tips, or integration experiences you might have.&lt;/p&gt;

&lt;p&gt;Thanks in advance!&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Tags:&lt;/strong&gt; AI, Comics, API, ImageGeneration, Manga, OpenSource, Feedback, SDK, JavaScript&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Useful Links:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;AFFiNE: &lt;a href="https://github.com/toeverything/AFFiNE" rel="noopener noreferrer"&gt;https://github.com/toeverything/AFFiNE&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;LlamaGen.ai Comic API: &lt;a href="https://llamagen.ai/comic-api" rel="noopener noreferrer"&gt;https://llamagen.ai/comic-api&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Main Platform: &lt;a href="https://llamagen.ai" rel="noopener noreferrer"&gt;https://llamagen.ai&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;npm package: &lt;a href="https://www.npmjs.com/package/comic" rel="noopener noreferrer"&gt;https://www.npmjs.com/package/comic&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;



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

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

&lt;/div&gt;

</description>
      <category>ai</category>
      <category>api</category>
      <category>javascript</category>
      <category>showdev</category>
    </item>
  </channel>
</rss>
