<?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: Sumit S Chawla</title>
    <description>The latest articles on DEV Community by Sumit S Chawla (@sumit_s_chawla).</description>
    <link>https://dev.to/sumit_s_chawla</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%2F4090672%2Ff60c4418-0dc7-4f05-afcf-e0f6e5d168d5.jpg</url>
      <title>DEV Community: Sumit S Chawla</title>
      <link>https://dev.to/sumit_s_chawla</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/sumit_s_chawla"/>
    <language>en</language>
    <item>
      <title>Campaory: a campaign tool that refuses to invent your event details</title>
      <dc:creator>Sumit S Chawla</dc:creator>
      <pubDate>Sat, 17 Oct 2026 18:33:52 +0000</pubDate>
      <link>https://dev.to/sumit_s_chawla/campaory-a-campaign-tool-that-refuses-to-invent-your-event-details-18d4</link>
      <guid>https://dev.to/sumit_s_chawla/campaory-a-campaign-tool-that-refuses-to-invent-your-event-details-18d4</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/hacktoberfest-week2-2026-10-12"&gt;Hacktoberfest Open-Source AI Challenge Week 2: Side Hustle&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;I organise PyData Indore. Every event I run turns into the same chore: the same handful of facts, retyped for LinkedIn, Instagram, WhatsApp and X, and retyped again whenever something changes.&lt;/p&gt;

&lt;p&gt;The mistakes are small, and they are mine. A venue post went out with the wrong location and the wrong year (2025, in 2026). I once sent people to the event info page when I meant the registration page, and had to correct it. For our Hack Day on 4 October, registration filled at 150, I raised the cap to 160, and that meant another round of posts on every platform. Afterwards I was a few days late with the recap, and while writing it I kept tripping over numbers that didn't agree: 154 registered, 94 checked in, "about 50 teams", 38 projects. Each platform got a slightly different version.&lt;/p&gt;

&lt;p&gt;We run on zero cash, with no social media person. It's me, copying a time from one tab to another and hoping I got it right.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Campaory&lt;/strong&gt; is the tool I wanted for the next event. It turns one event brief into a whole promotion campaign for &lt;strong&gt;LinkedIn, Instagram, WhatsApp and X&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%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Flcfpn6b773ozweqql850.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Flcfpn6b773ozweqql850.png" alt=" " width="800" height="379"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You paste a link or the event text. Campaory pulls out the facts (name, date, time, venue, registration link, speakers, price, seats) and shows each one next to the sentence it came from. &lt;strong&gt;You confirm them.&lt;/strong&gt; Only then does it plan the campaign (announcement, speaker intros, reminders, day-of, thank-you) and write each post in the right shape for each platform.&lt;/p&gt;

&lt;p&gt;The rule the whole app is built around:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;You confirm the facts. Code enforces them. The model only writes the copy.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Who would pay:&lt;/strong&gt; community organisers, college clubs, meetup hosts and small event agencies that promote several events a month and can't afford a wrong date reaching a few thousand people. Everything works as a guest with no sign-up. Signing in only matters if you want to save campaigns, and saving is where a paid plan would sit (the free plan keeps one saved campaign).&lt;/p&gt;

&lt;p&gt;I'd start at ₹499 per event, or ₹999 a month for someone running several. That is a guess I haven't tested. My own community runs on zero cash, so I'm not the buyer. The people who would pay are agencies and clubs running paid or sponsor-backed events.&lt;/p&gt;

&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Try it, no login needed:&lt;/strong&gt; &lt;a href="https://campaory.onrender.com" rel="noopener noreferrer"&gt;https://campaory.onrender.com&lt;/a&gt;, then click "Try a sample event".&lt;/p&gt;

&lt;h2&gt;
  
  
  Code
&lt;/h2&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/SamChawla" rel="noopener noreferrer"&gt;
        SamChawla
      &lt;/a&gt; / &lt;a href="https://github.com/SamChawla/campaory" rel="noopener noreferrer"&gt;
        campaory
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      One verified event brief to a campaign for LinkedIn, Instagram, WhatsApp and X. Facts confirmed by you, enforced by code; Gemma writes the copy.
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;Campaory&lt;/h1&gt;
&lt;/div&gt;
&lt;p&gt;Facts first. Then posts.&lt;/p&gt;
&lt;p&gt;Campaory turns one verified event brief into a coordinated campaign for LinkedIn, Instagram, WhatsApp and X. You confirm the facts; code checks every date, time and link; a Gemma model writes the copy. Try it without an account. Sign in only to save.&lt;/p&gt;
&lt;p&gt;Status: documentation pack only. No application code yet.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Start here&lt;/h2&gt;
&lt;/div&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;docs/HANDOFF.md&lt;/code&gt;: setup, accounts, decisions, risks&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;docs/IMPLEMENTATION_PLAN.md&lt;/code&gt;: task list with acceptance criteria&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;CLAUDE.md&lt;/code&gt;: rules for Claude Code in this repo&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Documents&lt;/h2&gt;
&lt;/div&gt;
&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Document&lt;/th&gt;
&lt;th&gt;Purpose&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;docs/Campaory_Business_Requirements_Document_v1.1.docx&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Business requirements (current). &lt;code&gt;docs/Campaory_BRD_v1.0_original.docx&lt;/code&gt; is the earlier version&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;docs/PRD.md&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Product requirements, stories, acceptance&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;docs/DESIGN.md&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Design overview and scope cut&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;docs/UI_SPEC.md&lt;/code&gt;, &lt;code&gt;docs/mockups/&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Visual design, tokens, mockup sources, unmocked screens&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;docs/ARCHITECTURE.md&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Diagrams (Mermaid)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;docs/HLD.md&lt;/code&gt;, &lt;code&gt;docs/LLD.md&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;High-level and low-level design, API, schema, algorithms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;docs/adr/&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Eight architecture decision records&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;docs/TEST_PLAN.md&lt;/code&gt;, &lt;code&gt;docs/DEPLOYMENT.md&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Testing and Render setup&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;docs/SUBMISSION.md&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;DEV submission kit&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Planned stack&lt;/h2&gt;

