<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Nishchay</title>
    <description>The latest articles on DEV Community by Nishchay (@kaushiknishchay).</description>
    <link>https://dev.to/kaushiknishchay</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4166799%2F1df5499e-35c9-4206-9518-b331fba5581f.png</url>
      <title>DEV Community: Nishchay</title>
      <link>https://dev.to/kaushiknishchay</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/kaushiknishchay"/>
    <language>en</language>
    <item>
      <title>Programmatic Video with Remotion: Building Videos in React with AI Skills</title>
      <dc:creator>Nishchay</dc:creator>
      <pubDate>Tue, 06 Oct 2026 17:04:50 +0000</pubDate>
      <link>https://dev.to/kaushiknishchay/programmatic-video-with-remotion-building-videos-in-react-with-ai-skills-2hfj</link>
      <guid>https://dev.to/kaushiknishchay/programmatic-video-with-remotion-building-videos-in-react-with-ai-skills-2hfj</guid>
      <description>&lt;p&gt;Every time you finish building a side project, SaaS product, or game, you face the same chore: creating a promo video that looks clean.&lt;/p&gt;

&lt;p&gt;Usually, that means opening Premiere Pro, After Effects, or DaVinci Resolve. You end up nudging keyframes on a timeline, wrestling with GUI export settings, manually lining up sound effects, and repeating the whole cycle whenever you need to fix copy in a 30-second clip. For developers used to code, Git, and component design, the workflow feels slow and disconnected from how we build software.&lt;/p&gt;

&lt;p&gt;Instead of timeline editors, you can build video animations using the tools you already know: React components, JSX, CSS flexbox, and spring physics, then render them directly into MP4 files from your terminal.&lt;/p&gt;

&lt;p&gt;This is where &lt;strong&gt;Remotion&lt;/strong&gt; fits in.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;What is Remotion?&lt;/strong&gt;  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Remotion&lt;/strong&gt; is an open-source framework that allows developers to create videos programmatically using React, TypeScript/JavaScript, and CSS. Instead of manual timeline editing, video frames are rendered deterministically based on React state and frame numbers, enabling automated video generation, CI/CD rendering, and dynamic personalized video pipelines.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Learn more:&lt;/em&gt; &lt;a href="https://www.remotion.dev/" rel="noopener noreferrer"&gt;Remotion Official Website&lt;/a&gt; | &lt;a href="https://github.com/remotion-dev/remotion" rel="noopener noreferrer"&gt;Remotion GitHub Repository&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;While building &lt;strong&gt;&lt;a href="https://tambola.nkaushik.in/" rel="noopener noreferrer"&gt;Tambola Live&lt;/a&gt;&lt;/strong&gt;, a real-time WebRTC multiplayer game (covered in my &lt;a href="https://nkaushik.in/projects/online-tambola" rel="noopener noreferrer"&gt;Tambola Architecture Case Study&lt;/a&gt;), I needed a 40-second animated promo trailer. Using Remotion, the official &lt;strong&gt;Remotion AI skills&lt;/strong&gt;, and &lt;strong&gt;Gemini 3.7 Flash&lt;/strong&gt;, I built the entire 1080p video with scene transitions, kinetic typography, and synchronized sound effects in React.&lt;/p&gt;

&lt;p&gt;Here is a breakdown of how programmatic video works, how Remotion's preview studio speeds up iteration, and how AI skills help you generate complete scenes without trial and error.&lt;/p&gt;




&lt;h2&gt;
  
  
  Remotion vs. traditional video editors: why code wins
&lt;/h2&gt;

&lt;p&gt;If you know how to build web apps, you already know most of what it takes to build a Remotion video. Similar to &lt;a href="https://nkaushik.in/writing/automating-social-images-with-satori-and-sharp" rel="noopener noreferrer"&gt;automating social images with Satori and Sharp&lt;/a&gt;, programmatic video replaces manual GUI work with reproducible code.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature / Dimension&lt;/th&gt;
&lt;th&gt;Traditional GUI Editors (Premiere / After Effects)&lt;/th&gt;
&lt;th&gt;Programmatic Video (Remotion)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Workflow Interface&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Proprietary timeline GUI with visual tracks&lt;/td&gt;
&lt;td&gt;React components, JSX, and standard CSS&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Version Control&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Heavy, binary &lt;code&gt;.prproj&lt;/code&gt; or &lt;code&gt;.aep&lt;/code&gt; files&lt;/td&gt;
&lt;td&gt;Standard Git diffs, pull requests, and code reviews&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Asset Reusability&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Manual copy-pasting across timeline layers&lt;/td&gt;
&lt;td&gt;Composable React components and design tokens&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Dynamic Data&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Manual re-editing per data variation&lt;/td&gt;
&lt;td&gt;Direct API, JSON, WebSocket, or database inputs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Feedback Loop&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Background timeline rendering for previews&lt;/td&gt;
&lt;td&gt;Fast browser Studio with instant Hot Module Replacement (HMR)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Automation &amp;amp; CI/CD&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Complex desktop rendering macros&lt;/td&gt;
&lt;td&gt;Headless CLI or serverless cloud rendering&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Traditional Video Workflow:
[GUI Timeline] ---&amp;gt; [Manual Keyframes] ---&amp;gt; [Heavy Local Render] ---&amp;gt; [Hard to Update / Automate]

Programmatic Remotion Workflow:
[React &amp;amp; CSS] ---&amp;gt; [Frame &amp;amp; Spring Hooks] ---&amp;gt; [Live Studio Preview] ---&amp;gt; [CLI / Cloud Render]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  The core mental model: how Remotion turns React into video
&lt;/h2&gt;

&lt;p&gt;In Remotion, a video is a sequence of still frames rendered at a fixed frame rate (such as 30 or 60 frames per second).&lt;/p&gt;

&lt;p&gt;Instead of relying on browser wall-clock timers like &lt;code&gt;setTimeout&lt;/code&gt; or CSS &lt;code&gt;@keyframes&lt;/code&gt; (which can drift or drop frames during heavy CPU loads), Remotion uses deterministic hooks tied directly to the current frame index:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;useCurrentFrame()&lt;/code&gt;&lt;/strong&gt;: Returns the integer index of the active frame (&lt;code&gt;0&lt;/code&gt;, &lt;code&gt;1&lt;/code&gt;, &lt;code&gt;2&lt;/code&gt;, ...).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;useVideoConfig()&lt;/code&gt;&lt;/strong&gt;: Provides composition metadata such as &lt;code&gt;fps&lt;/code&gt;, &lt;code&gt;durationInFrames&lt;/code&gt;, &lt;code&gt;width&lt;/code&gt;, and &lt;code&gt;height&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;interpolate()&lt;/code&gt;&lt;/strong&gt;: Maps a frame range to numerical values (for instance, fading opacity from &lt;code&gt;0&lt;/code&gt; to &lt;code&gt;1&lt;/code&gt; between frames 0 and 30).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;spring()&lt;/code&gt;&lt;/strong&gt;: Computes natural, physics-based motion using mass, stiffness, and damping parameters.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  A simple 3-second animated title
&lt;/h3&gt;

&lt;p&gt;Here is a minimal Remotion component:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&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;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&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;useCurrentFrame&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useVideoConfig&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;spring&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;interpolate&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;remotion&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;IntroTitle&lt;/span&gt; &lt;span class="o"&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;frame&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useCurrentFrame&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;fps&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useVideoConfig&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="c1"&gt;// Calculate smooth physics-based spring entrance&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;entrance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;spring&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="nx"&gt;frame&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;fps&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;config&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;damping&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;stiffness&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;100&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;scale&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;interpolate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;entrance&lt;/span&gt;&lt;span class="p"&gt;,&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="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="mf"&gt;0.8&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;opacity&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;interpolate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;entrance&lt;/span&gt;&lt;span class="p"&gt;,&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="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="mi"&gt;0&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="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;
      &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;flex&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="na"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;flex&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;alignItems&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;center&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;justifyContent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;center&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#090d16&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#ffffff&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;fontSize&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;fontWeight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;800&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`scale(&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;scale&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="nx"&gt;opacity&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      Tambola Live
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;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;Because &lt;code&gt;entrance&lt;/code&gt; depends strictly on &lt;code&gt;frame&lt;/code&gt;, Remotion guarantees pixel-perfect, frame-accurate rendering whether your local machine runs at 10 fps or 120 fps.&lt;/p&gt;




