<?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>Forem: Skapi</title>
    <description>The latest articles on Forem by Skapi (@skapi_api).</description>
    <link>https://forem.com/skapi_api</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3161077%2Ff42727c1-df28-406e-85bd-b25b4a006818.png</url>
      <title>Forem: Skapi</title>
      <link>https://forem.com/skapi_api</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/skapi_api"/>
    <language>en</language>
    <item>
      <title>The Fastest Way to Deploy a Site in 2026</title>
      <dc:creator>Skapi</dc:creator>
      <pubDate>Thu, 11 Dec 2025 08:01:39 +0000</pubDate>
      <link>https://forem.com/skapi_api/the-fastest-way-to-deploy-a-site-in-2026-a10</link>
      <guid>https://forem.com/skapi_api/the-fastest-way-to-deploy-a-site-in-2026-a10</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;“Most developers don’t need a backend. They need a fast way to launch.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;By the end of 2025, the question many developers ask is no longer how to design a website or structure a backend. The question has become much simpler and far more urgent: &lt;strong&gt;What is the fastest way to deploy a site?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Time to launch has become a key competitive factor for indie developers, small teams, and even established engineers who want to move faster without getting caught in configuration loops and infrastructure overhead.&lt;/p&gt;

&lt;p&gt;This article explores that question through the lens of Alex Lee, an early-career developer who has already grown tired of unnecessary complexity, juggling tools, and backend setup. His experience reveals a shift happening in the industry, and why platforms like &lt;a href="//www.skapi.com"&gt;Skapi&lt;/a&gt; are quickly becoming the fastest and most reliable way to deploy a site with zero configuration and no backend work.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Development Pain Point Alex Can’t Ignore:
&lt;/h2&gt;

&lt;p&gt;Alex Lee, a developer with two years of experience and a full-time job, decided to work on side projects he genuinely enjoyed. He was excited to get started, but quickly ran into problems he never expected.&lt;/p&gt;

&lt;p&gt;His idea was clear, the frontend code was ready, and the user flow was straightforward. He wasn’t building a large-scale SaaS platform or a complex distributed application. He just wanted to deploy a clean, static site – a ticket pre-sale platform for his favorite music band – with a few simple functional components: email handling, a form submission endpoint, and some basic state storage.&lt;/p&gt;

&lt;p&gt;Sounds simple, right? Looks even simpler:&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.amazonaws.com%2Fuploads%2Farticles%2Fih73wk2wrd9e57qkpqu8.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.amazonaws.com%2Fuploads%2Farticles%2Fih73wk2wrd9e57qkpqu8.png" alt="music group pre-sale platform website" width="800" height="370"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Yet deploying that site turned into a cycle of dashboards, configs, environment variables, SSL settings, file structures, and DNS delays. What should have taken minutes routinely took hours. For an early-career developer, the complexity felt disproportionate to the goal.&lt;/p&gt;

&lt;p&gt;This frustration is increasingly common, and it reveals the core of a major trend: &lt;strong&gt;developers want the fastest possible way to deploy a site without touching backend infrastructure at all&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Search for the Fastest Way to Deploy a Site
&lt;/h2&gt;

&lt;p&gt;In exploring options, Alex tried several of the popular hosting and deployment tools that have defined the industry over the past few years. Each one promised simplicity. Each one advertised speed. Yet most of them came with underlying complexity that slowed down the process:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;build configurations&lt;/li&gt;
&lt;li&gt;routing files&lt;/li&gt;
&lt;li&gt;backend functions that required separation&lt;/li&gt;
&lt;li&gt;authentication that needed setup&lt;/li&gt;
&lt;li&gt;email APIs requiring external providers&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Too much for a developer whose project did not require this level of machinery.&lt;/p&gt;

&lt;p&gt;Alex realized the actual question was not &lt;em&gt;What hosting tool should I use?&lt;/em&gt; but rather:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why does deploying a small, functional site still require thinking about backend infrastructure at all?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;And this is where Alex found &lt;strong&gt;Skapi&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  A New Approach: Zero-Backend Deployment
&lt;/h2&gt;

&lt;p&gt;Skapi stood out immediately because it answered the one question that mattered:&lt;br&gt;
&lt;strong&gt;How fast can a developer deploy a site without touching backend configuration?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Alex discovered that Skapi’s architecture does something different from traditional hosting platforms:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It hosts static sites instantly through a simple file-drop interface. index.html becomes your root entry point. Files are served instantly through global CDN.&lt;/li&gt;
&lt;li&gt;It removes the backend setup entirely.&lt;/li&gt;
&lt;li&gt;It provides automatic email handling and newsletter flows.&lt;/li&gt;
&lt;li&gt;It supports authentication without configuration.&lt;/li&gt;
&lt;li&gt;It includes built-in storage and database-like record handling.&lt;/li&gt;
&lt;/ul&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.amazonaws.com%2Fuploads%2Farticles%2F77dcx6m1dqjfx5smhjlq.jpg" 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.amazonaws.com%2Fuploads%2Farticles%2F77dcx6m1dqjfx5smhjlq.jpg" alt="easy no-setup backend" width="800" height="392"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In other words, Skapi collapses multiple layers of development work into a single environment that requires no manual setup. For a developer trying to deploy a side-project, it represented exactly what the industry has been moving toward: &lt;strong&gt;the fastest way to deploy a site with AI-assisted backend logic and zero configuration.&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Skapi let me deploy my project without touching any infrastructure at all.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Deploying the Side-Project: A Faster Workflow
&lt;/h2&gt;

&lt;p&gt;Alex’s deployment process shifted dramatically once he tried Skapi. &lt;/p&gt;

&lt;p&gt;The steps became straightforward:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Prepare the frontend folder.&lt;/li&gt;
&lt;li&gt;Drag files into Skapi’s File Hosting.&lt;/li&gt;
&lt;li&gt;The site is live instantly.&lt;/li&gt;
&lt;/ol&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.amazonaws.com%2Fuploads%2Farticles%2Fwk8g325injgm7xqwi0nm.jpg" 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.amazonaws.com%2Fuploads%2Farticles%2Fwk8g325injgm7xqwi0nm.jpg" alt="instant web hosting in 2 minutes" width="800" height="395"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There were no DNS tasks, no build steps, and no backend endpoints to configure. Alex was able to add a form submission flow with Skapi’s built-in API handling. He integrated email automation without any third-party providers. He added basic data storage without provisioning a database.&lt;/p&gt;

&lt;p&gt;This workflow matched exactly what many developers search for. When someone types &lt;strong&gt;the fastest way to deploy a site&lt;/strong&gt; or &lt;strong&gt;how to deploy a website quickly&lt;/strong&gt;, they’re not looking for server diagrams or configuration tutorials. They want a process that lets them build and deploy without obstacles.&lt;/p&gt;

&lt;p&gt;Skapi delivered that experience by treating backend complexity as optional rather than required.&lt;/p&gt;

&lt;p&gt;The industry is changing. Backends will always matter for large-scale systems, but most modern projects: side-project apps, landing pages, prototypes, microtools, and personal products do not require full backend environments. &lt;/p&gt;

&lt;p&gt;This gap between actual requirements and traditional infrastructure has opened the door for tools like Skapi to reshape deployment workflows entirely.&lt;/p&gt;

&lt;h2&gt;
  
  
  Happy Alex’s Conclusion
&lt;/h2&gt;

&lt;p&gt;Alex’s search for the fastest way to deploy a site ended not with a new tool to configure, but with a different approach to development itself. Skapi provided a clear path where the friction of backend setup disappeared, leaving space for building, refining, and launching a real side-project in a fraction of the time.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The fastest way to deploy a site in 2026 is to use tools that eliminate backend work entirely.&lt;/strong&gt; For anyone searching for the quickest and most effective deployment workflow, the answer is becoming clearer each year: choose the tools that let you build without barriers. &lt;/p&gt;

&lt;p&gt;In that landscape, Skapi is quickly emerging as one of the strongest options.&lt;/p&gt;

&lt;p&gt;Follow us on socials: &lt;a href="https://x.com/skapi_api" rel="noopener noreferrer"&gt;X&lt;/a&gt;, &lt;a href="https://www.youtube.com/@skapi_official" rel="noopener noreferrer"&gt;YouTube&lt;/a&gt;, &lt;a href="https://www.instagram.com/skapi_api" rel="noopener noreferrer"&gt;Instagram&lt;/a&gt;, &lt;a href="https://www.linkedin.com/company/skapi-backend-api/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;. More tutorials, code drops, and dev hacks are coming soon.&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>automation</category>
      <category>api</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Vibe coding ultimate beginner tutorial 2025</title>
      <dc:creator>Skapi</dc:creator>
      <pubDate>Fri, 28 Nov 2025 09:03:07 +0000</pubDate>
      <link>https://forem.com/skapi_api/vibe-coding-ultimate-beginner-tutorial-2025-461o</link>
      <guid>https://forem.com/skapi_api/vibe-coding-ultimate-beginner-tutorial-2025-461o</guid>
      <description>&lt;p&gt;We’ve binged a ton of YouTube videos about vibe coding so you don’t have to. Here’s the basic workflow most vibe coders use, but if you don’t care about all the theory and just want an easy way to get a beautiful, working design, keep reading. We’ll give you an ultimate guide using only two tools to make your project good, fast, and free.&lt;/p&gt;

&lt;p&gt;This is what tech bloggers usually do to build a “vibe-coded” website:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Hunt for references on Pinterest.&lt;/li&gt;
&lt;li&gt;Ask an AI to generate unique images based on those references.&lt;/li&gt;
&lt;li&gt;If they want extra flair, they add animations and interactivity in AI tools.&lt;/li&gt;
&lt;li&gt;In a website builder, they describe the idea and build it step by step. Right now, Lovable and Bolt are the big names. If you already know some coding and don’t mind paying a subscription, a lot of people go with Claude Code.&lt;/li&gt;
&lt;li&gt;Build backend logic and webhooks without traditional programming. n8n is the trendy choice for that right now.&lt;/li&gt;
&lt;li&gt;Connect the website to a custom domain and publish it using a hosting service.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Sounds like a lot, right? Not very “vibe.” And imagine how much you end up paying for all those tools and subscriptions.&lt;/p&gt;

&lt;p&gt;We’re going to save your time and your wallet, and show you how to do it in a short, fast, ultimate way using only AI and one smart tool (Skapi - as you’ve probably guessed already).&lt;/p&gt;

&lt;p&gt;Our project concept is an online pre-sale platform for a concert, where people can sign up and join a waiting list to be the first to know when tickets go on sale, and get the earliest chance to buy them.&lt;/p&gt;

&lt;p&gt;Even though we’re an IT company and know what we’re doing, for the sake of the experiment this project was built by our marketing manager, not a developer. If a marketing girl can do it, you can absolutely do it too.&lt;br&gt;
So if you’re ready - let’s get started.&lt;/p&gt;

&lt;h2&gt;
  
  
  Looking for references
&lt;/h2&gt;

&lt;p&gt;First things first - we want a pretty, stylish website. But let’s be honest, we’re not designers, right? So we head over to Pinterest and search for “band website”.&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.amazonaws.com%2Fuploads%2Farticles%2Fqut5k8jwa1f2ko77trwt.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.amazonaws.com%2Fuploads%2Farticles%2Fqut5k8jwa1f2ko77trwt.png" alt="band website pinterest reference" width="800" height="360"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I literally grabbed the first one, because we don’t need any special functionality from the design. The AI will take care of that for us. And honestly, I chose this one because it’s Joy Division. Enough said.&lt;/p&gt;

&lt;h2&gt;
  
  
  Backend in a minute
&lt;/h2&gt;

&lt;p&gt;Next, let’s go to &lt;a href="//www.skapi.com"&gt;Skapi&lt;/a&gt;. Create an account and start a free trial service. If you need help, you can find the full walkthrough &lt;a href="https://dev.to/skapi_api/no-more-backend-setup-launch-your-app-with-skapi-in-minutes-b85"&gt;here&lt;/a&gt;, but honestly, it’s straightforward even without instructions.&lt;/p&gt;

&lt;p&gt;After clicking “Create,” you’ll land on your service page. That’s where you’ll see your backend credentials. &lt;/p&gt;

