<?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: Love Otudor</title>
    <description>The latest articles on DEV Community by Love Otudor (@loveotudor).</description>
    <link>https://dev.to/loveotudor</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2892962%2F35aad0e7-7f68-4d57-aab9-314834591403.jpg</url>
      <title>DEV Community: Love Otudor</title>
      <link>https://dev.to/loveotudor</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/loveotudor"/>
    <language>en</language>
    <item>
      <title>Build a Web App with MongoDB Using Just Python</title>
      <dc:creator>Love Otudor</dc:creator>
      <pubDate>Tue, 13 Jan 2026 16:37:03 +0000</pubDate>
      <link>https://dev.to/anvil/build-a-web-app-with-mongodb-using-just-python-321a</link>
      <guid>https://dev.to/anvil/build-a-web-app-with-mongodb-using-just-python-321a</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Build and deploy a full-stack web app that interacts with your external database using only Python. No HTML, CSS, or JavaScript required.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/OX5L_8hH7xM"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;In this tutorial, we guide you step-by-step on how to create a &lt;strong&gt;Customer Relationship Management (CRM) system&lt;/strong&gt; connected to a &lt;strong&gt;MongoDB Atlas cluster&lt;/strong&gt;, starting completely from scratch. You'll see how to build both the frontend and backend in Python using Anvil and deploy it to the web with &lt;strong&gt;two clicks&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://anvil.works/build#clone:UJ3PW3CWLBQVGO6Q%3d3WYYRMWKPSTUZJV2NSW7ACBK?utm_source=crosspost:dev.to:/blog/crm-with-mongodb"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpkvbvqp0y0tdl5jyjcic.png" alt="Open in Anvil" width="461" height="140"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://anvil.works/?utm_source=crosspost:dev.to:/blog/crm-with-mongodb"&gt;&lt;strong&gt;Anvil&lt;/strong&gt;&lt;/a&gt; lets you build full-stack web apps with all the power of Python and the flexibility of code.&lt;/p&gt;

&lt;p&gt;In this tutorial, we will cover:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Installing Python packages in your Server Module&lt;/li&gt;
&lt;li&gt;Securing passwords with App Secrets&lt;/li&gt;
&lt;li&gt;Communicating between Forms with custom events&lt;/li&gt;
&lt;li&gt;Authentication with the Users Service&lt;/li&gt;
&lt;li&gt;Deploying your app on Anvil's free hosting&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  More about Anvil
&lt;/h2&gt;

&lt;p&gt;If you're new here, welcome! &lt;a href="https://anvil.works/?utm_source=crosspost:dev.to:/blog/crm-with-mongodb"&gt;Anvil&lt;/a&gt; is a platform for building full-stack web apps with nothing but Python. No need to wrestle with JS, HTML, CSS, Python, SQL and all their frameworks – just &lt;strong&gt;build it all in Python&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://anvil.works/build?utm_source=crosspost:dev.to:/blog/crm-with-mongodb"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz95af95e963brxl2o9zt.png" alt="Sign up for Anvil" width="800" height="191"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>python</category>
      <category>anvil</category>
      <category>webdev</category>
      <category>mongodb</category>
    </item>
    <item>
      <title>Case Study: How Chris Houston Built a BI Tool with Anvil</title>
      <dc:creator>Love Otudor</dc:creator>
      <pubDate>Fri, 11 Jul 2025 14:45:28 +0000</pubDate>
      <link>https://dev.to/anvil/case-study-how-chris-houston-built-a-bi-tool-with-anvil-4l7n</link>
      <guid>https://dev.to/anvil/case-study-how-chris-houston-built-a-bi-tool-with-anvil-4l7n</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Query Streams transforms Excel and Google Sheets into powerful BI tools by enabling real-time database queries directly within the spreadsheet—no coding required. Built as a nights-and-weekends side project by Chris using Anvil, Query Streams soft launched just four weeks ago and is already being used by data analysts across multiple companies.&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;em&gt;Built by a solo developer&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Production-ready in under 5 months&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Google Sheets add-on is live&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Microsoft Excel add-in is live&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  The Challenge: When BI Tools Meet Reality