&lt;h2&gt;
  
  
  Speeding up scene generation with Remotion AI skills &amp;amp; Gemini 3.7 Flash
&lt;/h2&gt;

&lt;p&gt;Calculating animation timings, keyframe curves, and scene transitions by hand can take time. To help with this, the Remotion team created official &lt;strong&gt;Agent Skills&lt;/strong&gt; that give coding assistants direct knowledge of Remotion's architecture and APIs.&lt;/p&gt;

&lt;p&gt;You can install Remotion skills into your AI agent environment with one command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx &lt;span class="nt"&gt;-y&lt;/span&gt; skills@latest add remotion-dev/skills &lt;span class="nt"&gt;-g&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This installs 12 specialized Remotion skills into your project:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Skill&lt;/th&gt;
&lt;th&gt;Purpose&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;code&gt;remotion-best-practices&lt;/code&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Enforces frame determinism, avoiding non-deterministic timers, and memory optimizations.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;code&gt;remotion-create&lt;/code&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Scaffolds new video projects, compositions, and sequence structures.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;code&gt;remotion-studio&lt;/code&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Guides interactive preview workflows and debugging via the local studio.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;code&gt;remotion-render&lt;/code&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Handles headless CLI rendering, codecs (H.264, ProRes, WebM), and output flags.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;code&gt;remotion-transitions&lt;/code&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Implements &lt;code&gt;@remotion/transitions&lt;/code&gt; (&lt;code&gt;fade&lt;/code&gt;, &lt;code&gt;slide&lt;/code&gt;, &lt;code&gt;wipe&lt;/code&gt;, &lt;code&gt;flip&lt;/code&gt;).&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;code&gt;remotion-multimedia&lt;/code&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Orchestrates audio tracks, sound effects synchronization, and video assets.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;code&gt;remotion-captions&lt;/code&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Generates dynamic word-by-word animated subtitles.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Pairing with Gemini 3.7 Flash
&lt;/h3&gt;

&lt;p&gt;With these skills installed, I gave &lt;strong&gt;Gemini 3.7 Flash&lt;/strong&gt; the scene outline for the promo video:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"Create a 40-second 1080p promo video for an online WebRTC Tambola game. We need 6 scenes: Hook, Host creating room, Player scanning QR code to join, Live number calling &amp;amp; ticket dabbing, Winning claim fanfare with confetti, and an Outro with a call to action. Use &lt;code&gt;@remotion/transitions&lt;/code&gt; with fade, spring-loaded kinetic typography, and synchronized sound effects."&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Because the model had direct access to &lt;code&gt;remotion-dev/skills&lt;/code&gt;, it avoided common AI errors like using &lt;code&gt;setInterval&lt;/code&gt; or non-deterministic CSS animations. Instead, it generated clean, modular Remotion sequence components with proper frame calculations and spring curves right away.&lt;/p&gt;




&lt;h2&gt;
  
  
  Fast iteration with Remotion preview studio
&lt;/h2&gt;

