{"slug": "listinglift-my-mother-s-kantha-listings-written-by-gemma-inside-a-browser-tab-0", "title": "ListingLift: My Mother's Kantha Listings, Written by Gemma Inside a Browser Tab (₹0 per Listing, 0 Bytes Uploaded)", "summary": "A Hacktoberfest Open-Source AI Challenge Week 2 submission called ListingLift generates marketplace listings from a seller's rough notes and a product photo using open-weight Google Gemma 3 1B running entirely in the browser via WebLLM and WebGPU, with no server, API key or per-listing cost. The tool targets Etsy, Amazon, eBay, Meesho, Shopify and Instagram, fitting output to each platform's limits (Etsy's 140-character titles and 13 tags, Amazon's 200-character titles and 7 search terms, eBay's 80-character titles) and running a Fact Guard that flags claims not present in the seller's notes. The first run downloads roughly 700 MB of model weights into the browser cache, after which the app works offline; the author proposes a free tier plus Seller Pro at ₹299/month and a Craft collective tier at ₹1,499/month, arguing zero marginal inference cost lets the core product stay free.", "body_md": "# ListingLift: My Mother's Kantha Listings, Written by Gemma Inside a Browser Tab (₹0 per Listing, 0 Bytes Uploaded)\n\nThis is a submission for the Hacktoberfest Open-Source AI Challenge Week 2: Side Hustle TL;DR ListingLift turns a seller's rough notes and a product photo into a ready-to-paste Etsy, Amazon, eBay, Meesho, Shopify or Instagram listing. The model is open-weight Google Gemma, running inside the browser\n\nThis is a submission for the Hacktoberfest Open-Source AI Challenge Week 2: Side Hustle TL;DR ListingLift turns a seller's rough notes and a product photo into a ready-to-paste Etsy, Amazon, eBay, Meesho, Shopify or Instagram listing. The model is open-weight Google Gemma, running inside the browser tab through WebLLM and WebGPU. No server. No API key. No per-listing bill. And a Fact Guard that catches the claims a small model invents before a buyer ever reads them. My mother makes Kantha-stitch dupattas in West Bengal. Every piece is a few layers of old saris, hand-quilted with a running stitch. Every piece is one of a kind. And every piece needs a listing: a title that fits the marketplace's character limit, five bullet points, a description, a dozen search tags, a meta line. Multiply that by thirty products and four marketplaces and you get the real bottleneck of a small online craft business. It isn't making the thing. It's describing it, over and over, in the exact shape each platform wants. ListingLift is a listing writer for that seller. You: Drop a product photo. ListingLift reads its dominant colours on your device (a tiny k-means pass on a 64×64 canvas; the pixels never leave memory). Type the notes you'd tell a friend: what it is, who made it, size, material, care. Pick a marketplace, a tone and a language. Hit Generate. Gemma streams a full listing token by token. ListingLift then fits it to the platform (trims titles to the limit, de-duplicates and caps tags, strips prompt echoes) and runs the Fact Guard, which highlights every claim that isn't in your notes. Copy, download CSV or JSON, done. Indian marketplace sellers (Meesho, Amazon.in, Etsy India), Instagram shops, and the long tail of handmade sellers everywhere. Today they either write every listing by hand, pay a freelancer, or pay a monthly subscription to a cloud \"AI listing generator\" that charges per generation and ships their unreleased product details to someone else's server. The business model I'd actually run: Plan Price What you get Free ₹0 Unlimited listings in the browser. Your hardware does the work, so this costs me nothing to give away. Seller Pro ₹299/month (≈ $3.50) Bulk mode (CSV in, CSV out), saved brand voices, marketplace-specific rule packs (Etsy 13-tag rules, Amazon style guide checks), custom risky-claim lists. Craft collective ₹1,499/month Shared brand voice and rule packs for a co-op of artisans, one admin. The interesting part: because inference runs on the customer's device, my marginal cost per listing is zero. A cloud competitor has to charge per generation to cover GPU bills. I can charge for the workflow instead, and the core product can stay free forever. That pricing is only possible because the model is open. 🎬 The studio, end to end (real recorded Gemma 3 1B run: stream, platform fit, Fact Guard, score): When you open the app, the first run downloads the model once into your browser cache (Gemma 3 1B is roughly 700 MB). After that it works offline: turn off Wi-Fi and generate again. If your browser has no WebGPU, the studio switches to replay mode and plays back real recorded Gemma runs (clearly labelled), so you still see the whole flow. Six marketplaces, each with its own rules baked into the prompt and the post-processor: Marketplace Title limit Tags Bullets Style the prompt asks for Etsy 140 chars 13 × 20 chars 5 warm, story-led, long-tail search phrases Amazon 200 chars 7 search terms 5 benefit-first, factual, no subjective hype eBay 80 chars 8 4 keyword-dense title, specifics up front Meesho 100 chars 8 5 simple, value-focused Shopify 70 chars 10 5 brand voice, SEO meta Instagram 90 chars 20 hashtags 3 casual caption, community hashtags This is a real Gemma 3 1B output for my mother's dupatta. Look at bullet 4: \"Made from 100% organically grown cotton.\" My notes never said organic. They never said 100%. A buyer who reads that and receives recycled sari cotton has a legitimate complaint, and the seller has a refund and a bad review. The Fact Guard caught four things: \"luxurious\", \"100%\", \"organic\" and the tag \"fair trade\". Each one is highlighted in place, in red, so the seller can delete it in two seconds. Every privacy page says \"we don't upload your data\". ListingLift shows you. The Network Witness panel reads the browser's own PerformanceObserver resource log and lists every request the page makes. Model shards and the WebLLM library come down from public CDNs. Then every outgoing URL is checked against the text of your notes. If any request ever contained them, the big green 0 would turn red. ListingLift is deliberately tiny: one HTML file, no build step, no backend, no framework. Open the live app and use View Source: every line is there, readable and commented. Here is the core of it. async function getEngine(model) { if (engine && engineModel === model) return engine; const webllm = await import(\"https://esm.run/@mlc-ai/web-llm@0.2.86\"); engine = await webllm.CreateMLCEngine(model, { initProgressCallback: (r) => { bar.style.width = Math.round(r.progress * 100) + \"%\"; label.textContent = r.text; }, }); engineModel = model; return engine; } The model picker offers three open-weight Gemma builds that WebLLM ships prebuilt: Model ID (WebLLM) Why you'd pick it gemma3-1b-it-q4f16_1-MLC Fastest, smallest download. Default. gemma-2-2b-it-q4f16_1-MLC Fewer invented claims in my tests (see benchmarks). gemma-4-E2B-it-q4f16_1-MLC Newest Gemma generation, bigger download. const stream = await engine.chat.completions.create({ messages: [{ role: \"user\", content: buildPrompt(opts) }], temperature: 0.6, stream: true, max_tokens: 900, }); for await (const chunk of stream) { raw += chunk.choices[0]?.delta?.content || \"\"; consoleEl.textContent = raw; // live token stream } const result = process(raw, opts); // fit + guard + score WebLLM exposes an OpenAI-compatible API, so the code reads exactly like a cloud call. The difference is where it runs. export function buildPrompt({ notes, platform, tone, lang, colors }) { const p = PLATFORMS[platform]; const col = colors?.length ? `\\nDominant photo colours (detected on-device): ${colors.join(\", \")}.` : \"\"; return `You are ListingLift, an expert ${p.name} copywriter for small independent sellers. Write a ${p.name} listing in ${lang}. Tone: ${tone}. Platform style: ${p.style}. Use ONLY facts from the seller notes. Never invent materials, percentages, certifications or sizes. Seller notes: ${notes}${col} Return ONLY JSON with keys: \"title\" (max ${p.titleMax} characters), \"bullets\" (exactly ${p.bullets} short benefit bullets), \"description\" (90-130 words), \"tags\" (exactly ${p.tagCount} unique search tags, each max ${p.tagLen} characters), \"seo_meta\" (one sentence, max 155 characters).`; } Notice the line \"Never invent materials, percentages, certifications or sizes.\" Gemma 3 1B still wrote \"100% organically grown cotton\". Prompting is necessary, and it is not sufficient. That's why the next part exists. const RISKY = [\"100%\", \"organic\", \"fair trade\", \"certified\", \"genuine leather\", \"pure silk\", \"silk\", \"waterproof\", \"hypoallergenic\", \"vegan\", \"non-toxic\", \"premium\", \"luxury\", \"luxurious\", \"antique\", \"vintage\", \"heirloom\", \"guaranteed\", \"warranty\", \"eco-friendly\", \"biodegradable\", \"high-temperature\", \"lead-free\", \"weather-resistant\", /* … */]; export function factGuard(listing, notes, lang = \"English\") { const src = notes.toLowerCase(); const flags = []; for (const [field, text] of fieldsOf(listing)) { const t = text.toLowerCase(); // 1. risky claims that the seller never made for (const w of RISKY) if (t.includes(w) && !src.includes(w)) flags.push({ field, claim: w, kind: \"unsupported claim\" }); // 2. numbers with units that aren't in the notes (invented sizes, weights, burn times) for (const m of t.matchAll(/(\\d+(?:\\.\\d+)?)\\s?(%|cm|mm|m|inch|inches|g|kg|ml|hours?)\\b/g)) if (!src.includes(m[1])) flags.push({ field, claim: m[0], kind: \"number not in notes\" }); // 3. script leaks, e.g. Arabic characters inside a Bengali listing if (/[\\u0600-\\u06FF]/.test(text) && ![\"Arabic\", \"Urdu\"].includes(lang)) flags.push({ field, claim: \"Arabic-script text\", kind: \"script leak\" }); } // tags get checked too, and the description must actually be in the requested script ... return dedupe(flags); } It's intentionally boring: a lexicon, a regex, and Unicode ranges. No second model, no extra download, runs in under a millisecond. It turns \"I hope the AI didn't lie\" into a short, highlighted to-do list. export function fitToPlatform(raw, platform) { const p = PLATFORMS[platform]; // title: cut at the last word boundary under the limit // bullets: drop prompt echoes like \"Return only JSON with keys:\", cap the count // tags: lowercase, strip '#', shorten to tagLen, de-duplicate, cap to tagCount // instagram: turn tags into #hashtags // meta: trim to 155 chars on a word boundary return { listing, fixes }; // every fix is reported back to the UI } Small models are great at content and sloppy at constraints. Gemma 3 1B returned 16 tags for a 13-tag Etsy slot (two of them duplicates), and once returned nine bullets when I asked for five, the last one being a copy of my own prompt. Deterministic code fixes that for free, and the UI lists every fix it made so nothing happens silently. Model: Google Gemma (open weights): Gemma 3 1B IT by default, Gemma 2 2B IT and Gemma 4 E2B selectable. 4-bit quantised MLC builds. Runtime: WebLLM 0.2.86 (MLC AI, Apache-2.0) on WebGPU. OpenAI-style streaming API in the browser. App: a single static HTML file, vanilla JS, no framework, no bundler. Canvas for the aurora background and colour extraction, CSS for every animation, IntersectionObserver for scroll reveals, PerformanceObserver for the Network Witness. localStorage for history (with a graceful fallback where storage is blocked). Benchmark harness: the same prompt builder ported to Python, driving Ollama with gemma3:1b and gemma2:2b on a 2-core ARM CPU with about 8 GB RAM and no GPU. Demo film: a 1920×1080 HTML \"film\" with a deterministic seek(t) timeline, rendered frame by frame with headless Chromium (1,837 frames at 24 fps), narrated with the open-source Piper TTS voice, and encoded with FFmpeg. Every tool in the video pipeline is open source, too. ┌──────────────── your browser tab ─────────────────┐ │ │ │ photo ──► canvas k-means ──► colour names ─┐ │ │ ▼ │ │ notes ───────────────────────────► buildPrompt() │ │ │ │ │ WebLLM + WebGPU ▼ │ │ ┌──────────────────────────────────────┐ │ │ │ Gemma (q4f16, cached in browser) │ │ │ └──────────────────────────────────────┘ │ │ │ streamed JSON │ │ ▼ │ │ fitToPlatform() ─► factGuard() ─► score() │ │ │ │ │ ▼ │ │ copy · CSV · JSON · local history │ │ │ │ PerformanceObserver ─► Network Witness (0) │ └────────────────────────────────────────────────────┘ ▲ one-time download of model weights (public CDN) There is no box outside the tab that ever sees the seller's data. I didn't want to write \"it's fast\" and \"it's accurate\" without numbers, so I ran the exact same prompts through the same post-processor on a deliberately weak machine: 2 CPU cores, about 8 GB RAM, no GPU at all. A laptop with WebGPU will be faster. These are floor numbers. Product Model Marketplace · language Speed (CPU only) Fact Guard flags Score 🧵 Kantha dupatta Gemma 3 1B Etsy · English 26.3 tok/s luxurious, 100%, organic, fair trade 80 🧵 Kantha dupatta Gemma 2 2B Etsy · English 16.0 tok/s none 96 🐎 Bankura terracotta horse Gemma 3 1B Amazon · English 26.4 tok/s high-temperature, antique 90 🐎 Bankura terracotta horse Gemma 2 2B Amazon · English 16.1 tok/s weather-resistant (×2) 78 🕯️ Chai soy candle Gemma 3 1B Instagram · English 26.5 tok/s none 90 🇧🇩 Kantha dupatta Gemma 3 1B Meesho · Bengali 20.6 tok/s Arabic-script leak 79 🇧🇩 Kantha dupatta Gemma 2 2B Meesho · Bengali 16.1 tok/s eco-friendly ×3, description not in Bengali 68 What I take from it: Gemma 3 1B is fast enough on a CPU (about 26 tokens/s; a full listing in roughly 15–19 s) but invents marketing claims. With the Fact Guard on top, it's usable. Gemma 2 2B is slower and more faithful to the notes in English: zero flags on the dupatta, but it still called an unglazed terracotta horse \"weather-resistant\". No small model is trustworthy on its own, which is exactly why the guard exists. Swapping between them is a dropdown. Bengali is hard for both small models. Gemma 3 1B wrote real Bengali but leaked a stray Arabic word and padded the bullets with nine items, including an echo of my own instructions. Gemma 2 2B mostly answered in English. The Fact Guard flagged both. This is the honest frontier: regional-language commerce needs bigger or fine-tuned open models, and because the weights are open, anyone can do that fine-tune. (Gemma 3 1B, Bengali, Meesho. Note the Fact Guard catching the Arabic-script word in bullet 1, and the auto-fixes trimming nine bullets down to five.) (Gemma 2 2B on the same dupatta: every claim traced back to the notes.) Deterministic guard rails over a second LLM. A \"critic model\" would double the download and the latency on exactly the hardware my users have. A lexicon plus regex catches the claims that cause refunds. Strict JSON, parsed leniently. I ask for JSON and then extract the first {…} block, because small models like to add a friendly sentence before it. Replay mode instead of a broken page. Many phones and some desktop browsers still lack WebGPU. Rather than an error, the studio replays recorded Gemma runs from my benchmark, labelled as recordings, so judges and sellers can see the full flow anywhere. One file. A seller's nephew can save it, put it on any static host, and it works. No build chain to rot. First load is a large download (roughly 700 MB to 1.4 GB depending on the model). After that it's cached. Needs WebGPU for live generation (recent Chrome or Edge on desktop, newer Android Chrome). Safari support is improving. The Fact Guard is a lexicon. It catches the common lies, not every subtle one. It's a seatbelt, not an autopilot. Regional-language quality from 1B–2B models is not production-grade yet (see the Bengali rows). Because for this product, a closed API isn't a slightly worse option. It's a different, worse product. 1. Privacy becomes a property of the architecture, not a promise. A seller's unreleased designs, supplier notes and pricing are business secrets. With an open-weight model I can run inference inside the user's own browser, and then prove it with the Network Witness. With a closed API, the best I could offer is a privacy policy. 2. Zero marginal cost changes who can afford AI. A closed API bills per token, forever, so every listing has a price and every rewrite costs more. For a craft seller earning a few hundred rupees per piece, that adds up. With open weights the user's own GPU does the work: my cost per listing is ₹0, so the core product can stay free and I charge for workflow features instead. 3. Offline is a feature in Bharat. Mobile data drops. Power cuts happen. Once the model is cached, ListingLift keeps working in airplane mode. No cloud product can say that. 4. Model choice is a dropdown, not a contract. My benchmark shows Gemma 2 2B makes fewer invented claims than Gemma 3 1B. Switching took one line. When a better open model ships tomorrow, sellers get it the same day. When one model is weak in Bengali, the open weights mean anyone can fine-tune a better one and drop it in. 5. It's auditable end to end. Open weights (Gemma), an open runtime (WebLLM, Apache-2.0), and an app that is one readable HTML file. A seller, or a judge, can inspect every step between their notes and the listing. That's what lets me make the privacy claim at all. My mother doesn't care what a transformer is. She cares that the listing is right, that it costs nothing, and that her designs stay hers. Open models are the only way I know to give her all three. Best Use of Gemma: the whole product is built around open-weight Gemma running locally (Gemma 3 1B default, Gemma 2 2B and Gemma 4 E2B selectable), with measured comparisons between Gemma generations. Built by @aniruddhaadak during Hacktoberfest 2026. Thanks to the Gemma team for open weights, the MLC/WebLLM team for making them run in a browser, and the Piper and FFmpeg communities whose tools made the demo film.\n\n## Key Takeaways\n\n- •This is a submission for the Hacktoberfest Open-Source AI Challenge Week 2: Side Hustle TL;DR ListingLift turns a seller's rough notes and a product photo into a ready-to-paste Etsy, Amazon, eBay, Meesho, Shopify or Instagram listing\n- •This story was reported by **Dev.to** , covering developments in the**dev** space.\n- •AI advancements continue to reshape industries — read the full article on Dev.to for complete coverage.\n\n📖 Continue reading the full article:\n\n[Read Full Article on Dev.to →](https://dev.to/aniruddhaadak/listinglift-my-mothers-kantha-listings-written-by-gemma-inside-a-browser-tab-0-per-listing-0-1k66)", "url": "https://wpnews.pro/news/listinglift-my-mother-s-kantha-listings-written-by-gemma-inside-a-browser-tab-0", "canonical_source": "https://ainexusdaily.vercel.app/article/2026-10-17-listinglift-my-mothers-kantha-listings-written-by-gemma-inside-a-browser-tab-0-p", "published_at": "2026-10-17 09:47:17+00:00", "updated_at": "2026-10-17 10:34:55.822973+00:00", "lang": "en", "topics": ["ai-tools", "generative-ai", "large-language-models", "ai-products"], "entities": ["ListingLift", "Google", "Gemma 3 1B", "WebLLM", "WebGPU", "Etsy", "Amazon", "Meesho"], "also_reported_by": [], "alternates": {"html": "https://wpnews.pro/news/listinglift-my-mother-s-kantha-listings-written-by-gemma-inside-a-browser-tab-0", "markdown": "https://wpnews.pro/news/listinglift-my-mother-s-kantha-listings-written-by-gemma-inside-a-browser-tab-0.md", "text": "https://wpnews.pro/news/listinglift-my-mother-s-kantha-listings-written-by-gemma-inside-a-browser-tab-0.txt", "jsonld": "https://wpnews.pro/news/listinglift-my-mother-s-kantha-listings-written-by-gemma-inside-a-browser-tab-0.jsonld"}}