<?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: cedricfan57</title>
    <description>The latest articles on DEV Community by cedricfan57 (@cedricfan57).</description>
    <link>https://dev.to/cedricfan57</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%2F4120789%2F69a88dd8-d1d3-468e-a18b-b86aeff461ad.png</url>
      <title>DEV Community: cedricfan57</title>
      <link>https://dev.to/cedricfan57</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/cedricfan57"/>
    <language>en</language>
    <item>
      <title>GPT Image 2.6 vs Nano Banana Pro: 6 Prompts Tested (2026)</title>
      <dc:creator>cedricfan57</dc:creator>
      <pubDate>Sun, 08 Nov 2026 14:45:11 +0000</pubDate>
      <link>https://dev.to/awakepix/gpt-image-26-vs-nano-banana-pro-6-prompts-tested-2026-a35</link>
      <guid>https://dev.to/awakepix/gpt-image-26-vs-nano-banana-pro-6-prompts-tested-2026-a35</guid>
      <description>&lt;p&gt;&lt;em&gt;Disclosure: this post was written with AI. The images and scores come from a test we ran on November 8, 2026. We build AwakePix, an AI image and video app. Originally published on the &lt;a href="https://awakepix.com/blog/gpt-image-2-6-vs-nano-banana-pro" rel="noopener noreferrer"&gt;AwakePix blog&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Short answer:&lt;/strong&gt; We ran the same six prompts through &lt;strong&gt;GPT Image 2.6 Sunburst&lt;/strong&gt;, &lt;strong&gt;GPT Image 2.6 Flare&lt;/strong&gt; and &lt;strong&gt;Nano Banana Pro&lt;/strong&gt; on November 8, 2026, kept the first image from each model and scored it against what the prompt asked for. &lt;strong&gt;Sunburst scored 22 out of 24, Flare 21 and Nano Banana Pro 18.&lt;/strong&gt; GPT Image 2.6 followed layout, counting and "do not" instructions more closely, and Flare was about 2.7 times faster than Sunburst.&lt;/p&gt;

&lt;p&gt;Use &lt;strong&gt;Flare&lt;/strong&gt; for quick drafts, &lt;strong&gt;Sunburst&lt;/strong&gt; when a layout has to be right, and &lt;strong&gt;Nano Banana Pro&lt;/strong&gt; when you need the things Google documents and this test did not cover: &lt;strong&gt;4K output&lt;/strong&gt;, &lt;strong&gt;up to 14 reference images&lt;/strong&gt; and &lt;strong&gt;Google Search grounding&lt;/strong&gt;. Only GPT Image 2.6 offers &lt;strong&gt;animated GIF&lt;/strong&gt; and &lt;strong&gt;SVG&lt;/strong&gt; output.&lt;/p&gt;

&lt;p&gt;Below: the scorecard, all six prompts and images, what changed in 2.6, the documented differences and which model to use.&lt;/p&gt;

&lt;h2&gt;
  
  
  GPT Image 2.6 vs Nano Banana Pro: test results
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Test&lt;/th&gt;
&lt;th&gt;GPT Image 2.6 Sunburst&lt;/th&gt;
&lt;th&gt;GPT Image 2.6 Flare&lt;/th&gt;
&lt;th&gt;Nano Banana Pro&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Course card (text layout)&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Notice board (counting and text)&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Perfume bottle (product photo)&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Recipe card (strict text limits)&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Greenhouse portrait&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Pixel sprite sheet&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Total out of 24&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;22&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;21&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;18&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Average time per image&lt;/td&gt;
&lt;td&gt;34.1 s&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;12.4 s&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;35.2 s&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;All 18 requests completed on the first try. Time runs from submission to completion, checked every five seconds, so treat it as approximate.&lt;/p&gt;

&lt;h3&gt;
  
  
  How we tested
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Prompts:&lt;/strong&gt; six text-to-image prompts, sent unchanged to every model.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;First image only:&lt;/strong&gt; one image per model per prompt, with no reruns and no cherry-picking.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scoring:&lt;/strong&gt; one point each for correct text, correct counts and layout, the requested subject and scene, and no obvious distortion or unrequested elements. We wrote these four checks before generating anything.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Settings:&lt;/strong&gt; GPT Image 2.6 used medium quality, 1K, high complexity and PNG. Nano Banana Pro used its default settings.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Size:&lt;/strong&gt; Nano Banana Pro returned about twice the width and height (2048×2048 against 1024×1024 at 1:1). The images below are resized to the same width, and sharpness was not scored.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is a small test scored by one reviewer. It shows how these models handled these six prompts, and it is not a general ranking.&lt;/p&gt;

&lt;h3&gt;
  
  
  Test 1: course card with three numbered sections
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;Create a 9:16 course card for a fictional workshop called ‘MAKE A ZINE’. Divide it into three numbered sections: PLAN, DRAW, SHARE. Give each section one simple icon and one short invented sentence. Use cobalt, apricot and paper white on a clean grid, with generous margins and strong type hierarchy. No real logos, tiny copy, photos or extra headings.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;GPT Image 2.6 Sunburst: 4/4&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7t83l7jv7wzym46ebo6u.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7t83l7jv7wzym46ebo6u.webp" alt="Make a Zine course card, generated by GPT Image 2.6 Sunburst" width="768" height="1360"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GPT Image 2.6 Flare: 4/4&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fy55k37ogqlny4jy2rnvj.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fy55k37ogqlny4jy2rnvj.webp" alt="Make a Zine course card, generated by GPT Image 2.6 Flare" width="768" height="1360"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Nano Banana Pro: 3/4&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fslrxqvmwmrxjga9vgtr4.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fslrxqvmwmrxjga9vgtr4.webp" alt="Make a Zine course card, generated by Nano Banana Pro" width="800" height="1434"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;All three spelled every word correctly. Sunburst and Flare gave each section one icon as asked. Nano Banana Pro paired two icons in its sections, such as a brain with a light bulb.&lt;/p&gt;