&lt;p&gt;Download SKAPI.md file and copy the prompt. It already contains your credentials.&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.amazonaws.com%2Fuploads%2Farticles%2F904z6ughf3tt26rxokj4.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.amazonaws.com%2Fuploads%2Farticles%2F904z6ughf3tt26rxokj4.png" alt="skapi credentials easy backend" width="800" height="329"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Give the prompt to AI
&lt;/h2&gt;

&lt;p&gt;Now let’s jump into Lovable. That’s our tool of choice for this project, because it lets us visually tweak sections of the site and then download the generated code.&lt;/p&gt;

&lt;p&gt;Here’s the prompt I’m using, and when sending it, don’t forget to attach SKAPI.md file and the reference picture:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Use the file "SKAPI.md" as a system prompt. &lt;br&gt;
My Skapi service ID is: [YOUR CREDENTIALS HERE].&lt;br&gt;
Build me a website for Joy Division. A PNG reference is attached.&lt;br&gt;
Adapt it into an online pre-sale platform for a concert tour, where users can subscribe to a newsletter and join a waiting list to be the first to know when tickets go on sale and get early access to buy them. Send users a confirmation email using Skapi’s newsletter feature.&lt;/p&gt;
&lt;/blockquote&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.amazonaws.com%2Fuploads%2Farticles%2Fsl5n10eq2uimr9l8fek8.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.amazonaws.com%2Fuploads%2Farticles%2Fsl5n10eq2uimr9l8fek8.png" alt="AI website generator" width="800" height="353"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here’s the functionality Lovable generated from my prompt:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Newsletter subscription via Skapi — visitors can enter their email and instantly join the waitlist&lt;/li&gt;
&lt;li&gt;Email confirmation flow — users receive a confirmation email and must verify their address&lt;/li&gt;
&lt;li&gt;Success handling — automatic redirect after successful verification&lt;/li&gt;
&lt;li&gt;Tour information — clean layout with stats and pre-sale details&lt;/li&gt;
&lt;li&gt;Fully responsive design&lt;/li&gt;
&lt;li&gt;Skapi initialized in index.html using my service ID &lt;/li&gt;
&lt;li&gt;Uses subscribeNewsletter() with group: 'public' for public newsletter subscriptions&lt;/li&gt;
&lt;li&gt;Automatic confirmation email sent through Skapi&lt;/li&gt;
&lt;li&gt;Redirect URL for after the user verifies their email&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Testing ready website
&lt;/h2&gt;

&lt;p&gt;Now let’s test it. We can do everything directly from Lovable’s preview.&lt;br&gt;
And yes, it works. I entered my email and immediately received the verification link.&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.amazonaws.com%2Fuploads%2Farticles%2Fhspeofiopelgw56fjikv.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.amazonaws.com%2Fuploads%2Farticles%2Fhspeofiopelgw56fjikv.png" alt="testing ready website" width="800" height="402"&gt;&lt;/a&gt;&lt;br&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.amazonaws.com%2Fuploads%2Farticles%2Fhtgn2oacigxrnx87nh1u.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.amazonaws.com%2Fuploads%2Farticles%2Fhtgn2oacigxrnx87nh1u.png" alt="email confirmation" width="800" height="345"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Customize your email&lt;/strong&gt;&lt;br&gt;
You can customize all automated emails directly in your Skapi My Services Dashboard.&lt;/p&gt;

&lt;p&gt;Here’s a quick DIY walkthrough:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Open the Automated Emails section.&lt;/li&gt;
&lt;li&gt;Create a new entry, give it a name, and register it.&lt;/li&gt;
&lt;li&gt;Copy the generated email address (the one highlighted in red).&lt;/li&gt;
&lt;li&gt;Open your regular email provider - Gmail, Outlook, whatever you use.&lt;/li&gt;
&lt;li&gt;Write the email you want your users to receive and send it to that copied address.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That email becomes your template for the signup confirmation message. From now on, users will receive your version instead of the default one.&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.amazonaws.com%2Fuploads%2Farticles%2Frbzr1qem5wb9a98wy0et.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.amazonaws.com%2Fuploads%2Farticles%2Frbzr1qem5wb9a98wy0et.png" alt="automated emails" width="800" height="357"&gt;&lt;/a&gt;&lt;br&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.amazonaws.com%2Fuploads%2Farticles%2F4qoc2e46sp83g9qrkwqu.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.amazonaws.com%2Fuploads%2Farticles%2F4qoc2e46sp83g9qrkwqu.png" alt="automated email send" width="800" height="351"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Deploy your website
&lt;/h2&gt;

&lt;p&gt;Now, back to our Joy Division website.&lt;/p&gt;

&lt;p&gt;The final step is deployment — and here’s the good news:&lt;br&gt;
You can handle everything right inside Skapi, without hunting for third-party hosting or paying extra.&lt;/p&gt;

&lt;p&gt;Here’s how:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Go to Skapi and open File Hosting from the left dashboard.&lt;/li&gt;
&lt;li&gt;Create a new domain by choosing a name and clicking Register.&lt;/li&gt;
&lt;/ul&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.amazonaws.com%2Fuploads%2Farticles%2Fapjr48z2joxw6y90xeh4.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.amazonaws.com%2Fuploads%2Farticles%2Fapjr48z2joxw6y90xeh4.png" alt="skapi file hosting feature" width="800" height="349"&gt;&lt;/a&gt;&lt;br&gt;
Next, head over to Lovable:&lt;/p&gt;

&lt;p&gt;Click the GitHub button and connect your GitHub account to create a repository.&lt;br&gt;
If it’s your first time, just follow Lovable’s guided steps.&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.amazonaws.com%2Fuploads%2Farticles%2F97h7xnk7qmo5gtaoptvz.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.amazonaws.com%2Fuploads%2Farticles%2F97h7xnk7qmo5gtaoptvz.png" alt="link to github" width="800" height="291"&gt;&lt;/a&gt;&lt;br&gt;
Once the repo is generated, Lovable will give you a link, open it on GitHub and download the code as a ZIP file.&lt;/p&gt;

&lt;p&gt;Inside the ZIP, locate your dist folder (you’ll need to build it through your Terminal) - that’s the production-ready build.&lt;/p&gt;

&lt;p&gt;Go back to Skapi → File Hosting and upload all the files from the dist folder.&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.amazonaws.com%2Fuploads%2Farticles%2Ff1gw43ri9fgbm57v39qt.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.amazonaws.com%2Fuploads%2Farticles%2Ff1gw43ri9fgbm57v39qt.png" alt="skapi file hosting" width="800" height="345"&gt;&lt;/a&gt;&lt;br&gt;
And that’s it - your Joy Division pre-sale site is live! You can check our version here: &lt;a href="https://joydivision.skapi.com/" rel="noopener noreferrer"&gt;https://joydivision.skapi.com/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It’s honestly incredibly fast and simple. And if you want to go further, you absolutely can. You can ask the AI to build a full user dashboard showing upcoming tour details, their position in the waiting list, login/signup flows, and even an admin panel with restricted access so you can manage users and send notifications. Or you can push the design in a more complex or artistic direction. &lt;/p&gt;

&lt;p&gt;With this setup, pretty much anything is possible.&lt;/p&gt;

&lt;p&gt;You can also skip Lovable entirely and ask ChatGPT to generate the HTML code for you. But keep in mind that if you need visual changes later, raw code isn’t nearly as flexible if you don’t know how to code. Most AI models will regenerate the entire page, which often breaks everything you already built. That’s why a visual AI website builder is usually the more practical choice.&lt;/p&gt;

&lt;p&gt;I hope you enjoyed this walkthrough. If you have any questions or need help while following the guide, let us know in the comments or send us an email at &lt;a href="mailto:support@broadwayinc.com"&gt;support@broadwayinc.com&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;And remember: Skapi gives you a single, unified backend you can reuse across every AI-built project.&lt;/p&gt;

&lt;p&gt;Whether you build in Lovable, Bolt, Claude, Cursor, or raw HTML, your backend remains stable, portable, and easy to understand.&lt;/p&gt;

&lt;p&gt;Follow us on socials: &lt;a href="https://x.com/skapi_api" rel="noopener noreferrer"&gt;X&lt;/a&gt;, &lt;a href="https://www.youtube.com/@skapi_official" rel="noopener noreferrer"&gt;YouTube&lt;/a&gt;, &lt;a href="https://www.instagram.com/skapi_api" rel="noopener noreferrer"&gt;Instagram&lt;/a&gt;, &lt;a href="https://www.linkedin.com/company/skapi-backend-api/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;. More tutorials, code drops, and dev hacks are coming soon.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>productivity</category>
      <category>beginners</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>How Skapi Helped Me Finally Get a Raise with Just 15 Minutes of Code</title>
      <dc:creator>Skapi</dc:creator>
      <pubDate>Fri, 14 Nov 2025 10:10:39 +0000</pubDate>
      <link>https://forem.com/skapi_api/how-skapi-helped-me-finally-get-a-raise-with-just-15-minutes-of-code-58ab</link>
      <guid>https://forem.com/skapi_api/how-skapi-helped-me-finally-get-a-raise-with-just-15-minutes-of-code-58ab</guid>
      <description>&lt;p&gt;A few weeks ago, my boss asked me to go through a huge stack of resumes to help shortlist candidates. It sounded simple until I realized just how many there were. I spent hours reading through pages, trying to pick out key skills and relevant experience. It was exhausting.&lt;/p&gt;

&lt;p&gt;So instead of getting buried in paperwork, I did what developers do best, I automated the process.&lt;/p&gt;

&lt;p&gt;The goal was to build a &lt;strong&gt;resume summarizer app&lt;/strong&gt; that could generate short, clear summaries using AI. Since I'm a &lt;a href="https://www.skapi.com/" rel="noopener noreferrer"&gt;Skapi&lt;/a&gt; user, a serverless backend that makes things ridiculously simple, I figured it was the fastest way to pull this off.&lt;/p&gt;

&lt;p&gt;In less than 15 minutes, I had a fully functional web app running on &lt;strong&gt;plain HTML and JavaScript&lt;/strong&gt;, powered by Skapi for authentication and data handling, no server setup, no database stress.&lt;/p&gt;

&lt;p&gt;The result? A clean AI-powered tool that saved hours of manual work and made me look like a productivity hero. My boss was impressed, and let’s just say it paid off in the best way possible.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;[Frontend] ←→ [Skapi] ←→ [Google Auth + Gemini API]&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.amazonaws.com%2Fuploads%2Farticles%2Fr03g69slsp2bz3apik2m.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.amazonaws.com%2Fuploads%2Farticles%2Fr03g69slsp2bz3apik2m.png" alt="CV resume summarizer app UI" width="800" height="427"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here’s what we’ll cover in this guide to achieve the screenshot above:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Google Login&lt;/strong&gt; – implemented with Skapi’s OpenID (no backend code required).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Gemini AI Integration&lt;/strong&gt; – to generate smart, professional resume summaries.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Skapi Records&lt;/strong&gt; – to securely save and fetch summaries for each logged-in user.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And the best part? It all runs entirely on the frontend &lt;strong&gt;no backend servers required&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;By the end of this tutorial, you’ll see exactly how our “15-minute experiment” ended up impressing the boss enough to get me a raise.&lt;/p&gt;

&lt;h2&gt;
  
  
  Core Implementation: The Magic Pieces
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Step 1: Skapi Setup&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;1.Head to Skapi.com and create an account.&lt;br&gt;
2.Once logged in, create a new service in your Dashboard.&lt;br&gt;
3.You’ll find there your unique Service ID&lt;br&gt;
4.Add it to your frontend script:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;skapi&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Skapi&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;SERVICE_ID&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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.amazonaws.com%2Fuploads%2Farticles%2Fug8hltzwj0puevtq6akb.jpg" 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.amazonaws.com%2Fuploads%2Farticles%2Fug8hltzwj0puevtq6akb.jpg" alt="for frontend developers" width="800" height="381"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;These IDs connect your frontend directly to Skapi’s secure backend with no custom server setup required.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 2: Configure Secrets in Skapi&lt;/strong&gt;&lt;br&gt;
In your Skapi Dashboard → Client Secrets, add two secrets:&lt;/p&gt;

&lt;p&gt;1.Google OAuth Client Secret&lt;/p&gt;

