<?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: Adam Hawk</title>
    <description>The latest articles on DEV Community by Adam Hawk (@adamhawk).</description>
    <link>https://dev.to/adamhawk</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%2F3859970%2F052b0e37-bca0-4494-94b4-7d2bdbd1101e.jpeg</url>
      <title>DEV Community: Adam Hawk</title>
      <link>https://dev.to/adamhawk</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/adamhawk"/>
    <language>en</language>
    <item>
      <title>I built a fully automated AI party platform that earns passive income — here's the full code</title>
      <dc:creator>Adam Hawk</dc:creator>
      <pubDate>Mon, 06 Apr 2026 16:25:01 +0000</pubDate>
      <link>https://dev.to/adamhawk/i-built-a-fully-automated-ai-party-platform-that-earns-passive-income-heres-the-full-code-4bb7</link>
      <guid>https://dev.to/adamhawk/i-built-a-fully-automated-ai-party-platform-that-earns-passive-income-heres-the-full-code-4bb7</guid>
      <description>&lt;p&gt;A few months ago I started wondering: could I build a content platform that runs completely on its own — generates content, publishes it, and earns money — without me touching it after setup?&lt;/p&gt;

&lt;p&gt;The answer turned out to be I think so lol. Here's what I built, the interesting engineering problems I ran into, and the full code so you can run it yourself.&lt;/p&gt;




&lt;p&gt;**What it does&lt;/p&gt;