&lt;h3&gt;
  
  
  Test 2: notice board with exactly five papers
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;Design a 16:9 fictional community notice board outside a small library. Pin exactly five papers: a choir flyer, a lost-cat card, a piano lesson note, a four-row bus timetable and one blank card. Use one clear heading, large simple type, soft overcast light and a tidy cork texture. Keep text invented and readable, with no real names, logos or extra papers.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;GPT Image 2.6 Sunburst: 4/4&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fmn81ax6s462ba7mhcfrj.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fmn81ax6s462ba7mhcfrj.webp" alt="Community notice board, generated by GPT Image 2.6 Sunburst" width="800" height="452"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GPT Image 2.6 Flare: 3/4&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fv9kw2pcamw92jzsgm0sy.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fv9kw2pcamw92jzsgm0sy.webp" alt="Community notice board, generated by GPT Image 2.6 Flare" width="800" height="452"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Nano Banana Pro: 2/4&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fwda4q6szx2i8fsk51q4n.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fwda4q6szx2i8fsk51q4n.webp" alt="Community notice board, generated by Nano Banana Pro" width="799" height="446"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;All three pinned exactly five papers, including one blank card. Sunburst was the only one to pair a four-row timetable with large, simple type. Flare's timetable had four rows, but its type was small. Nano Banana Pro's text was readable at full size, but its timetable had seven lines of times instead of four rows, and the type was small.&lt;/p&gt;

&lt;h3&gt;
  
  
  Test 3: product photo of a perfume bottle
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;Create a 1:1 premium product photograph of a fictional AwakePix coffee fragrance bottle, centered in a three-quarter view on a walnut slab. Add a few coffee beans, one folded linen cloth and a soft window shadow. Warm morning light, realistic glass and liquid, tactile label area with no readable brand text, shallow depth of field, quiet brown and cream palette. One bottle only, no hands and no extra packaging.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;GPT Image 2.6 Sunburst: 3/4&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fuq5nnf9pooxgcooeft51.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fuq5nnf9pooxgcooeft51.webp" alt="Coffee fragrance bottle, generated by GPT Image 2.6 Sunburst" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GPT Image 2.6 Flare: 3/4&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8owctymzy83uybjisprf.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8owctymzy83uybjisprf.webp" alt="Coffee fragrance bottle, generated by GPT Image 2.6 Flare" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Nano Banana Pro: 3/4&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F86wz9ealpsdcqdn25fin.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F86wz9ealpsdcqdn25fin.webp" alt="Coffee fragrance bottle, generated by Nano Banana Pro" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;All three delivered one bottle, beans, linen and a window shadow with no readable brand text. None produced a clear three-quarter view, so each lost one point.&lt;/p&gt;

&lt;h3&gt;
  
  
  Test 4: recipe card with only three headings
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;Create a 1:1 social recipe card for fictional ‘LEMON BEAN TOAST’. Show three numbered panels: ingredients, stir, and serve. Use one bowl, lemon slices, white beans and toast as distinct objects, with a small finished plate in the last panel. Add only the headings ‘1 / GATHER’, ‘2 / STIR’, ‘3 / SERVE’. Warm tabletop light, no brand, people or extra text.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;GPT Image 2.6 Sunburst: 3/4&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fk6r1xrelvbfg7mc8jpp8.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fk6r1xrelvbfg7mc8jpp8.webp" alt="Lemon bean toast recipe card, generated by GPT Image 2.6 Sunburst" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GPT Image 2.6 Flare: 3/4&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Faaqjjyr7xligusz41qca.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Faaqjjyr7xligusz41qca.webp" alt="Lemon bean toast recipe card, generated by GPT Image 2.6 Flare" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Nano Banana Pro: 3/4&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Falcy3m2419kg1576j5vl.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Falcy3m2419kg1576j5vl.webp" alt="Lemon bean toast recipe card, generated by Nano Banana Pro" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The tie hides two different mistakes. Sunburst and Flare kept to the three headings but put two bowls in the first panel. Nano Banana Pro used one bowl but added the title "LEMON BEAN TOAST" when the prompt allowed only the three headings.&lt;/p&gt;

&lt;h3&gt;
  
  
  Test 5: environmental portrait in a greenhouse
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;Make a 16:9 environmental portrait of an older adult gardener in a fictional community greenhouse, leaning lightly beside a worktable with terracotta pots in the foreground. Capture a candid side glance, leaf texture, morning haze and realistic mixed light. The subject is an ordinary adult, not a celebrity; show natural age lines, no readable signage, logos or extra people.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;GPT Image 2.6 Sunburst: 4/4&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F5qf18rr1sg3us92h0bpw.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F5qf18rr1sg3us92h0bpw.webp" alt="Older gardener in a greenhouse, generated by GPT Image 2.6 Sunburst" width="800" height="452"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GPT Image 2.6 Flare: 4/4&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Flrqszpthpvlu375n17b4.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Flrqszpthpvlu375n17b4.webp" alt="Older gardener in a greenhouse, generated by GPT Image 2.6 Flare" width="800" height="452"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Nano Banana Pro: 4/4&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F4jq2mxag5eybrn8cndcq.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F4jq2mxag5eybrn8cndcq.webp" alt="Older gardener in a greenhouse, generated by Nano Banana Pro" width="799" height="446"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;All three met every requirement. The difference is framing: both 2.6 models moved in close, while Nano Banana Pro placed the gardener further back in the room.&lt;/p&gt;