&lt;p&gt;Name: &lt;code&gt;ggltoken&lt;/code&gt;&lt;br&gt;
Value: Your Google OAuth Client Secret from Google Cloud Console&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.amazonaws.com%2Fuploads%2Farticles%2Fciomwv8takysceggzpm5.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.amazonaws.com%2Fuploads%2Farticles%2Fciomwv8takysceggzpm5.png" alt="google 0auth client secret" width="800" height="390"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;2.Gemini API Key&lt;/p&gt;

&lt;p&gt;Name: &lt;code&gt;GEMINI_API_KEY&lt;/code&gt;&lt;br&gt;
Value: Your Gemini API key from &lt;a href="https://aistudio.google.com/app/apikey" rel="noopener noreferrer"&gt;Google AI Studio&lt;/a&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.amazonaws.com%2Fuploads%2Farticles%2Fgpwx59uv6eh84izxzqid.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.amazonaws.com%2Fuploads%2Farticles%2Fgpwx59uv6eh84izxzqid.png" alt="gemini api key" width="800" height="423"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Skapi securely stores these secrets and injects them automatically when using &lt;code&gt;clientSecretRequest()&lt;/code&gt; — meaning your frontend never exposes sensitive data.&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.amazonaws.com%2Fuploads%2Farticles%2F7bdlpxyofyiy0253vnru.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.amazonaws.com%2Fuploads%2Farticles%2F7bdlpxyofyiy0253vnru.png" alt="client secret key" width="800" height="429"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 3: Set Up Google OAuth&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Go to the Google Cloud Console:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Navigate to APIs &amp;amp; Services → Credentials&lt;/li&gt;
&lt;li&gt;Create a new OAuth 2.0 Client ID&lt;/li&gt;
&lt;li&gt;Set Application Type to Web Application&lt;/li&gt;
&lt;li&gt;Add your redirect URL (e.g., &lt;code&gt;http://localhost:5500/&lt;/code&gt;) under Authorized redirect URIs&lt;/li&gt;
&lt;li&gt;Copy your Client ID and Client Secret&lt;/li&gt;
&lt;li&gt;Add your &lt;code&gt;GOOGLE_CLIENT_ID&lt;/code&gt; to the script:
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;GOOGLE_CLIENT_ID&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;YOUR_GOOGLE_CLIENT_ID&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;CLIENT_SECRET_NAME&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ggltoken&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;OPENID_LOGGER_ID&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;google&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;REDIRECT_URL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;http://localhost:5500/&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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.amazonaws.com%2Fuploads%2Farticles%2Fkhikadb4y7v8z971et3o.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.amazonaws.com%2Fuploads%2Farticles%2Fkhikadb4y7v8z971et3o.png" alt="google cloud" width="800" height="395"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 4: Google Login Flow&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Integrating Google OAuth&lt;/p&gt;

&lt;p&gt;A. Redirect User to Google&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;googleLogin&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;random&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;36&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://accounts.google.com/o/oauth2/v2/auth&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;url&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;?client_id=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nf"&gt;encodeURIComponent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;GOOGLE_CLIENT_ID&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;url&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;&amp;amp;redirect_uri=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nf"&gt;encodeURIComponent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;REDIRECT_URL&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;url&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;&amp;amp;response_type=code&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;url&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;&amp;amp;scope=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nf"&gt;encodeURIComponent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;openid email profile&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;url&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;&amp;amp;prompt=consent&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;url&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;&amp;amp;access_type=offline&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;url&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;&amp;amp;state=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nf"&gt;encodeURIComponent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;href&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;B. Handle the Redirect and Log In Securely&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;handleRedirect&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;params&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;URLSearchParams&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;search&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;code&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;code&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;code&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="c1"&gt;// Exchange auth code for tokens securely via Skapi&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tokenResp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;skapi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;clientSecretRequest&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;clientSecretName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;CLIENT_SECRET_NAME&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://oauth2.googleapis.com/token&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Content-Type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;application/x-www-form-urlencoded&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;code&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;client_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;GOOGLE_CLIENT_ID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;client_secret&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;$CLIENT_SECRET&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Skapi injects this securely&lt;/span&gt;
      &lt;span class="na"&gt;redirect_uri&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;REDIRECT_URL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;grant_type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;authorization_code&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;accessToken&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;tokenResp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;access_token&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="c1"&gt;// Use OpenID login with the returned token&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;skapi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;openIdLogin&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;OPENID_LOGGER_ID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;token&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;accessToken&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;profile&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;skapi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getProfile&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Logged in user:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;profile&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
  Refer to this for more insights &lt;a href="https://docs.skapi.com/authentication/openid-login.html#google-oauth-example" rel="noopener noreferrer"&gt;Google-OAuth-Example&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Skapi’s &lt;code&gt;clientSecretRequest()&lt;/code&gt; handles the token exchange securely — the client secret is never exposed in your code.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 5: Summarize Resumes with Gemini&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Once the user logs in, they can paste their resume text and summarize it using Gemini:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;summarizeBtn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;click&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;resumeText&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;alert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Please paste your résumé text first.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;skapi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;clientSecretRequest&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;clientSecretName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;GEMINI_API_KEY&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash-lite:generateContent&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Content-Type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;application/json&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;params&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;$CLIENT_SECRET&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;contents&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt;
        &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;user&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;parts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt; &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Summarize this resume in 5 bullet points:&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt; &lt;span class="p"&gt;}],&lt;/span&gt;
      &lt;span class="p"&gt;}],&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;summary&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;candidates&lt;/span&gt;&lt;span class="p"&gt;?.[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]?.&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;parts&lt;/span&gt;&lt;span class="p"&gt;?.[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]?.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;summary&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And retrieving past summaries:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;records&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;skapi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getRecords&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;table&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;resume_summaries&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;access_group&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;private&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;limit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;access_group: "private"&lt;/code&gt; setting ensures that only the logged-in user can access their own data.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 7: Putting It All Together&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Here’s the simplified flow:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;User clicks Login with Google&lt;/li&gt;
&lt;li&gt;Google redirects back → Skapi securely exchanges tokens&lt;/li&gt;
&lt;li&gt;User pastes resume text&lt;/li&gt;
&lt;li&gt;Gemini API summarizes it&lt;/li&gt;
&lt;li&gt;Summary is saved securely to the user’s private database&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  What You’ve Built
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Secure Google Authentication using OAuth and Skapi&lt;/li&gt;
&lt;li&gt;AI-Powered Summarization with Gemini API&lt;/li&gt;
&lt;li&gt;Private Data Storage per user in Skapi’s database&lt;/li&gt;
&lt;li&gt;100% serverless and frontend-only implementation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This combination lets you build production-ready apps without deploying your own backend.&lt;/p&gt;

&lt;p&gt;You can find the whole project in our &lt;a href="https://github.com/broadwayinc/demo_resume_summary" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;Follow us on socials: &lt;a href="https://x.com/skapi_api" rel="noopener noreferrer"&gt;X&lt;/a&gt;, &lt;a href="https://www.youtube.com/@skapi_official" rel="noopener noreferrer"&gt;YouTube&lt;/a&gt;, &lt;a href="https://www.instagram.com/skapi_api" rel="noopener noreferrer"&gt;Instagram&lt;/a&gt;, &lt;a href="https://www.linkedin.com/company/skapi-backend-api/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;. More tutorials, code drops, and dev hacks are coming soon.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>tutorial</category>
      <category>beginners</category>
      <category>webdev</category>
    </item>
    <item>
      <title>When Telegram Cocoon Goes Live: The Future of the AI Internet</title>
      <dc:creator>Skapi</dc:creator>
      <pubDate>Fri, 31 Oct 2025 09:39:35 +0000</pubDate>
      <link>https://forem.com/skapi_api/when-telegram-cocoon-goes-live-the-future-of-the-ai-internet-2e67</link>
      <guid>https://forem.com/skapi_api/when-telegram-cocoon-goes-live-the-future-of-the-ai-internet-2e67</guid>
      <description>&lt;p&gt;At &lt;strong&gt;Blockchain Life 2025&lt;/strong&gt; in Dubai, &lt;strong&gt;Telegram CEO Pavel Durov&lt;/strong&gt; unveiled &lt;strong&gt;Cocoon (Confidential Compute Open Network)&lt;/strong&gt; — a decentralized AI compute network built on &lt;strong&gt;The Open Network (TON)&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Cocoon will allow GPU owners around the world to contribute computing power for AI inference and get rewarded in &lt;strong&gt;Toncoin (TON)&lt;/strong&gt;. Telegram itself will become Cocoon’s first large-scale user, integrating this technology into its &lt;strong&gt;Mini Apps and AI tools&lt;/strong&gt; for its &lt;strong&gt;billion-plus users&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cocoon in a Nutshell
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Compute&lt;/strong&gt;: Decentralized AI tasks running securely across a distributed network of GPUs.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Incentives&lt;/strong&gt;: GPU miners are rewarded in TON for powering these computations.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Privacy&lt;/strong&gt;: Data remains encrypted end-to-end — even from the machines processing it.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Goal&lt;/strong&gt;: To challenge centralized AI infrastructure monopolies like AWS and Azure.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Cocoon represents a privacy-first approach to AI infrastructure, aligning with Telegram and TON’s shared vision of &lt;strong&gt;user-owned digital freedom&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Core Problem of Cocoon
&lt;/h2&gt;

&lt;p&gt;While Cocoon decentralizes &lt;strong&gt;AI compute&lt;/strong&gt;, building real applications requires much more than inference.&lt;/p&gt;

&lt;p&gt;Developers still need to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Handle user authentication&lt;/li&gt;
&lt;li&gt;Manage data persistence&lt;/li&gt;
&lt;li&gt;Store and serve user-generated content&lt;/li&gt;
&lt;li&gt;Host frontend interfaces&lt;/li&gt;
&lt;li&gt;Securely connect all these components&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Cocoon offers a distributed engine for AI workloads — but it doesn’t solve the &lt;strong&gt;data and logic layer&lt;/strong&gt; that connects these models to real users and applications.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Missing Layer of Decentralized Infrastructure
&lt;/h2&gt;

&lt;p&gt;Telegram will be Cocoon’s first client, embedding it into its vast ecosystem of Mini Apps.&lt;/p&gt;

&lt;p&gt;But as the network expands, developers and businesses will be the next wave of adopters.&lt;/p&gt;

&lt;p&gt;To participate in that ecosystem — to build AI-powered apps that leverage Cocoon’s decentralized compute — you’ll need a backend that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Manages your users securely&lt;/li&gt;
&lt;li&gt;Stores their data without central control&lt;/li&gt;
&lt;li&gt;Authenticates AI access and app permissions&lt;/li&gt;
&lt;li&gt;Scales automatically as your app grows&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That’s exactly what &lt;a href="https://www.skapi.com/" rel="noopener noreferrer"&gt;Skapi&lt;/a&gt; provides. &lt;strong&gt;Skapi&lt;/strong&gt; provides a &lt;strong&gt;serverless backend for web apps&lt;/strong&gt;, purpose-built for the privacy-centric future Cocoon is enabling.&lt;/p&gt;

&lt;p&gt;Developers using Skapi get:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Authentication &amp;amp; identity&lt;/strong&gt;: Secure user accounts without traditional servers&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Databases&lt;/strong&gt;: Structured data storage with private, encrypted access&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;File hosting&lt;/strong&gt;: For AI models, assets, and user uploads&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Zero DevOps&lt;/strong&gt;: No configuration, no server maintenance, no central authority&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Skapi already supports a &lt;strong&gt;decentralized approach to data&lt;/strong&gt;: users own their data, and developers never need to expose it.&lt;/p&gt;

&lt;h2&gt;
  
  
  A New Web Stack for Decentralized AI Apps
&lt;/h2&gt;

&lt;p&gt;It’s important to note that &lt;strong&gt;Cocoon doesn’t store user data&lt;/strong&gt; — it only processes it securely.&lt;/p&gt;

&lt;p&gt;That means your application still needs a trusted layer to &lt;strong&gt;store, recall, and protect user information&lt;/strong&gt; before and after AI computation happens.&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.amazonaws.com%2Fuploads%2Farticles%2Fyz5gcht159di1ye3q9k3.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.amazonaws.com%2Fuploads%2Farticles%2Fyz5gcht159di1ye3q9k3.png" alt="New Web Stack for Decentralized AI Apps" width="800" height="452"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This architecture keeps every layer decentralized, private, and user-owned.&lt;/p&gt;

