<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by Empat  on Medium]]></title>
        <description><![CDATA[Stories by Empat  on Medium]]></description>
        <link>https://medium.com/@empat_tech?source=rss-1a9b55ae7822------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/1*kGV_ZIHKBX14PD2fVT-I1A.png</url>
            <title>Stories by Empat  on Medium</title>
            <link>https://medium.com/@empat_tech?source=rss-1a9b55ae7822------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Wed, 15 Apr 2026 17:05:33 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@empat_tech/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com" rel="hub"/>
        <item>
            <title><![CDATA[How to Choose the Right Software Development Partner]]></title>
            <link>https://medium.com/@empat_tech/how-to-choose-the-right-software-development-partner-3b4730ba5f0c?source=rss-1a9b55ae7822------2</link>
            <guid isPermaLink="false">https://medium.com/p/3b4730ba5f0c</guid>
            <dc:creator><![CDATA[Empat ]]></dc:creator>
            <pubDate>Fri, 24 Oct 2025 16:45:41 GMT</pubDate>
            <atom:updated>2025-10-24T16:45:41.192Z</atom:updated>
            <content:encoded><![CDATA[<p>If you need a software development partner, it seems like there’s no problem. You can find thousands of software development companies on Google. They all promise the same — expertise, flexibility, and impressive results. However, when it comes to building your product, the difference between expectations and reality may be huge.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*X9Fy-8ITCoFuHzaI4MWFxg.png" /></figure><p>The problem is that good code alone cannot save a project. A successful development partnership requires shared understanding, clear communication, and mutual accountability.</p><p>In this article, we’ll provide a step-by-step guide on how to find a software development partner that meets all your requirements, supports your values, and can help build a business that lasts.</p><h3>1. Define What You Need</h3><p>Before you start browsing portfolios or jumping on introductory calls, take some time to define your project goal. Are you testing an idea with a quick prototype? Creating an <a href="https://www.empat.tech/startup-development/mvp-development">MVP</a> to attract investors? Or scaling a full-fledged product that needs ongoing support?</p><p>Each of these stages requires a different type of team. Some vendors specialize in fast, experimental builds. Others are better at enterprise-level stability or long-term maintenance. Mixing them up is one of the most common and expensive mistakes companies make.</p><p>When you understand your exact goals, timeline, and success criteria, you’ll recognize the right partner faster. They’ll speak the same language, ask the right questions, and shape their process around your priorities.</p><h3>2. Check Their Process, Not Just Their Portfolio</h3><p>A good-looking website or impressive case studies can definitely catch your attention. And they are important to have. However, keep in mind that they don’t show how the team really works day to day.</p><p>Before signing anything, ask developers about their work process. How do they plan and manage projects? What happens when priorities change? How do they test quality before release? And how will you stay updated on progress?</p><p>A reliable partner is open about how things get done. They’ll walk you through their workflow, show you the tools they use, and be clear about who’s responsible for what. That level of transparency tells you a lot more than any list of past clients ever will.</p><p><em>For example, at Empat, we make sure our clients clearly understand the workflow — from the very start of our cooperation and throughout the entire project.</em></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*i5PQTIeenIWQogCXwti0aA.png" /></figure><h3>3. Evaluate Communication</h3><p>Technical skills are very important, but they’re not what make or break a project. According to <a href="https://www.statista.com/statistics/1490077/it-professionals-soft-skills-worldwide/">Statista</a>, problem-solving, effective communication, and relationship-building are the top three soft skills among IT professionals.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*cKKZz-SmO0NiNpeTsd044Q.png" /></figure><p>In practice, try to notice how the team talks to you from the very first message. Do they reply quickly? Do they explain things in plain language? Do they ask thoughtful questions about your goals instead of jumping straight into tech talk?</p><p>These little signs can tell you a lot. A team that listens, challenges your ideas respectfully, and keeps you in the loop is more than just a vendor; they can become your real partner.</p><p>Clear, honest communication saves time, prevents mistakes, and keeps everyone focused on the same goal. Without it, even the best code won’t help.</p><h3>4. Understand Their Tech Choices</h3><p>Don’t pick a team because they use the latest-sounding framework. It’s better to select them because their choices fit your needs. A good partner will explain the trade-offs and how their stack helps your product, not just name-drop tools.</p><p>Ask simple, practical questions:</p><ul><li>Will this be easy to update or extend later?</li><li>Can it handle more users or data without a full rewrite?</li><li>Who owns the code, and how do you hand it over if needed?</li><li>How long will they support the product after launch?</li><li>Are there third-party services that could lock us in or add costs?</li></ul><p>The right team talks about long-term maintenance and future features, not only about what they’ll deliver this sprint.</p><h3>5. Look for partnership, not just service</h3><p>A good development team doesn’t just do what you ask — they help you make smarter decisions along the way.</p><p>You’ll know you’ve found a real partner when:</p><ul><li>They question unclear requirements and suggest better options.</li><li>Someone takes clear responsibility for progress and deadlines.</li><li>They’re open about both results and challenges — and help solve issues, not hide them.</li><li>They focus on how the product performs and supports your goals, not just on closing tasks.</li></ul><p>When communication is honest and collaboration feels natural, you’re not just outsourcing work — you’re building together.</p><h3>6. Red flags to avoid</h3><p>Small warning signs early usually mean bigger headaches later. Watch for:</p><ul><li><strong>Estimates that feel too good to be true.</strong> If the price is extremely low, quality or delivery will likely suffer.</li><li><strong>Vague answers.</strong> “We’ll handle it” without details or a plan.</li><li><strong>No single owner.</strong> If no one is clearly responsible for the project, tasks slip through cracks.</li><li><strong>Refusal to share references or sample code.</strong> Trust is built on proof.</li><li><strong>Evasive on testing or maintenance.</strong> If they won’t explain QA or post-launch support, you’ll pay later.</li><li><strong>Constant scope surprises.</strong> If requirements keep changing and they blame you, that’s a process problem, not yours.</li></ul><p>If something feels off in the first conversations — slow replies, dodgy explanations, or a rush to sign — slow down. Fix it now, or you’ll fix it later at a higher cost.</p><h3>Conclusion</h3><p>The right software development partner needs not only to deliver code, but they also have to bring stability, clarity, and long-term impact to your product. At Empat, that’s exactly what we focus on.</p><ul><li><strong>85%</strong> of our developers have strong technical or math backgrounds, which helps us dive deep into complex problems and build truly innovative solutions.</li><li>Nearly <strong>40%</strong> of our team has been with us for over two years — proof that we value consistency as much as growth.</li><li>And the most important: our clients are satisfied with our work, which is proven with the <strong>100% positive feedback on Clutch</strong>.</li></ul><p>So if you’re looking for a team that understands business goals as well as technology, <a href="https://www.empat.tech/">Empat</a> might be the place to start.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=3b4730ba5f0c" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[PoCs in a Weekend: Welcome to the AI-Powered Startup Era]]></title>
            <link>https://medium.com/@empat_tech/pocs-in-a-weekend-welcome-to-the-ai-powered-startup-era-2c0373c8aaa8?source=rss-1a9b55ae7822------2</link>
            <guid isPermaLink="false">https://medium.com/p/2c0373c8aaa8</guid>
            <dc:creator><![CDATA[Empat ]]></dc:creator>
            <pubDate>Fri, 13 Jun 2025 16:36:11 GMT</pubDate>
            <atom:updated>2025-06-13T16:36:11.046Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*gt4t7HpqgEIgp7WmJZLWEA.png" /></figure><p>At <a href="https://www.empat.tech/?utm_source=Medium&amp;utm_medium=PoCs+in+a+Weekend%3A+Welcome+to+the+AI-Powered+Startup+Era"><strong>Empat</strong></a>, we work closely with founders building in this new AI-powered reality. What we’re witnessing is more than just a tech shift — it’s a mindset shift. We are entering a new era of launching tech startups, and it’s scarily exciting. It’s Eldorado, and it’s our job to differentiate golden nuggets from shiny wrappers.</p><h3>AI Tools Are the New Co-Founders</h3><p>AI tools like Lovable, Claude, Cursor and many others enabled founders to ship their POCs and MVPs with unprecedented speeds while at the same time lowering the bar for technical knowledge required to do so. Operational burden on founders is close to none: you don’t need to spend days/weeks with devs, brainstorming ideas, documenting those, drafting your vision just to realize that it’s not what you meant. Over the weekend, a persistent founder with almost no technical background would be able to build a proof-of-concept (PoC) that 1 year ago would require 2–3 months of work for the small dev team.</p><h3>The Investment Landscape Is Playing Catch-Up</h3><p>But where does it all lead us to?</p><p>The vast majority of startups depend on capital for their growth, predominantly VCs, but also angels and private equity. That’s a mature industry, with its own processes, tools, methods and selection criteria that’s now being challenged from every corner. Founders drop PoCs on VCs desks that look great, have first users and validated ideas but behind these products there often is zero understanding of underlying risks for future scaling.</p><p>Product awareness is close to zero: most founders that rely exclusively on AI for building their product won’t be able to take full ownership of system intelligence, aka they won’t be able to tell you exactly why things work and how they work together. Things just “work”.</p><p>VCs, on the other hand, have no technical knowledge or capacity to evaluate these shiny nuggets that look like gold but could just be a wrapper. Before this age of gen-AI on average, over 30% of the seed-round funding went into re-writting the code. Considering an average seed round size of $2m we are talking about $700k to “redo” things. Imagine what will happen now if before we lived in an era where there was at least some intellectual ownership of a product?</p><p>And this is where we are entering a real interesting shift in mature economies.</p><p>We will definitely see a tectonic shift in how capital is deployed and startups are evaluated but in the meantime, at <a href="http://Published by Dmytro Naumenko, Head os Sales at Empat">Empat</a> we developed a package to help VCs quickly evaluate technical readiness of the product before deploying their money into scaling. With fast report turnaround we hope to help both startups requiring additional audit as well as VCs that want to hedge their risks.</p><p>We help founders not just move fast, but move smart — building products that are not only impressive at first glance, but deeply valuable over time.</p><p>Because in this new gold rush, it’s not just about speed. It’s about knowing where to dig.</p><p><em>Published by </em><a href="https://www.linkedin.com/in/dmytro-naumenko/"><em>Dmytro Naumenko</em></a><em>, Head os Sales at Empat</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=2c0373c8aaa8" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Design Estimation: Guessing Smart, Not Wild (Free estimation starter pack)]]></title>
            <link>https://medium.com/@empat_tech/design-estimation-guessing-smart-not-wild-free-estimation-starter-pack-1e08ffae6672?source=rss-1a9b55ae7822------2</link>
            <guid isPermaLink="false">https://medium.com/p/1e08ffae6672</guid>
            <dc:creator><![CDATA[Empat ]]></dc:creator>
            <pubDate>Mon, 02 Jun 2025 16:39:17 GMT</pubDate>
            <atom:updated>2025-06-03T10:12:50.938Z</atom:updated>
            <content:encoded><![CDATA[<p><em>You’re being asked to price something that doesn’t exist yet. And honestly? That’s the weirdest, most interesting part of design work.</em></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*-373q1rzr1eFyWcQmOLRLQ.png" /></figure><p>At <a href="https://www.empat.tech/?utm_source=medium&amp;utm_medium=Design+Estimation%3A+Guessing+Smart%2C+Not%C2%A0Wild"><strong>Empat</strong></a>, we see everything from sharply defined MVPs to beautifully vague requests like “make this feel friendlier, but still serious.” Estimating these can be tricky, but that’s also where the fun begins. Because even if the input is fuzzy, the outcome needs to be clear: how long will it take, and what will we get?</p><p>That’s where estimation steps in. Not to predict the future, but to reduce surprises. Done right, a good estimate brings clarity, sets expectations, and gives everyone a fair shot at planning better.</p><p>Some tasks feel straightforward:</p><blockquote><em>“Design a landing page.” → We’ve done dozens. Feels like 16–24h.</em></blockquote><p>Others feel like diving into the unknown:</p><blockquote><em>“Redefine the product’s tone across the whole UI.” → Hmm… okay, let’s unpack that.</em></blockquote><p>The trick is not to guess. It’s to structure the guess well enough that it turns into a conversation — and eventually, a plan.</p><h3>Three ways to size the fog</h3><p>Over the years, I’ve found three tactics that help bring structure and sanity.</p><h3>t-shirt sizing (XS–XL)</h3><p>This one’s great when you’re still in a fuzzy planning stage. You compare the new task to something familiar, then assign a size based on effort, not hours.</p><p>It works well when your team shares a mental library of past features. A small marketing banner might be an XS. A moderately complex checkout flow? Maybe a M. A custom analytics dashboard with user roles? Definitely an L or XL.</p><p>Behind the scenes, you map sizes to hour bands (e.g., M = 24–40h), so you’re not guessing every time. The key is to revisit and calibrate those ranges regularly.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*u9P-y6LXRLNtsNEKVFZe7w.png" /></figure><h3>Optimistic vs. realistic ranges</h3><p>Once you know 60–70% of the scope, ranges help paint a more honest picture. You give two estimates:</p><ul><li>If all goes smoothly: <strong>optimistic</strong></li><li>If there are bumps, feedback, or blockers: <strong>realistic</strong></li></ul><p>For example, designing five mobile screens might take 16 hours at best, 24 realistically. Communicate the full range, and consider committing closer to the realistic number (with a buffer if needed).</p><p>Clients love the lower number, but they respect the thinking behind the higher one.</p><h3>Buffer time</h3><p>No matter how smart your guess is, you’ll need margin for the unknown: feedback rounds, handoff hiccups, sick days, someone’s sudden love for neumorphism. Add 15–25% to your estimate. And don’t hide it — make the buffer a visible line item.</p><p>Buffer isn’t padding. It’s a safety net for everyone’s sanity.</p><h3>Combining the three</h3><p>Here’s a typical path we follow at Empat:</p><ol><li>Use t-shirt sizes to quickly map early ideas.</li><li>As scope becomes clearer, break down tasks into ranges.</li><li>Apply a thoughtful buffer, based on complexity and risk.</li></ol><p>You don’t need to pick just one approach. The power comes from knowing <em>when</em> to use each one.</p><h3>What AI is actually good at (and where you still need a human)</h3><p>I’ve been using AI as a helpful assistant in our work at <strong>Empat</strong> long before it became trendy. It’s not just for writing emails — it’s also great for making design estimates more reliable and transparent. Here’s how I personally use it:</p><ul><li><strong>Analyze past work:</strong> Based on anonymized trends from past Figma histories or project notes, I use AI to explore average effort per screen type. No sensitive client data is shared — just patterns and context to help shape better estimates.</li><li><strong>Run what-if scenarios:</strong> “What if we add another feedback cycle or iteration loop?” LLMs adjust the timeline instantly.</li><li><strong>Catch blind spots:</strong> Paste your plan and ask AI to check for forgotten states or flows (empty states, accessibility, localization).</li></ul><p>Just remember: AI is like a turbocharged intern. Brilliant at spotting patterns. Terrible at context.</p><h3>Your free estimation starter pack</h3><p>Before you panic, Google “UX/UI estimation spreadsheet,” here’s a quick reference table our design team has built from dozens of real projects at <a href="https://www.empat.tech/?utm_source=medium&amp;utm_medium=Design+Estimation%3A+Guessing+Smart%2C+Not%C2%A0Wild">Empat</a>. Use it as a starting point — not a rulebook.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*--3xZ8cNQ2pUJacOyNBwGQ.png" /></figure><p>Adjust these numbers based on your needs. Add risk indicators. Compare them against your real-world results. Consider this a starting point, not a limitation.</p><h3>If you want better estimates, build better habits</h3><p>Getting good at estimation doesn’t come from one great template. It comes from repetition, reflection, and a bit of documentation.</p><ul><li>Track your actuals vs. estimates (yes, even in a spreadsheet).</li><li>Keep your sizing examples up to date.</li><li>Talk about risks early and often.</li></ul><p>At <a href="https://www.empat.tech/?utm_source=medium&amp;utm_medium=Design+Estimation%3A+Guessing+Smart%2C+Not%C2%A0Wild">Empat</a>, we take estimation seriously — not just because it protects time and budget, but because it helps everyone stay on the same page. We’re lucky to have a sharp New Business team and a super-capable Pre-Sales manager who make our lives a whole lot easier. They break down client needs, ask the right questions early, and keep communication flowing fast and clearly. That kind of support makes it possible for specialists like me to focus on making accurate, thoughtful estimates.</p><p>And in the end, clients tell us they feel informed, confident, and listened to. That’s what we’re really aiming for — not just numbers, but trust.</p><p>Thanks for reading. If any of this helped you stress less or explain your hours better, mission accomplished.</p><p><em>Published by </em><a href="https://www.linkedin.com/in/andriitsabanov/"><em>Andrii Tsabanov</em></a><em>, Head of Design at Empat</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=1e08ffae6672" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[If AI were your tractor, but you’re not a farmer — How far can you really get building your MVP?]]></title>
            <link>https://medium.com/@empat_tech/if-ai-were-your-tractor-but-youre-not-a-farmer-how-far-can-you-really-get-building-your-mvp-d08a7f048c9e?source=rss-1a9b55ae7822------2</link>
            <guid isPermaLink="false">https://medium.com/p/d08a7f048c9e</guid>
            <category><![CDATA[entrepreneurship]]></category>
            <category><![CDATA[startup-lessons]]></category>
            <category><![CDATA[artificial-intelligence]]></category>
            <category><![CDATA[ai-tools]]></category>
            <category><![CDATA[mvp]]></category>
            <dc:creator><![CDATA[Empat ]]></dc:creator>
            <pubDate>Wed, 14 May 2025 13:44:07 GMT</pubDate>
            <atom:updated>2025-05-14T13:57:54.654Z</atom:updated>
            <content:encoded><![CDATA[<h3>If AI were your tractor, but you’re not a farmer — How far can you really get building your MVP?</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*-lf7vEbTd7htrSEYl7baXQ.png" /></figure><p>We are surrounded by AI today. And when I say “today,” I mean May 2025, since in just a couple of months, this information will most likely be outdated. That’s exactly why we decided to test how far AI tools can take you in building actual products — to separate hype from reality. At <a href="https://www.empat.tech/?utm_source=medium&amp;utm_medium=article&amp;utm_campaign=How+far+can+you+really+get+building+your+MVP">Empat</a>, we’ve been increasingly encountering cases where clients start building a mobile app using AI tools and then come to us for help to finish it. But that’s a whole other story; let’s take it step by step. Every article tells us about the dawn of software engineers, about how tools like Replit, Vercel, Lovable, Cursor, and others are taking over. But are they really?</p><h3>Why AI tools don’t magically turn anyone into an app builder</h3><p>The promise is there; the progress is visible, but we are still waiting to connect the dots and remove the noise. When tractors came to replace horses and bulls in the fields, school teachers did not suddenly become efficient and successful farmers. Those who knew nothing about farming didn’t become farmers overnight. The same way as business founders today are not able to take advantage of these AI tools. It’s one thing to “start the tractor and plow the field”, it’s a totally different thing to yield anything from that field.</p><h3>Testing AI in the field: two roles, same result</h3><p>We had a chance to test a number of tools as well as go over the studies and just reflections published by numerous others and here are the largest bottlenecks we see for mass adoption of AI code writing tools as of today. For the sake of clarity of the experiment we used two different approaches: an experienced software engineer using Cursor to build an LMS system and me, an experienced non-technical founder (who also spent over 6 years in business development positions in firms building custom software) using the same application to build a basic mobile app.</p><p>The journey was very different, but the results were the same: you cannot rely completely on AI.</p><h3>AI can get you far, but not far enough if you can’t debug</h3><p>An experienced engineer was able to achieve an “almost” fully functional web application due to the extensive knowledge of the underlying principles of software development, architecture, and product deployment. An experienced founder, a person who’s driven by “business problems” with basic knowledge of how products are built, was able to build an “almost” fully functional app. The key difference was in the fact that the engineer knew exactly “why” the product didn’t work. A founder just knew it didn’t work, but had no clue why, or where to look for an answer.</p><p>To give you a clearer understanding of how the two experiences compare, I’ve put together a simple table that highlights the key differences in how both the engineer and the founder approached building their products using AI. Take a look at the table below for a side-by-side comparison.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*LOugGWt_D419_7sGFf2ssw.png" /></figure><h3>The real potential of AI for MVPs</h3><p>There is no doubt that we will see the time when we can rely on AI more. It will become a major disruptor for building initial PoCs and MVPs to test and validate technical products for small, non-technical teams. But there is a high chance that we will never be able to rely on it completely.</p><h3>Caution Ahead: Founders Still Need the Fundamentals</h3><p>Being able to identify the “why” is the major reason why founders should be cautious when using AI to write their code. An experienced farmer knows exactly “why” the yield was lower than expected this year. An amateur just scratches his head and has no idea where to start next year to improve.</p><h3>So… Should You Build with AI?</h3><p>In our experience at <a href="https://www.empat.tech/?utm_source=medium&amp;utm_medium=article&amp;utm_campaign=How+far+can+you+really+get+building+your+MVP">Empat</a>, we’ve seen how AI tools like Cursor, Lovable, Bolt, and others can help in the early stages of product development, especially if the founder has a basic technical understanding.</p><p>Overall, AI can be a powerful tool to accelerate the initial stages, but it’s important to remember that without an understanding of the fundamental principles of development and technical details, creating a fully-fledged product will be challenging.</p><p><em>Published by </em><a href="https://www.linkedin.com/in/dmytro-naumenko/"><em>Dmytro Naumenko</em></a><em>, Head os Sales at Empat</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=d08a7f048c9e" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[RAG + Multimodal AI: The Secret Sauce Behind Truly Smart AI Products]]></title>
            <link>https://medium.com/@empat_tech/rag-multimodal-ai-the-secret-sauce-behind-truly-smart-ai-products-c621eec36673?source=rss-1a9b55ae7822------2</link>
            <guid isPermaLink="false">https://medium.com/p/c621eec36673</guid>
            <category><![CDATA[multimodal-ai]]></category>
            <category><![CDATA[vector-search]]></category>
            <category><![CDATA[artificial-intelligence]]></category>
            <category><![CDATA[chatbots]]></category>
            <dc:creator><![CDATA[Empat ]]></dc:creator>
            <pubDate>Fri, 09 May 2025 15:38:26 GMT</pubDate>
            <atom:updated>2025-05-09T15:59:12.040Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*eRrjkZXk60edQMKtI8KPGQ.png" /></figure><p>AI is everywhere these days. Chances are you’ve already tried ChatGPT at least once, even just out of curiosity. We at <a href="https://www.empat.tech/?utm_source=medium&amp;utm_medium=article&amp;utm_campaign=Multimodal+RAG">Empat</a> started experimenting with AI before it became cool. Naturally, we wanted to go beyond the hype. But we quickly ran into common limitations: models like GPT have knowledge cutoffs and no access to your own data.</p><p>Sure, LLMs (Large Language Models) are great for general questions. But in real-world products, AI needs access to <strong>your</strong> data to be useful — to recommend items, answer questions, assist with support, or analyze internal knowledge. You can technically stuff some of your data into prompts, but that doesn’t scale. In our first prototype — a chatbot that recommends products based on user queries — there was no way we could include tens of thousands of product descriptions in a single prompt.</p><p>Back then, we weren’t aware this technique had a name — RAG. Our idea is to use a search to find relevant product descriptions first, then include only those in the prompt in the language model. But a basic keyword search wasn’t enough. Users asked naturally, not with exact keywords.</p><p>That’s when we discovered <strong>vector search</strong> — the ability to search semantically, by meaning, not just by matching words. We used OpenAI’s embeddings + ElasticSearch’s vector capabilities. It was a breakthrough.</p><p>Later, we realized this approach had a name: RAG — using search to augment generation.</p><h3>Beyond Text: What is Multimodal Search?</h3><p>If embeddings are just vector representations of data, why limit yourself to text? Why not embed images and videos too?</p><p>We started looking into models that could generate embeddings for multiple data types and found Google’s <strong>Vertex AI multimodal embedding model</strong>, which supports text, images, and video. That’s when it clicked: imagine searching your content — documents, screenshots, tutorials — not just by keywords, but by context and meaning. Search your company’s media files like you search Google Photos.</p><p>This opens up huge possibilities — and it’s surprisingly easy to build.</p><h3>Practical Use Cases</h3><p>You might wonder: where can this actually be used?</p><p>Let your imagination run wild:</p><ul><li><strong>Developer Portals &amp; Docs</strong>: Search across Swagger files, screenshots, videos, API guides, and diagrams — all in one place.</li><li><strong>Internal Knowledge Tools</strong>: Ask questions about onboarding videos, UI workflows, recorded calls, or technical flows.</li><li><strong>Educational Platforms</strong>: Ask questions about lectures, slides, and reading material — get answers grounded in mixed media.</li><li><strong>Video Platforms</strong>: Power recommendations by matching user questions to relevant video content.</li><li><strong>Support &amp; Help Centers</strong>: Users submit a screenshot or describe an issue, and get relevant videos, docs, and error logs.</li></ul><h3>Architecture Overview</h3><p>At its core, this project uses a simple and efficient backend stack built with <strong>Node.js + Express</strong>, chosen to create a minimal and fast microservice for demonstration purposes.</p><p>It leverages:</p><ul><li><strong>Google Vertex AI</strong> for generating multimodal embeddings (text, image, video)</li><li><strong>Pinecone</strong> for storing and querying vector representations</li></ul><p>The architecture is intentionally kept simple and easy to extend — and the same approach can be implemented using <strong>any backend framework or language</strong> you prefer. Whether you’re working with Django, FastAPI, Laravel, or anything else, the principles behind RAG and multimodal search remain the same.</p><p><strong>So</strong>, pick the tools you like best — and build it your way.</p><h3>Implementation Steps</h3><p>The full implementation of this backend is already available in the public repository: <a href="https://github.com/ym-empat/multimodal-rag-nodejs"><strong>https://github.com/ym-empat/multimodal-rag-nodejs</strong></a></p><p>Below are explanations for each of the main files in the repository. The code shown in the article is taken directly from this repo. <strong>Feel free to use, adapt, and build on top of it</strong> — it’s open and ready for experimentation.</p><ol><li><strong>.env - Environment Configuration</strong></li></ol><pre>PORT=3000</pre><pre>GCP_LOCATION=us-central1<br>GOOGLE_APPLICATION_CREDENTIALS=./service-account.json</pre><pre>PINECONE_API_KEY=example_api_key<br>PINECONE_INDEX_NAME=example_index</pre><p>This file contains all necessary configuration values. It defines the server port, GCP project location, path to your service account credentials, and Pinecone API/index configuration. You must:</p><ul><li>Create a service account in Google Cloud with access to Vertex AI and download the key as service-account.json.</li><li>Create a Pinecone index and copy its name and API key.</li><li>Use a region (GCP_LOCATION) where Vertex AI multimodal embedding is available, like us-central1.</li></ul><p>2. <strong>app.js - API Server (Express)</strong></p><p>This is the main entry point of the application. It sets up the Express server, configures file uploads via multer, and defines two routes: /upload and /search/text. The /upload endpoint handles both text and file inputs (images or videos), determines the content type, and sends it for embedding and storage. The /search/text endpoint receives a text query, vectorizes it, searches for matches in Pinecone, and returns metadata about the most relevant results.</p><pre>const express = require(&#39;express&#39;);<br>const dotenv = require(&#39;dotenv&#39;);<br>const multer = require(&#39;multer&#39;);</pre><pre>const { embedText, embedImage, embedVideo } = require(&#39;./vertex&#39;);<br>const { upsertToIndex, search } = require(&#39;./pinecone&#39;);</pre><pre>dotenv.config();</pre><pre>const app = express();<br>const port = process.env.PORT || 3000;</pre><pre>const upload = multer({ storage: multer.memoryStorage() });</pre><pre>app.use(express.json());</pre><pre>app.get(&#39;/&#39;, (req, res) =&gt; {<br>    res.status(200).json({ message: &#39;OK&#39; });<br>});</pre><pre>app.post(&#39;/upload&#39;, upload.single(&#39;content&#39;), async (req, res) =&gt; {<br>    const file = req.file;<br>    const text = req.body.content;<br>    const filename = file?.originalname || &#39;text_input&#39;;</pre><pre>try {<br>        if(file) {<br>            const mime = file.mimetype;</pre><pre>if (mime.startsWith(&#39;image/&#39;)) {<br>                <br>                console.log(&#39;embedding image&#39;);<br>                const vector = await embedImage(file);<br>                await upsertToIndex({ vectors: [vector], type: &#39;image&#39;, filename });<br>            <br>            } else if (mime.startsWith(&#39;video/&#39;)) {<br>            <br>                console.log(&#39;embedding video&#39;);<br>                const vectors = await embedVideo(file);<br>                await upsertToIndex({ vectors, type: &#39;video&#39;, filename });<br>        <br>            } else {<br>                return res.status(400).json({ error: &#39;Unsupported file type&#39; });<br>            }<br>        } else if (text) {<br>            <br>            console.log(&#39;text&#39;);<br>            const vector = await embedText(text);<br>            await upsertToIndex({ vectors: [vector], type: &#39;text&#39;, filename: &#39;text_input&#39; });<br>       <br>        }</pre><pre>res.status(200).json({ message: &#39;OK&#39; });<br>    } catch (err) {<br>        console.error(err);</pre><pre>res.status(500).json({ message: &#39;Internal Server Error&#39; });<br>    }<br>});</pre><pre>app.post(&#39;/search/text&#39;, async (req, res) =&gt; {<br>    const { query } = req.body;</pre><pre>if (!query || typeof query !== &#39;string&#39;) {<br>        return res.status(400).json({ error: &#39;Invalid or missing &quot;query&quot; field in JSON body&#39; });<br>    }</pre><pre>try {<br>        <br>        const vector = await embedText(query);<br>        const results = await search(vector, 3);<br>        res.status(200).json({ results });<br>        <br>    } catch (err) {<br>        console.error(err);<br>        res.status(500).json({ error: &#39;Search failed&#39; });<br>    }<br>});</pre><pre>app.listen(port, () =&gt; {<br>    console.log(`Server is running on &lt;http://localhost&gt;:${port}`);<br>});</pre><p>3. <strong>vertex.js - Vertex AI Integration</strong></p><p>This module connects to Google’s Vertex AI multimodal embedding model using the official REST API. It defines three functions: embedText, embedImage, and embedVideo. Each function sends the appropriate type of input to the model and returns the embedding(s). For videos, the full file is sent with a configuration that tells the model to return multiple embeddings - one per 15-second segment - each enriched with timing metadata.</p><pre>const { GoogleAuth } = require(&#39;google-auth-library&#39;);</pre><pre>const location = process.env.GCP_LOCATION || &#39;us-central1&#39;;<br>const dimension = 1408;</pre><pre>const auth = new GoogleAuth({<br>    scopes: &#39;&lt;https://www.googleapis.com/auth/cloud-platform&gt;&#39;,<br>});</pre><pre>async function getClient() {<br>    const client = await auth.getClient();<br>    const projectId = await auth.getProjectId();<br>    const url = `https://${location}-aiplatform.googleapis.com/v1/projects/${projectId}/locations/${location}/publishers/google/models/multimodalembedding@001:predict`;</pre><pre>return [client, url];<br>}</pre><pre>async function embedText(text) {<br>    [client, url] = await getClient();</pre><pre>const res = await client.request({<br>        method: &#39;POST&#39;,<br>        url,<br>        body: JSON.stringify({<br>            instances: [<br>                {<br>                    text<br>                }<br>            ],<br>            parameters: {<br>                dimension<br>            }<br>        })<br>    });</pre><pre>return res.data.predictions[0].textEmbedding;<br>}</pre><pre>async function embedImage(image) {<br>    [client, url] = await getClient();</pre><pre>const res = await client.request({<br>        method: &#39;POST&#39;,<br>        url,<br>        body: JSON.stringify({<br>            instances: [<br>                {<br>                    image: {<br>                        bytesBase64Encoded: image.buffer.toString(&#39;base64&#39;)<br>                    }<br>                }<br>            ],<br>            parameters: {<br>                dimension<br>            }<br>        })<br>    });</pre><pre>return res.data.predictions[0].imageEmbedding;<br>}</pre><pre>async function embedVideo(video) {<br>    [client, url] = await getClient();</pre><pre>const res = await client.request({<br>        method: &#39;POST&#39;,<br>        url,<br>        body: JSON.stringify({<br>            instances: [<br>                {<br>                    video: {<br>                        bytesBase64Encoded: video.buffer.toString(&#39;base64&#39;),<br>                        videoSegmentConfig: {<br>                            intervalSec: 15<br>                        }<br>                    }<br>                }<br>            ],<br>            parameters: {<br>                dimension<br>            }<br>        })<br>    });</pre><pre>return res.data.predictions[0].videoEmbeddings;<br>}</pre><pre>module.exports = {<br>    embedText,<br>    embedImage,<br>    embedVideo<br>};</pre><p>4. <strong>pinecone.js - Vector Storage and Search</strong></p><p>This module manages interaction with the Pinecone vector database. It provides functionality to upsert vectors with metadata (upsertToIndex) and to query for nearest matches (search). All vectors are stored in a namespace, and each includes metadata such as filename, type, and**,** optionally**,** segment time (for videos). The search function performs similarity matching and returns only the metadata of the top results.</p><pre>const { Pinecone } = require(&#39;@pinecone-database/pinecone&#39;);<br>const dotenv = require(&#39;dotenv&#39;);</pre><pre>dotenv.config();</pre><pre>const pinecone = new Pinecone({<br>    apiKey: process.env.PINECONE_API_KEY<br>});</pre><pre>const indexName = process.env.PINECONE_INDEX_NAME;</pre><pre>const index = pinecone.index(indexName);</pre><pre>async function upsertToIndex({ vectors, type, filename }) {<br>    const pineconeVectors = vectors.map((v, i) =&gt; {<br>        const id = `${filename.replace(/\\W/g, &#39;_&#39;)}_${Date.now()}_${i}`;<br>        const metadata = {<br>            type,<br>            filename,<br>        };<br>    <br>        if (v.startOffsetSec !== undefined) metadata.startOffsetSec = v.startOffsetSec;<br>        if (v.endOffsetSec !== undefined) metadata.endOffsetSec = v.endOffsetSec;<br>    <br>        return {<br>            id,<br>            values: v.embedding || v,<br>            metadata,<br>        };<br>    });</pre><pre>console.log(pineconeVectors);</pre><pre>await index.namespace(&#39;ns1&#39;).upsert(pineconeVectors);<br>}</pre><pre>async function search(vector, topK) {<br>    const response = await index.namespace(&#39;ns1&#39;).query({<br>        topK,<br>        vector,<br>        includeMetadata: true,<br>    });</pre><pre>return response.matches.map(match =&gt; match.metadata);<br>}</pre><pre>module.exports = {<br>    upsertToIndex,<br>    search<br>};</pre><h3>Output &amp; Limitations</h3><p>This backend is intentionally minimal and API-only. Its main purpose is to demonstrate how to build a working multimodal RAG system using modern tools like Vertex AI and Pinecone. When uploading content, the API returns a simple confirmation message indicating success. When performing a search, the API responds with metadata describing the top matching results — such as the filename, content type, and video segment timestamps (if applicable). No embeddings or file contents are returned, and no front-end interface is provided.</p><p>The current implementation lacks authentication, deduplication logic, and advanced filtering or ranking strategies. Each upload is stored as a new item, and the system does not track ownership or user sessions. The semantic search results rely entirely on embedding similarity and may require tuning (e.g., adjusting topK or score thresholds) in production use cases.</p><p>This minimal setup is ideal for experimentation, rapid prototyping, or as a foundation for more advanced systems that build upon it.</p><h3>What’s Coming Next</h3><p>In <strong>Part 2</strong>, we’ll build on top of this RAG backend and add:</p><ul><li>A <strong>chatbot interface</strong> using Gemini</li><li>Session memory: so the assistant can “remember” previous questions</li><li>Full conversation support over your multimodal data</li><li>Image / Video input to chat</li></ul><p>Stay tuned — and if you’re a dev, feel free to fork the repo and try it out.</p><p>At <a href="https://www.empat.tech/?utm_source=medium&amp;utm_medium=article&amp;utm_campaign=Multimodal+RAG">Empat</a>, we’ve already built multiple real-world projects using RAG-based architectures — including document processing systems for the construction industry, post-mortem analysis tools for completed projects, and LLM-powered bots that assist teams in making sense of large internal knowledge bases. We’ve tested these patterns across domains, and know how to make them work in practice.</p><p>If you’re exploring how to apply RAG in your own product or workflow — feel free to reach out.</p><p><em>Published by </em><a href="https://medium.com/@ya.melnychenko"><em>Yaroslav Melnychenko</em></a><em>, Backend Lead at Empat</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=c621eec36673" width="1" height="1" alt="">]]></content:encoded>
        </item>
    </channel>
</rss>