&lt;/h2&gt;

&lt;p&gt;Every data team knows the cycle: Companies invest heavily in BI tools because everyone loves beautiful dashboards. Yet somehow, the most common follow-up question is still:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;"The dashboards look great… uh, how do I export this to a spreadsheet?"&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;And then it all ends up in a spreadsheet anyway. Despite years of trying to move away from Excel and Google Sheets, spreadsheets are more popular than ever. According to a 2025 survey by &lt;a href="https://www.alteryx.com/about-us/newsroom/press-release/new-research-reveals-that-ai-brings-productivity-gains-but-reliance-on-spreadsheets-puts-data-quality-at-risk" rel="noopener noreferrer"&gt;Alteryx&lt;/a&gt;, &lt;strong&gt;76% of data analysts still use spreadsheets as their primary tool&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  What If We Stopped Fighting Spreadsheets?
&lt;/h3&gt;

&lt;p&gt;Chris had been thinking about this for years. What if, instead of replacing spreadsheets, we empowered them?&lt;br&gt;
&lt;em&gt;“What if we didn’t try to replace spreadsheets with BI tools? What if we made spreadsheets the BI tool?”&lt;/em&gt;&lt;br&gt;
This idea stuck with him until just after Thanksgiving 2024, when he started building a solution.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Solution: Turn Spreadsheets Into the BI Tool
&lt;/h2&gt;

&lt;p&gt;Query Streams is a real-time data integration platform that lets users run SQL queries from Google Sheets and Excel directly against remote databases, without exposing credentials, setting up VPNs, or configuring firewalls. It supports SQL Server, MySQL, PostgreSQL, SQLite, Access, and other databases. You can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Share and receive queries&lt;/li&gt;
&lt;li&gt;Build live dashboards&lt;/li&gt;
&lt;li&gt;Securely expose specific database queries&lt;/li&gt;
&lt;li&gt;Choose what data to share and with whom&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqxj7yb3ru10rddalwv9f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqxj7yb3ru10rddalwv9f.png" alt="Query Streams Image" width="800" height="389"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;No hassle. No copy-pasting. No manual exports. Just real-time data, right where analysts already work.&lt;/p&gt;

&lt;h2&gt;
  
  
  Building Query Streams: Smarter Tools, Built Faster with Anvil
&lt;/h2&gt;

&lt;p&gt;The most challenging part of building Query Streams was building the network agent in C# and other technologies that Chris wasn’t familiar with. Once he overcame that technical hurdle, building the web app in Anvil was straightforward.&lt;/p&gt;

&lt;p&gt;With minimal experience in HTML, CSS, and JavaScript, Chris leaned heavily on &lt;a href="https://anvil.works/docs/ui/custom-components/html-components?utm_source=crosspost:dev.to:/case-studies/querystreams"&gt;Anvil’s custom HTML support &lt;/a&gt; and Anvil components to bring his unique UI ideas to life.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I thought we were locked into the Anvil components on the designer. But as I explored custom components in Anvil, I realised that, wow, you can build anything in Anvil.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/chris_houston_7d34a375ece"&gt;&lt;strong&gt;Chris Houston&lt;/strong&gt;&lt;/a&gt; — &lt;em&gt;Founder and CEO, Query Streams&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In just four months, Query Streams was ready to use. Built entirely in Chris's spare time while working a full-time job. Since Anvil is web-based, he could work on Query Streams wherever and whenever he had time—whether at home, in early mornings, or even while travelling with just his laptop.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Results: From Idea to Impact
&lt;/h2&gt;

&lt;p&gt;Query Streams has begun gaining traction even before its official launch. In the four weeks since its soft launch with the Google Sheets add-on, teams and analysts across several organisations have started using the platform.&lt;/p&gt;