&lt;p&gt;The most convenient part of developing with Remotion is the &lt;strong&gt;Remotion Studio&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;You start the preview studio with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx remotion studio src/remotion/index.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This launches a local preview interface on &lt;code&gt;http://localhost:3000&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Interactive Timeline:&lt;/strong&gt; Drag the playhead to scrub across frames smoothly.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Frame-by-Frame Stepping:&lt;/strong&gt; Use arrow keys to step through individual frames and inspect alignment.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Responsive Canvas Zoom:&lt;/strong&gt; Scale from 10% to 200% to verify typography, badges, and mobile mockups.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Instant Hot Module Replacement (HMR):&lt;/strong&gt; Update CSS padding, color values, or spring physics in your code editor, and see the canvas update in milliseconds without restarting.&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;+-------------------------------------------------------------------+
|  Remotion Studio (http://localhost:3000)                          |
+-------------------------------------------------------------------+
|  [ Play / Pause ]  [ Frame: 450 / 1200 ]  [ 30 FPS ]  [ 1080p ]   |
|                                                                   |
|  +-------------------------------------------------------------+  |
|  |                                                             |  |
|  |           [ Animated Ticket &amp;amp; Live Ball Calling ]           |  |
|  |                                                             |  |
|  +-------------------------------------------------------------+  |
|                                                                   |
|  [================== Timeline Scrubbing Bar ===================]  |
|  |-- Scene 1 --|-- Scene 2 --|-- Scene 3 --|-- Scene 4 Gameplay -|  |
+-------------------------------------------------------------------+
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Case study: building the Tambola Live promo video
&lt;/h2&gt;

&lt;p&gt;Here is how the promo video was organized in &lt;code&gt;/src/remotion/&lt;/code&gt; for &lt;a href="https://tambola.nkaushik.in/" rel="noopener noreferrer"&gt;Tambola Live&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Root Composition setup (&lt;code&gt;Root.jsx&lt;/code&gt;)
&lt;/h3&gt;

&lt;p&gt;The video root declares the compositions available in the project, defining the resolution, frame rate, and total duration in frames (40 seconds at 30 fps = 1,200 frames):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&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;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&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;Composition&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;remotion&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&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;PromoVideo&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;./PromoVideo.jsx&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Root&lt;/span&gt; &lt;span class="o"&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="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Composition&lt;/span&gt;
      &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"PromoVideo"&lt;/span&gt;
      &lt;span class="na"&gt;component&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;PromoVideo&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="na"&gt;durationInFrames&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;1200&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="na"&gt;fps&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;1920&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;1080&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&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="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;Root&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Scene sequencing with transitions (&lt;code&gt;PromoVideo.jsx&lt;/code&gt;)
&lt;/h3&gt;

&lt;p&gt;Rather than manually offsetting start frames for every scene, &lt;code&gt;@remotion/transitions&lt;/code&gt; chains scenes together cleanly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&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;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&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;AbsoluteFill&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;remotion&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&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;TransitionSeries&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;linearTiming&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;@remotion/transitions&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&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;fade&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;@remotion/transitions/fade&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;AudioManager&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;./audio/AudioManager.jsx&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Scene1Hook&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;./scenes/Scene1Hook.jsx&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Scene2Host&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;./scenes/Scene2Host.jsx&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Scene3Join&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;./scenes/Scene3Join.jsx&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Scene4Gameplay&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;./scenes/Scene4Gameplay.jsx&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Scene5Winning&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;./scenes/Scene5Winning.jsx&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Scene6Outro&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;./scenes/Scene6Outro.jsx&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="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;PromoVideo&lt;/span&gt;&lt;span class="p"&gt;()&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="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;AbsoluteFill&lt;/span&gt; &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;backgroundColor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#090d16&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#ffffff&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* Synchronized Audio &amp;amp; SFX Layer */&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;AudioManager&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;

      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* Cinematic Transition Sequences */&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;TransitionSeries&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;TransitionSeries&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Sequence&lt;/span&gt; &lt;span class="na"&gt;durationInFrames&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;155&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Scene1Hook&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;TransitionSeries&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Sequence&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;TransitionSeries&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Transition&lt;/span&gt;
          &lt;span class="na"&gt;presentation&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;fade&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
          &lt;span class="na"&gt;timing&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;linearTiming&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;durationInFrames&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;12&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;

        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;TransitionSeries&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Sequence&lt;/span&gt; &lt;span class="na"&gt;durationInFrames&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;185&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Scene2Host&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;TransitionSeries&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Sequence&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;TransitionSeries&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Transition&lt;/span&gt;
          &lt;span class="na"&gt;presentation&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;fade&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
          &lt;span class="na"&gt;timing&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;linearTiming&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;durationInFrames&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;12&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;

        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;TransitionSeries&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Sequence&lt;/span&gt; &lt;span class="na"&gt;durationInFrames&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;185&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Scene3Join&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;TransitionSeries&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Sequence&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;TransitionSeries&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Transition&lt;/span&gt;
          &lt;span class="na"&gt;presentation&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;fade&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
          &lt;span class="na"&gt;timing&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;linearTiming&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;durationInFrames&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;12&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;

        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;TransitionSeries&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Sequence&lt;/span&gt; &lt;span class="na"&gt;durationInFrames&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;305&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Scene4Gameplay&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;TransitionSeries&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Sequence&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;TransitionSeries&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Transition&lt;/span&gt;
          &lt;span class="na"&gt;presentation&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;fade&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
          &lt;span class="na"&gt;timing&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;linearTiming&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;durationInFrames&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;12&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;

        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;TransitionSeries&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Sequence&lt;/span&gt; &lt;span class="na"&gt;durationInFrames&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;245&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Scene5Winning&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;TransitionSeries&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Sequence&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;TransitionSeries&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Transition&lt;/span&gt;
          &lt;span class="na"&gt;presentation&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;fade&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
          &lt;span class="na"&gt;timing&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;linearTiming&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;durationInFrames&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;12&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;

        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;TransitionSeries&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Sequence&lt;/span&gt; &lt;span class="na"&gt;durationInFrames&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;185&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Scene6Outro&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;TransitionSeries&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Sequence&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;TransitionSeries&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;AbsoluteFill&lt;/span&gt;&lt;span class="p"&gt;&amp;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;h3&gt;
  
  
  3. Adding audio and synthetic sound effects without external files
&lt;/h3&gt;

&lt;p&gt;For the audio layer, we layered background music using Remotion's &lt;code&gt;&amp;lt;Audio&amp;gt;&lt;/code&gt; component alongside &lt;strong&gt;synthetic PCM WAV sound effects generated directly in JavaScript&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&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;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&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;Audio&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Sequence&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;staticFile&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;remotion&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&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;SOUND_POP&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;SOUND_DAB&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;SOUND_WIN&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;SOUND_CHIME&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;./sounds.js&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="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;AudioManager&lt;/span&gt;&lt;span class="p"&gt;()&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="p"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* 40-Second Upbeat Background Music Track */&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Audio&lt;/span&gt; &lt;span class="na"&gt;src&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;staticFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;promo-music.wav&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;volume&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="mf"&gt;0.8&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;

      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* Synchronized Sound Effects */&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Sequence&lt;/span&gt; &lt;span class="na"&gt;from&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;180&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;durationInFrames&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Audio&lt;/span&gt; &lt;span class="na"&gt;src&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;SOUND_CHIME&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;volume&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="mf"&gt;0.4&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Sequence&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Sequence&lt;/span&gt; &lt;span class="na"&gt;from&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;540&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;durationInFrames&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Audio&lt;/span&gt; &lt;span class="na"&gt;src&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;SOUND_POP&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;volume&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="mf"&gt;0.5&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Sequence&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Sequence&lt;/span&gt; &lt;span class="na"&gt;from&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;570&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;durationInFrames&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Audio&lt;/span&gt; &lt;span class="na"&gt;src&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;SOUND_DAB&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;volume&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="mf"&gt;0.55&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Sequence&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Sequence&lt;/span&gt; &lt;span class="na"&gt;from&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;870&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;durationInFrames&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;60&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Audio&lt;/span&gt; &lt;span class="na"&gt;src&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;SOUND_WIN&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;volume&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="mf"&gt;0.65&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Sequence&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&amp;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;By generating data-URI WAV sounds mathematically (sine waves with exponential decay envelopes at 22,050 Hz), sound effects like ball pop sounds, ticket dabs, chimes, and victory fanfares are completely self-contained, requiring zero external asset downloads during rendering.&lt;/p&gt;




&lt;h2&gt;
  
  
  Rendering to production MP4 from the CLI
&lt;/h2&gt;

&lt;p&gt;When you are ready to produce the final video, render it directly from your terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Render high-quality MP4 using H.264 codec&lt;/span&gt;
npx remotion render src/remotion/index.js PromoVideo public/promo-video.mp4 &lt;span class="nt"&gt;--codec&lt;/span&gt; h264
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can also extract poster images and video thumbnails at specific frames:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Extract frame 100 as high-resolution poster JPEG&lt;/span&gt;
npx remotion still src/remotion/index.js PromoVideo public/promo-poster.jpg &lt;span class="nt"&gt;--frame&lt;/span&gt; 100
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For large-scale production (such as generating personalized recap videos for users), you can deploy Remotion to &lt;strong&gt;AWS Lambda&lt;/strong&gt; or &lt;strong&gt;Google Cloud Run&lt;/strong&gt; using &lt;code&gt;@remotion/lambda&lt;/code&gt; to render videos in parallel across distributed serverless functions.&lt;/p&gt;




&lt;h2&gt;
  
  
  See the game and video live in action
&lt;/h2&gt;

&lt;p&gt;The complete promo video generated through this workflow is live today.&lt;/p&gt;

&lt;p&gt;You can visit &lt;strong&gt;&lt;a href="https://tambola.nkaushik.in/" rel="noopener noreferrer"&gt;Tambola Live (tambola.nkaushik.in)&lt;/a&gt;&lt;/strong&gt; to:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Play the game:&lt;/strong&gt; Host a room, invite friends via QR code or direct link, roll 1-90 numbers with real-time WebRTC sync, and auto-verify winning tickets.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Watch the promo video:&lt;/strong&gt; Scroll down to the &lt;strong&gt;"How To Play"&lt;/strong&gt; section on the homepage to watch the full Remotion-rendered video running in the web player.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Final thoughts
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Code is a practical video tool:&lt;/strong&gt; If you know React and CSS, Remotion gives you full control over animations, typography, and automated rendering.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;AI skills remove the boilerplate:&lt;/strong&gt; Installing &lt;code&gt;remotion-dev/skills&lt;/code&gt; gives models like Gemini 3.7 Flash the exact context needed to write working sequence timings and spring curves without guesswork.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;The Studio provides immediate feedback:&lt;/strong&gt; You can inspect frames, test responsive viewports, and tweak CSS without waiting for full exports.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you have put off creating a promo video for your project because video editing software feels cumbersome, building it in React with Remotion is worth exploring.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://nkaushik.in/writing/programmatic-video-with-remotion-react-and-ai" rel="noopener noreferrer"&gt;nkaushik.in&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>remotion</category>
      <category>geminiflash</category>
      <category>javascript</category>
      <category>programmaticvideo</category>
    </item>
    <item>
      <title>AdGuard Home: Stop Ads &amp; Trackers for Your Entire Family</title>
      <dc:creator>Nishchay</dc:creator>
      <pubDate>Tue, 06 Oct 2026 17:04:28 +0000</pubDate>
      <link>https://dev.to/kaushiknishchay/adguard-home-stop-ads-trackers-for-your-entire-family-42oi</link>
      <guid>https://dev.to/kaushiknishchay/adguard-home-stop-ads-trackers-for-your-entire-family-42oi</guid>
      <description>&lt;p&gt;How often have you encountered the scenario where you search something and suddenly everywhere you go, you start seeing ads for it. Or, when you try to read a news article and you can barely read anything with all the ads showing up.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fvnv2hcr8rlau0z4uniof.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fvnv2hcr8rlau0z4uniof.jpg" alt="example of a website filled with full page ads" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Although you might use apps like Firefox or extensions such as Adblock, they must be installed on every device, which is often impractical.&lt;/p&gt;

&lt;p&gt;I faced a similar issue because my family, like many others, isn't tech-savvy. I needed a solution that could be implemented to shield them from ads and malware without requiring any changes on their part.&lt;/p&gt;

&lt;h2&gt;
  
  
  Enter, AdGuard Home
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/AdguardTeam/AdGuardHome" rel="noopener noreferrer"&gt;AdGuard Home&lt;/a&gt; is an open-source, network-wide DNS server that blocks ads, telemetry, and tracking domains before they ever reach your smartphones, laptops, smart TVs, or IoT devices.&lt;/p&gt;

&lt;p&gt;In this guide, we'll cover how to install AdGuard Home, configure the &lt;strong&gt;best 2026 blocklists&lt;/strong&gt;, optimize upstream DNS settings, and deploy it across your entire home network.&lt;/p&gt;

&lt;p&gt;🤖&lt;/p&gt;

&lt;p&gt;Let's assume we're working in a Linux environment (such as a Raspberry Pi, Debian mini PC, or Docker container), as it simplifies 24/7 reliability. However, the installation and web interface steps are identical across platforms.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;* *&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Installation
&lt;/h2&gt;

&lt;p&gt;Head over to the &lt;a href="https://github.com/AdguardTeam/AdGuardHome?tab=readme-ov-file#automated-install-linux-and-mac" rel="noopener noreferrer"&gt;AdGuard Home Automated Install&lt;/a&gt;. Installing AdGuard is as simple as running a single command.&lt;/p&gt;

&lt;p&gt;To install with &lt;code&gt;curl&lt;/code&gt; run the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="nt"&gt;-S&lt;/span&gt; &lt;span class="nt"&gt;-L&lt;/span&gt; https://raw.githubusercontent.com/AdguardTeam/AdGuardHome/master/scripts/install.sh | sh &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="nt"&gt;--&lt;/span&gt; &lt;span class="nt"&gt;-v&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To install with &lt;code&gt;wget&lt;/code&gt; run the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;wget &lt;span class="nt"&gt;--no-verbose&lt;/span&gt; &lt;span class="nt"&gt;-O&lt;/span&gt; - https://raw.githubusercontent.com/AdguardTeam/AdGuardHome/master/scripts/install.sh | sh &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="nt"&gt;--&lt;/span&gt; &lt;span class="nt"&gt;-v&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This installs the AdGuard Home service, which will act as your local recursive/forwarding DNS server.&lt;/p&gt;

&lt;h4&gt;
  
  
  What is DNS?
&lt;/h4&gt;

&lt;p&gt;DNS stands for &lt;strong&gt;Domain Name System&lt;/strong&gt;. In simple terms, it is the internet's address book. Every website you visit has an underlying IP address (e.g. &lt;code&gt;66.11.184.216&lt;/code&gt;). When your browser asks for &lt;code&gt;google.com&lt;/code&gt;, DNS translates that human-friendly name into the server's IP address. By acting as your DNS server, AdGuard Home inspects domain requests and instantly drops requests to known advertising, tracker, and phishing domains.&lt;/p&gt;




&lt;h2&gt;
  
  
  Setting Up AdGuard Home &amp;amp; Web Interface
&lt;/h2&gt;

&lt;p&gt;After installation, the setup wizard starts on port &lt;code&gt;3000&lt;/code&gt;. Open your browser and navigate to &lt;code&gt;http://&amp;lt;your-server-ip&amp;gt;:3000&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 1:&lt;/strong&gt; Click &lt;strong&gt;Get Started&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F85ckudm4soczsrgcmst1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F85ckudm4soczsrgcmst1.png" alt="AdGuard Home Get Started page" width="800" height="418"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 2:&lt;/strong&gt; Configure Admin Web Interface &amp;amp; DNS Port.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;By default, the admin web UI listens on port &lt;code&gt;80&lt;/code&gt;. If you already run a web server (like Nginx or Traefik), change the admin port to &lt;code&gt;3000&lt;/code&gt; or &lt;code&gt;8080&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Keep the &lt;strong&gt;DNS server port&lt;/strong&gt; on &lt;code&gt;53&lt;/code&gt; (standard DNS port).&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F3fdnqvb7pwouvqecx1kj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F3fdnqvb7pwouvqecx1kj.png" alt="AdGuard Home network port configuration page" width="800" height="610"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 3:&lt;/strong&gt; Set your admin username and password.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fyeplrb5bq2n848tb0vst.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fyeplrb5bq2n848tb0vst.png" alt="AdGuard Home admin credentials setup" width="800" height="418"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once the wizard completes, log into the dashboard at &lt;code&gt;http://&amp;lt;your-server-ip&amp;gt;:3000&lt;/code&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Best AdGuard Home Blocklists (2026 Recommended)
&lt;/h2&gt;

&lt;p&gt;To add blocklists, go to &lt;strong&gt;Filters → DNS blocklists → Add blocklist → Add a custom list&lt;/strong&gt; in your AdGuard Home dashboard. &lt;/p&gt;

&lt;p&gt;Here is our curated, tested stack of blocklists that provides maximum protection with zero false positives (safe for family use without breaking online banking or streaming):&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Blocklist Name&lt;/th&gt;
&lt;th&gt;Focus Category&lt;/th&gt;
&lt;th&gt;Recommended Source URL&lt;/th&gt;
&lt;th&gt;Best For&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;AdGuard DNS Filter&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Ads &amp;amp; Trackers&lt;/td&gt;
&lt;td&gt;&lt;code&gt;https://adguardteam.github.io/HostlistsRegistry/assets/filter_1.txt&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Core ad blocking&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;OISD Basic / Big&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Universal Ad &amp;amp; Telemetry&lt;/td&gt;
&lt;td&gt;&lt;code&gt;https://big.oisd.nl&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Zero false positives (Family-safe)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Peter Lowe's List&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Ad &amp;amp; Tracking Servers&lt;/td&gt;
&lt;td&gt;&lt;code&gt;https://pgl.yoyo.org/adservers/serverlist.php?hostformat=adblockplus&amp;amp;showintro=0&amp;amp;mimetype=plaintext&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;High performance &amp;amp; lightweight&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Steven Black Unified Hosts&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Malware + Adware&lt;/td&gt;
&lt;td&gt;&lt;code&gt;https://raw.githubusercontent.com/StevenBlack/hosts/master/hosts&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Malicious domain protection&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Phishing URL Blocklist&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Phishing &amp;amp; Scams&lt;/td&gt;
&lt;td&gt;&lt;code&gt;https://adguardteam.github.io/HostlistsRegistry/assets/filter_30.txt&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Security &amp;amp; Anti-Phishing&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;AdGuard Popup Hosts&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Annoying Popups&lt;/td&gt;
&lt;td&gt;&lt;code&gt;https://adguardteam.github.io/HostlistsRegistry/assets/filter_11.txt&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Notification &amp;amp; popup spam&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fp9oxwgbhbagyw1dernnr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fp9oxwgbhbagyw1dernnr.png" alt="AdGuard Home DNS blocklist settings" width="800" height="418"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Recommended DNS Settings &amp;amp; Upstream DNS
&lt;/h2&gt;

&lt;p&gt;To maximize speed and prevent ISP snooping, navigate to &lt;strong&gt;Settings → DNS Settings&lt;/strong&gt; and configure encrypted upstream DNS providers (DoH / DoT):&lt;/p&gt;

&lt;h3&gt;
  
  
  Upstream DNS Servers (Copy &amp;amp; Paste)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://dns.quad9.net/dns-query
https://cloudflare-dns.com/dns-query
https://dns.adguard-dns.com/dns-query
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Optimal DNS Settings:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Upstream mode:&lt;/strong&gt; &lt;em&gt;Parallel requests&lt;/em&gt; (queries all upstream servers concurrently and uses the fastest response).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;DNS cache size:&lt;/strong&gt; &lt;code&gt;67108864&lt;/code&gt; (64 MB cache for instant sub-millisecond local responses).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Optimistic caching:&lt;/strong&gt; Enable (serves cached responses while refreshing stale entries in background).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Can AdGuard Home Block YouTube Ads in 2026? (The Truth &amp;amp; Workarounds)
&lt;/h2&gt;

&lt;p&gt;One of the most frequent questions homelabbers ask is: &lt;em&gt;"Can I block YouTube ads network-wide using AdGuard Home?"&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The short answer: No, not via DNS alone.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why?&lt;/strong&gt; Google serves YouTube video advertisements from the exact same content delivery networks (CDNs) and domain names (e.g., &lt;code&gt;*.googlevideo.com&lt;/code&gt;) as the real video you are trying to watch. If AdGuard Home blocks that domain, the YouTube video will simply fail to buffer.&lt;/p&gt;

&lt;h3&gt;
  
  
  Effective Workarounds for YouTube Ads:
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Desktop / Mobile Browser:&lt;/strong&gt; Use &lt;strong&gt;uBlock Origin&lt;/strong&gt; or the &lt;strong&gt;Brave Browser&lt;/strong&gt;, which perform deep cosmetic and request filtering inside the browser DOM.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Android &amp;amp; Android TV:&lt;/strong&gt; Use open-source third-party clients like &lt;strong&gt;SmartTube&lt;/strong&gt; (for Android TV) or &lt;strong&gt;ReVanced&lt;/strong&gt; (for Android smartphones).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Parental Controls on AdGuard:&lt;/strong&gt; While it cannot block YouTube ads, AdGuard Home &lt;em&gt;can&lt;/em&gt; enforce &lt;strong&gt;YouTube SafeSearch&lt;/strong&gt; or schedule full blocking of YouTube during study hours under &lt;strong&gt;Filters → Blocked Services&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Deploying AdGuard Home to All Devices (Router Level)
&lt;/h2&gt;

&lt;p&gt;To protect your entire house without configuring every phone, tablet, and TV individually, set AdGuard Home as your home router's primary DNS server.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Log into your Wi-Fi router's admin panel (typically &lt;code&gt;192.168.1.1&lt;/code&gt; or &lt;code&gt;192.168.0.1&lt;/code&gt;).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Navigate to &lt;strong&gt;DHCP Settings / LAN Settings / DNS&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Set &lt;strong&gt;Primary DNS Server&lt;/strong&gt; to your AdGuard Home IP address (e.g. &lt;code&gt;192.168.1.150&lt;/code&gt;).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Set &lt;strong&gt;Secondary DNS Server&lt;/strong&gt; to your backup DNS or leave blank.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Save and reboot your router.&lt;/p&gt;&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F317zyeg1z6wplg046eih.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F317zyeg1z6wplg046eih.jpg" alt="TP-Link Router DHCP DNS settings example" width="800" height="1566"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once refreshed, every phone, laptop, and smart appliance connecting to your Wi-Fi will automatically query AdGuard Home, blocking ads and tracking seamlessly.&lt;/p&gt;




&lt;h2&gt;
  
  
  Parental Controls &amp;amp; Service Scheduling
&lt;/h2&gt;

&lt;p&gt;AdGuard Home includes built-in service blocking under &lt;strong&gt;Filters → Blocked services&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fl5u1kp5vvbhzbph83idg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fl5u1kp5vvbhzbph83idg.png" alt="Adguard Home block services eg., youtube, tiktok" width="800" height="418"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can toggle one-click restrictions on specific platforms (TikTok, Roblox, Discord, adult domains) or schedule service downtime for bedtime:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F0mx83j7smlyuasxgow69.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F0mx83j7smlyuasxgow69.png" alt="Adguard home schedule service blocking" width="800" height="156"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  💬 Frequently Asked Questions (FAQ)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  What are the best AdGuard Home blocklists to use in 2026?
&lt;/h3&gt;

&lt;p&gt;The ideal blocklist stack includes &lt;strong&gt;AdGuard DNS Filter&lt;/strong&gt; (for general ads), &lt;strong&gt;OISD Basic/Big&lt;/strong&gt; (near-zero false positives, family-friendly), &lt;strong&gt;Steven Black's Unified Hosts&lt;/strong&gt; (malware and adware), and &lt;strong&gt;Peter Lowe's List&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Can AdGuard Home block YouTube ads?
&lt;/h3&gt;

&lt;p&gt;No, DNS blockers cannot block YouTube video ads because the ads and the video streams originate from identical domain names (&lt;code&gt;*.googlevideo.com&lt;/code&gt;). Use browser extensions like &lt;strong&gt;uBlock Origin&lt;/strong&gt; or client apps like &lt;strong&gt;SmartTube&lt;/strong&gt; on Android TV.&lt;/p&gt;

&lt;h3&gt;
  
  
  What are the best upstream DNS servers for AdGuard Home?
&lt;/h3&gt;

&lt;p&gt;Use encrypted DNS-over-HTTPS (DoH) providers such as &lt;strong&gt;Quad9&lt;/strong&gt; (&lt;code&gt;https://dns.quad9.net/dns-query&lt;/code&gt;) for malware filtering and &lt;strong&gt;Cloudflare&lt;/strong&gt; (&lt;code&gt;https://cloudflare-dns.com/dns-query&lt;/code&gt;) for speed.&lt;/p&gt;

&lt;h3&gt;
  
  
  Does AdGuard Home slow down internet connection speeds?
&lt;/h3&gt;

&lt;p&gt;No. In fact, AdGuard Home accelerates browsing by caching frequent DNS queries locally and blocking heavy tracking scripts and media ads from ever downloading.&lt;/p&gt;




&lt;h2&gt;
  
  
  Related Homelab &amp;amp; Self-Hosting Guides
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://nkaushik.in/writing/securing-your-homelab-with-crowdsec-traefik-and-docker" rel="noopener noreferrer"&gt;Securing My Homelab: Integrating CrowdSec, Traefik, and Ntfy in Docker&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://nkaushik.in/writing/monitoring-homelab-with-beszel-and-dozzle" rel="noopener noreferrer"&gt;How to Monitor Your Homelab with Beszel and Dozzle&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://nkaushik.in/writing/replace-google-photos-self-host-immich-in-2026" rel="noopener noreferrer"&gt;Replace Google Photos: Self-Host Immich in 2026&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://nkaushik.in/writing/getting-started-with-self-hosting-in-2026" rel="noopener noreferrer"&gt;Getting Started with Self-Hosting in 2026&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://nkaushik.in/writing/adguard-home-for-families-how-to-stop-ads-and-trackers-without-installing-extensions" rel="noopener noreferrer"&gt;nkaushik.in&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>adblock</category>
      <category>adguard</category>
      <category>adguardhome</category>
      <category>ads</category>
    </item>
    <item>
      <title>Top 4 ways to Run LLM locally on Android and iOS</title>
      <dc:creator>Nishchay</dc:creator>
      <pubDate>Tue, 06 Oct 2026 16:29:29 +0000</pubDate>
      <link>https://dev.to/kaushiknishchay/top-4-ways-to-run-llm-locally-on-android-and-ios-539c</link>
      <guid>https://dev.to/kaushiknishchay/top-4-ways-to-run-llm-locally-on-android-and-ios-539c</guid>
      <description>&lt;p&gt;In my previous blog, I explored the technical rabbit hole of running Llama.cpp in Termux on an old Android phone. While that was a rewarding experiment, let's be honest: it wasn't exactly "plug-and-play" for most people.&lt;/p&gt;

&lt;p&gt;But it's 2026, and the game has changed. You no longer need to be a Linux wizard to have a private, powerful AI in your pocket. In this guide, I'm covering the &lt;strong&gt;Top 4 ways&lt;/strong&gt; you can run LLMs locally on your Android or iOS device—completely for free, with &lt;strong&gt;unlimited requests&lt;/strong&gt;, and &lt;strong&gt;zero data leaving your phone&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Quick Comparison Matrix (2026 Tested)
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;App / Method&lt;/th&gt;
&lt;th&gt;Best For&lt;/th&gt;
&lt;th&gt;Platform&lt;/th&gt;
&lt;th&gt;RAM Required&lt;/th&gt;
&lt;th&gt;Supported Formats&lt;/th&gt;
&lt;th&gt;Offline Mode&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Google Edge Gallery&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;One-click setup &amp;amp; NPU speed&lt;/td&gt;
&lt;td&gt;Android / iOS&lt;/td&gt;
&lt;td&gt;2GB - 4GB&lt;/td&gt;
&lt;td&gt;LiteRT / Gemma 4 / Gemma 3&lt;/td&gt;
&lt;td&gt;✅ 100% Offline&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;PocketPal AI&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Daily chat &amp;amp; Uncensored models&lt;/td&gt;
&lt;td&gt;Android / iOS&lt;/td&gt;
&lt;td&gt;4GB - 8GB&lt;/td&gt;
&lt;td&gt;GGUF (llama.cpp)&lt;/td&gt;
&lt;td&gt;✅ 100% Offline&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;AnythingLLM&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;PDF &amp;amp; Document RAG&lt;/td&gt;
&lt;td&gt;Android / iOS&lt;/td&gt;
&lt;td&gt;6GB - 12GB&lt;/td&gt;
&lt;td&gt;GGUF / Ollama API / Cloud&lt;/td&gt;
&lt;td&gt;✅ 100% Offline&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Termux + Ollama&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Power users &amp;amp; CLI automation&lt;/td&gt;
&lt;td&gt;Android&lt;/td&gt;
&lt;td&gt;4GB - 8GB&lt;/td&gt;
&lt;td&gt;Ollama Library / GGUF&lt;/td&gt;
&lt;td&gt;✅ 100% Offline&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  1. Google AI Edge Gallery: The "One-Click" Starter
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/google-ai-edge/gallery" rel="noopener noreferrer"&gt;https://github.com/google-ai-edge/gallery&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Google's official showcase is the perfect starting point. It's the easiest way to see what your phone is actually capable of. It's optimized for mobile NPUs, meaning it's fast and efficient for tasks like tone refinement, audio transcription, and image understanding.&lt;/p&gt;

&lt;p&gt;The latest version now supports &lt;strong&gt;Gemma 4&lt;/strong&gt; and &lt;strong&gt;Gemma 3&lt;/strong&gt;, models specifically "distilled" to run on mobile hardware without eating up your RAM. For a dedicated deep-dive on setting up Gemma 4 with Edge Gallery, check out my &lt;a href="https://nkaushik.in/writing/running-gemma-4-locally-on-ios-android-ai-edge-gallery" rel="noopener noreferrer"&gt;Running Gemma 4 Locally on iOS &amp;amp; Android Guide&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The "Skills" Update:&lt;/strong&gt; One of the coolest additions is support for &lt;strong&gt;SKILLS&lt;/strong&gt;. You can now extend what the AI can do by pulling from a vast library at &lt;a href="https://skills.sh/" rel="noopener noreferrer"&gt;skills.sh&lt;/a&gt;. My personal favorite is the &lt;a href="https://skills.sh/blader/humanizer/humanizer" rel="noopener noreferrer"&gt;Humanizer&lt;/a&gt; skill—it's great for making AI-generated text sound more, well, human.&lt;/p&gt;

&lt;h3&gt;
  
  
  Demo
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://youtube.com/shorts/1H6z2-K7gvw" rel="noopener noreferrer"&gt;https://youtube.com/shorts/1H6z2-K7gvw&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Models Available
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Gemma 4 E2B and E4B&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Gemma 3 1B&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Gemma 3n E2B and E4B&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;DeepSeek R1 Distill Qwen 1.5B&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Qwen 2.5 1.5B&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;LiteRT distilled models&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%2Fcdn.hashnode.com%2Fuploads%2Fcovers%2F6984dc9e559eb2d777b15a66%2F1043f69c-870f-4a48-84fc-405b37014bdc.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%2Fcdn.hashnode.com%2Fuploads%2Fcovers%2F6984dc9e559eb2d777b15a66%2F1043f69c-870f-4a48-84fc-405b37014bdc.png" alt="List of models available in google edge gallery app" width="800" height="4476"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Bundling your own model
&lt;/h4&gt;

&lt;p&gt;If you're feeling adventurous, you can even bundle your own models by following the &lt;a href="https://huggingface.co/litert-community" rel="noopener noreferrer"&gt;LiteRT community guide&lt;/a&gt;. It walks you through converting models from Pytorch or other formats.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. PocketPal AI (Best for General Chat &amp;amp; Uncensored Models)
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/a-ghorbani/pocketpal-ai" rel="noopener noreferrer"&gt;PocketPal AI&lt;/a&gt; is the one I keep coming back to. It's built on &lt;strong&gt;llama.cpp&lt;/strong&gt; (the industry standard), but the interface is actually designed for a human using a phone, not a developer staring at a terminal.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;'Pals' feature&lt;/strong&gt; is the standout here. Instead of one messy chat thread, you can set up different "Pals" with their own system prompts. I have one for coding and another for creative writing. It also handles the latest architectures like &lt;strong&gt;Qwen 3.5&lt;/strong&gt; and &lt;strong&gt;LFM 2.5&lt;/strong&gt;, which are incredibly fast on mobile.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why it works for me:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Easy Model Setup:&lt;/strong&gt; You can download GGUF models directly within the app. For a smooth experience, I recommend any GGUF model (try &lt;strong&gt;Unsloth's&lt;/strong&gt; uploads) with &lt;strong&gt;Q4_K_M quantization&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;100% Private:&lt;/strong&gt; Once the model is on your phone, you can go into Airplane Mode and the AI won't even notice.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Live Stats:&lt;/strong&gt; It shows you tokens per second in real-time. It's satisfying to see your phone's hardware in action.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Running Uncensored Local LLMs on Android with PocketPal
&lt;/h3&gt;

&lt;p&gt;If you need a local model without restrictive alignment filters for creative writing or raw coding analysis, PocketPal AI makes loading uncensored GGUFs simple:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Open PocketPal AI → Navigate to the &lt;strong&gt;Models&lt;/strong&gt; tab.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Tap &lt;strong&gt;Add Custom Model (Hugging Face URL)&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Paste a direct GGUF link for an uncensored model (such as &lt;code&gt;Dolphin-2.9.4-Llama3.1-8B-GGUF&lt;/code&gt; in &lt;code&gt;Q4_K_M&lt;/code&gt; quantization or &lt;code&gt;Qwen2.5-1.5B-Instruct-GGUF&lt;/code&gt;).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;PocketPal downloads the GGUF weights directly to internal storage and runs them completely sandboxed with 0 guardrails.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  3. AnythingLLM: The Researcher's Workspace
&lt;/h2&gt;

&lt;p&gt;If you need your AI to actually &lt;em&gt;do&lt;/em&gt; something with your files, &lt;a href="https://anythingllm.com/mobile" rel="noopener noreferrer"&gt;AnythingLLM&lt;/a&gt; is a different beast. It's less of a chatbot and more of a portable workspace.&lt;/p&gt;

&lt;p&gt;The killer feature is &lt;strong&gt;On-Device RAG&lt;/strong&gt;. You can feed it a PDF or text file sitting on your phone, and the AI will answer questions based &lt;strong&gt;only&lt;/strong&gt; on that document. I've used this to summarize 50-page technical docs during flights with zero internet.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What sets it apart:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Chat with your docs:&lt;/strong&gt; Local indexing means your data never touches a server.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Tools &amp;amp; Agents:&lt;/strong&gt; It supports web scraping, calendar editing, and the &lt;strong&gt;Model Context Protocol (MCP)&lt;/strong&gt;, so it's slowly becoming a true mobile agent.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;The "Infinite Power" Trick:&lt;/strong&gt; If your phone is struggling, you can connect it to a massive 70B model running on your home PC via API and use your phone as a remote window into that power.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  4. Termux + Ollama: The Power User Shortcut
&lt;/h2&gt;

&lt;p&gt;This is for my Android users who miss the command line. We're using &lt;a href="https://termux.dev/" rel="noopener noreferrer"&gt;Termux&lt;/a&gt; to run &lt;a href="https://ollama.com/" rel="noopener noreferrer"&gt;Ollama&lt;/a&gt; directly on the device. It's the closest you'll get to a desktop experience on a mobile screen.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Quick Setup:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Install Termux (use the version from F-Droid, not the Play Store).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Run &lt;code&gt;pkg install ollama&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Type &lt;code&gt;ollama run qwen2.5:0.5b&lt;/code&gt; or &lt;code&gt;ollama run qwen3.5:0.8b&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;For the full setup guide, check out my companion tutorials:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://nkaushik.in/writing/install-ollama-in-termux-android-2026-guide" rel="noopener noreferrer"&gt;How to Install and Run Ollama in Termux on Android (2026 Guide)&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://nkaushik.in/writing/how-to-install-llamacpp-windows-mac-linux-termux" rel="noopener noreferrer"&gt;How to Install llama.cpp on Windows, Mac, Linux, and Termux (2026)&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://nkaushik.in/writing/running-24-7-local-ai-on-an-old-android-without-overheating" rel="noopener noreferrer"&gt;Running 24/7 Local AI on an Old Android without Overheating&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;p&gt;That's it. Ollama will auto-download the model and drop you into a CLI chat. You can run pretty much anything from the &lt;a href="https://ollama.com/search" rel="noopener noreferrer"&gt;Ollama Library&lt;/a&gt; as long as your RAM can handle it. It's the fastest way to test new models the second they drop.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary: Which one should you pick?
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Method&lt;/th&gt;
&lt;th&gt;Best For&lt;/th&gt;
&lt;th&gt;RAM &amp;amp; Hardware Specs&lt;/th&gt;
&lt;th&gt;Supported Models &amp;amp; Classes&lt;/th&gt;
&lt;th&gt;Ease of Use&lt;/th&gt;
&lt;th&gt;Customization&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Google Edge Gallery&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Beginners &amp;amp; NPU Acceleration&lt;/td&gt;
&lt;td&gt;2GB - 4GB RAM (Tensor / Snapdragon NPUs like Pixel 8/9, Galaxy S24)&lt;/td&gt;
&lt;td&gt;Gemma 3 1B/4B, Gemma 4, LiteRT distilled models&lt;/td&gt;
&lt;td&gt;⭐⭐⭐⭐⭐&lt;/td&gt;
&lt;td&gt;⭐⭐&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;PocketPal AI&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Daily Chats &amp;amp; Uncensored Models&lt;/td&gt;
&lt;td&gt;4GB - 8GB RAM (OnePlus 11/12, Galaxy S23/S24, iPhone 15/16)&lt;/td&gt;
&lt;td&gt;Qwen 3.5, LFM 2.5, Llama 3.2 (1B/3B GGUF)&lt;/td&gt;
&lt;td&gt;⭐⭐⭐⭐&lt;/td&gt;
&lt;td&gt;⭐⭐⭐⭐&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;AnythingLLM&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Document RAG &amp;amp; Local Workspaces&lt;/td&gt;
&lt;td&gt;6GB - 12GB RAM (Galaxy S24 Ultra, iPhone 16 Pro Max)&lt;/td&gt;
&lt;td&gt;Custom Local GGUF, Ollama endpoints, Cloud APIs&lt;/td&gt;
&lt;td&gt;⭐⭐⭐&lt;/td&gt;
&lt;td&gt;⭐⭐⭐⭐⭐&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Termux + Ollama&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Developers &amp;amp; Command Line Users&lt;/td&gt;
&lt;td&gt;4GB - 8GB RAM (64-bit ARM devices on Android 10+)&lt;/td&gt;
&lt;td&gt;Qwen 2.5/3.5 (0.8B/1.5B), Llama 3.2 1B/3B&lt;/td&gt;
&lt;td&gt;⭐&lt;/td&gt;
&lt;td&gt;⭐⭐⭐⭐&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Related Local AI Guides
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://nkaushik.in/writing/install-ollama-in-termux-android-2026-guide" rel="noopener noreferrer"&gt;How to Install and Run Ollama in Termux on Android (2026 Guide)&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://nkaushik.in/writing/how-to-install-llamacpp-windows-mac-linux-termux" rel="noopener noreferrer"&gt;How to Install llama.cpp on Windows, Mac, Linux, and Termux (2026)&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://nkaushik.in/writing/running-gemma-4-locally-on-ios-android-ai-edge-gallery" rel="noopener noreferrer"&gt;Running Gemma 4 Locally on iOS and Android: The Google AI Edge Gallery Guide&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://nkaushik.in/writing/running-24-7-local-ai-on-an-old-android-without-overheating" rel="noopener noreferrer"&gt;Running 24/7 Local AI on an Old Android without Overheating&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://nkaushik.in/writing/how-to-run-llm-models-on-old-android-devices-locally" rel="noopener noreferrer"&gt;How to Run LLM Models on Old Android Devices Locally&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Happy (Local) Chatting!&lt;/strong&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://nkaushik.in/posts/top-4-ways-to-run-llm-locally-on-android-and-ios" rel="noopener noreferrer"&gt;nkaushik.in&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>android</category>
      <category>localllm</category>
      <category>gemma4</category>
    </item>
    <item>
      <title>Building Web ScreenShare using WebRTC</title>
      <dc:creator>Nishchay</dc:creator>
      <pubDate>Tue, 06 Oct 2026 16:15:30 +0000</pubDate>
      <link>https://dev.to/kaushiknishchay/building-web-screenshare-using-webrtc-1e3g</link>
      <guid>https://dev.to/kaushiknishchay/building-web-screenshare-using-webrtc-1e3g</guid>
      <description>&lt;p&gt;The web is a very powerful platform it grants you the ability to share something with everyone irrespective of what device they are using, be it an Android or iOS phone or a Windows, Linux, or Mac laptop.&lt;/p&gt;

&lt;p&gt;With time the things, a browser could do have also increased greatly (except IE11, switch to Firefox already). A webpage is no longer about some text and images, you can add a lot more power-hungry features to your webpage. You can create Games, Build Services like Google Docs, Browser Stack, and a lot more all running on a browser.&lt;/p&gt;

&lt;p&gt;This post is going to talk about one of the browser’s features I had a chance to work with and the tech I explored for integrating it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Problem Statement
&lt;/h3&gt;

&lt;p&gt;The problem statement I had in front of me was to implement a screen-share feature where-in when a User is sharing the screen it would be possible for others to view it over the internet as a real-time video.&lt;/p&gt;

&lt;p&gt;The first step was to break down this problem into smaller problems and build a prototype around it.  &lt;/p&gt;

&lt;p&gt;As I saw it, the problem had two pieces, first figuring out how to capture the screen, second, how to send it across to other users as a live video feed.  &lt;/p&gt;

&lt;p&gt;I’ll start with the Screen-share bit first.&lt;/p&gt;

&lt;h3&gt;
  
  
  Screen-share/Record
&lt;/h3&gt;

&lt;p&gt;I knew websites already do it (you would’ve seen it in action on Zoom or Google Meet) but wasn’t aware How easy it is to do it on our own.&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;promise&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;navigator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;mediaDevices&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getDisplayMedia&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;constraints&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above line is all it takes to get started with screen-sharing. It is supported by all the latest browsers and you can read more on its support at &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getDisplayMedia" rel="noopener noreferrer"&gt;https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getDisplayMedia&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When you run the above code snippet you will get a &lt;code&gt;Promise&amp;lt;MediaStream&amp;gt;&lt;/code&gt;, now it is up-to us to decide how we want to use this.&lt;/p&gt;

&lt;p&gt;We can either share it with other people using WebRTC (more on it later) or even record it and download the video.&lt;/p&gt;

&lt;p&gt;Example snippet to download the recorded video (taken from &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/MediaStream_Recording_API" rel="noopener noreferrer"&gt;https://developer.mozilla.org/en-US/docs/Web/API/MediaStream_Recording_API&lt;/a&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;promise&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;stream&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;var&lt;/span&gt; &lt;span class="nx"&gt;recordedChunks&lt;/span&gt; &lt;span class="o"&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;stream&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="kd"&gt;var&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;mimeType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;video/webm; codecs=vp8&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="nx"&gt;mediaRecorder&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;MediaRecorder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;stream&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="nx"&gt;mediaRecorder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ondataavailable&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;handleDataAvailable&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;mediaRecorder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;start&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;handleDataAvailable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;data-available&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="nx"&gt;event&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;size&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;recordedChunks&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;event&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;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;recordedChunks&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="nf"&gt;download&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&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;function&lt;/span&gt; &lt;span class="nf"&gt;download&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;blob&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;Blob&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;recordedChunks&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;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;video/webm&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;
        &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;url&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="nf"&gt;createObjectURL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;blob&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;a&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;createElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;a&lt;/span&gt;&lt;span class="dl"&gt;"&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="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;appendChild&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;display: none&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nx"&gt;a&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="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;download&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;test.webm&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;click&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;URL&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;revokeObjectURL&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="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// demo: to download after 9sec&lt;/span&gt;
    &lt;span class="nf"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;stopping&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="nx"&gt;mediaRecorder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stop&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="mi"&gt;9000&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;One thing to note about the above &lt;code&gt;getDisplayMedia&lt;/code&gt; API is it behaves differently on browsers. For example, Chrome lets you share between a single tab/window/desktop, Firefox shares the whole window and Safari shares the entire desktop.&lt;/p&gt;

&lt;p&gt;A limitation this API has is, it won’t let you share only a part of your webpage.&lt;/p&gt;

&lt;p&gt;Now that we have solved half of the problem, let’s get to the second part.&lt;/p&gt;

&lt;h3&gt;
  
  
  WebRTC
&lt;/h3&gt;

&lt;p&gt;If you haven’t heard about it, don’t worry, I will add resources for you to read. It is an interesting topic so you should give it a try.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;WebRTC&lt;/strong&gt; (Web Real-Time Communication) is a technology that enables Web applications and sites to capture and optionally stream audio and/or video media, as well as to exchange arbitrary data between browsers without requiring an intermediary.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The above definition is taken from MDN docs which captures the gist of what WebRTC is (&lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/WebRTC_API" rel="noopener noreferrer"&gt;https://developer.mozilla.org/en-US/docs/Web/API/WebRTC_API&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;WebRTC is a very detailed topic and it won’t be easy to cover all that it provides in this article. I’d highly recommend going through this video on YouTube.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=p2HzZkd2A40" rel="noopener noreferrer"&gt;https://www.youtube.com/watch?v=p2HzZkd2A4&lt;/a&gt;0&lt;/p&gt;

&lt;p&gt;Based on the above video, we derive two important steps, we need to acquire a video/audio stream and then use WebRTC to communicate it with peers.&lt;/p&gt;

&lt;p&gt;This video stream that we share can either be a stream from your webcam or any MediaStream from other sources.&lt;/p&gt;

&lt;p&gt;If you recall, the screen-share stream we acquired is also a MediaStream which can be used with WebRTC.&lt;/p&gt;

&lt;p&gt;So once we have set-up our WebRTC connection we can simply publish this Screen-share stream on it and make it available to peers in real-time.&lt;/p&gt;

&lt;p&gt;Implementing WebRTC from scratch using the basic API can be a tedious task, there are various libraries and frameworks available for use. These libraries hides away the software complexity, but to ensure WebRTC works for 100% of the users you would also need to setup a server of your own.&lt;/p&gt;

&lt;p&gt;PeerJS (&lt;a href="https://peerjs.com/" rel="noopener noreferrer"&gt;https://peerjs.com&lt;/a&gt;) is one such example, which makes it easier for you to get started.&lt;/p&gt;

&lt;p&gt;Various companies provide you with the infrastructure and SDK needed to get started with real-time video, for example, Twilio. This takes away both the software and hardware complexity and makes it easier for you to implement and support a wide variety of users and devices.&lt;/p&gt;

&lt;p&gt;In my case, we were already utilizing Twilio for the video call feature and it also let us publish more MediaStream if needed for a user.&lt;/p&gt;

&lt;p&gt;This made sharing screen-share with other users a breeze, as all it required was to acquire the screen-share stream and then publish it on the connection for a user.&lt;/p&gt;

&lt;p&gt;Twilio also has a sample app that you can refer to for understanding how to do the above.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/twilio/twilio-video-app-react" rel="noopener noreferrer"&gt;https://github.com/twilio/twilio-video-app-react&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;This was just one example of what can be achieved using these 2 pieces of technologies: WebRTC &amp;amp; getDisplayMedia.&lt;/p&gt;

&lt;p&gt;The possibilities are limitless.&lt;/p&gt;

&lt;p&gt;For example, You can make a piece of software which records your webcam as well as your screen to make a coding tutorial with few lines of code right from your browser.&lt;/p&gt;

&lt;p&gt;A small experiment I did was to find a way to only share a part of webpage. For this I wrapped the area which I wanted to share with a distinctive color border and on other users before showing the video stream I simply used image processing to crop the pieces outside of the border. This isn’t a very great solution and is extremely memory intensive to do it in JavaScript so I won’t recommend it.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Special shout-out to &lt;a href="https://medium.com/u/372f5561ad9b" rel="noopener noreferrer"&gt;Punit Gupta&lt;/a&gt; for helping me with this article.&lt;/p&gt;

&lt;p&gt;Thanks for reading.  &lt;/p&gt;

&lt;p&gt;Do share your thoughts and suggestions.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://nkaushik.in/writing/exploring-the-power-of-web-browsers-in-2020" rel="noopener noreferrer"&gt;nkaushik.in&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>react</category>
      <category>streaming</category>
      <category>webrtc</category>
    </item>
    <item>
      <title>Hello World!</title>
      <dc:creator>Nishchay</dc:creator>
      <pubDate>Tue, 06 Oct 2026 15:50:21 +0000</pubDate>
      <link>https://dev.to/kaushiknishchay/hello-world-d4c</link>
      <guid>https://dev.to/kaushiknishchay/hello-world-d4c</guid>
      <description>&lt;p&gt;Hi there👋, I’m Nishchay, an Engineer, I am currently exploring the world of AI and Self Hosting. This is my space to share my thoughts with you.&lt;/p&gt;

&lt;p&gt;I have over ten years of experience in the software industry, where I have worked with various organizations in both B2C and B2B sectors.&lt;/p&gt;

&lt;p&gt;Over the years, I have worked with many technologies and tools that fascinated me. I began my journey with PHP and have since built Native Android Apps and React Native Apps. I've also had the chance to work with Ruby on Rails, Golang, and Python. Additionally, I have hands-on experience in maintaining services and infrastructure on both Google Cloud (GCP) and AWS, as well as with Kubernetes (k8s).&lt;/p&gt;

&lt;p&gt;I currently work in the JavaScript/TypeScript ecosystem, specializing in React.JS &amp;amp; Node.js.&lt;/p&gt;

&lt;p&gt;I possess extensive expertise in the frontend domain, which I recently leveraged to build a comprehensive Performance Testing platform from the ground up. This project encompassed not only the frontend but also the backend and the data engineering aspects. I undertook this ambitious endeavor with a very small team, yet we successfully implemented the entire platform. It is now widely used throughout the organization and serves as a crucial guardrail for performance-related checks across the entire company. The platform's integration has significantly enhanced our ability to monitor and optimize performance, ensuring that all our systems operate efficiently and effectively. This achievement has not only streamlined our processes but also reinforced the importance of performance testing within our organizational framework.&lt;/p&gt;

&lt;p&gt;I enjoy building things and trying out new ideas. I've been working to keep up with the rapid advancements in the Generative AI space.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://nkaushik.in/posts/hello-world" rel="noopener noreferrer"&gt;nkaushik.in&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>generativeai</category>
      <category>helloworld</category>
      <category>javascript</category>
      <category>programmingblogs</category>
    </item>
  </channel>
</rss>