&lt;h3&gt;
  
  
  Test 6: 4×4 pixel-art sprite sheet
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;Create a 1:1 4x4 pixel-art sprite sheet of one original non-human clay creature performing a looping idle animation. Keep the same silhouette, colors, scale and baseline in all 16 cells; vary only blink, breathing and a tiny ear movement. Use a plain solid background for easy removal, no grid lines, labels, text, shadows or extra characters.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;GPT Image 2.6 Sunburst: 4/4&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F9h33miecgdp9bx76pb89.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F9h33miecgdp9bx76pb89.webp" alt="Pixel-art creature sprite sheet, generated by GPT Image 2.6 Sunburst" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GPT Image 2.6 Flare: 4/4&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F3a7jc62y0t67ihi5fizt.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F3a7jc62y0t67ihi5fizt.webp" alt="Pixel-art creature sprite sheet, generated by GPT Image 2.6 Flare" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Nano Banana Pro: 3/4&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fccr4lz6cqeuo4oftjwqy.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fccr4lz6cqeuo4oftjwqy.webp" alt="Pixel-art creature sprite sheet, generated by Nano Banana Pro" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;All three drew 16 consistent cells on a plain background. Nano Banana Pro added grid lines, which the prompt ruled out.&lt;/p&gt;

&lt;h3&gt;
  
  
  What the results suggest
&lt;/h3&gt;

&lt;p&gt;In this set, Nano Banana Pro broke an explicit instruction more often: extra icons, an extra title, grid lines and a timetable in the wrong format. Flare gave up only one point to Sunburst while returning images in about 12 seconds. The portrait test was a tie, so the gap we saw is about following instructions and not about photorealism.&lt;/p&gt;

&lt;h2&gt;
  
  
  What changed in GPT Image 2.6
&lt;/h2&gt;

&lt;p&gt;OpenAI released &lt;strong&gt;Images 2.6&lt;/strong&gt; on &lt;strong&gt;November 4, 2026&lt;/strong&gt; in ChatGPT, Codex and the API. It can return an &lt;strong&gt;animated GIF (2 to 64 frames)&lt;/strong&gt; or an &lt;strong&gt;editable SVG&lt;/strong&gt; straight from a prompt. In the API it ships as two models: &lt;strong&gt;GPT-Image-2.6 Sunburst&lt;/strong&gt; for detailed work and &lt;strong&gt;GPT-Image-2.6 Flare&lt;/strong&gt; for speed.&lt;/p&gt;

&lt;p&gt;Compared with GPT Image 2.5, the release adds five things:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;What it does&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Animated GIF&lt;/td&gt;
&lt;td&gt;Turns a prompt or a photo into a looping GIF of 2 to 64 frames. In ChatGPT you can change the playback speed and edit single frames.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SVG output&lt;/td&gt;
&lt;td&gt;Returns a vector file with real paths, shapes and colours. One SVG per request, no streaming.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Markup editing&lt;/td&gt;
&lt;td&gt;You draw on a transparent layer over the image to show where the change goes, instead of supplying a mask.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Complexity control&lt;/td&gt;
&lt;td&gt;A new complexity setting (low, medium, high, default high) controls how much the model changes. It has no separate fee.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Saved references&lt;/td&gt;
&lt;td&gt;In ChatGPT you can save a reference image once and reuse it in later chats.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;OpenAI positions &lt;strong&gt;Sunburst&lt;/strong&gt; for&lt;br&gt;
"detailed visual work" with better consistency across edits, and &lt;strong&gt;Flare&lt;/strong&gt; for fast iteration.&lt;br&gt;
OpenAI says Flare can return an image in as little as six seconds; it averaged about 12 seconds in our test.&lt;/p&gt;

&lt;p&gt;Two limits are worth knowing before you build on it. The model pages list the &lt;strong&gt;Batch API as not&lt;br&gt;
supported&lt;/strong&gt;, so the usual batch discount is not available yet. And OpenAI warns that a higher&lt;br&gt;
complexity setting can increase latency and "introduce unwanted changes". For small edits, start&lt;br&gt;
with low complexity.&lt;/p&gt;

&lt;h2&gt;
  
  
  GPT Image 2.6 vs Nano Banana Pro: documented differences
&lt;/h2&gt;