&lt;p&gt;Now, with the Excel add-in also live on the Microsoft AppSource marketplace, Query Streams has expanded its reach to both major spreadsheet platforms. With both add-ons available, Chris is preparing for the official launch and broader publicity efforts. You can follow along and get updates on &lt;a href="https://x.com/querystreams" rel="noopener noreferrer"&gt;X&lt;/a&gt; and &lt;a href="https://www.linkedin.com/company/querystreams/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Anvil is like a Swiss army knife of awesome! It allowed me to build Query Streams with a lot of ease while working alone.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/chris_houston_7d34a375ece"&gt;&lt;strong&gt;Chris Houston&lt;/strong&gt;&lt;/a&gt; — &lt;em&gt;Founder and CEO, Query Streams&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

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

&lt;h2&gt;
  
  
  More Information
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Query Streams&lt;/strong&gt; lets you run real-time database queries directly from Excel or Google Sheets — no code required.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.querystreams.com/" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fle7jxf944svyjd9kxnba.png" alt=" " width="608" height="140"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you’re new to &lt;strong&gt;Anvil&lt;/strong&gt; and want to see how you can build powerful web apps using just Python, up to 7× faster than traditional development:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://anvil.works?utm_source=crosspost:dev.to:/case-studies/querystreams"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flywzy5mdmou1v27k104o.png" alt=" " width="608" height="140"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Have questions or want to get in touch? Visit &lt;a href="https://anvil.works/contact?utm_source=crosspost:dev.to:/case-studies/querystreams"&gt;anvil.works/contact&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>businessintelligence</category>
      <category>webdev</category>
      <category>python</category>
      <category>startup</category>
    </item>
    <item>
      <title>Secure Team Collaboration in Anvil</title>
      <dc:creator>Love Otudor</dc:creator>
      <pubDate>Fri, 30 May 2025 14:48:49 +0000</pubDate>
      <link>https://dev.to/anvil/secure-team-collaboration-in-anvil-3680</link>
      <guid>https://dev.to/anvil/secure-team-collaboration-in-anvil-3680</guid>
      <description>&lt;p&gt;You asked and we answered! We put together a practical how-to guide on collaborating as a team in Anvil. Building amazing Anvil apps is even better with your team by your side, and we've developed foolproof methods to make this process hassle-free.&lt;/p&gt;

&lt;p&gt;This guide walks you through how to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Set up secure, real-world workflows for collaborating on Anvil apps while keeping your production environment isolated and safe.&lt;/li&gt;
&lt;li&gt;Separate development and production environments to ensure only well-tested and reviewed changes reach your users.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Whether your team prefers working together on a shared Anvil app or on individual ones, this step-by-step guide will help you implement Git-based workflows that improve code quality and team efficiency.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://anvil.works/docs/how-to/collaborate-in-anvil?utm_source=crosspost:devto:/blog/secure-team-collaboration" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwrc91ohsy7sslyw2vqwz.png" alt="Check out the full guide here" width="379" height="86"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  More about Anvil
&lt;/h2&gt;

&lt;p&gt;If you're new here, welcome! &lt;a href="https://anvil.works?utm_source=crosspost:devto:/blog/secure-team-collaboration" rel="noopener noreferrer"&gt;Anvil&lt;/a&gt; is a platform for building full-stack web apps with nothing but Python. No need to wrestle with JS, HTML, CSS, Python, SQL and all their frameworks - just build it all in Python.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://anvil.works/build?utm_source=crosspost:devto:/blog/secure-team-collaboration" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsw66qxlkopgppg50i2i7.png" alt="Sign up for Anvil" width="800" height="191"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>python</category>
      <category>anvil</category>
      <category>webdev</category>
      <category>git</category>
    </item>
    <item>
      <title>Building a Game App with Just Python</title>
      <dc:creator>Love Otudor</dc:creator>
      <pubDate>Wed, 16 Apr 2025 16:51:04 +0000</pubDate>
      <link>https://dev.to/anvil/building-a-game-app-with-just-python-4fbm</link>
      <guid>https://dev.to/anvil/building-a-game-app-with-just-python-4fbm</guid>
      <description>&lt;p&gt;"&lt;strong&gt;Guess the Sketch&lt;/strong&gt;" is a multiplayer game where you draw sketches and challenge friends to guess what they are. Players earn points for correct guesses, with fewer attempts leading to higher scores. Each round, one player is chosen to sketch, while the others try to guess as quickly as possible.&lt;/p&gt;