&lt;p&gt;This is what we can start calling &lt;strong&gt;Private AI-as-a-Service (PAaaS)&lt;/strong&gt; — a model where both compute and storage are user-owned and secured.&lt;/p&gt;

&lt;h2&gt;
  
  
  Developers Build AI Web3 Applications
&lt;/h2&gt;

&lt;p&gt;With Cocoon and Skapi together, developers can finally build &lt;strong&gt;truly independent applications&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;AI-powered bots&lt;/strong&gt; that process private data without central servers&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Mini Apps&lt;/strong&gt; that run entirely on decentralized compute and storage&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Full-stack businesses&lt;/strong&gt; where both compute and data belong to the users&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Think of Skapi as your bridge into Cocoon’s ecosystem — the part that allows you to manage your users, data, and authentication &lt;strong&gt;without betraying the principles of decentralization&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Because if your AI runs on a decentralized GPU network, your users still log in through a centralized database, you’re &lt;strong&gt;only halfway free&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;That’s where Skapi bridges the gap, enabling developers to build full-stack decentralized apps that align perfectly with Cocoon’s vision:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;An internet where AI is private, infrastructure is open, and ownership belongs to the user.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Follow us on socials: &lt;a href="https://x.com/skapi_api" rel="noopener noreferrer"&gt;X&lt;/a&gt;, &lt;a href="https://www.youtube.com/@skapi_official" rel="noopener noreferrer"&gt;YouTube&lt;/a&gt;, &lt;a href="https://www.instagram.com/skapi_api" rel="noopener noreferrer"&gt;Instagram&lt;/a&gt;, &lt;a href="https://www.linkedin.com/company/skapi-backend-api/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;. More tutorials, code drops, and dev hacks are coming soon.&lt;/p&gt;

&lt;p&gt;Let us know in the comments what's your vision of future Internet!&lt;/p&gt;

</description>
      <category>ai</category>
      <category>blockchain</category>
      <category>web3</category>
      <category>cloud</category>
    </item>
    <item>
      <title>The Meme Game That Changed How We Build Secure APIs — Skapi’s Story</title>
      <dc:creator>Skapi</dc:creator>
      <pubDate>Fri, 17 Oct 2025 09:54:16 +0000</pubDate>
      <link>https://forem.com/skapi_api/the-cat-that-changed-api-rules-164p</link>
      <guid>https://forem.com/skapi_api/the-cat-that-changed-api-rules-164p</guid>
      <description>&lt;h2&gt;
  
  
  How a meme app improved Skapi’s backend logic (and made our cat very happy)
&lt;/h2&gt;

&lt;p&gt;It started as a joke.&lt;/p&gt;

&lt;p&gt;We wanted to make a &lt;a href="https://shouldifeedthecat.skapi.com/" rel="noopener noreferrer"&gt;tiny web app&lt;/a&gt; called “&lt;strong&gt;Should I Feed the Cat&lt;/strong&gt;?” - a pixel-art voting game where anyone could click &lt;strong&gt;YES&lt;/strong&gt; or &lt;strong&gt;NO&lt;/strong&gt;, watch the scores rise in real time, and decide the fate of a digital cat.&lt;/p&gt;

&lt;p&gt;But that dumb little cat ended up exposing something much bigger: a flaw in how we handled &lt;strong&gt;public data submission&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The meme cat web app in question:&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.amazonaws.com%2Fuploads%2Farticles%2F9g4bk6biw494cafgv05v.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.amazonaws.com%2Fuploads%2Farticles%2F9g4bk6biw494cafgv05v.png" alt="meme cat" width="800" height="612"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the process, this little web application changed how &lt;strong&gt;Skapi&lt;/strong&gt;, our secure backend platform, works.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem: Login Walls vs. Public Data
&lt;/h2&gt;

&lt;p&gt;Originally, Skapi was designed with strict security in mind.&lt;/p&gt;

&lt;p&gt;Everything a user sent to the database had to come from a logged-in session. That made sense for apps dealing with sensitive or user-specific data, things like notes, messages, or private uploads.&lt;/p&gt;

&lt;p&gt;But for our cat game, this was absurd.&lt;/p&gt;

&lt;p&gt;Did we really need to force people to &lt;strong&gt;sign up and log in&lt;/strong&gt; just to click “YES, feed the cat”?&lt;/p&gt;

&lt;p&gt;The cat didn’t care who you were.&lt;br&gt;
It just wanted food.&lt;/p&gt;

&lt;p&gt;Yet our system said:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“postRecord(): Login is required.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That was the moment we realized something was off. The world needed a way to collect &lt;strong&gt;anonymous, public data&lt;/strong&gt; safely.&lt;/p&gt;
&lt;h2&gt;
  
  
  When Security is a Problem
&lt;/h2&gt;

&lt;p&gt;“Should I Feed the Cat?” was supposed to be a lighthearted test of Skapi’s frontend integration.&lt;/p&gt;

&lt;p&gt;We added:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Pixel-style cats (waiting, happy, dead)&lt;/li&gt;
&lt;li&gt;Eye blinks and tear animations&lt;/li&gt;
&lt;li&gt;Confetti explosions for 10,000 “YES” votes&lt;/li&gt;
&lt;li&gt;Thunderstorms if the “NO” side wins&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each visitor could spam votes as much as they wanted.&lt;br&gt;
It was chaotic, hilarious, and strangely addictive.&lt;/p&gt;

&lt;p&gt;But when we deployed it, reality hit:&lt;br&gt;
No one could vote unless they logged in.&lt;/p&gt;

&lt;p&gt;The backend was doing its job — protecting data integrity — but in this case, &lt;strong&gt;the protection was the problem&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;We wanted people to interact instantly and just have fun without login.&lt;/p&gt;
&lt;h2&gt;
  
  
  The Breakthrough: Public postRecord()
&lt;/h2&gt;

&lt;p&gt;That’s when we realized something powerful.&lt;/p&gt;

&lt;p&gt;We could safely open part of Skapi’s data system to &lt;strong&gt;public anonymous writes&lt;/strong&gt;, without exposing user data or compromising backend security.&lt;/p&gt;

&lt;p&gt;How?&lt;/p&gt;

&lt;p&gt;By allowing the &lt;code&gt;postRecord()&lt;/code&gt; method to accept submissions from unauthenticated users when writing to public tables.&lt;/p&gt;

&lt;p&gt;Here’s how it looked like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;skapi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;postRecord&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;nickname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;choice&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;table&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;cat_votes_open&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;index&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`choice.&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;choice&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It’s easy to just let anonymous users post data to a backend, but doing it safely was the hard part.&lt;/p&gt;

&lt;p&gt;We needed a way to ensure that anonymous users couldn’t access restricted tables or modify anyone else’s data.&lt;/p&gt;

&lt;p&gt;Normally, Skapi enforces permissions using profile information from a user’s JWT token. But since anonymous users don’t have one, Skapi now generates a randomized, temporary security hash derived from each client’s public address.&lt;/p&gt;

&lt;p&gt;Behind the scenes, Skapi also fully separates &lt;strong&gt;public tables&lt;/strong&gt; from &lt;strong&gt;restricted tables&lt;/strong&gt;, ensuring that anonymous submissions can only write new records but never edits or deletes existing ones. Each anonymous client is tracked as its own isolated device identity, allowing open participation without compromising data integrity or security.&lt;/p&gt;

&lt;p&gt;That’s it. No login. No auth token. The cat finally got fed.&lt;/p&gt;

&lt;p&gt;Under the hood, Skapi still handles all security:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Public tables are isolated from private ones.&lt;/li&gt;
&lt;li&gt;No user data is exposed.&lt;/li&gt;
&lt;li&gt;The backend validates every request.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Rate limits and data shape protections still apply.&lt;br&gt;
In short — &lt;strong&gt;anyone can submit data, but no one can break the system.&lt;/strong&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Technical Key of Viral Web Apps
&lt;/h2&gt;

&lt;p&gt;This isn’t just about a cat. It’s about lowering friction in web apps that rely on &lt;em&gt;public engagement&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Think:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Polls &amp;amp; surveys&lt;/li&gt;
&lt;li&gt;Comment walls&lt;/li&gt;
&lt;li&gt;Feedback widgets&lt;/li&gt;
&lt;li&gt;Micro games&lt;/li&gt;
&lt;li&gt;Anonymous reactions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For all these, forcing logins just kills the vibe.&lt;br&gt;
But letting the world interact freely, while keeping the backend secure, is how you make &lt;strong&gt;lightweight, viral apps&lt;/strong&gt; that spread fast.&lt;/p&gt;

&lt;p&gt;With this Skapi update, developers can now collect &lt;strong&gt;public, anonymous data safely.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That’s something few backends do right.&lt;/p&gt;
&lt;h2&gt;
  
  
  Secure vs. Accessible Web Application
&lt;/h2&gt;

&lt;p&gt;Our little meme experiment revealed a gap between “secure” and “accessible.” And fixing it made Skapi better for everyone.&lt;/p&gt;

&lt;p&gt;Now, anyone can use &lt;code&gt;skapi.postRecord()&lt;/code&gt; to collect open data, whether it’s a public poll, an art project, or a crowdsourced idea board.&lt;/p&gt;

&lt;p&gt;We built a cat game. The cat changed our API.&lt;/p&gt;
&lt;h2&gt;
  
  
  Try It Yourself
&lt;/h2&gt;

&lt;p&gt;If you want to play (or feed the cat), you can check it out here: &lt;a href="https://shouldifeedthecat.skapi.com/" rel="noopener noreferrer"&gt;https://shouldifeedthecat.skapi.com/&lt;/a&gt;, or build your own version in minutes.&lt;/p&gt;

&lt;p&gt;Here’s the minimal setup:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;script&lt;/span&gt; &lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://cdn.jsdelivr.net/npm/skapi-js@latest/dist/skapi.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/script&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;script&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;skapi&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Skapi&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;SERVICE_ID&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; 
  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;vote&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;choice&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;skapi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;postRecord&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;choice&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;table&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;public_votes&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;index&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`choice.&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;choice&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/script&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That’s how a real backend logic with zero setup works.&lt;/p&gt;

&lt;p&gt;Follow us on socials: &lt;a href="https://x.com/skapi_api" rel="noopener noreferrer"&gt;X&lt;/a&gt;, &lt;a href="https://www.youtube.com/@skapi_official" rel="noopener noreferrer"&gt;YouTube&lt;/a&gt;, &lt;a href="https://www.instagram.com/skapi_api" rel="noopener noreferrer"&gt;Instagram&lt;/a&gt;, &lt;a href="https://www.linkedin.com/company/skapi-backend-api/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;. More tutorials, code drops, and dev hacks are coming soon.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>api</category>
      <category>security</category>
    </item>
    <item>
      <title>Skapi vs Firebase vs Supabase: Choosing the Best Backend for Performance and Scalability</title>
      <dc:creator>Skapi</dc:creator>
      <pubDate>Thu, 02 Oct 2025 10:33:15 +0000</pubDate>
      <link>https://forem.com/skapi_api/skapi-vs-firebase-vs-supabase-choosing-the-best-backend-for-performance-and-scalability-27e9</link>
      <guid>https://forem.com/skapi_api/skapi-vs-firebase-vs-supabase-choosing-the-best-backend-for-performance-and-scalability-27e9</guid>
      <description>&lt;p&gt;Choosing the right backend service is crucial for the performance, scalability, and user experience of your application. From query response times to concurrent user handling and file upload speeds, your backend directly impacts how smooth, fast, and reliable your app feels.&lt;/p&gt;

&lt;p&gt;Pick the wrong backend, and you risk getting locked into infrastructure that slows down your app, limits scalability, and frustrates users with lag and downtime. Pick the right one, and you’re set up for growth and speed from day one.&lt;/p&gt;

&lt;p&gt;While Firebase and Supabase are popular backend-as-a-service (BaaS) platforms, their added complexity can introduce performance overhead. Skapi takes a different approach: offering speed and scalability out of the box. &lt;/p&gt;

&lt;p&gt;In this article, we’ll compare Firebase, Supabase, and Skapi across three key backend performance metrics:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Query Response Times (basic and complex)&lt;/li&gt;
&lt;li&gt;Concurrent User Handling (scalability under load)&lt;/li&gt;
&lt;li&gt;File Upload Speeds (media-heavy app performance)&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  1. Query Response Times
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Basic Queries:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Basic query response time is the foundation of backend performance. If it lags, your whole app feels broken, from dashboards to search results to profile loads.&lt;/p&gt;