&lt;p&gt;Nano Banana Pro is Google's Gemini 3 Pro Image model, released on November 20, 2025.&lt;br&gt;
This table uses only what each company documents.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;GPT Image 2.6&lt;/th&gt;
&lt;th&gt;Nano Banana Pro&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Released&lt;/td&gt;
&lt;td&gt;November 4, 2026&lt;/td&gt;
&lt;td&gt;November 20, 2025&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Output formats&lt;/td&gt;
&lt;td&gt;Still images, &lt;strong&gt;animated GIF&lt;/strong&gt;, &lt;strong&gt;SVG&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;PNG, JPEG&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Max resolution&lt;/td&gt;
&lt;td&gt;Not stated separately for 2.6&lt;/td&gt;
&lt;td&gt;1K, 2K and &lt;strong&gt;4K&lt;/strong&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Aspect ratios&lt;/td&gt;
&lt;td&gt;Not listed separately for 2.6&lt;/td&gt;
&lt;td&gt;10 ratios, from 21:9 to 9:16&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Reference images&lt;/td&gt;
&lt;td&gt;One or more; no published cap&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Up to 14&lt;/strong&gt;: 6 objects, 5 characters, 3 style references&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Editing control&lt;/td&gt;
&lt;td&gt;Markup layer plus complexity setting&lt;/td&gt;
&lt;td&gt;Conversational, prompt-based editing&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Text in images&lt;/td&gt;
&lt;td&gt;Not detailed for 2.6&lt;/td&gt;
&lt;td&gt;Google calls it its best model for legible text&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Web knowledge&lt;/td&gt;
&lt;td&gt;Not documented&lt;/td&gt;
&lt;td&gt;Google Search grounding&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Watermark&lt;/td&gt;
&lt;td&gt;Not documented for the API&lt;/td&gt;
&lt;td&gt;SynthID on every image&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Speed tiers&lt;/td&gt;
&lt;td&gt;Sunburst (quality) and Flare (speed)&lt;/td&gt;
&lt;td&gt;One model; Nano Banana 2.1 is Google's lighter option&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Two notes on this table. First, "not documented" does not mean "cannot". OpenAI's guide has&lt;br&gt;
not yet published a full size table or a reference-image cap for 2.6, so we leave those cells&lt;br&gt;
open instead of guessing. Second, Google's own documentation now recommends&lt;br&gt;
&lt;strong&gt;Nano Banana 2.1&lt;/strong&gt; for most new projects. Nano Banana Pro remains the choice for complex&lt;br&gt;
graphic design, product mockups and data visuals.&lt;/p&gt;

&lt;h2&gt;
  
  
  Independent rankings: still early
&lt;/h2&gt;

&lt;p&gt;As of November 8, 2026, we have not found a stable independent ranking for Images 2.6. The early leaderboard figures we saw were described as preliminary. Our six prompts are one small data point, so the fairest test is still your own prompts run on both models.&lt;/p&gt;

&lt;h2&gt;
  
  
  GPT Image 2.6 or Nano Banana Pro: which one to use
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Your job&lt;/th&gt;
&lt;th&gt;Better pick&lt;/th&gt;
&lt;th&gt;Why&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;A poster or card with strict text and layout rules&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;GPT Image 2.6 Sunburst&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Highest score in our layout tests&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;A looping sticker, reaction GIF or animated emote&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;GPT Image 2.6&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Native GIF output; Nano Banana Pro has none&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;A logo, icon, cut file or anything that must scale&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;GPT Image 2.6&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Native SVG output&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Fix one area of a photo without touching the rest&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;GPT Image 2.6&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;You can draw exactly where the change goes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;A large poster or print at 4K&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Nano Banana Pro&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Documented 4K output&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;A group scene that must keep several real people's look&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Nano Banana Pro&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Up to 5 consistent characters and 14 references&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;An infographic or map that needs current facts&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Nano Banana Pro&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Google Search grounding&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Many quick drafts&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;GPT Image 2.6 Flare&lt;/strong&gt; or &lt;strong&gt;Nano Banana 2.1&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;Both are built for speed; Flare averaged about 12 seconds in our test&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;One practical point about GIFs: a 2.6 GIF is capped at 64 frames and has no sound. If you want a&lt;br&gt;
smooth, longer clip of a photo with real camera movement, an image-to-video model will do more.&lt;/p&gt;

&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;When was GPT Image 2.6 released?&lt;/strong&gt;&lt;br&gt;
OpenAI announced Images 2.6 on November 4, 2026, for ChatGPT, Codex and the API.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What is the difference between GPT Image 2.6 Sunburst and Flare?&lt;/strong&gt;&lt;br&gt;
Sunburst is aimed at detailed images and consistent edits;&lt;br&gt;
Flare is aimed at fast iteration and can return an image in about six seconds.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Can GPT Image 2.6 make GIFs?&lt;/strong&gt;&lt;br&gt;
Yes. It can create animated GIFs of 2 to 64 frames from a prompt or a photo. In ChatGPT you can&lt;br&gt;
also change the speed and edit single frames.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Can GPT Image 2.6 export SVG?&lt;/strong&gt;&lt;br&gt;
Yes. The API can return an editable SVG, one file per request. Streaming is not supported for SVG.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Can Nano Banana Pro make GIFs or SVG files?&lt;/strong&gt;&lt;br&gt;
Google's documentation lists PNG and JPEG output only, with no GIF or SVG option.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Is GPT Image 2.6 better than Nano Banana Pro?&lt;/strong&gt;&lt;br&gt;
In our six-prompt test, GPT Image 2.6 Sunburst scored 22 out of 24, Flare 21 and Nano Banana Pro 18, mostly because 2.6 followed layout and "do not" instructions more closely. Nano Banana Pro has the documented edge for 4K stills, many-reference scenes and fact-based graphics, which we did not test.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Which is faster, GPT Image 2.6 or Nano Banana Pro?&lt;/strong&gt;&lt;br&gt;
In our test, Flare averaged about 12 seconds, Sunburst about 34 seconds and Nano Banana Pro about 35 seconds per image. Your timing will vary with settings and load.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Sources: &lt;a href="https://developers.openai.com/api/docs/models/gpt-image-2.6-sunburst" rel="noopener noreferrer"&gt;OpenAI, GPT-Image-2.6 Sunburst model page&lt;/a&gt;;&lt;br&gt;
&lt;a href="https://developers.openai.com/api/docs/models/gpt-image-2.6-flare" rel="noopener noreferrer"&gt;OpenAI, GPT-Image-2.6 Flare model page&lt;/a&gt;;&lt;br&gt;
&lt;a href="https://developers.openai.com/api/docs/guides/image-generation" rel="noopener noreferrer"&gt;OpenAI image generation guide&lt;/a&gt;;&lt;br&gt;
&lt;a href="https://community.openai.com/t/images-upgraded-introducing-chatgpt-images-2-6/1412901" rel="noopener noreferrer"&gt;OpenAI Developer Community, "Introducing ChatGPT Images 2.6"&lt;/a&gt;;&lt;br&gt;
&lt;a href="https://blog.google/technology/ai/nano-banana-pro/" rel="noopener noreferrer"&gt;Google, "Introducing Nano Banana Pro"&lt;/a&gt;;&lt;br&gt;
&lt;a href="https://aistudio.google.com/docs/image-generation" rel="noopener noreferrer"&gt;Google AI Studio, image generation docs&lt;/a&gt;;&lt;br&gt;
&lt;a href="https://aistudio.google.com/docs/models/gemini-3-pro-image" rel="noopener noreferrer"&gt;Google AI Studio, Gemini 3 Pro Image model page&lt;/a&gt;.&lt;br&gt;
Specs checked November 4, 2026; prompts tested November 8, 2026.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>openai</category>
      <category>machinelearning</category>
      <category>webdev</category>
    </item>
    <item>
      <title>gpt2.6</title>
      <dc:creator>cedricfan57</dc:creator>
      <pubDate>Sun, 08 Nov 2026 13:33:10 +0000</pubDate>
      <link>https://dev.to/cedricfan57/gpt26-nf6</link>
      <guid>https://dev.to/cedricfan57/gpt26-nf6</guid>
      <description></description>
    </item>
    <item>
      <title>Designing a free text preview inside a paid AI video workflow</title>
      <dc:creator>cedricfan57</dc:creator>
      <pubDate>Tue, 27 Oct 2026 05:50:58 +0000</pubDate>
      <link>https://dev.to/cedricfan57/designing-a-free-text-preview-inside-a-paid-ai-video-workflow-1nmh</link>
      <guid>https://dev.to/cedricfan57/designing-a-free-text-preview-inside-a-paid-ai-video-workflow-1nmh</guid>
      <description>&lt;p&gt;A free text preview inside a paid media workflow creates a very specific UI problem: what, exactly, has the user approved?&lt;/p&gt;

