This is a submission for the Gemma 4 Challenge: Build with Gemma 4
What I Built
I developed SMM Turbo - a blazing-fast, completely free graphic editor for creating Instagram carousels that works directly in the browser.
Instead of traditional <canvas>, SMM Turbo uses a DOM-based architecture with Svelte 5 runes for state management. But its real superpower is the Hybrid AI Co-Pilot, which combines local in-browser neural networks (for background removal) and cloud-based LLMs to completely automate the SMM workflow.
Demo
Live Project: https://smm.shcho-i-yak.pp.ua
Code
GitHub Repository: https://github.com/bodikinf/smm-turbo-open (Make sure to open it!)
How I Used Gemma 4
To create a truly intelligent "SMM Strategist", I integrated the Gemma 4 31B model via the Google Generative Language API.
Why Gemma 4 31B? Generating a cohesive, conversion-focused 5-slide marketing carousel (Hook, Pain, Solution, Proof, CTA) requires deep reasoning and high context retention. Smaller models often lose the marketing context, but the 31B model handles complex instructional prompts flawlessly, delivering ready-to-publish strategies.
Technical Challenge Overcome:
Because the 31B model takes around 12-15 seconds to generate a highly detailed marketing structure, it consistently hit the strict 10-second serverless timeout limit on my hosting (resulting in 502 Bad Gateway errors).
To solve this, I bypassed heavy official SDKs and implemented a native fetch request within an Edge Function (runtime: 'edge'). This extended the timeout limit to 30 seconds and drastically reduced the memory footprint, allowing the Gemma 4 31B model to unleash its full reasoning capabilities without timeouts.
But let's start from the beginning. Here is the full story of how SMM Turbo was born and how it works under the hood...
Hello. 👋 If you work in marketing, run your own business, or develop your personal brand, you know how much time creating visual content takes. Photoshop is too "heavy", expensive, and complicated for daily tasks. And popular online services like Canva are becoming increasingly overloaded with unnecessary features and require a paid subscription for the simplest tools.
That's why I decided to take matters into my own hands. I developed my own graphic editor for creating Instagram carousels, which works directly in the browser, uses the power of artificial intelligence, and is completely free.
Today, I'll tell you the story of creating SMM Turbo. We'll take a look "under the hood", explore the magic of the latest Svelte 5, break down in-browser artificial intelligence, and learn how to create a cool tool for SMM specialists from scratch. Let's go. 🚀
🛠 Why I decided to write my own graphic editor for creating Instagram carousels?
Creating carousels for Instagram is a very specific task. You need to keep the overall visual style in mind, seamlessly move elements between slides, and quickly export everything in the correct format with optimized weight.
Most existing solutions didn't give me the speed I needed. So, I formed three main requirements for my future product:
- Lightning-fast speed. No long uploads or lags when dragging layers. The interface must respond instantly.
- AI assistant at hand. I wanted AI to not just be "for show", but really help generate ideas, texts, and cut out the background right on the canvas.
- Free and accessible. The tool must work in any browser without installing "heavy" software on a PC.
To implement this ambitious plan, I chose the SvelteKit framework (with the latest Svelte 5). Its compiled nature and new reactive "runes" allowed me to create an extremely complex interface without losing productivity.
We also recommend reading: Overview of the Svelte 5 ecosystem: What's new and why you should switch
🏗 Architecture: DOM instead of Canvas
If you've ever been interested in developing graphic editors, you know that the standard approach is to use HTML5 <canvas> or special libraries like Fabric.js or Konva. But I took a different, somewhat rebellious path 🐧.
In SMM Turbo, the working area is ordinary HTML elements (<div>, <span>, <img>) that are positioned absolutely using x and y coordinates.
Why so? Because CSS is a superpower! 🦸♂️
Rendering through DOM allowed me to implement incredibly complex typography in just a few lines of code, instead of writing complex math for drawing pixels on Canvas.
Here's what regular CSS gives you:
-
Gradient text: Using
-webkit-background-clip: text. -
Stroke (outline): Works through
-webkit-text-stroke. -
Shadows and glow: Elementary
drop-shadowandtext-shadow. -
Text bending along a circle: Implemented by breaking the text into separate
<span>elements usingtransform: rotate(...) translateY(...).
But how do you save the finished picture then? That's where the html-to-image library comes in.
Here's what my script for exporting to +page.svelte looks like, which takes a "screenshot" of the DOM node, packs the slides into an archive using JSZip, and converts them "on the fly":
const options = {
width: editor.canvasWidth,
height: editor.canvasHeight,
style: { transform: 'scale(1)', transformOrigin: 'top left' },
pixelRatio: 1,
cacheBust: true
};
// Draw Canvas from DOM
const canvas = await toCanvas(node, options);
// Save in the selected format (WebP/JPEG) with the desired quality
const dataUrl = canvas.toDataURL(editor.exportFormat, qualityDecimal);
capturedImages.push(dataUrl);
// Pack all slides into a ZIP archive
const zip = new JSZip();
capturedImages.forEach((img, i) => {
const base64Data = img.split(',')[1];
zip.file(`smm-slide-${i + 1}.webp`, base64Data, {base64: true});
});
const content = await zip.generateAsync({type: "blob"});
Thanks to this, we get perfect text quality, flexibility of CSS filters, and fast export of the entire carousel.
🌍 Multilingualism with Runes: On-the-Fly Localization
As the project expanded, there was a need to add an English version of the interface and landing page to attract an international audience. In the React or Vue ecosystem, you'd typically install heavy libraries like i18next for this. But in Svelte 5, we can do it much more elegantly thanks to "runes".
I created a simple localization service based on the reactive $state, which instantly repaints the entire interface when the language changes, without resetting any unsaved changes on the carousel canvas:
// src/lib/i18n/i18n.svelte.ts
class I18nService {
locale = $state('uk'); // Reactive language state
t(key: string) {
return translations[this.locale][key] || key;
}
setLocale(newLocale: string) {
this.locale = newLocale;
localStorage.setItem('smm_lang', newLocale);
}
}
export const i18n = new I18nService();
Because locale is a $state, any component using i18n.t('key') will instantly update as soon as the language changes. This also made it painless to set up automatic language detection: if a person enters the editor from an English or German browser, the script immediately reads navigator.language and automatically turns on the English version of the interface.
🪄 AI Magic: In-Browser background removal
A cool graphic editor for creating Instagram carousels in 2026 can't exist without built-in artificial intelligence.
Usually, services ask for money for background removal, because they send your photo to remote powerful servers with GPU. I decided to make this process local and free!
I used the incredible @imgly/background-removal library. This is a real revolution! The neural network is loaded in WebAssembly (WASM) format directly into your browser.
async function handleRemoveBackground() {
isRemovingBg = true;
try {
const imgly = await import('@imgly/background-removal');
const removeBg = imgly.removeBackground;
// AI works directly on the user's device
const imageBlob = await removeBg(selected.content);
const url = URL.createObjectURL(imageBlob);
selected.content = url;
editor.saveState();
} catch (error) {
alert("Failed to remove background.");
} finally {
isRemovingBg = false;
}
}
You just select a photo, click the "Remove Background" button, and your computer perfectly cuts out the main object in a couple of seconds. No limits, subscriptions, or transferring confidential photos to third-party servers.
We also recommend reading: How to integrate AI into your web application using Groq API
🤖 Hybrid AI Co-Pilot: Combining Gemma 4 and Llama 3.1
In addition to working with images, I added a powerful text AI assistant. But during development, I faced a classic problem: quick tasks (like idea generation) require minimal latency, while deep analytics (strategy development) require powerful "heavy" models that take longer to think.
Therefore, I created a Hybrid Engine that automatically routes requests:
- 🧙♂️ Alchemist, 🎨 Artist, and 💬 To Canvas (Cloud Fast Mode) run through the ultra-fast API from Groq powered by the Llama 3.1 8B model. This model is perfect for micro-tasks. You ask for a clickbait headline, the AI instantly gives you 3 options, and you add the text directly to the current slide with one click.
- 🧠 SMM Strategist (Cloud Reasoning Mode) is our "heavy artillery". It works directly through the Google API powered by the cutting-edge Gemma 4 31B model. This mode conducts a deep analysis of the topic and provides a ready-made 5-slide carousel structure (Hook, Pain, Solution, Proof, CTA).
Bypassing Free Server Limits (Edge Functions)
To give the "Strategist" enough time to think so the Netlify server wouldn't drop the connection due to the standard 10-second timeout (the infamous 502 Bad Gateway error), I moved this API route to the Edge architecture, which allows up to 30 seconds for execution. I also completely abandoned the "heavy" official SDKs in favor of native fetch.
Here is the real backend code (src/routes/api/ai/+server.ts) that drives this hybrid magic:
import { json } from '@sveltejs/kit';
import { GROQ_API_KEY, GOOGLE_AI_API_KEY } from '$env/static/private';
// Switching to Edge runtime to bypass Netlify's 10-second limit
export const config = { runtime: 'edge' };
export async function POST({ request }) {
try {
const { prompt, mode, locale } = await request.json();
// ==========================================
// 🧠 STRATEGIST MODE: Direct call to Gemma 4 31B
// ==========================================
if (mode === 'strategist') {
const systemInstruction = locale === 'en'
? `You are a Senior SMM Strategist. Create a detailed 5-slide Instagram carousel structure based on the user's topic: "${prompt}".\nFormat:\nSlide 1 (Hook): [Headline & Visual]\nSlide 2 (Pain): [Problem]\nSlide 3 (Solution): [How to solve]\nSlide 4 (Proof): [Benefits]\nSlide 5 (CTA): [Action]\nLanguage: English. Be concise.`
: `Ти — Senior SMM-стратег. Розроби структуру Instagram-каруселі на 5 слайдів для теми: "${prompt}".\nФормат:\nСлайд 1 (Гачок): [Заголовок та візуал]\nСлайд 2 (Біль): [Проблема]\nСлайд 3 (Рішення): [Як вирішити]\nСлайд 4 (Докази/Користь): [Переваги]\nСлайд 5 (Заклик): [Дія]\nВідповідай ВИКЛЮЧНО українською. Будь лаконічним.`;
const googleRes = await fetch(`https://generativelanguage.googleapis.com/v1beta/models/gemma-4-31b-it:generateContent?key=${GOOGLE_AI_API_KEY}`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
contents: [{ role: "user", parts: [{ text: systemInstruction }] }],
generationConfig: { temperature: 0.7, maxOutputTokens: 1024 }
})
});
if (!googleRes.ok) throw new Error(`Google API Error: ${googleRes.status}`);
const googleData = await googleRes.json();
return json({ result: googleData.candidates?.[0]?.content?.parts?.[0]?.text || '' });
}
// ==========================================
// ⚡ FAST MODES: Lightning-fast Llama 3.1 via Groq
// ==========================================
let systemMessage = "";
if (mode === 'canvas') {
systemMessage = locale === 'en'
? `You are a creative copywriter. Generate exactly 3 short text options. Start each with 🔹. No intro! Language: English.`
: `Надай рівно 3 коротких варіанти тексту. Кожен починається з 🔹. Без вступних слів! Мова: українська.`;
}
// ... (additional configurations for other modes)
const groqRes = await fetch('[https://api.groq.com/openai/v1/chat/completions](https://api.groq.com/openai/v1/chat/completions)', {
method: 'POST',
headers: {
'Authorization': `Bearer ${GROQ_API_KEY}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
model: 'llama-3.1-8b-instant',
messages: [
{ role: 'system', content: systemMessage },
{ role: 'user', content: prompt }
],
temperature: 0.7,
max_tokens: 1024
})
});
if (!groqRes.ok) throw new Error(`Groq API Error: ${groqRes.status}`);
const groqData = await groqRes.json();
return json({ result: groqData.choices?.[0]?.message?.content || '' });
} catch (error: any) {
return json({ error: error.message || 'Failed to generate response.' }, { status: 500 });
}
}
Additionally, the editor has a convenient help section that transparently explains to users how this hybrid system works, and how they can activate Edge AI (local execution) for maximum privacy:
🔄 State Management: Svelte 5 Magic
One of the biggest challenges in developing a graphic editor is state management (State Management). We need to store the position of each element, manage the active slide, and implement the undo/redo function.
Thanks to the new runes in Svelte 5 ($state), creating such a global storage has become incredibly elegant. I created a state.svelte.ts file, where I described the editor object:
function createEditorState() {
let state = $state({
mode: 'carousel',
canvasFormat: '1:1',
currentSlides: [{ id: Date.now().toString(), elements: [], backgroundOverlay: 0 }],
activeSlideIndex: 0,
selectedId: null,
history: [],
historyIndex: -1,
get activeSlide() {
return state.currentSlides[state.activeSlideIndex];
},
saveState() {
// Logic for saving steps for Undo/Redo
if (state.historyIndex < state.history.length - 1) {
state.history = state.history.slice(0, state.historyIndex + 1);
}
state.history.push(JSON.stringify(state.currentSlides));
state.historyIndex++;
},
undo() {
if (state.historyIndex > 0) {
state.historyIndex--;
state.currentSlides = JSON.parse(state.history[state.historyIndex]);
}
}
});
return state;
}
export const editor = createEditorState();
Every time an element's coordinates change (Drag & Drop), editor.saveState() is called, which adds a new snapshot of the data to the history array. Now the user can safely press Ctrl+Z, and the system will instantly revert the changes.
📦 Storage and Integration with Stocks
So that users don't lose their masterpieces after closing the tab, I connected a backend based on Supabase (PostgreSQL + Auth + Storage).
Authorization takes a few seconds. After that, all your projects are automatically saved to the cloud database. To upload your own images, I use Supabase Storage, generating unique file names so they don't overwrite each other.
I also integrated the free photo stock Pixabay. The user can directly in the editor enter a search query in English (e.g., dark space, aesthetic coffee), get a grid of results through the Pixabay API, and with one click set the image as the slide background or add it as a separate element.
We also recommend reading: Full design control on WordPress.com: Global Styles and custom CSS
🏁 Conclusion
Creating your own technical product is always a challenge, but it's an incredible experience. SMM Turbo grew from a simple idea for personal needs into a full-fledged graphic editor for creating Instagram carousels, capable of closing 90% of a marketer's or developer's daily tasks.
A lightning-fast interface on Svelte 5, powerful artificial intelligence "under the hood", seamless background removal, and complete freedom of action (without annoying watermarks or limits) make it a great alternative to paid monopolists.
🔥 Want to try this magic for yourself? My editor is completely free and already available for testing. Go to the platform and create your first conversion carousels faster than AI!
And if you want to support the project, you can always treat me to a coffee through the link in the editor itself. 😉
🚀 Try SMM Turbo right now
No subscriptions, payments, or hidden fees. Experience the speed of Svelte 5 and the intelligence of Gemma 4.






Top comments (0)