&lt;p&gt;Here’s the query we will be requesting to the backend:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Skapi:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;skapi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getRecords&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;table&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;performance_test&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;access_group&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;public&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;limit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;fetch_limit&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Supabase:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;supabase&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;performance_test&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;select&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;*&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;limit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fetch_limit&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Firebase:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nf"&gt;collection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;performance_test&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="nf"&gt;limit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fetch_limit&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We will do simple data fetching query testing with various ranges of fetch limits.&lt;/p&gt;

&lt;p&gt;In benchmark tests, Skapi consistently outperforms Firebase and Supabase in basic query speed, making apps feel instantly responsive without extra optimization.&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.amazonaws.com%2Fuploads%2Farticles%2Ffrn8xvkq0cvcyvkkaaed.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.amazonaws.com%2Fuploads%2Farticles%2Ffrn8xvkq0cvcyvkkaaed.png" alt="Firebase Supabase Skapi benchmark tests" width="800" height="130"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Complex Queries:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Complex queries such as joins, sorts, or aggregations, push systems harder. Firebase and Supabase tend to slow down as complexity grows, while Skapi maintains low latency even under demanding query loads.&lt;/p&gt;

&lt;p&gt;Each service uses a different underlying database model:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Skapi&lt;/strong&gt;: NoSQL with auto-indexing and client-defined access control&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Firebase&lt;/strong&gt;: NoSQL document store (Firestore) with structured indexes&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Supabase&lt;/strong&gt;: SQL/Postgres with schema-driven indexes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To compare, here are equivalent examples of range queries:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Skapi:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;skapi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getRecords&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;table&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;performance_test&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;access_group&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;public&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;index&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;test_index&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;range&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Supabase:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;supabase&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;performance_test&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;select&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;*&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;gte&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;data-&amp;gt;test_index_value&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;lte&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;data-&amp;gt;test_index_value&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Firebase:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nf"&gt;collection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;performance_test&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="nf"&gt;where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;test_index_value&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;&amp;gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="nf"&gt;where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;test_index_value&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Notes on Indexing and Joins&lt;/strong&gt;&lt;br&gt;
Index condition queries rely on conditional lookups using comparison operators &lt;code&gt;(&amp;gt;, &amp;lt;, &amp;gt;=, &amp;lt;=)&lt;/code&gt; on indexed fields.&lt;/p&gt;

&lt;p&gt;For more complex operations such as joins, sorts, or aggregations, the approach differs by platform:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Skapi&lt;/strong&gt;: Supports indexed conditional lookups directly, but for multi-table relationships or advanced aggregations, data is typically fetched in ranges and then joined or aggregated on the client.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Firebase (Firestore)&lt;/strong&gt;: Works similarly - queries can filter indexed fields efficiently, but there is no native join support. Developers usually fetch multiple datasets and merge them client-side. Composite indexes must be explicitly created for more complex queries.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Supabase (Postgres)&lt;/strong&gt;: Can handle joins, sorts, and aggregations directly in SQL, but these operations are heavier on the backend. While powerful, they often introduce more latency compared to client-side merges, especially under load.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&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.amazonaws.com%2Fuploads%2Farticles%2F4o84pp7dyz3xn2kp68qz.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.amazonaws.com%2Fuploads%2Farticles%2F4o84pp7dyz3xn2kp68qz.png" alt="Indexing and joins query" width="800" height="232"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Result&lt;/strong&gt;: Skapi ensures your app’s navigation, filtering, and data-heavy features remain fast and smooth, no matter the complexity.&lt;/p&gt;


&lt;h2&gt;
  
  
  2. Concurrent User Handling
&lt;/h2&gt;

&lt;p&gt;Scalability isn’t just about spinning up more servers, it’s about maintaining performance under heavy load. Some backends choke as traffic scales.&lt;/p&gt;

&lt;p&gt;In stress tests, Skapi’s backend architecture holds steady, delivering fast, consistent response times even with thousands of concurrent users. This makes it ideal for apps expecting growth, viral traffic spikes, or global audiences.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Examples of concurrent test:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Sends multiple requests simultaneously&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;promises&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
&lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;concurrentCount&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;promises&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;skapi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getRecords&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;table&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;performance_test&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;access_group&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;public&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;promises&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// All execute at once&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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.amazonaws.com%2Fuploads%2Farticles%2F211zv6radv7yp2syjwko.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.amazonaws.com%2Fuploads%2Farticles%2F211zv6radv7yp2syjwko.png" alt="concurrent user handling" width="800" height="549"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;With Skapi, you get true horizontal scalability, meaning your app grows seamlessly without compromising speed or user experience.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Notes on Concurrency&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Skapi&lt;/strong&gt;: Designed with serverless elasticity; concurrency scaling is handled automatically by the platform.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Supabase&lt;/strong&gt;: Concurrency depends on underlying Postgres + connection pooling; under extreme load, queries may queue or slow down.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Firebase&lt;/strong&gt;: Firestore handles a high degree of concurrent reads and writes, but performance can degrade if many clients hit the same document paths, since hot-spotting leads to throttling.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  3. File Upload Speeds
&lt;/h2&gt;

&lt;p&gt;For apps handling images, video, or large files, upload performance is critical. No user wants to stare at a stuck progress bar.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Firebase and Supabase can slow down significantly on large file uploads.&lt;/li&gt;
&lt;li&gt;Skapi maintains consistently fast uploads across small and large files.&lt;/li&gt;
&lt;/ul&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.amazonaws.com%2Fuploads%2Farticles%2Fqsaci9ofbszu5n2ax0fo.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.amazonaws.com%2Fuploads%2Farticles%2Fqsaci9ofbszu5n2ax0fo.png" alt="file upload speed" width="800" height="288"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In fact, the performance gap widens as file sizes increase, making Skapi the clear winner for media-heavy apps, SaaS platforms, and social apps.&lt;/p&gt;




&lt;h2&gt;
  
  
  How the Tests Were Conducted
&lt;/h2&gt;

&lt;p&gt;To ensure a fair and transparent comparison, each test followed structured benchmarks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Basic Query Test&lt;/strong&gt;: Measured how quickly backends respond to simple database queries (profile loads, product lists, or recent posts). Average, min, and max response times were recorded, with success rates checked for 100% delivery.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Complex Query Test&lt;/strong&gt;: Ran 16 variations across 8 categories, including index lookups, range queries, tag searches, sorting, aggregations, and multi-filters. Data sets included realistic fields like price, rating, category, and tags.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Concurrent User Test&lt;/strong&gt;: Simulated loads from 5 to 100,000 simultaneous users, measuring how response times and success rates held up under spikes (such as flash sales, viral content, or product launches).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;File Upload Test&lt;/strong&gt;: Uploaded files from 1KB to 1GB, tracking average speeds and time-to-completion. These mirrored real-world use cases such as profile images, PDFs, audio, and full HD videos.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All tests were repeated multiple times under identical conditions to rule out anomalies. Data sets were auto-cleaned after runs to ensure fair results.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Skapi Wins on Performance
&lt;/h2&gt;

&lt;p&gt;Across all three categories  - query response time, concurrent user handling, and file uploads, Skapi outperforms Firebase and Supabase.&lt;/p&gt;

&lt;p&gt;The key technical advantages that set Skapi apart are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Fully serverless infrastructure&lt;/strong&gt;: elastic scaling without servers to deploy or manage&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;NoSQL with unique indexing&lt;/strong&gt;: optimized for high-speed lookups and range queries&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Direct client-to-backend access&lt;/strong&gt;: no middle-layer bottlenecks slowing things down&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By choosing Skapi, you’re building on a backend that guarantees speed, scalability, and responsiveness from day one.&lt;/p&gt;




&lt;h2&gt;
  
  
  Final Thoughts: Skapi vs Firebase vs Supabase
&lt;/h2&gt;

&lt;p&gt;If your app’s success depends on speed, scalability, and user experience, Skapi is the backend built for you. While Firebase and Supabase are solid options, their overhead can slow you down as your project scales.&lt;/p&gt;

&lt;p&gt;Skapi delivers performance superiority across the board, ensuring your app stays fast, reliable, and scalable, whether you’re building a social media platform, SaaS product, or media-heavy mobile app.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;In short&lt;/strong&gt;: With Skapi, there are no delays, no bottlenecks, and no compromises, just the backend performance your project deserves.&lt;/p&gt;

&lt;p&gt;Follow us on socials: &lt;a href="https://x.com/skapi_api" rel="noopener noreferrer"&gt;X&lt;/a&gt;, &lt;a href="https://www.youtube.com/@skapi_official" rel="noopener noreferrer"&gt;YouTube&lt;/a&gt;, &lt;a href="https://www.instagram.com/skapi_api" rel="noopener noreferrer"&gt;Instagram&lt;/a&gt;, &lt;a href="https://www.linkedin.com/company/skapi-backend-api/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;. More tutorials, code drops, and dev hacks are coming soon.&lt;/p&gt;

</description>
      <category>database</category>
      <category>testing</category>
      <category>backend</category>
      <category>serverless</category>
    </item>
    <item>
      <title>How to Create a Video Streaming Platform with HTML, CSS, JS, and Skapi</title>
      <dc:creator>Skapi</dc:creator>
      <pubDate>Fri, 19 Sep 2025 09:02:16 +0000</pubDate>
      <link>https://forem.com/skapi_api/how-to-create-a-video-streaming-platform-with-html-css-js-and-skapi-2f23</link>
      <guid>https://forem.com/skapi_api/how-to-create-a-video-streaming-platform-with-html-css-js-and-skapi-2f23</guid>
      <description>&lt;p&gt;These days, we all stream everything: movies, shows, random videos we find online. But the big streaming platforms often come with strict rules, changing algorithms, and sometimes even censorship.&lt;/p&gt;

&lt;p&gt;For small creators, that can be exhausting. So many creators are taking a different path: building their own little streaming spaces. Smaller, more personal platforms where they can share what they want, connect directly with their audience, and stay in control over their content.&lt;/p&gt;

&lt;p&gt;Building your own platform can be tough, especially when it comes to setting up the backend and database. In this guide, we’ll explain step-by-step so even beginners can follow along and create a working video-on-demand platform in a single afternoon.&lt;/p&gt;

&lt;h2&gt;
  
  
  Meet Skapi
&lt;/h2&gt;

&lt;p&gt;Skapi is here to help you do it, taking away the stress of developing a web infrastructure and allowing you to focus on giving your viewers the best experience. Thanks to Skapi, a modern backend-as-a-service (BaaS), you can set up user accounts, video uploads, and content delivery using just HTML, CSS, and JavaScript. No servers, no complicated set up, just a few lines of code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting Started
&lt;/h2&gt;

&lt;p&gt;Connecting your project with Skapi is a very easy process. You can follow a step-by-step guide on how to do it in our &lt;a href="https://dev.to/skapi_api/no-more-backend-setup-launch-your-app-with-skapi-in-minutes-b85"&gt;No More Backend Setup: Launch Your App with Skapi in Minutes&lt;/a&gt; article. &lt;/p&gt;

&lt;h2&gt;
  
  
  Adding User Authentication
&lt;/h2&gt;

&lt;p&gt;Every video streaming platform needs user accounts. Skapi makes this simple with built-in signup and login methods.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Signup Example&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;parameters&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;user@email.com&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;password&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Password must be between 6 and 60 characters.&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;User's name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;login&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="c1"&gt;// If set to true, users will be automatically logged in after signup.&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nx"&gt;skapi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;signup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;parameters&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;u&lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;alert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Hello &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;u&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Login Example&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;parameters&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;user@email.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;password&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;skapi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;login&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;parameters&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;href&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;welcome.html&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once logged in, users can upload videos or view restricted content depending on your settings.&lt;/p&gt;

&lt;h2&gt;
  
  
  Uploading Videos
&lt;/h2&gt;