&lt;p&gt;I built this game using Python and Anvil, and it was surprisingly easy! I didn’t need to write HTML, CSS, or JavaScript. In this post, I will walk you through the key parts of building Guess the Sketch:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
Building the UI,&lt;/li&gt;
&lt;li&gt;
Saving and sending sketches,&lt;/li&gt;
&lt;li&gt;
Sending invites,&lt;/li&gt;
&lt;li&gt;
Managing players and scores, and&lt;/li&gt;
&lt;li&gt;
Publishing and sharing.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let's get started!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd4m8wl12p5mv20ylnzts.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd4m8wl12p5mv20ylnzts.gif" alt="Game Demo" width="1114" height="868"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://anvil.works/build#clone:LBYMHJ3D5VHWUS3G=V2TWD2XDO3Z6MHCCXTEPXQVF" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpkvbvqp0y0tdl5jyjcic.png" alt="Open in Anvil" width="461" height="140"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Building the UI
&lt;/h2&gt;

&lt;p&gt;With Anvil’s drag-and-drop editor, building the UI was very intuitive. Instead of writing HTML and CSS, I simply dragged components from the &lt;a href="https://anvil.works/docs/editor/form-editor?utm_source=crosspost:dev.to:/blog/guess-the-sketch-game#toolbox"&gt;Toolbox&lt;/a&gt; onto the Form and arranged them as needed. Here is how easy it was to build the &lt;strong&gt;SketchScreen&lt;/strong&gt;, where players create and name their sketches.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fezl5ads6zoss1frjfeq7.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fezl5ads6zoss1frjfeq7.gif" alt="Creating the Sketch Screen in Anvil" width="640" height="427"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Anvil’s &lt;a href="https://anvil.works/docs/ui/components/canvas?utm_source=crosspost:dev.to:/blog/guess-the-sketch-game"&gt;Canvas component&lt;/a&gt; provided a seamless way to add a drawing area to the game. It is a Python wrapper around the HTML &lt;code&gt;&amp;lt;canvas&amp;gt;&lt;/code&gt; element, with built-in &lt;a href="https://anvil.works/docs/api/anvil?utm_source=crosspost:dev.to:/blog/guess-the-sketch-game#Canvas_attributes"&gt;methods and event handlers&lt;/a&gt; that handle drawing effortlessly. I used the &lt;code&gt;mouse_down&lt;/code&gt;, &lt;code&gt;mouse_move&lt;/code&gt;, and &lt;code&gt;mouse_up&lt;/code&gt; events to track real-time mouse movement and draw lines on the canvas. Adding an eraser was as simple as setting the brush colour to match the background of the drawing area.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Want to learn more about the Canvas component? Check out this Canvas Tutorial:&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://anvil.works/learn/tutorials/canvas?utm_source=crosspost:dev.to:/blog/guess-the-sketch-game"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnv7i6eqqgwpg06ac8dbz.png" alt="Canvas Tutorial" width="745" height="90"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Saving and Sending Sketches
&lt;/h2&gt;

&lt;p&gt;Once a player finishes drawing and clicks the &lt;strong&gt;Send Sketch&lt;/strong&gt; button, the image is retrieved from the Canvas using the &lt;code&gt;.get_image()&lt;/code&gt; method:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;sketch&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;canvas_1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_image&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This converts the sketch into a &lt;a href="https://anvil.works/docs/working-with-files/media?utm_source=crosspost:dev.to:/blog/guess-the-sketch-game#media-objects"&gt;Media object&lt;/a&gt;, which is then stored in a &lt;a href="https://anvil.works/docs/data-tables?utm_source=crosspost:dev.to:/blog/guess-the-sketch-game"&gt;Data Table&lt;/a&gt; for later retrieval.&lt;/p&gt;