&lt;/div&gt;
&lt;p&gt;FastAPI, React (Vite), PostgreSQL on Render…&lt;/p&gt;&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/SamChawla/campaory" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;MIT licensed. FastAPI + React, one Docker service on Render. 539 backend tests, 75 frontend tests, and Playwright end-to-end runs at phone and desktop widths.&lt;/p&gt;

&lt;h2&gt;
  
  
  How I Built It
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Model:&lt;/strong&gt; &lt;a href="https://ai.google.dev/gemma" rel="noopener noreferrer"&gt;Gemma 4&lt;/a&gt; (&lt;code&gt;google/gemma-4-26B-A4B-it&lt;/code&gt;), an open-weight model, served through Euri's OpenAI-compatible API.&lt;/p&gt;

&lt;p&gt;Gemma does two jobs and nothing else:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Extraction:&lt;/strong&gt; read a messy event page and return candidate facts, each with an exact quote from the source.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Writing:&lt;/strong&gt; turn confirmed facts and a plan item into one post per platform.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Everything that can be wrong in a way that hurts is decided by plain Python, not the model:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Every extracted fact must quote its source.&lt;/strong&gt; If the quote isn't in the page text, the fact is thrown away and marked missing. A made-up fact can't sneak in.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The plan and the dates are computed, not generated.&lt;/strong&gt; Reminder timing, "registration closes" posts and the day-of post come from the confirmed dates.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Every generated post goes through a guard.&lt;/strong&gt; Each URL, date, time, amount, handle and count in the text must match a confirmed fact. Here is real guard output for a post about the sample event that got the details wrong:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;UNKNOWN_DATE    '25 October'
UNKNOWN_TIME    '9:30 AM'
UNKNOWN_COUNT   '50 seats'
UNKNOWN_AMOUNT  'Rs 199'
UNKNOWN_URL     'https://example.org/riverside-hackday/rsvp'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The correct version of the same post comes back with zero flags. A flagged post can't be approved until you fix it.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Platform rules are code too:&lt;/strong&gt; X's 280 characters, Instagram's hashtag limit, WhatsApp's readable length.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Change impact:&lt;/strong&gt; change the time after posts exist and Campaory lists exactly which posts mention it and proposes a redraft for each. Posts you've already marked published are never touched. It suggests a correction post instead. This is the feature I wanted most, because it is the 150-to-160 problem solved.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;What Gemma was like to work with:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It wraps JSON in a 

``&lt;code&gt;

json fence instead of returning it raw, so the app strips fences and repairs the output before validating it.
- It invented key names (&lt;/code&gt;mentor_asha_verma_specialty`) until the prompt listed the allowed keys.
- It was very good at the "copy an exact quote" rule. Snippets matched the source.
- Latency is uneven. Extraction took 15 s on one try and over 45 s on two others. In production a call times out at 25 s and falls back to clearly labelled &lt;strong&gt;Demo model&lt;/strong&gt; output instead of an error. Generating posts for two plan items across four platforms took about 22 s on the live site.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;The part that wasn't the model:&lt;/strong&gt; my first interface looked like every AI tool: mono labels, hairline tables, one highlight colour. I threw it away and redesigned it twice before it looked like a product for organisers rather than a prompt box.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Stack:&lt;/strong&gt; Python 3.12, FastAPI, Pydantic v2, SQLAlchemy, Alembic · React 18, Vite, TypeScript, Zustand · Postgres on Render · one Docker image. Guest campaigns live only in the browser. The server never stores them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Does Open Innovation Matter?
&lt;/h2&gt;

&lt;p&gt;On 4 October I handed out a Best Use of Gemma 4 prize at our Hack Day. A week later I was building on Gemma 4 myself. I could do that because the model was cheap enough to use in a tool for a community with no budget.&lt;/p&gt;

&lt;p&gt;That is why open models matter to me. It isn't a benchmark. It is whether someone like me can afford to build the thing at all.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The weights are open, so I'm not renting the core of the product.&lt;/strong&gt; Today Gemma runs through a hosted API. A college club or agency that doesn't want event data leaving its own machines can run the same model on its own hardware without rewriting the app.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cost decides whether this is a side hustle at all.&lt;/strong&gt; Organisers will pay a few hundred rupees a month, not a few thousand. A small open model (26B total, about 4B active per token) keeps the cost per campaign low enough for that to work.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The design doesn't depend on the model being smart.&lt;/strong&gt; Facts, dates and links are&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>devchallenge</category>
      <category>hf26challenge</category>
      <category>ai</category>
      <category>python</category>
    </item>
  </channel>
</rss>