&lt;p&gt;To upload videos and any other file, you can use the method highlighted in &lt;a href="https://dev.to/skapi_api/the-easiest-way-to-add-file-upload-to-your-website-34bn"&gt;The Easiest Way to Add File Upload to Your Website&lt;/a&gt; article. But just as a quick example, here’s how to do it with a &lt;code&gt;form&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;form&lt;/span&gt; &lt;span class="na"&gt;onsubmit=&lt;/span&gt;&lt;span class="s"&gt;"skapi.postRecord(event, {
    table: {
        name: 'videos',
        access_group: 'public'
    })&amp;gt;
  &amp;lt;input name="&lt;/span&gt;&lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="err"&gt;"&lt;/span&gt; &lt;span class="na"&gt;placeholder=&lt;/span&gt;&lt;span class="s"&gt;"Video Title"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"description"&lt;/span&gt; &lt;span class="na"&gt;placeholder=&lt;/span&gt;&lt;span class="s"&gt;"Video Description"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"video"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"file"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"submit"&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"Submit"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/form&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On submitting the form, your video will be uploaded to Skapi via the &lt;code&gt;postRecord()&lt;/code&gt; method, making it instantly available to be watched.&lt;/p&gt;

&lt;h2&gt;
  
  
  Display Videos on Your Platform
&lt;/h2&gt;

&lt;p&gt;Fetch all uploaded videos and display them in a simple gallery with HTML5 &lt;code&gt;video&lt;/code&gt; tags.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"videoGallery"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;loadVideos&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;videos&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;skapi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getRecords&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;table&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;videos&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;gallery&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;videoGallery&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;gallery&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerHTML&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;videos&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;list&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;v&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;`
    &amp;lt;div&amp;gt;
      &amp;lt;h3&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;v&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;/h3&amp;gt;
      &amp;lt;video src="&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;v&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bin&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;" controls width="480"&amp;gt;&amp;lt;/video&amp;gt;
    &amp;lt;/div&amp;gt;
  `&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;loadVideos&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This gives you a dynamic video feed — as soon as someone uploads a video, it appears for viewers.&lt;/p&gt;

&lt;h2&gt;
  
  
  Adding Premium Content
&lt;/h2&gt;

&lt;p&gt;Sometimes you’ll want to control who can see your content. &lt;br&gt;
When posting any type of &lt;code&gt;record&lt;/code&gt; to Skapi, one of the config options is &lt;code&gt;access_group&lt;/code&gt;. This is used to limit the visibility of the record, and is used as such:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;table&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;access_group&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;number&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;private&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;public&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;authorized&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;admin&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  &lt;span class="c1"&gt;// Default: 'public'&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;access_group&lt;/code&gt; config is optional and defaults to public if not specified. The possible settings are: &lt;/p&gt;

&lt;p&gt;&lt;code&gt;number&lt;/code&gt;: Integer from 0 to 99. Compares the record access requirement to the user profile access level. Only users with access levels equal or greater than the record’s requirement may see it. User's access level can be upgraded from the "Users" page in Skapi service dashboard.&lt;br&gt;
&lt;code&gt;private&lt;/code&gt;: Only the uploader is allowed to have access to the record. The uploader can give access to others.&lt;br&gt;
&lt;code&gt;public&lt;/code&gt;: Everyone can see the record. (Equivalent to &lt;code&gt;number&lt;/code&gt;: 0)&lt;br&gt;
&lt;code&gt;authorized&lt;/code&gt;: Only people logged to the project may see the record. (Equivalent to &lt;code&gt;number&lt;/code&gt;: 1)&lt;br&gt;
&lt;code&gt;admin&lt;/code&gt;: Only the admins of your service will be allowed to view this record. (Equivalent to &lt;code&gt;number&lt;/code&gt;: 99)&lt;/p&gt;

&lt;p&gt;Want to charge for videos or keep some content exclusive?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Set &lt;code&gt;access_group&lt;/code&gt;: 2 to 4 for example, when uploading.&lt;/li&gt;
&lt;li&gt;Now you have tiered content, all you need to do is charge to upgrade users accounts to higher tiers.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Subscriptions
&lt;/h2&gt;

&lt;p&gt;Another important aspect of streaming is being able to subscribe to your preferred content creators. Using Skapi’s subscriptions system you won’t have to worry about designing a whole subscription pipeline. It’s all ready to be used.&lt;/p&gt;

&lt;p&gt;When uploading a video, you can choose to make it available only to your subscribers, like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;skapi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;postRecord&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;videoData&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;table&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;videos&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;access_group&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;authorized&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;subscription&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;is_subscription_record&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will make it so that only users subscribed to the uploader will be able to see the video.&lt;br&gt;
And to subscribe is even easier, just use the &lt;code&gt;subscribe()&lt;/code&gt; method, like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;skapi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;user_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;user_id_of_user_A&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And now you can have subscriber only content in your platform, allowing another type of exclusivity to your users.&lt;/p&gt;

&lt;h2&gt;
  
  
  That's it!
&lt;/h2&gt;

&lt;p&gt;As you can see, Skapi empowers you to create a streaming platform with full user authentication, tiered content and subscriptions, all without writing a single backend line of code.&lt;/p&gt;

&lt;p&gt;Simply connect your project to a Skapi service and you can start your own streaming platform today.&lt;/p&gt;

&lt;p&gt;Follow us on socials: &lt;a href="https://x.com/skapi_api" rel="noopener noreferrer"&gt;X&lt;/a&gt;, &lt;a href="https://www.youtube.com/@skapi_official" rel="noopener noreferrer"&gt;YouTube&lt;/a&gt;, &lt;a href="https://www.instagram.com/skapi_api" rel="noopener noreferrer"&gt;Instagram&lt;/a&gt;, &lt;a href="https://www.linkedin.com/company/skapi-backend-api/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;. More tutorials, code drops, and dev hacks are coming soon.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>tutorial</category>
      <category>programming</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Build a Serverless FAQ Bot with Skapi + Vanilla JS (No Backend Needed!)</title>
      <dc:creator>Skapi</dc:creator>
      <pubDate>Fri, 19 Sep 2025 09:02:05 +0000</pubDate>
      <link>https://forem.com/skapi_api/build-a-serverless-faq-bot-with-skapi-vanilla-js-no-backend-needed-20cj</link>
      <guid>https://forem.com/skapi_api/build-a-serverless-faq-bot-with-skapi-vanilla-js-no-backend-needed-20cj</guid>
      <description>&lt;p&gt;I remember the first time I wanted to add a simple FAQ bot to a website. My plan was:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I’ll just throw the FAQs in a database, write a quick API… how hard can it be?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;em&gt;Spoiler&lt;/em&gt;: it turned into a mini backend project with hosting, endpoints, and authentication before I even wrote a single line of UI code.&lt;/p&gt;

&lt;p&gt;So when I joined &lt;strong&gt;Skapi&lt;/strong&gt; — a serverless backend for frontend developers, no coders, and anyone who wants to save their time on backend — the first thing that I did, I decided to see if I could build the entire FAQ bot with just frontend code.&lt;/p&gt;

&lt;p&gt;And you totally can. In this tutorial, I’ll show you exactly how.&lt;/p&gt;

&lt;p&gt;By the end, you’ll have a:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Serverless FAQ bot running entirely in the browser&lt;/li&gt;
&lt;li&gt;Zero backend setup (Skapi handles the data for you)&lt;/li&gt;
&lt;li&gt;Frontend-only guidance using plain HTML + JavaScript&lt;/li&gt;
&lt;/ul&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.amazonaws.com%2Fuploads%2Farticles%2Fhf6waev0db1pxpuyz2m7.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.amazonaws.com%2Fuploads%2Farticles%2Fhf6waev0db1pxpuyz2m7.png" alt="FAQ bot" width="800" height="346"&gt;&lt;/a&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.amazonaws.com%2Fuploads%2Farticles%2Fmy9l1z9q45wh0pkinrcg.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.amazonaws.com%2Fuploads%2Farticles%2Fmy9l1z9q45wh0pkinrcg.png" alt="FAQ bot dataset" width="800" height="320"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Skapi Is Perfect for This
&lt;/h2&gt;

&lt;p&gt;If you’ve ever spun up a backend just to store a few rows of data, you’ll appreciate this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Serverless: No API endpoints or servers to maintain&lt;/li&gt;
&lt;li&gt;Frontend-friendly: Works with plain HTML, React, Vue, anything&lt;/li&gt;
&lt;li&gt;Data + Auth in one place: Store records, handle users, all from the browser&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;For this project, we’ll use it to:&lt;/strong&gt;&lt;br&gt;
1.Store FAQs in a Skapi table&lt;br&gt;
2.Fetch them with &lt;code&gt;getRecords()&lt;/code&gt;&lt;br&gt;
3.Display answers based on user input&lt;/p&gt;
&lt;h2&gt;
  
  
  1. Setting Up Skapi
&lt;/h2&gt;

&lt;p&gt;Sign up at Skapi → create a service → copy your Service ID.&lt;br&gt;
Create an index.html and add:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;charset=&lt;/span&gt;&lt;span class="s"&gt;"UTF-8"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;Serverless FAQ Bot&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://cdn.jsdelivr.net/npm/skapi-js@latest/dist/skapi.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
    &lt;span class="c1"&gt;// Replace with your real IDs from Skapi dashboard&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;skapi&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Skapi&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;your_service_id&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;Serverless FAQ Bot&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"questionInput"&lt;/span&gt; &lt;span class="na"&gt;placeholder=&lt;/span&gt;&lt;span class="s"&gt;"Ask me anything..."&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;onclick=&lt;/span&gt;&lt;span class="s"&gt;"getAnswer()"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Ask&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"answerBox"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"faqList"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  2. Adding FAQ Data (One-Time Setup)
&lt;/h2&gt;

&lt;p&gt;Here’s the fun part: instead of writing SQL or spinning up an API, you just run this once to store FAQs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;uploadFAQs&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;faqs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;question&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;What is Skapi?&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;answer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Skapi is a serverless backend for your frontend apps.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;question&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Is Skapi free?&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;answer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Yes! It has a free tier perfect for small projects.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;question&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Do I need a backend?&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;answer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Nope. Everything runs in the frontend.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;];&lt;/span&gt;

  &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;faq&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;faqs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;skapi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;postRecord&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;faq&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;table&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;faqs&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nf"&gt;alert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;FAQs uploaded successfully!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nf"&gt;uploadFAQs&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It’s like having a mini Firebase, but simpler.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Building the FAQ Bot Logic
&lt;/h2&gt;

&lt;p&gt;Now let’s make the bot actually answer questions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getAnswer&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;userQuestion&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;questionInput&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toLowerCase&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="c1"&gt;// Fetch all FAQs from Skapi&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;skapi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getRecords&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;table&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;faqs&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="c1"&gt;// Naive matching: find the first question that appears in user input&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;bestMatch&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;list&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;faq&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;userQuestion&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;faq&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;question&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toLowerCase&lt;/span&gt;&lt;span class="p"&gt;()));&lt;/span&gt;

  &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;answerBox&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;innerText&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;bestMatch&lt;/span&gt;
    &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;bestMatch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;answer&lt;/span&gt;
    &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hmm… I don’t have an answer for that yet.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Yes, it’s basic string matching, but it works surprisingly well for FAQs.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Showing All FAQs
&lt;/h2&gt;

&lt;p&gt;I like showing all FAQs below the search bar so users can browse manually:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;showFAQs&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;skapi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getRecords&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;table&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;faqs&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;container&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;faqList&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nx"&gt;container&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerHTML&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;h3&amp;gt;All FAQs:&amp;lt;/h3&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; 
    &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;list&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;f&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;`&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;question&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;/b&amp;gt;&amp;lt;br&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;answer&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;/p&amp;gt;`&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;showFAQs&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  5. What I Learned Building This
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Skapi is stupidly simple: Adding data feels easier than copy-pasting it.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Frontend-only apps are underrated: For small tools, backend code is often overkill.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;We just built a serverless FAQ bot in under 100 lines of code — no backend, no database headaches.&lt;/p&gt;

&lt;p&gt;Skapi turned out to be the perfect tool for this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Simple CRUD from the frontend&lt;/li&gt;
&lt;li&gt;Scales without extra work&lt;/li&gt;
&lt;li&gt;Free tier to experiment with&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Easy and fast deployment using Skapi’s&lt;/em&gt; &lt;strong&gt;File Upload&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you’re a frontend dev who wants to ship full-stack features without writing backend code, Skapi is worth a look.&lt;/p&gt;