&lt;p&gt;When a player submits a sketch, one of two things happens:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A new game is created, along with its first round (if the player is starting a new game).&lt;/li&gt;
&lt;li&gt;A new round is added to an existing game, which happens when a player joins an ongoing game and takes their turn.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here’s how I handled both scenarios:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;sketch&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;canvas_1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_image&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="c1"&gt;# Add a round to an existing game
&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;game_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
  &lt;span class="n"&gt;anvil&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;add_game_round&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;game_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sketch&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sketch_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nf"&gt;navigate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/invite/:id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;game_id&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="c1"&gt;# Create a new game
&lt;/span&gt;&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
  &lt;span class="n"&gt;game_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;anvil&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;start_game&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sketch&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sketch_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nf"&gt;navigate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/invite/:id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;game_id&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In both cases, a new game round is created and linked to the current game, whether the game is newly created or ongoing.&lt;/p&gt;

&lt;p&gt;With &lt;a href="https://anvil.works/docs/data-tables?utm_source=crosspost:dev.to:/blog/guess-the-sketch-game"&gt;Data Tables&lt;/a&gt;, creating a round is as simple as inserting a new row into the Rounds Table and adding the round ID to the corresponding game's &lt;code&gt;rounds&lt;/code&gt; column (which stores a list of round IDs for that game).&lt;/p&gt;

&lt;p&gt;Here’s how I create and link a round to an existing game:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="nd"&gt;@anvil.server.callable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;require_user&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;add_game_round&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;game_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;image&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sketch_name&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
  &lt;span class="c1"&gt;# Other game logic...
&lt;/span&gt;  &lt;span class="n"&gt;game&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;app_tables&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;game_table&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_by_id&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;game_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nb"&gt;round&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;app_tables&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rounds_table&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_row&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;game_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;game_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;image&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;image&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;owner&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;player&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sketch_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;sketch_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;start_time&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
  &lt;span class="n"&gt;game&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;rounds&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;round&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="c1"&gt;# Other game logic... 
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Sending Invites
&lt;/h2&gt;

&lt;p&gt;Anvil has a built-in  &lt;a href="https://anvil.works/docs/email?utm_source=crosspost:dev.to:/blog/guess-the-sketch-game"&gt;Email Service&lt;/a&gt;, which makes sending invites as simple as a single function call. I used &lt;code&gt;anvil.email.send()&lt;/code&gt; to email friends a game invite with a preview of the sketch as an  &lt;a href="https://anvil.works/docs/email/attachments?utm_source=crosspost:dev.to:/blog/guess-the-sketch-game#using-inline-attachments"&gt;inline attachment&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;  &lt;span class="n"&gt;anvil&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;bcc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;emails&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
    &lt;span class="n"&gt;from_address&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;player&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;email&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; 
    &lt;span class="n"&gt;subject&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;player&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; is inviting you to Guess the Sketch!&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;html&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
      Hey,
      I just created this sketch:&amp;lt;br&amp;gt;
      &amp;lt;img src=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;cid:sketch&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;&amp;gt;&amp;lt;br&amp;gt;
      Think you can figure out what it is? Click this link to play: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;link&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; 
    &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;inline_attachments&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;sketch&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;image&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Players receive this email with a preview of the sketch right in their inbox. Here’s how it looks:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1vuarvjrg1mda7qi0r2b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1vuarvjrg1mda7qi0r2b.png" alt="Invite Email" width="800" height="508"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This makes it really easy for players to see the sketch before they click the link to play.&lt;/p&gt;




&lt;h2&gt;
  
  
  Managing Players and Scores
&lt;/h2&gt;

&lt;p&gt;To manage player authentication, I used Anvil’s &lt;a href="https://anvil.works/docs/users?utm_source=crosspost:dev.to:/blog/guess-the-sketch-game"&gt;Users Service&lt;/a&gt;, which automatically created a &lt;strong&gt;Users Table&lt;/strong&gt; that stored player details.&lt;/p&gt;