&lt;p&gt;I am the maker of &lt;a href="https://airapvideos.app/" rel="noopener noreferrer"&gt;StarBop&lt;/a&gt;, where a person or pet photo becomes a short rap performance. The public flow lets people preview and edit four English lyric lines before purchasing a video. That gives a concrete example for the design pattern below. This is a suggested frontend model, not a description of our private backend or a claim about conversion results.&lt;/p&gt;

&lt;h2&gt;
  
  
  Separate three promises
&lt;/h2&gt;

&lt;p&gt;A lyric preview shows the words. It does not preview the final voice, timing, facial motion or complete video. A price quote describes a purchase. A generation result proves that a file exists.&lt;/p&gt;

&lt;p&gt;Those three promises should have different labels and states. A single boolean such as &lt;code&gt;isReady&lt;/code&gt; cannot tell a component which promise it is making.&lt;/p&gt;

&lt;h2&gt;
  
  
  Make stale previews visible
&lt;/h2&gt;

&lt;p&gt;Consider this sequence:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;A user requests a birthday verse for Alex.&lt;/li&gt;
&lt;li&gt;The user changes the name to Sam before the response arrives.&lt;/li&gt;
&lt;li&gt;The older request returns with Alex's lyrics.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If the UI simply renders the last response to finish, it can show an apparently successful preview for the wrong input. Disabling the button alone does not solve requests already in flight.&lt;/p&gt;

&lt;p&gt;A minimal illustrative TypeScript model can attach a local revision to requests:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;PreviewState&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
  &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;idle&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;loading&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nl"&gt;revision&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ready&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nl"&gt;revision&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nl"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;error&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nl"&gt;revision&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nl"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;acceptPreview&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;currentRevision&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;responseRevision&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;PreviewState&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;responseRevision&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="nx"&gt;currentRevision&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ready&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;revision&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;responseRevision&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The caller should ignore a null result, not replace the current screen with it. Increment the revision when preview-relevant inputs change. Cancellation can reduce wasted work, but the revision check still matters if cancellation arrives too late. This is a UI consistency mechanism; it is not authorization for a paid job.&lt;/p&gt;

&lt;h2&gt;
  
  
  Treat editing as ownership
&lt;/h2&gt;

&lt;p&gt;Once a person edits the verse, an automatic refresh should not silently replace it. Keep the editable draft distinct from a proposed replacement, and let the person choose whether to apply the new version. Preserve the draft after a recoverable failure.&lt;/p&gt;

&lt;p&gt;Some settings affect the preview and others affect only the output. Define that boundary explicitly. Changing the subject name should invalidate a verse about the old name; changing portrait to landscape need not discard the person's writing if the text remains applicable.&lt;/p&gt;

&lt;h2&gt;
  
  
  Keep payment language precise
&lt;/h2&gt;

&lt;p&gt;Use a label such as “Preview my lyrics · free” for the text step, and show the paid video price separately. On our public page, standard 480p and HD 720p also consume different amounts of video balance. A resolution change therefore needs a clear cost update even when the lyrics stay unchanged.&lt;/p&gt;

&lt;p&gt;The server must independently check the final request, balance and applicable rules. A frontend &lt;code&gt;ready&lt;/code&gt; state must never serve as payment proof.&lt;/p&gt;

&lt;h2&gt;
  
  
  Test the transitions, not just the happy path
&lt;/h2&gt;

&lt;p&gt;Useful checks for this pattern include an old response arriving after a new one, edits made while a request is running, changing a cost-affecting option after preview, and retrying after a network error without losing the draft. Also check that keyboard focus and an accessible status message make loading and errors understandable.&lt;/p&gt;