&lt;p&gt;Follow us on socials: &lt;a href="https://x.com/skapi_api" rel="noopener noreferrer"&gt;X&lt;/a&gt;, &lt;a href="https://www.youtube.com/@skapi_official" rel="noopener noreferrer"&gt;YouTube&lt;/a&gt;, &lt;a href="https://www.instagram.com/skapi_api" rel="noopener noreferrer"&gt;Instagram&lt;/a&gt;, &lt;a href="https://www.linkedin.com/company/skapi-backend-api/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;. More tutorials, code drops, and dev hacks are coming soon.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>tutorial</category>
      <category>beginners</category>
      <category>programming</category>
    </item>
    <item>
      <title>How to Link Records Without SQL: Skapi Makes It Easy</title>
      <dc:creator>Skapi</dc:creator>
      <pubDate>Fri, 05 Sep 2025 08:15:27 +0000</pubDate>
      <link>https://forem.com/skapi_api/how-to-link-records-without-sql-skapi-makes-it-easy-1063</link>
      <guid>https://forem.com/skapi_api/how-to-link-records-without-sql-skapi-makes-it-easy-1063</guid>
      <description>&lt;p&gt;Possibly the most important aspect of a relational database is that a record can reference other records in the same or different tables, allowing you to build a web of structured data. But setting up your own database, wiring primary key and foreign key constraints can be a headache, especially when you want to launch your app as soon as possible.&lt;/p&gt;

&lt;p&gt;This is where Skapi can save you hours and hours of work. Using our top of the line API, you have access to a fully functional relational database. No more coding an entire database or setting a backend-server.&lt;/p&gt;

&lt;p&gt;To start using Skapi on your project right now, follow &lt;a href="https://dev.to/skapi_api/no-more-backend-setup-launch-your-app-with-skapi-in-minutes-b85"&gt;this step-by-step guide&lt;/a&gt; and be ready to use our database and much more in just 5 minutes.&lt;/p&gt;

&lt;p&gt;In our &lt;a href="https://dev.to/skapi_api/no-more-ddl-headaches-use-skapis-zero-setup-relational-database-api-16g4"&gt;previous article&lt;/a&gt;, we gave you an overview of how to create and fetch some simple records and now we start to delve into some nuances of creating more complex data structures within Skapi.&lt;/p&gt;

&lt;p&gt;Now, to illustrate let’s simulate a social media structure with posts and comments.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;post&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="err"&gt;‘&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt; &lt;span class="nx"&gt;is&lt;/span&gt; &lt;span class="nx"&gt;my&lt;/span&gt; &lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="err"&gt;’&lt;/span&gt; 
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;table&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Posts&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="na"&gt;access_group&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;public&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;referenced_record_id&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;skapi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;postRecord&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;reference_record_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;record_id&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once the original post is created, Skapi returns its unique &lt;code&gt;record_id&lt;/code&gt;. We’ll store this in the variable &lt;code&gt;referenced_record_id&lt;/code&gt;. That ID now acts as the anchor for any related records, such as comments.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;commentRecord&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;comment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="err"&gt;‘&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt; &lt;span class="nx"&gt;is&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="nx"&gt;good&lt;/span&gt; &lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="err"&gt;’&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;commentConfig&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;table&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="err"&gt;‘&lt;/span&gt;&lt;span class="nx"&gt;Comments&lt;/span&gt;&lt;span class="err"&gt;’&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;access_group&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;public&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; 
&lt;span class="p"&gt;},&lt;/span&gt;

    &lt;span class="na"&gt;reference&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;referenced_record_id&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nx"&gt;skapi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;postRecord&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;commentRecord&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;commentConfig&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And like this, the comment is posted. As you can see, the &lt;code&gt;reference&lt;/code&gt; property inside the &lt;code&gt;config&lt;/code&gt; data is what governs the relationship between records.&lt;/p&gt;

&lt;p&gt;You can easily fetch all data referencing the original post using the &lt;code&gt;getRecords()&lt;/code&gt; method passing the &lt;code&gt;reference&lt;/code&gt; property. Just like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;skapi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getRecords&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
&lt;span class="na"&gt;table&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Comments&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;access_group&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;public&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="na"&gt;reference&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;referenced_record_id&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With this powerful config you can build an intricate web of data without having to write any DDL code.&lt;/p&gt;

&lt;p&gt;It’s like setting the foreign key without having to write any SQL, all is done automatically by Skapi’s top-tier backend API to deliver you high speed data transfers. You just focus on your app logic.&lt;/p&gt;

&lt;p&gt;Follow us on socials: &lt;a href="https://x.com/skapi_api" rel="noopener noreferrer"&gt;X&lt;/a&gt;, &lt;a href="https://www.youtube.com/@skapi_official" rel="noopener noreferrer"&gt;YouTube&lt;/a&gt;, &lt;a href="https://www.instagram.com/skapi_api" rel="noopener noreferrer"&gt;Instagram&lt;/a&gt;, &lt;a href="https://www.linkedin.com/company/skapi-backend-api/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;. More tutorials, code drops, and dev hacks are coming soon.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>productivity</category>
      <category>api</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>No More DDL Headaches: Use Skapi’s Zero-Setup Relational Database API</title>
      <dc:creator>Skapi</dc:creator>
      <pubDate>Fri, 22 Aug 2025 10:15:00 +0000</pubDate>
      <link>https://forem.com/skapi_api/no-more-ddl-headaches-use-skapis-zero-setup-relational-database-api-16g4</link>
      <guid>https://forem.com/skapi_api/no-more-ddl-headaches-use-skapis-zero-setup-relational-database-api-16g4</guid>
      <description>&lt;p&gt;Databases are the lifeblood of modern services. From user accounts to transaction records, being able to save and retrieve relational data is what makes dynamic applications possible.&lt;/p&gt;

&lt;p&gt;But writing DDL scripts is not for everyone. Personally, we’ve never liked to write SQL schemas and define constraints, mapping classes, matching data types, managing NOT NULLs and wiring foreign keys to build a functional web of related data.&lt;/p&gt;

&lt;p&gt;And that’s where Skapi comes in. We provide, amongst other tools, a high-performance database, ready to use and with no setup required. Just connect your project to your Skapi service by following this &lt;a href="https://dev.to/skapi_api/no-more-backend-setup-launch-your-app-with-skapi-in-minutes-b85"&gt;step-by-step guide&lt;/a&gt; and in 5 minutes you’ll be ready to use our powerful database and much more.&lt;/p&gt;

&lt;p&gt;In this article, we'll give you an overview of our database methods. How to create, fetch, update records and create tables.&lt;/p&gt;

&lt;p&gt;To create a new record on Skapi’s database, you’ll need to use our &lt;code&gt;postRecord()&lt;/code&gt; method. You can do this through the &lt;code&gt;onsubmit&lt;/code&gt; function on a &lt;code&gt;&amp;lt;form&amp;gt;&lt;/code&gt; tag since Skapi is able to process FormData directly, or if you prefer a little more control of your object’s data structure, you can call the function from javascript.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;For HTML forms:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;
&lt;span class="nt"&gt;&amp;lt;form&lt;/span&gt; &lt;span class="na"&gt;onsubmit=&lt;/span&gt;&lt;span class="s"&gt;"skapi.postRecord(event, { table: { name: 'my_collection', access_group: 'public' } })"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"something"&lt;/span&gt; &lt;span class="na"&gt;placeholder=&lt;/span&gt;&lt;span class="s"&gt;"Say something"&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"Hello World"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"submit"&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"Submit"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/form&amp;gt;&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;For Javascript:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;
&lt;span class="c1"&gt;// Data to be saved in key:value pairs&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;something&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hello World&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Configuration for the record to be uploaded&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;table&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;my_collection&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;access_group&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;public&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;skapi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;postRecord&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You’ll notice that in both situations there are two main objects to be sent. The &lt;code&gt;data&lt;/code&gt; and the &lt;code&gt;config&lt;/code&gt;. The &lt;code&gt;data&lt;/code&gt; is self-explanatory, it’s whatever you need to save to the database, files included. But the &lt;code&gt;config&lt;/code&gt; is where you start taking advantage of the multitude of features from our database.&lt;/p&gt;

&lt;p&gt;Let’s start with the most basic, the &lt;code&gt;table&lt;/code&gt; config.&lt;/p&gt;

&lt;p&gt;This is where you set a table for your database, but you’ll notice that you did not have to write any SQL or match datatypes. That’s right, Skapi automatically creates new tables for you.&lt;/p&gt;

&lt;p&gt;When you post a new record, it automatically looks at the table config and searches the database for a matching table and inserts the record. But if none exists, it creates a new one ready to store your data.&lt;br&gt;
Let’s take a look at how to do it:&lt;/p&gt;

&lt;p&gt;In the previous example, we created a record with the table config &lt;code&gt;name: ‘my collection’&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;something&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hello World&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;table&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;my_collection&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;access_group&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;public&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;skapi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;postRecord&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we add a second record to the same table like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;something&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;This is the new data&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;table&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;my_collection&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;access_group&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;public&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;skapi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;postRecord&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Skapi will automatically detect that the table exists and add the new data to the same one, allowing you to fetch data by filtering by table if you desire.&lt;br&gt;
And to talk about fetching data, let us explore how to do it with the &lt;code&gt;getRecords()&lt;/code&gt; method.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;query&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;table&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;my_collection&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;access_group&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;public&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;skapi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getRecords&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This would return a response with a &lt;code&gt;list&lt;/code&gt; object containing the &lt;code&gt;RecordData&lt;/code&gt; of all public objects in the ‘my_collection’ table.&lt;/p&gt;

&lt;p&gt;Now, &lt;code&gt;RecordData&lt;/code&gt; includes all the data you set, as well as some other important properties set by Skapi automatically, like the property &lt;code&gt;record_id&lt;/code&gt;. With it, you are able to reference a single record directly, something essential to the function of every application. Here is how to fetch the data from a single record using &lt;code&gt;record_id: 1234&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;query&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;record_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1234&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;skapi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getRecords&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This returns to you a response with a &lt;code&gt;list&lt;/code&gt; with a single Json object containing the data of the selected record.&lt;/p&gt;

&lt;p&gt;Another important function that you need the &lt;code&gt;record_id&lt;/code&gt; for is updating an existing record. The way to do this is very simple, just use the &lt;code&gt;postRecord()&lt;/code&gt;function, but add the &lt;code&gt;record_id&lt;/code&gt; string to the &lt;code&gt;config&lt;/code&gt; object. Let me show you how to do it for our record with the &lt;code&gt;record_id: 1234&lt;/code&gt; from before.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;something&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;New data&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;record_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1234&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;table&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;my_collection&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;access_group&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;public&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;skapi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;postRecord&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And we’re done, your record is updated with the new data.&lt;/p&gt;

&lt;p&gt;As you can see, Skapi is very easy to use. You’re able to start using our database right away without the massive overhead of building a custom schema and a back-end API.&lt;/p&gt;

&lt;p&gt;Follow us on socials: &lt;a href="https://x.com/skapi_api" rel="noopener noreferrer"&gt;X&lt;/a&gt;, &lt;a href="https://www.youtube.com/@skapi_official" rel="noopener noreferrer"&gt;YouTube&lt;/a&gt;, &lt;a href="https://www.instagram.com/skapi_api" rel="noopener noreferrer"&gt;Instagram&lt;/a&gt;, &lt;a href="https://www.linkedin.com/company/skapi-backend-api/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;. More tutorials, code drops, and dev hacks are coming soon.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>javascript</category>
      <category>database</category>
    </item>
    <item>
      <title>No More Backend Setup: Launch Your App with Skapi in Minutes</title>
      <dc:creator>Skapi</dc:creator>
      <pubDate>Fri, 08 Aug 2025 09:28:35 +0000</pubDate>
      <link>https://forem.com/skapi_api/no-more-backend-setup-launch-your-app-with-skapi-in-minutes-b85</link>
      <guid>https://forem.com/skapi_api/no-more-backend-setup-launch-your-app-with-skapi-in-minutes-b85</guid>
      <description>&lt;p&gt;When starting a new project, the initial excitement often dies when you hit the wall of backend setup. Figuring out databases, authentication, file storage, access control, deployment… suddenly you’re deep into weeks or months of boring work before you can start to develop the actual features of your project.&lt;/p&gt;