&lt;p&gt;With just one line, I could add a login Form:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;anvil&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;login_with_form&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This allows players to sign up and log in with their Google accounts, making it easy to track their progress across games. Each new user is automatically added as a row in the Users Table.&lt;/p&gt;

&lt;p&gt;At any point in the app, I can access the currently logged-in player by calling:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;player&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;anvil&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_user&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Tracking Player Scores
&lt;/h3&gt;

&lt;p&gt;To track scores, I added a &lt;code&gt;points&lt;/code&gt; column to the automatically generated &lt;strong&gt;Users Table&lt;/strong&gt;, where I store the total points each player accumulates.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fynl7wag7d2rcmxeyhpeb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fynl7wag7d2rcmxeyhpeb.png" alt="Users Table" width="800" height="367"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For every point a player earns in a game, I update the player’s total score:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;player&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;anvil&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_user&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="c1"&gt;# Other game logic...
&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;player&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;points&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
      &lt;span class="n"&gt;player&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;points&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;points_gained&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="n"&gt;player&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;points&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;points_gained&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;This ensures that scores remain updated and persistent across game sessions.&lt;/p&gt;




&lt;h2&gt;
  
  
  Publishing and Sharing
&lt;/h2&gt;

&lt;p&gt;Once everything was ready, publishing the game was just one click on the  &lt;a href="https://anvil.works/docs/deployment/environments?utm_source=crosspost:dev.to:/blog/guess-the-sketch-game"&gt;Publish button&lt;/a&gt; in the Anvil editor. I instantly got a public URL, that I could share with friends to start playing right away!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd4m8wl12p5mv20ylnzts.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd4m8wl12p5mv20ylnzts.gif" alt="Full Game Demo" width="1114" height="868"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Want to Build Your Own?
&lt;/h2&gt;

&lt;p&gt;These are just some of the highlights, but you can clone the full project and explore how it works yourself.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://anvil.works/build#clone:LBYMHJ3D5VHWUS3G=V2TWD2XDO3Z6MHCCXTEPXQVF" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo74xkd1d2ganf56ftrnp.png" alt="Image description" width="608" height="140"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  More about Anvil
&lt;/h2&gt;

&lt;p&gt;If you're new here, welcome! &lt;a href="https://anvil.works/?utm_source=crosspost:dev.to:/blog/guess-the-sketch-game"&gt;Anvil&lt;/a&gt; is a platform for building full-stack web apps with nothing but Python. No need to wrestle with JS, HTML, CSS, Python, SQL and all their frameworks – just &lt;strong&gt;build it all in Python&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://anvil.works/build?utm_source=crosspost:dev.to:/blog/guess-the-sketch-game"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fow63l4svon8tal3uola3.png" alt="Sign up for Anvil" width="800" height="178"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>gamedev</category>
      <category>python</category>
      <category>anvil</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Introducing the Interactive Debugger in Anvil</title>
      <dc:creator>Love Otudor</dc:creator>
      <pubDate>Wed, 26 Feb 2025 09:47:49 +0000</pubDate>
      <link>https://dev.to/anvil/introducing-the-interactive-debugger-in-anvil-10kn</link>
      <guid>https://dev.to/anvil/introducing-the-interactive-debugger-in-anvil-10kn</guid>
      <description>&lt;h2&gt;
  
  
  Say Hello to the Interactive Debugger in Anvil
&lt;/h2&gt;

&lt;p&gt;We are very excited to announce the first release of &lt;strong&gt;the Interactive Debugger&lt;/strong&gt; in Anvil. Say goodbye to countless &lt;code&gt;print&lt;/code&gt; statements!&lt;/p&gt;

&lt;p&gt;With the Interactive Debugger, you can now pause your code as it executes, inspect variables, and gain deeper insights into what’s happening in your code—whether on the client or server side.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgjo3kcs35m3i2p9i79yq.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgjo3kcs35m3i2p9i79yq.gif" alt="Debugger Demo" width="1024" height="1024"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  What is the Interactive Debugger?
&lt;/h2&gt;