&lt;p&gt;These checks answer a narrower, testable question than “is the generator working?”: does the UI consistently show the text and price the user actually chose?&lt;/p&gt;

&lt;p&gt;Disclosure: I make the linked product. This article was drafted with AI assistance and checked against the current public product flow; the code is an illustrative pattern, not production source.&lt;/p&gt;

</description>
      <category>design</category>
      <category>frontend</category>
      <category>product</category>
      <category>ui</category>
    </item>
    <item>
      <title>Building a pet-only meme video page: what the sample needs to prove</title>
      <dc:creator>cedricfan57</dc:creator>
      <pubDate>Sun, 11 Oct 2026 14:28:23 +0000</pubDate>
      <link>https://dev.to/cedricfan57/building-a-pet-only-meme-video-page-what-the-sample-needs-to-prove-2die</link>
      <guid>https://dev.to/cedricfan57/building-a-pet-only-meme-video-page-what-the-sample-needs-to-prove-2die</guid>
      <description>&lt;p&gt;I built &lt;a href="https://bulin47.xyz/" rel="noopener noreferrer"&gt;Bulin47&lt;/a&gt;, a pet-only video project inspired by the Bulin 47 freestyle meme. The idea is deliberately narrow: use one authorized pet photo to replace the lead performer in a fixed clip, keeping the other people and the scene unchanged.&lt;/p&gt;

&lt;p&gt;The output specification is about 19 seconds, vertical 9:16, 480p, with the original freestyle audio. The frontend uses TanStack Start, React and TypeScript, with Cloudflare Workers for deployment. The video-editing integration uses Seedance 2.5 through EvoLink.&lt;/p&gt;

&lt;h2&gt;
  
  
  A comparison is more useful than a polished thumbnail
&lt;/h2&gt;

&lt;p&gt;A thumbnail can show the pet but hide whether the motion, timing and surrounding scene survived the edit. I put an original-versus-pet comparison alongside the input photo on the public page. That gives visitors three things to inspect: the source identity, the replaced performer, and the unchanged context.&lt;/p&gt;

&lt;p&gt;For this kind of app, I would evaluate a sample along separate axes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Does the pet remain recognizable throughout the clip?&lt;/li&gt;
&lt;li&gt;Does the lead follow the reference movement and timing?&lt;/li&gt;
&lt;li&gt;Do background people and objects stay consistent?&lt;/li&gt;
&lt;li&gt;Does the exported file preserve the expected duration, orientation and audio?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;One attractive frame cannot answer all four. A full clip and a visible input make the example easier to judge.&lt;/p&gt;

&lt;h2&gt;
  
  
  Keep the input boundary explicit
&lt;/h2&gt;

&lt;p&gt;This project accepts pet photos only, without human faces or bodies. It is a useful constraint to communicate directly in the upload instructions instead of leaving it inside a policy page. The goal is pet entertainment, with a single fixed reference rather than an unrestricted face-swap interface.&lt;/p&gt;

&lt;h2&gt;
  
  
  Make the example match the copy
&lt;/h2&gt;

&lt;p&gt;I also checked that the deployed sample assets matched the reviewed video files. A page can have correct copy while still serving an older sample. Keeping the input photo, comparison video and description aligned matters just as much as the framework choice.&lt;/p&gt;

&lt;p&gt;You can inspect the &lt;a href="https://bulin47.xyz/" rel="noopener noreferrer"&gt;Bulin47 sample comparison&lt;/a&gt;. I would welcome feedback on whether the comparison makes the intended edit clear.&lt;/p&gt;

&lt;p&gt;This is an independent fan-made project, not affiliated with the artists or their labels. Results vary; the example is not a quality guarantee for every pet photo.&lt;/p&gt;

</description>
      <category>frontend</category>
      <category>react</category>
      <category>showdev</category>
      <category>typescript</category>
    </item>
    <item>
      <title>I built an AI pet dance app: one photo, one generator</title>
      <dc:creator>cedricfan57</dc:creator>
      <pubDate>Sat, 10 Oct 2026 13:25:30 +0000</pubDate>
      <link>https://dev.to/cedricfan57/i-built-an-ai-pet-dance-app-one-photo-one-generator-138m</link>
      <guid>https://dev.to/cedricfan57/i-built-an-ai-pet-dance-app-one-photo-one-generator-138m</guid>
      <description>&lt;p&gt;I built &lt;a href="https://catdance.app/" rel="noopener noreferrer"&gt;CatDance&lt;/a&gt;, a small web app that turns a pet photo into an AI dance video. The idea is playful: take a cat, dog or plush photo and make it the star of a short dance clip.&lt;/p&gt;

&lt;p&gt;Update — October 23, 2026: CatDance now offers a &lt;a href="https://catdance.app/templates/neon" rel="noopener noreferrer"&gt;NEON cat dance template&lt;/a&gt; alongside Smalltown Boy. Personalized generation is paid; the earlier free-preview offer described at launch has ended.&lt;/p&gt;

&lt;h2&gt;
  
  
  One photo, two dance templates
&lt;/h2&gt;

&lt;p&gt;For &lt;a href="https://catdance.app/templates/neon" rel="noopener noreferrer"&gt;NEON&lt;/a&gt;, upload a clear cat photo to replace the lead dancer in the routine to A2O LITE’s NEON. Add a second pet photo, reuse the same photo for both dancers, or leave B empty to keep the default tuxedo cat. The scene is fixed. New videos are approximately 10 seconds, 720p and landscape 16:9, with original template audio and no watermark. The white-cat demo is labeled 480p; it is not a paid 720p output example.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://catdance.app/smalltown-boy" rel="noopener noreferrer"&gt;Smalltown Boy&lt;/a&gt; remains a separate template: about 19 seconds, 720p and portrait 9:16, with an optional second pet and preset backgrounds. Its background choices do not apply to NEON.&lt;/p&gt;