&lt;p&gt;Every night at 6pm, a cron job fires a Node.js script that creates a party and content for &lt;a href="https://flashparty.co" rel="noopener noreferrer"&gt;FlashParty.co&lt;/a&gt;:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Asks Claude to invent a party theme (seasonal, holiday-aware, never repeats)&lt;/li&gt;
&lt;li&gt;Builds 25 unique scenes with varied shot types, camera styles, and subject counts&lt;/li&gt;
&lt;li&gt;Generates all 25 captions in a single AI call&lt;/li&gt;
&lt;li&gt;Submits a batch image generation job to PartyLab (powered by xAI's Grok)&lt;/li&gt;
&lt;li&gt;Uploads each photo to FlashParty as it completes — free photos are public, NSFW photos are behind a $5 Party Pass&lt;/li&gt;
&lt;li&gt;Sets a cover photo and the party goes live&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Total runtime: 5–10 minutes. Human effort after initial setup: zero.&lt;/p&gt;




&lt;p&gt;**The stack&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://console.anthropic.com" rel="noopener noreferrer"&gt;Claude (Anthropic)&lt;/a&gt;&lt;/strong&gt; — theme generation and batch caption writing. I use Haiku because it's fast and cheap. Three API calls per party cost less than half a cent.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://partylab.dev" rel="noopener noreferrer"&gt;PartyLab&lt;/a&gt;&lt;/strong&gt; — wraps xAI's Grok image model with a party-specific API. You describe scenes and characters, it generates photos in batch and gives you a polling endpoint.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://flashparty.co/developers" rel="noopener noreferrer"&gt;FlashParty&lt;/a&gt;&lt;/strong&gt; — the platform that hosts the parties, handles user signups, and processes Party Pass payments. They have a REST API for creating parties and uploading media.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  The interesting problems
&lt;/h2&gt;

&lt;p&gt;I'll be honest — the naive version of this looked terrible. Here's what went wrong and how I fixed each thing.&lt;/p&gt;

&lt;h3&gt;
  
  
  Problem 1: Every photo looked like it was taken by the same person
&lt;/h3&gt;

&lt;p&gt;The first version picked one camera style for the entire party and baked it into the image generation job. 25 photos all with the same cinematic teal-and-orange look. Real parties have people with DSLRs, people with disposable cameras, people with iPhones taking blurry selfies.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt; Instead of one job-level camera style, I assign a random style to each individual scene. There are 8 styles: DSLR candid, 35mm film, editorial night, disposable flash cam, cinematic telephoto, iPhone Portrait mode, Google Pixel night mode, and vintage point-and-shoot. Each image picks one independently.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;CAMERA_STYLES&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Film Photography&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;descriptors&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;shot on 35mm Kodak Portra 400 film, warm golden tones, organic film grain, slight halation, nostalgic analog texture&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Flash Party Cam&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;descriptors&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;disposable camera aesthetic, direct on-camera flash, overexposed highlights, red-eye effect, Fujifilm disposable lo-fi&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="c1"&gt;// ... 6 more&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="c1"&gt;// Each scene gets its own randomly selected style&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cam&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;pick&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;CAMERA_STYLES&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;scene&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;prompt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;scene&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;, &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;cam&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;descriptors&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Problem 2: All NSFW photos clustered at the top
&lt;/h3&gt;

&lt;p&gt;The scene list was built by appending NSFW scenes after all the SFW scenes. PartyLab processes them in order, so they all completed and uploaded together in a block. Users saw a wall of adult content at the top of the party feed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt; Interleave NSFW scenes at evenly-spaced positions within the SFW list before submitting the job. Since PartyLab generates in scene order, the photos now appear distributed naturally across the party.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Interleave NSFW scenes at evenly-spaced positions&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;scenes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[...&lt;/span&gt;&lt;span class="nx"&gt;sfwScenes&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;nsfwScenes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;step&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;scenes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;nsfwScenes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;nsfwScenes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;scene&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;idx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;scenes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;splice&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;round&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;step&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;idx&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;idx&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;scene&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;h3&gt;
  
  
  Problem 3: NSFW photos weren't actually NSFW
&lt;/h3&gt;

&lt;p&gt;About half the "NSFW" photos were just kissing or a hand on a shoulder. Users paid $5 for a Party Pass, unlocked the content, and felt ripped off.&lt;/p&gt;

&lt;p&gt;The root cause: prompts like "two people kissing passionately, intense chemistry, R-rated" don't produce NSFW images — they produce a kiss. I rewrote every prompt to explicitly describe nudity rather than implying it. If you want the model to render bare skin, you have to ask for it directly.&lt;/p&gt;

&lt;h3&gt;
  
  
  Problem 4: The AI kept generating the same party theme
&lt;/h3&gt;

&lt;p&gt;Three nights in a row: "Spring Fling Soirée." Claude Haiku sees "Today is April, Season: spring" and converges on the obvious answer every time. There's no memory between runs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt; A &lt;code&gt;logs/used-themes.json&lt;/code&gt; file stores the last 90 theme names. Before each run, the script reads the last 30 and passes them to Claude as an explicit exclusion list.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;recentThemes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;readUsedThemes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;30&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;exclusionLine&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;recentThemes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
  &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="s2"&gt;`Do NOT use any of these recently used themes:\n&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;recentThemes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;`- &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;
  &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Injected into the Claude prompt&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;prompt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`...&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;exclusionLine&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;
Generate ONE party theme for tonight...`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Problem 5: Every image had the same framing
&lt;/h3&gt;

&lt;p&gt;The AI was defaulting to 2–3 people in a medium shot, every single time. Real party galleries mix wide crowd shots, tight close-ups, solo portraits, selfies, and detail shots of cocktails or decorations.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt; I added two new pools — &lt;code&gt;SHOT_TYPES&lt;/code&gt; (10 framing/angle options) and &lt;code&gt;SUBJECT_COUNTS&lt;/code&gt; (6 options from "just one person" to "packed crowd") — and assigned them randomly per image. I also added two new scene types: &lt;strong&gt;Selfie&lt;/strong&gt; (with front-facing iPhone camera descriptors) and &lt;strong&gt;Atmosphere&lt;/strong&gt; (detail shots with no people at all).&lt;/p&gt;

&lt;p&gt;Scene types are weighted to match what a real party gallery looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;SFW_TEMPLATES&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Dance Floor&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;    &lt;span class="na"&gt;weight&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="c1"&gt;// ~8 of 23 SFW images&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Candid Moments&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;weight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;  &lt;span class="c1"&gt;// ~6&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;At the Bar&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;     &lt;span class="na"&gt;weight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;  &lt;span class="c1"&gt;// ~4&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Arrivals&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;       &lt;span class="na"&gt;weight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;  &lt;span class="c1"&gt;// ~2&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Selfie&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;         &lt;span class="na"&gt;weight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;  &lt;span class="c1"&gt;// ~2&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Atmosphere&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;     &lt;span class="na"&gt;weight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.5&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="c1"&gt;// ~1&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Problem 6: Captions were 7 phrases on repeat
&lt;/h3&gt;

&lt;p&gt;The original caption function had 4 SFW options and 3 NSFW options. With 25 images per party you're guaranteed to see "Party vibes only" four times.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt; A single Claude API call generates all 25 captions at once. The model sees the full ordered scene list and the theme name, and writes unique, contextual captions for each one.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;prompt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`Write exactly &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;scenes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; captions for a "&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;themeName&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;" party.
Scenes: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;sceneList&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;
Rules: under 10 words, no hashtags, vary the tone, never repeat.
Respond with ONLY a JSON array of strings.`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Cost for 25 captions via Claude Haiku: about $0.001. The static fallback pool still runs if the API call fails.&lt;/p&gt;




&lt;h2&gt;
  
  
  The monetization
&lt;/h2&gt;

&lt;p&gt;The script sets &lt;code&gt;premium_pass_price: 5&lt;/code&gt; when creating the party. FlashParty handles the paywall — NSFW photos are blurred until a user buys a Party Pass.&lt;/p&gt;

&lt;p&gt;At a level 2 theme (5–9 NSFW images), each party has enough premium content to make the pass feel worth it. One sale covers roughly a week of nightly generation costs.&lt;/p&gt;




&lt;h2&gt;
  
  
  Get the code
&lt;/h2&gt;

&lt;p&gt;Everything is on GitHub: &lt;strong&gt;github.com/adamhawk-maker/flashparty-party-generator.git](&lt;a href="https://github.com/adamhawk-maker/flashparty-party-generator.git" rel="noopener noreferrer"&gt;https://github.com/adamhawk-maker/flashparty-party-generator.git&lt;/a&gt;)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Setup takes about 5 minutes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/adamhawk-maker/flashparty-party-generator.git
&lt;span class="nb"&gt;cd &lt;/span&gt;ai-party-generator
npm &lt;span class="nb"&gt;install
cp&lt;/span&gt; .env.example .env
&lt;span class="c"&gt;# Add your three API keys to .env&lt;/span&gt;
node party-generator.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You'll need API keys from &lt;a href="https://flashparty.co/developers" rel="noopener noreferrer"&gt;FlashParty&lt;/a&gt;, &lt;a href="https://partylab.dev" rel="noopener noreferrer"&gt;PartyLab&lt;/a&gt;, and &lt;a href="https://console.anthropic.com" rel="noopener noreferrer"&gt;Anthropic&lt;/a&gt;. The README has the full setup guide and a cost breakdown.&lt;/p&gt;




&lt;h2&gt;
  
  
  What I'd build next
&lt;/h2&gt;

&lt;p&gt;A few things on the roadmap if you want to extend this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;User-submitted themes&lt;/strong&gt; — let your audience vote on tomorrow night's party theme&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Multi-party batching&lt;/strong&gt; — generate a week's worth of parties in one run on Sundays&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Engagement hooks&lt;/strong&gt; — email or push notification when a new party goes live&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dynamic pricing&lt;/strong&gt; — higher &lt;code&gt;premium_pass_price&lt;/code&gt; on higher NSFW level themes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you build something with it, I'd love to see it. Drop a link in the comments.&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