&lt;p&gt;The Interactive Debugger lets you:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Add breakpoints&lt;/strong&gt; to your code to pause execution at specific lines.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Inspect variables&lt;/strong&gt; and &lt;strong&gt;values&lt;/strong&gt; at runtime.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Debug&lt;/strong&gt; both &lt;strong&gt;client-side&lt;/strong&gt; and &lt;strong&gt;server-side code&lt;/strong&gt;, including &lt;strong&gt;background tasks&lt;/strong&gt; and &lt;strong&gt;HTTP endpoints&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Getting started is simple:&lt;/strong&gt; Click in the gutter next to any executable line of code to add a breakpoint and then run your code. When this breakpoint is hit, the debugger pauses execution and opens the Debugger Window, where you can easily view and inspect all the variables in your code.&lt;/p&gt;




&lt;h2&gt;
  
  
  Get Deeper Insights into your Code in real time
&lt;/h2&gt;

&lt;p&gt;With the debugger, you can add and remove breakpoints even while execution is paused, allowing you to adjust your debugging strategy as needed. The debugger toolbar gives you complete control to resume, restart, or stop execution, step over breakpoints, and step into or out of functions effortlessly. This makes it easy to navigate through your code seamlessly and gain a deeper understanding of its behaviour.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fho05ikm5nko21y3v1162.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fho05ikm5nko21y3v1162.gif" alt="Add and remove breakpoints" width="1512" height="819"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Easy Debugging Across Client and Server Code
&lt;/h2&gt;

&lt;p&gt;Anvil’s debugger allows you to step into server code directly from client code. For example, you can start in your client-side form code and step directly into your server code while showing the entire call stack on the browser frame.&lt;/p&gt;

&lt;p&gt;Here is a demo illustrating how you can step into server code from client code seamlessly:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F77ho3wq2ct1iuxfk7wqh.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F77ho3wq2ct1iuxfk7wqh.gif" alt="Step into server code" width="760" height="579"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Debug Background Tasks and HTTP Endpoints
&lt;/h2&gt;

&lt;p&gt;Debugging background tasks and HTTP endpoints in server modules has never been easier. By adding breakpoints to your background tasks or endpoint calls, you can pause execution, inspect variables, and diagnose issues with accuracy and confidence.&lt;/p&gt;




&lt;h2&gt;
  
  
  Availability
&lt;/h2&gt;

&lt;p&gt;The debugger is available to everyone!&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Free users can use Anvil’s debugger only on the client-side (Form) code.&lt;/li&gt;
&lt;li&gt;Client-side and server-side debugging is available on a Business Plan or higher.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  What’s Next?
&lt;/h2&gt;

&lt;p&gt;This is just the first version of the Anvil Debugger and we have plans for more interesting features, so stay tuned! In the meantime, we would love to hear your feedback! Try out the debugger today and let us know how it works for you.&lt;/p&gt;

&lt;p&gt;For a deep dive into debugging with the interactive debugger in Anvil, as well as additional tools to enhance your debugging process, check out our &lt;a href="https://anvil.works/docs/debugger?utm_source=crosspost:dev.to:/blog/announcing-the-debugger"&gt;Debugging Documentation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Happy debugging!&lt;/p&gt;




&lt;h2&gt;
  
  
  More about Anvil
&lt;/h2&gt;

&lt;p&gt;If you're new here, welcome! &lt;a href="https://anvil.works?utm_source=crosspost:dev.to:/blog/announcing-the-debugger"&gt;Anvil&lt;/a&gt; is a platform for building full-stack web apps with nothing but Python. No need to wrestle with JS, HTML, CSS, Python, SQL and all their frameworks – just &lt;strong&gt;build it all in Python&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://anvil.works?utm_source=crosspost:dev.to:/blog/announcing-the-debugger"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fow63l4svon8tal3uola3.png" alt="Sign up for Anvil" width="800" height="178"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>python</category>
      <category>webapp</category>
    </item>
  </channel>
</rss>