&lt;p&gt;Both use one-time USD purchases: $9.90 for one generation or $29.90 for four. There is no subscription or free personalized generation. Confirmed failed generations restore the credit; completed AI results can vary in appearance and movement. Including original template audio does not grant additional music rights or a commercial-use license.&lt;/p&gt;

&lt;h2&gt;
  
  
  Generation is only half the job
&lt;/h2&gt;

&lt;p&gt;The frontend uses React and TanStack Start, with the application running on Cloudflare Workers. Generated files are delivered through object storage.&lt;/p&gt;

&lt;p&gt;One practical lesson: a provider reporting “completed” is not the same as a customer having a downloadable video. The application still has to retrieve the output, assemble the full clip when necessary, attach template audio and persist the final file.&lt;/p&gt;

&lt;p&gt;I now treat delivery as an explicit part of the job lifecycle. Errors record which stage failed, retries have a limit, and failed orders return the generation credit. An ambiguous submission should also be investigated before automatically submitting the same paid model request again.&lt;/p&gt;

&lt;h2&gt;
  
  
  Show the output before asking for a purchase
&lt;/h2&gt;

&lt;p&gt;The homepage includes real input-photo and video examples. For a creative tool, those pairs explain the product better than a long feature list: people can judge whether the result is something they would want to share.&lt;/p&gt;

&lt;p&gt;Photo quality and subject identity still matter. A clear image with one visible subject is a better starting point than a crowded or heavily cropped photo. Two-pet replacement is a more demanding task than replacing a single pet, and AI results can vary.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;

&lt;p&gt;You can see the examples and use the generator at &lt;strong&gt;&lt;a href="https://catdance.app/" rel="noopener noreferrer"&gt;catdance.app&lt;/a&gt;&lt;/strong&gt;. I am the maker of the product; this is a launch note, not an independent review.&lt;/p&gt;

&lt;p&gt;For the new routine, start with the &lt;a href="https://catdance.app/templates/neon" rel="noopener noreferrer"&gt;NEON examples and generator&lt;/a&gt;. I would be interested in feedback on whether the template examples and upload flow make the choices clear.&lt;/p&gt;

</description>
      <category>showdev</category>
    </item>
    <item>
      <title>Why nuke simulators show different numbers (and how to compare them)</title>
      <dc:creator>cedricfan57</dc:creator>
      <pubDate>Fri, 02 Oct 2026 14:37:02 +0000</pubDate>
      <link>https://dev.to/cedricfan57/why-nuke-simulators-show-different-numbers-and-how-to-compare-them-5a7h</link>
      <guid>https://dev.to/cedricfan57/why-nuke-simulators-show-different-numbers-and-how-to-compare-them-5a7h</guid>
      <description>&lt;p&gt;After I posted a short video of a simulated 15 kiloton airburst, a viewer commented that they had checked another calculator and got different numbers. That is a fair point, and the answer is not that one tool is broken. Blast simulators make different modelling choices, and those choices move the rings a lot.&lt;/p&gt;

&lt;p&gt;I build &lt;a href="https://kaboomly.app/" rel="noopener noreferrer"&gt;Kaboomly&lt;/a&gt;, a free nuke map that runs in the browser, so here are the four choices that matter most.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Airburst or surface burst
&lt;/h2&gt;

&lt;p&gt;The same weapon behaves very differently depending on where it goes off. An airburst spreads the blast wave over a wider area, so the light-damage rings get bigger. A surface burst gives smaller blast rings but pulls soil into the fireball and creates local fallout. Some tools default to one, some to the other.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Burst height
&lt;/h2&gt;

&lt;p&gt;Even among airbursts, height matters. There is a height that maximizes the area of a given overpressure, and it is different for every pressure level. Kaboomly does not optimize this. It takes one documented historical example, Hiroshima at about 1,670 ft for roughly 12.5 kt, and scales it with the cube root of the yield. A tool that picks a different height will show different rings for the same yield.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Which threshold a ring represents
&lt;/h2&gt;

&lt;p&gt;A ring labelled "heavy damage" might be drawn at 5 psi in one tool and at 10 or 20 psi in another. Thermal rings can mean first, second or third-degree burns, and the distance changes a lot between them. Always check the legend before comparing two maps.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Scaling law and source data
&lt;/h2&gt;

&lt;p&gt;Most public calculators, including NUKEMAP and Kaboomly, trace back to &lt;em&gt;The Effects of Nuclear Weapons&lt;/em&gt; by Glasstone and Dolan (1977). Blast distances scale with the cube root of yield, so ten times the yield gives only about 2.15 times the distance. The fireball has its own scaling, about W^0.4. Tools that use rounded rules of thumb instead of the published curves will drift, especially at very small or very large yields.&lt;/p&gt;

&lt;h2&gt;
  
  
  An example
&lt;/h2&gt;

&lt;p&gt;For a 15 kt airburst Kaboomly shows the 5 psi ring at about 1.6 km (1.0 mi) and the 1 psi ring at about 4.5 km (2.8 mi). If another tool uses a surface burst or a different height, its numbers for the same yield can be noticeably smaller or larger, and both can be correct for their own assumptions.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I did about it
&lt;/h2&gt;

&lt;p&gt;On Kaboomly every result shows the burst type and the thresholds, and there is a page explaining &lt;a href="https://kaboomly.app/how-it-works/" rel="noopener noreferrer"&gt;how the numbers are calculated&lt;/a&gt; with references. The site never shows casualty estimates, only the rings and the number of residents living inside an area.&lt;/p&gt;