&lt;p&gt;That’s where &lt;a href="https://www.skapi.com/" rel="noopener noreferrer"&gt;Skapi&lt;/a&gt; comes in. It’s a ready-to-use, fully managed backend that you can connect to in minutes. With just a few API calls, you get secure data storage, user authentication, file uploads and much more.&lt;/p&gt;

&lt;p&gt;You don’t need complicated setup steps like other SDK’s. There is no need to build your own database like Supabase does or setting each feature individually like in Firebase. Skapi provides all you need from the start, with only a simple copy-paste setup.&lt;/p&gt;

&lt;p&gt;In this article, we’ll guide you step-by-step on your way to creating your very first Skapi service, connecting your project and verifying your connection.&lt;/p&gt;

&lt;h2&gt;
  
  
  Create a service
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Sign up to create an account at &lt;a href="https://www.skapi.com/" rel="noopener noreferrer"&gt;skapi.com&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Log in and navigate to the My Services page.&lt;/li&gt;
&lt;li&gt;Click on Create New Service.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Initialize the Skapi Library
&lt;/h2&gt;

&lt;p&gt;After creating a Service, you will be redirected to its starting page where you can get your service’s credentials. These are essential to setting up Skapi on your project.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Using Skapi with Plain HTML&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For those who prefer vanilla HTML and JavaScript evangelizers, you can import Skapi directly using a &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; tag. Just make sure that the Skapi class is initialized in the HTML header of all pages as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;
&lt;span class="cp"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://cdn.jsdelivr.net/npm/skapi-js@latest/dist/skapi.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;skapi&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Skapi&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;service_id&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;For SPA Projects&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;To use Skapi on a SPA framework such as React, Angular or Vue, you can install skapi-js via npm by simply executing the command &lt;code&gt;$ npm i skapi-js&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Then, import the library into your main JavaScript file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;
&lt;span class="c1"&gt;// main.js&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Skapi&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;skapi-js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;skapi&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Skapi&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;service_id&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;skapi&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// You can now import Skapi from anywhere in your project.&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Test your connection
&lt;/h2&gt;

&lt;p&gt;When your client is successfully connected, you can use the &lt;code&gt;getConmnectionInfo()&lt;/code&gt; method to retrieve your connection information.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;For HTML&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;
&lt;span class="c"&gt;&amp;lt;!-- index.html --&amp;gt;&lt;/span&gt;
&lt;span class="cp"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://cdn.jsdelivr.net/npm/skapi-js@latest/dist/skapi.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;skapi&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Skapi&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;service_id&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
&lt;span class="nx"&gt;skapi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getConnectionInfo&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;info&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;info&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="cm"&gt;/*
    Returns:
    {
        service_name: "Your Service Name",
        user_ip: "Connected user's IP address",
        user_agent: "Connected user agent",
        user_location: "Connected user's country code",
        version: 'x.x.x' // Skapi library version
    }
    */&lt;/span&gt;
   &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;alert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Connected to &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;info&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;service_name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;For SPA frameworks&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;skapi&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../location/of/your/main.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;skapi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getConnectionInfo&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;info&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;info&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="cm"&gt;/*
    Returns:
    {
        service_name: "Your Service Name",
        user_ip: "Connected user's IP address",
        user_agent: "Connected user agent",
        user_location: "Connected user's country code",
        version: 'x.x.x' // Skapi library version
    }
    */&lt;/span&gt;
   &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;alert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Connected to &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;info&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;service_name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you’re set to use all the features Skapi provides, including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Authentication: A fully fledged user authentication flow.&lt;/li&gt;
&lt;li&gt;Realtime Connection: Notifications, WebRTC for streaming or video chats and WebSocket data exchange to transfer JSON data such as in text chats.&lt;/li&gt;
&lt;li&gt;A ready-to-use relational Database: Save and retrieve your data with our high performance database.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All that and more without the headache of developing it yourself, allowing you to focus on your main features that are unique to your project.&lt;/p&gt;

&lt;p&gt;For example, you can build a language learning app that lets users save vocabulary, upload images, and track their progress, all without writing a single line of backend code. Skapi is going to handle the authentication, data storage, and file uploads flawlessly. You can check our tutorial of a &lt;a href="https://youtu.be/Fgyod7n-4LI?si=0T-Brcw-QGlsEdEA" rel="noopener noreferrer"&gt;Translation tool&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Also recently we made an AI-powered &lt;a href="https://youtu.be/HVE1QOiM1LA?si=1UarCVqSvXRMQwWk" rel="noopener noreferrer"&gt;To-Do List&lt;/a&gt; that stores everything through Skapi's database API. It's amazing how quickly you can iterate without getting bogged down in backend setup.&lt;/p&gt;

&lt;p&gt;In future articles we’ll be diving into specific functions to bring you easy-to-follow instructions on how to use our service to its fullest. But if you can’t wait, you can visit our documentation right now on &lt;a href="https://docs.skapi.com/introduction/getting-started.html" rel="noopener noreferrer"&gt;docs.skapi.com&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Follow us on socials: &lt;a href="https://x.com/skapi_api" rel="noopener noreferrer"&gt;X&lt;/a&gt;, &lt;a href="https://www.youtube.com/@skapi_official" rel="noopener noreferrer"&gt;YouTube&lt;/a&gt;, &lt;a href="https://www.instagram.com/skapi_api" rel="noopener noreferrer"&gt;Instagram&lt;/a&gt;, &lt;a href="https://www.linkedin.com/company/skapi-backend-api/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;. More tutorials, code drops, and dev hacks are coming soon.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>database</category>
      <category>api</category>
    </item>
    <item>
      <title>The Easiest Way to Add File Upload to Your Website</title>
      <dc:creator>Skapi</dc:creator>
      <pubDate>Fri, 25 Jul 2025 09:54:00 +0000</pubDate>
      <link>https://forem.com/skapi_api/the-easiest-way-to-add-file-upload-to-your-website-34bn</link>
      <guid>https://forem.com/skapi_api/the-easiest-way-to-add-file-upload-to-your-website-34bn</guid>
      <description>&lt;p&gt;File upload features are very tedious to implement. From cloud storage (Amazon’s S3 or Firebase’s Firestore) to Database file storage (BLOBs and CLOBs), custom endpoints, form handling…It’s a lot of work.&lt;/p&gt;

&lt;p&gt;Skapi makes all of that disappear. It is a backend-as-a-service platform that takes care of user authentication, file storage, and data management. It lets you build full-featured web apps with zero backend infrastructure building, and zero server maintenance.&lt;/p&gt;

&lt;p&gt;With Skapi, you can build a complete upload flow (from user authentication to storage and retrieval) using just a few lines of frontend code. &lt;/p&gt;

&lt;p&gt;In this guide, you’ll see just how easy it is to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Set up Skapi in your project&lt;/li&gt;
&lt;li&gt;Authenticate users&lt;/li&gt;
&lt;li&gt;Upload files through forms&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let’s do it.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Set Up Your Skapi Credentials
&lt;/h2&gt;

&lt;p&gt;First, we need to grab your Skapi credentials.&lt;/p&gt;

&lt;p&gt;Head to your &lt;a href="https://www.skapi.com/" rel="noopener noreferrer"&gt;Skapi Dashboard&lt;/a&gt;, open your Service, and navigate to the Getting Started page.&lt;/p&gt;

&lt;p&gt;Copy your Service ID from there.&lt;br&gt;
Now paste those value into your HTML file to initialize Skapi:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://cdn.jsdelivr.net/npm/skapi-js@latest/dist/skapi.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;skapi&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Skapi&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;your_service_id&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With Skapi initialized, you're ready to authenticate users. Let’s start with account creation.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. How to handle User Signup
&lt;/h2&gt;

&lt;p&gt;Now, with your credentials set your user will need to &lt;a href="https://docs.skapi.com/authentication/create-account.html" rel="noopener noreferrer"&gt;create an account&lt;/a&gt; for your service, and that is as easy and straightforward as you could ask for using Skapi's &lt;a href="https://docs.skapi.com/api-reference/authentication/README.html#signup" rel="noopener noreferrer"&gt;signup()&lt;/a&gt; endpoint.&lt;/p&gt;

&lt;p&gt;Here’s a basic example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;parameters&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;user@email.com&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;password&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Must be 6–60 characters.&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;User's name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nx"&gt;skapi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;signup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;parameters&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;href&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;login.html&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;alert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is the bare minimum required to register a user. You can also include additional fields like age, phone number, and any custom data your service needs.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. How to set up Logging In
&lt;/h2&gt;

&lt;p&gt;And &lt;a href="https://docs.skapi.com/authentication/login-logout.html" rel="noopener noreferrer"&gt;logging in&lt;/a&gt; is even easier. Here’s how to use the &lt;a href="https://docs.skapi.com/api-reference/authentication/README.html#login" rel="noopener noreferrer"&gt;login()&lt;/a&gt; method:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;parameters&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;user@email.com&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;password&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;


&lt;span class="nx"&gt;skapi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;login&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;parameters&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;href&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;welcome.html&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;alert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And just like that, your user is logged in and ready to go.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. How to add File Upload
&lt;/h2&gt;

&lt;p&gt;Now let’s upload some files!&lt;br&gt;
The easiest way to handle file uploads with Skapi is through a simple HTML form. Here’s how to do it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;form&lt;/span&gt; &lt;span class="nx"&gt;onsubmit&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;skapi.postRecord(event, {
    table: 'my_photos',
    progress: (p) =&amp;gt; console.log(p)
  }).then(rec =&amp;gt; console.log(rec))&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;


  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;description&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;placeholder&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Photo description&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;picture&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;file&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;multiple&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;submit&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Submit&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/form&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When the form is submitted, Skapi automatically uploads the selected files as an array of BinaryFile objects under the key picture (matching the name of the file input).&lt;br&gt;
Here’s what a resulting record might look like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;record_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;...&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;...,&lt;/span&gt;
    &lt;span class="nx"&gt;bin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nl"&gt;picture&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="na"&gt;access_group&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;public&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="na"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;...&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://...&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.../...&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="na"&gt;size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1234&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="na"&gt;uploaded&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1234&lt;/span&gt;
                &lt;span class="na"&gt;getFile&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{...};&lt;/span&gt;
            &lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="p"&gt;...&lt;/span&gt;
        &lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And that’s it, your files are uploaded and securely stored in Skapi, ready to be accessed or managed whenever you need.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final Thoughts: Skapi vs Traditional Setup
&lt;/h2&gt;

&lt;p&gt;Building a complete file upload flow usually means juggling multiple tools and layers. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Traditional Setup Example:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Backend API to receive files (e.g. Node.js + Express)&lt;/li&gt;
&lt;li&gt;Cloud storage config (e.g. AWS S3 buckets and permissions)&lt;/li&gt;
&lt;li&gt;Authentication system (e.g. JWT, OAuth)&lt;/li&gt;
&lt;li&gt;Frontend integration with fetch() or axios&lt;/li&gt;
&lt;li&gt;Middleware for file parsing (e.g. multer)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Skapi Setup Example:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;One &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; tag&lt;/li&gt;
&lt;li&gt;One &lt;code&gt;signup()&lt;/code&gt; call&lt;/li&gt;
&lt;li&gt;One &lt;code&gt;login()&lt;/code&gt; call&lt;/li&gt;
&lt;li&gt;One &lt;code&gt;&amp;lt;form&amp;gt;&lt;/code&gt; element&lt;/li&gt;
&lt;li&gt;One &lt;code&gt;postRecord()&lt;/code&gt; call&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That’s it. You get secure uploads, authentication, storage, and access control without touching a memory stream or cloud config. What usually takes days to build, test, and deploy can now be done in minutes.&lt;/p&gt;

&lt;p&gt;Drop a comment below and let us know your struggles in the File Upload process and how do you solve them. &lt;/p&gt;

&lt;p&gt;Follow us on socials: &lt;a href="https://x.com/skapi_api" rel="noopener noreferrer"&gt;X&lt;/a&gt;, &lt;a href="https://www.youtube.com/@skapi_official" rel="noopener noreferrer"&gt;YouTube&lt;/a&gt;, &lt;a href="https://www.instagram.com/skapi_api" rel="noopener noreferrer"&gt;Instagram&lt;/a&gt;, &lt;a href="https://www.linkedin.com/company/skapi-backend-api/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;. More tutorials, code drops, and dev hacks are coming soon.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>tutorial</category>
      <category>api</category>
      <category>filehosting</category>
    </item>
  </channel>
</rss>