&lt;p&gt;If you compare simulators, compare like with like: same yield, same burst type, same threshold. The differences mostly disappear.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>maps</category>
      <category>history</category>
    </item>
    <item>
      <title>Splitting a large image across multiple printed pages without alignment marks</title>
      <dc:creator>cedricfan57</dc:creator>
      <pubDate>Fri, 18 Sep 2026 00:46:00 +0000</pubDate>
      <link>https://dev.to/cedricfan57/splitting-a-large-image-across-multiple-printed-pages-without-alignment-marks-115c</link>
      <guid>https://dev.to/cedricfan57/splitting-a-large-image-across-multiple-printed-pages-without-alignment-marks-115c</guid>
      <description>&lt;p&gt;I recently added tiled printing to a small static tool I run (&lt;a href="https://griddrawing.org" rel="noopener noreferrer"&gt;ArtGrid&lt;/a&gt;) — the kind of "print a big image across several A4 sheets and tape them together" feature you've probably seen in poster-printing tools. The naive version is easy: slice the enlarged image into a grid of page-sized rectangles, export each as a PDF page. The annoying version is making the pieces line back up on paper, where a fraction of a millimeter of printer scaling error compounds across every seam.&lt;/p&gt;

&lt;p&gt;Most tools solve this with &lt;strong&gt;alignment marks&lt;/strong&gt; — corner crosses or registration dots you have to trim to and match by eye. I skipped that entirely by changing where the cuts land.&lt;/p&gt;

&lt;h2&gt;
  
  
  The trick: cut on lines that are already there
&lt;/h2&gt;

&lt;p&gt;My tool overlays a grid on the reference image — rows and columns of equal square cells, used for the classic grid-method drawing technique. Once you're enlarging that grid to poster size, you already have a full set of straight lines running across the whole surface. If every page boundary is forced to land exactly on one of those grid lines, the seam &lt;em&gt;is&lt;/em&gt; the line. There's nothing to trim, because the join is a continuation of a mark you were going to draw anyway.&lt;/p&gt;

&lt;p&gt;The constraint this puts on the math: instead of dividing by fixed page dimensions, you divide by &lt;strong&gt;however many whole cells fit on a page&lt;/strong&gt;, and let the last row/column of pages be a partial page if it doesn't divide evenly.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;tileGeometry&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;geometry&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;GridGeometry&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;TileResult&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;area&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;tileArea&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;geometry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;paper&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// printable area minus margins&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;drawingCell&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;columns&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;rows&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;geometry&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;drawingCell&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;area&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;w&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;drawingCell&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;area&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;h&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;ok&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`cell &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;drawingCell&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;mm exceeds printable area`&lt;/span&gt; &lt;span class="p"&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;colsPerPage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;floor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;area&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;w&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nx"&gt;drawingCell&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;rowsPerPage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;floor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;area&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;h&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nx"&gt;drawingCell&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;pagesX&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ceil&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;columns&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nx"&gt;colsPerPage&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;pagesY&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ceil&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;rows&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nx"&gt;rowsPerPage&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;ok&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;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;colsPerPage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;rowsPerPage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;pagesX&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;pagesY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;pageCount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;pagesX&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;pagesY&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each page then covers a &lt;code&gt;[colStart, colEnd) × [rowStart, rowEnd)&lt;/code&gt; slice of cells, and the pixel crop for that page is just that slice's bounding box in the source image, scaled the same way the whole grid was scaled. Cutting on &lt;code&gt;floor(printable_area / cell_size)&lt;/code&gt; rather than on the raw page dimension is the entire trick — it's a one-line change from "divide by page size" that removes a whole category of physical-alignment UX.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this only works if the cells are square
&lt;/h2&gt;

&lt;p&gt;This only holds together because every cell is guaranteed to be the same width and height. If rows and columns are sized independently — which most grid tools do, because it lets you fill the page edge-to-edge — a "cell" isn't a fixed unit you can tile against, and you're back to needing marks. Forcing square cells (deriving whichever axis you didn't set, rather than letting both float to fill the sheet) was originally a decision about drawing accuracy — a square cell's diagonal is a clean 45°, useful for judging angles by eye — but it turned out to be the same property that makes tiling trivial later. One geometric constraint paid for two unrelated features.&lt;/p&gt;

&lt;h2&gt;
  
  
  Testing the seams
&lt;/h2&gt;

&lt;p&gt;The part I actually didn't trust until I checked it: does the printable rectangle reconstructed from all the tiles equal the original enlarged rectangle, to the millimeter? I wrote this as a standalone assertion rather than trusting the math by inspection:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;topRowWidth&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;pages&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;rowStart&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;sum&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tileRectMm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;assert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;abs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;topRowWidth&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;drawingRect&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;w&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mf"&gt;0.01&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;— summed the top row's page widths, summed the left column's page heights, compared both against the target enlargement size. It matched to a hundredth of a millimeter, which is the point where you stop worrying about floating point and start worrying about your actual printer's calibration instead (which is why there's still a 50mm ruler printed on the first page — measure it, and if your printer scaled the page, you'll catch it before taping together nine sheets).&lt;/p&gt;

&lt;p&gt;If you want to see the live version: &lt;a href="https://griddrawing.org/print-large-image-multiple-pages" rel="noopener noreferrer"&gt;griddrawing.org/print-large-image-multiple-pages&lt;/a&gt;. It's a static site, runs entirely client-side, source reference stays in the browser tab.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>canvas</category>
      <category>math</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
