<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:media="http://search.yahoo.com/mrss/"><channel><title><![CDATA[Bold Tech Blog]]></title><description><![CDATA[Learn from the internal tool experts. Tutorials, guides, top tips and more to help you build custom business software fast on platforms like Retool.]]></description><link>http://143.198.97.195:2369/</link><image><url>http://143.198.97.195:2369/favicon.png</url><title>Bold Tech Blog</title><link>http://143.198.97.195:2369/</link></image><generator>Ghost 5.60</generator><lastBuildDate>Tue, 19 Aug 2025 19:13:24 GMT</lastBuildDate><atom:link href="http://143.198.97.195:2369/rss/" rel="self" type="application/rss+xml"/><ttl>60</ttl><item><title><![CDATA[Five years of building boldly with Retool]]></title><description><![CDATA[To celebrate our five year anniversary on Retool and the launching of the Agency program, we reflect on five years of building on Retool, how much the platform has changed and how far we've come. ]]></description><link>http://143.198.97.195:2369/bold-tech-five-years-on-retool/</link><guid isPermaLink="false">67f8fdec8ddcb004e6520045</guid><category><![CDATA[Retool]]></category><category><![CDATA[Customer Stories]]></category><category><![CDATA[Retool Enterprise]]></category><dc:creator><![CDATA[Joey Karczewski]]></dc:creator><pubDate>Fri, 25 Apr 2025 13:00:30 GMT</pubDate><media:content url="http://143.198.97.195:2369/content/images/2025/04/Bold-tech-blog-thumb--2-.jpg" medium="image"/><content:encoded><![CDATA[<img src="http://143.198.97.195:2369/content/images/2025/04/Bold-tech-blog-thumb--2-.jpg" alt="Five years of building boldly with Retool"><p><em>Bold Tech has been building internal tools on Retool for 5 years now, and to honour this occasion we&apos;re excited to share more about our story, and how Retool has shaped the way we work.</em></p><p>At <a href="https://www.boldtech.dev/?ref=143.198.97.195">Bold Tech</a>, our mission has always been clear: reduce complexity, deliver impact, and make internal tools not just functional, but satisfying. Over five years and 50,000+ hours of development time, Retool has been a cornerstone of that mission.</p><p>From helping scale startups to transforming enterprise back offices, we&#x2019;ve pushed the boundaries of what&#x2019;s possible for internal tools and what can be done on the Retool platform itself. This blog post is a look back at the innovations, best practices, and <a href="http://143.198.97.195:2369/tag/ux-ui-guides/">UI craftsmanship</a> that have defined our collaboration with Retool on this exciting anniversary and a preview of where we&#x2019;re headed next.<br></p><h2 id="our-beginnings">Our beginnings</h2><p>In 2020, after months of building on the platform and quickly becoming the top contributor on the Retool forum, Joey was introduced to Retool&#x2019;s Growth team to support new enterprise customers - like Stripe - with their buildouts. At the time, Retool was still in its early growth phase and looking for a partner who could showcase the platform&apos;s full potential and build deep, trusted relationships with clients.</p><p>Fast forward a few years... Retool has steadily evolved into the business software powerhouse it is today and, with a rich legacy and deep-rooted expertise in the platform, Bold Tech has solidified its role as a key development partner. Having worked closely with Retool as it&#x2019;s grown from a 40-person to a 400+-person company, Bold Tech brings a level of historical context and enterprise expertise that&#x2019;s difficult to replicate. </p><p>In 2021, we launched <a href="http://143.198.97.195:2369/">our blog</a> to share that expertise - collaborating with the Retool content team to publish tutorials, guides, and videos that help developers build faster and smarter on the platform.</p><p>Along the way, the Bold Tech team has produced tons of unique learning pieces for the Retool community. We&apos;ve received great feedback from customers and developers on how our blog has helped them build better in Retool - a huge thanks to everyone who takes the time to read it. </p><p>Here are some of our favorites over the years:<br></p><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="http://143.198.97.195:2369/creating-pdfs-in-retool/"><div class="kg-bookmark-content"><div class="kg-bookmark-title">Creating PDFs In Retool (4+ methods, updated for 2023)</div><div class="kg-bookmark-description">For many companies looking for Retool apps, PDF end products are essential. Here are 4+ options to generate PDFs within Retool.</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="http://143.198.97.195:2369/content/images/size/w256h256/2023/08/Copy-of-Untitled-Design.png" alt="Five years of building boldly with Retool"><span class="kg-bookmark-author">Bold Tech Blog</span><span class="kg-bookmark-publisher">Joey Karczewski</span></div></div><div class="kg-bookmark-thumbnail"><img src="http://143.198.97.195:2369/content/images/2023/11/Bold-tech-blog-thumb--6-.jpg" alt="Five years of building boldly with Retool"></div></a></figure><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="http://143.198.97.195:2369/tag/ux-ui-guides/"><div class="kg-bookmark-content"><div class="kg-bookmark-title">UX / UI Guides - Bold Tech Blog</div><div class="kg-bookmark-description">User experience is just as important in internal tools as in external apps. We give tips, tricks, and best UX/UI practices when creating internal applications. Learn great layouts, performance tricks, and more. Learn to build better on platforms like Retool.</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="http://143.198.97.195:2369/content/images/size/w256h256/2023/08/Copy-of-Untitled-Design.png" alt="Five years of building boldly with Retool"><span class="kg-bookmark-author">Bold Tech Blog</span><span class="kg-bookmark-publisher">Joey Karczewski</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://images.unsplash.com/photo-1552845108-5f775a2ccb9b?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wxMTc3M3wwfDF8c2VhcmNofDF8fGJsdWUlMjBtb3VudGFpbnxlbnwwfHx8fDE2OTM5MTQ4MjV8MA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=2000" alt="Five years of building boldly with Retool"></div></a></figure><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="http://143.198.97.195:2369/creating-great-multi-page-applications-in-retool/"><div class="kg-bookmark-content"><div class="kg-bookmark-title">How to create great multi-page applications in Retool</div><div class="kg-bookmark-description">Retool has just had a boost in speed and power, so switching between applications much more seamless and performant. In this article, we discuss how to make great multi-page applications with optimal performance and effective UI.</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="http://143.198.97.195:2369/content/images/size/w256h256/2023/08/Copy-of-Untitled-Design.png" alt="Five years of building boldly with Retool"><span class="kg-bookmark-author">Bold Tech Blog</span><span class="kg-bookmark-publisher">Sophie Becker</span></div></div><div class="kg-bookmark-thumbnail"><img src="http://143.198.97.195:2369/content/images/2023/08/1.jpg" alt="Five years of building boldly with Retool"></div></a></figure><p></p><h2 id="the-clients-that-made-it-all-happen">The clients that made it all happen</h2><p>We&#x2019;ve had the pleasure of working with <a href="https://www.boldtech.dev/customers?ref=143.198.97.195">incredible clients</a> across a multitude of industries: Edtech giants like Seesaw, Fintech enterprises like <a href="http://143.198.97.195:2369/bilt-on-retool-a-bold-tech-client-case-study/">Bilt</a>, Ramp and Stripe. We&#x2019;ve also supported plenty of plucky SMBs and start-ups with scaling their ideas, growing and developing increasingly complex, customized systems to support their unique and often-changing models. </p><p>We&#x2019;re lucky to have worked closely with so many great teams and innovative companies, and we&#x2019;ve learned tons about all the technology that goes into making them the well-oiled machines they need to be. </p><p>What&#x2019;s more, our ever-growing portfolio of enterprise clients has allowed us to become specialists in large and secure internal infrastructures that require the highest levels of data compliance, so much so that we now have a dedicated DevOps engineer to support teams with complex deployment. <br></p><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://www.boldtech.dev/customers?ref=143.198.97.195"><div class="kg-bookmark-content"><div class="kg-bookmark-title">Bold Tech | Our Customers</div><div class="kg-bookmark-description">Meet our customers. We are proud to share some of our client success stories, as well as our happy client testimonials.</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://cdn.prod.website-files.com/60661125a9ae6fff5ce860e8/606b3a411cff2c3ff9f39e10_favicon-32x32.png" alt="Five years of building boldly with Retool"><span class="kg-bookmark-author">Bold Technology Consulting Company Logo</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://cdn.prod.website-files.com/60661125a9ae6fff5ce860e8/6066113b87fc3110129e3a4e_boldtechlogo.jpg" alt="Five years of building boldly with Retool"></div></a></figure><p></p><h2 id="bold-tech-five-years-on">Bold Tech: five years on</h2><p>Now, Bold Tech is a tight-knit crew of 14 and has delivered over 50,000 hours of development work for more than 80 clients. This depth of hands-on experience has given the developers a deep understanding of the platform&#x2019;s nuances&#x2014;along with a toolkit of performance, security, and UX best practices that only come from time in the trenches.</p><p>What sets Bold Tech apart is how we select developers: each member is chosen not just for technical skill, but for their ability to translate complex business logic into effective, intuitive applications. We thrive on being dropped into unfamiliar, high-stakes challenges&#x2014;and designing tools that solve them with clarity and precision, from UI to backend logic. We work to align ourselves as brains for hire that go beyond the typical task-based, agency-style engagements.</p><p>Special mention goes to Stefan, our Head of Development&#x2014;a Retool-obsessed magician whose precision and creativity continue to push the platform&#x2019;s limits.</p><p>While Bold Tech has long been a trusted center of excellence partner&#x2014;known for building powerful, user-friendly internal tools on Retool&#x2014;the scope of its work has expanded significantly in recent years. With thousands of hours of development and deep exposure to the technologies surrounding Retool in real-world environments, we now operate at a higher level of advisory&#x2014;supporting clients not just in what they build, but in how they scale, secure, and structure their internal tooling.</p><p></p><p>Here is a selection of these new services we are proud to offer:<br></p><h3 id="devops-for-retool-at-scale">DevOps for Retool at Scale</h3><p>Bold Tech helps organizations deploy, manage, and optimize their Retool instances across complex environments. From self-hosted setups to highly complex cloud configurations, we ensure that infrastructure is resilient, secure, and built for long-term maintainability.<br></p><h3 id="enterprise-permissioning-frameworks">Enterprise Permissioning Frameworks</h3><p>Robust access control is critical for any serious Retool implementation. Bold Tech works with clients to design and implement permissioning models that map cleanly to organizational roles, compliance needs, and security best practices&#x2014;ensuring the right people see the right data at the right time.<br></p><h3 id="saas-product-architecture-in-retool">SaaS Product Architecture in Retool</h3><p>For SaaS companies building customer-facing or operational tools directly within Retool, Bold Tech provides architectural guidance on how to structure multi-tenant apps, enforce data isolation, and streamline workflows. This goes beyond building fast&#x2014;it&#x2019;s about building responsibly, with scalability and product quality in mind.<br></p><h3 id="training-enablement">Training &amp; Enablement</h3><p>Whether it&#x2019;s onboarding new teams, documenting best practices, or running interactive workshops, Bold Tech helps clients level up their internal Retool fluency so they&#x2019;re enabled to build better too.</p><h3 id="looking-ahead"><br>Looking ahead</h3><p><strong>Looking ahead, Bold Tech remains as committed as ever to raising the bar for what internal tools can be.</strong> We&#x2019;ve spent the last five years playing our part in Retool&#x2019;s evolution from the inside&#x2014;through code, content, and client outcomes&#x2014;and we&#x2019;re just getting started. As the complexity of modern businesses grows, so does our ambition to solve their hardest operational problems. Whether it&#x2019;s standing up secure, enterprise-grade infrastructure or helping a founder turn their back-office chaos into clarity, Bold Tech is here to be more than a vendor&#x2014;we&#x2019;re your internal tools partner of record. Here&#x2019;s to what we build next.&#x2003;<br></p><div class="kg-card kg-callout-card kg-callout-card-blue"><div class="kg-callout-emoji">&#x1F4A1;</div><div class="kg-callout-text"><strong>If your team is ready to take Retool further&#x2014;faster, and with more confidence&#x2014;</strong><a href="https://www.boldtech.dev/contact?ref=143.198.97.195"><strong>reach out</strong>.</a> We&#x2019;d love to talk through your use case, share what&#x2019;s working across the industry, and explore how we can help you build internal tools that actually move the needle.</div></div><p></p>]]></content:encoded></item><item><title><![CDATA[UI tips: Creating dropdown actions in Retool]]></title><description><![CDATA[In this tutorial we show you a great UI tip in Retool - using table buttons to set up dropdown actions that save space in your apps. ]]></description><link>http://143.198.97.195:2369/dropdown-actions-in-retool/</link><guid isPermaLink="false">67f8bd388ddcb004e652000c</guid><category><![CDATA[Tutorials]]></category><category><![CDATA[UI inspiration]]></category><category><![CDATA[UX/UI]]></category><dc:creator><![CDATA[Sophie Becker]]></dc:creator><pubDate>Fri, 11 Apr 2025 11:20:29 GMT</pubDate><media:content url="http://143.198.97.195:2369/content/images/2025/04/Bold-tech-blog-thumb--6-.png" medium="image"/><content:encoded><![CDATA[<img src="http://143.198.97.195:2369/content/images/2025/04/Bold-tech-blog-thumb--6-.png" alt="UI tips: Creating dropdown actions in Retool"><p><br>We&#x2019;ve moaned plenty before about <a href="http://143.198.97.195:2369/bold-tech-ui-sessions-6-and-a-bit-ways-to-use-buttons-more-effectively-in-retool/">button overload</a> and offered <a href="http://143.198.97.195:2369/ui-tips-efficient-dashboards-retool/">several tricks for UI</a> that keep your apps extra efficient, but in this tutorial, we&#x2019;re going to address a common UI sticking point we see in many Retool apps: creating tidy options for multiple actions. Building dropdown buttons with actions in Retool helps keep your interface clean and user-friendly and is a really intuitive design pattern used in many web apps. </p><p>Instead of cluttering your UI with multiple buttons, you can group related actions&#x2014;like <strong>Edit, Delete, or Disable User</strong>&#x2014;into a single dropdown. This makes interacting with data much more streamlined. In Retool, you can do this with a neat trick involving a table custom column and an option list.<br></p><p>Here&#x2019;s what this will look like when we&#x2019;re done: <br></p><!--kg-card-begin: html--><!--ARCADE EMBED START--><div style="position: relative; padding-bottom: calc(44.28969359331476% + 41px); height: 0; width: 100%;"><iframe src="https://demo.arcade.software/vlXQC41EV4zGtRdBukuf?embed&amp;embed_mobile=tab&amp;embed_desktop=inline&amp;show_copy_link=true" title="Dropdown actions" frameborder="0" loading="lazy" webkitallowfullscreen mozallowfullscreen allowfullscreen allow="clipboard-write" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; color-scheme: light;"></iframe></div><!--ARCADE EMBED END→<!--kg-card-end: html--><p><br>We&#x2019;re also going to show you best practices for setting up your create and edit forms to be more maintainable and less prone to error.<br></p><p>Let&#x2019;s jump in!<br></p><h2 id="configuring-dropdown-actions-in-retool">Configuring Dropdown Actions in Retool<br></h2><p>To get started, click on <strong>+ </strong>at the left side of your screen and drag a Table onto the editor to display your data. <br></p><figure class="kg-card kg-image-card"><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXdtAv5NDnpD58sTbkPeGfqhAhyjS7x0rmPdm9pAuN3jVrGnR06b5rfr7Fhp8AfkO_4CMBM6edlE5WW5vM4XnbKa8KPG_teSblZG4dEeH_7Lnc9hbMKqnr8ve4AP59QNcKNOIkEg?key=9yv7UAmcaEnDSKDTiEbY5cKx" class="kg-image" alt="UI tips: Creating dropdown actions in Retool" loading="lazy" width="672" height="381"></figure><p><br>Connect it to a data source: For this tutorial, we&#x2019;ve used Retool&#x2019;s sample data.</p><figure class="kg-card kg-image-card"><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXc__6BbuyMFpCvXtLXkOSCKAbSShN4Reix5MPiJuk8ML8Mwl_OVw7yAT9EmizpV7EnjH7nWG-AD6_towWaltdTMXmVcqZRgL51w-Y2zNT0o_cNLUfO5BoCNBYVdI9lk2S2b4DXrQg?key=9yv7UAmcaEnDSKDTiEbY5cKx" class="kg-image" alt="UI tips: Creating dropdown actions in Retool" loading="lazy" width="672" height="288"></figure><p><br>Add a column to your table, set the ID to &quot;actions&quot; and label it &quot;Actions&quot;. Then, <strong>enable the</strong> <strong>Editable toggle </strong>for user selections. Set a placeholder like &quot;View &gt;&gt;&quot; to make the dropdown button visible in the table. We added this to the left-hand side of the table as this is a common design pattern to which users will be accustomed.</p><figure class="kg-card kg-image-card"><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXfFHw9hxqaIgOj-WWJxbe1aALvLhg5xJ7s3NA0I2c7JCKbvIzCaDRPZzqqPGeh335ybngdR98WaxqsPBEsZvj3QNWHn5ANA7Ze3auJb_KrOg6hwweIYP0C4dDoDent7YmgRO1O9?key=9yv7UAmcaEnDSKDTiEbY5cKx" class="kg-image" alt="UI tips: Creating dropdown actions in Retool" loading="lazy" width="672" height="299"></figure><p>Next, to set the dropdown options, add an <strong>Add-on &#x201C;Option-List&#x201D; </strong>to the column. Configure the options by selecting <strong>Manual input, </strong>clicking the <strong>&#x2795;</strong>to add a new option, then setting each option&#x2019;s <strong>Value</strong> and <strong>Label</strong>.</p><figure class="kg-card kg-image-card"><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXdTSykfDsOX-RAet6gjSuAZReoZAwALmLO3AiZdye07slyjAujEOJ9heYBUPYdA-as9Ju9dRnhgXbkpxRQ-7nWSx1stovuYdvW97rNU5LEjzu-TrpjeQ6AElk0J8PPtLaAhOSEh?key=9yv7UAmcaEnDSKDTiEbY5cKx" class="kg-image" alt="UI tips: Creating dropdown actions in Retool" loading="lazy" width="672" height="437"></figure><p><br>For this example, we&#x2019;ve added options like &quot;Update&quot;, &quot;Disable User&quot;, and &quot;View User&quot;. Though it can be tempting to put all actions into a single dropdown on a webpage, it&#x2019;s important to create logical lists and group similar actions, such as the user actions in this table. This is because otherwise, dropdowns can quickly become bloated with options, making it harder for the user to find the action they are looking for and slowing them down.</p><p>Finally, make sure to disable <strong>&#x2018;</strong>Allow custom Values&#x2019;<strong> </strong>to prevent users from entering their own options.<br></p><h2 id="using-event-handlers-to-trigger-actions">Using event handlers to trigger actions</h2><p>Add a modal frame to your app and call it something like addAndEditModal.</p><figure class="kg-card kg-image-card"><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXcsEqJJrW-Mafl6eA-2ifUl26MgmqhLYKOoeiQWxmKoDRUDAU7U-v_F1Su70PYmgTX71PJTDpIwKeEamjInI-lw7-6arr0GikidOgvH1ULM-DPnPGBH8-BaNFcYDpLnRiqeT-ea7Q?key=9yv7UAmcaEnDSKDTiEbY5cKx" class="kg-image" alt="UI tips: Creating dropdown actions in Retool" loading="lazy" width="672" height="368"></figure><p>Next, let&#x2019;s connect this modal up to our Actions column and our &#x2018;Update&#x2019; button in the sourceTable. Head to the setting of your actions dropdown button.</p><ul><li>Click <strong>&#x2795;</strong> in <strong>Event Handlers</strong>.</li><li>Set the event to <strong>Change cell</strong> to detect dropdown selection.</li><li>Choose <strong>Run script</strong> as the action and paste the code below</li></ul><pre><code class="language-JavaScript">const latestChange = sourceTable.changesetArray[sourceTable.changesetArray.length - 1];
if (latestChange &amp;&amp; latestChange.id === sourceTable.selectedRow.id) {
const selectedAction = latestChange.actions;
if (selectedAction === &quot;update&quot;) {
addAndEditForm.setData(sourceTable.selectedSourceRow);
addAndEditModal.show();
} else if (selectedAction === &quot;disable&quot;) {
disableUser.trigger();
} else if (selectedAction === &quot;view&quot;) {
userModal.show();
parentData.setValue(sourceTable.selectedRow);
}
sourceTable.clearChangeset();
}</code></pre><figure class="kg-card kg-image-card"><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXd-4gkrKgEL7rEKyIc9d6Ki9-wq4f858O1Xn3sgfqPR1jacYEDOiGdBo5BZF_Z5cC8sDBnuBqyiCLyyhNgQiFpHCcMJryEl2HZN3j6MBNFQK1LRY6USz41D9pvEjeasNVlP0jva?key=9yv7UAmcaEnDSKDTiEbY5cKx" class="kg-image" alt="UI tips: Creating dropdown actions in Retool" loading="lazy" width="672" height="351"></figure><p><br><strong>What does this do? </strong>This listens for the most recent dropdown selection (latestChange) and checks if it matches the currently selected row. It proceeds to run the appropriate action based on the user&#x2019;s selection</p><p><strong>Update:</strong> Prefills the form with row data and opens the modal</p><p><strong>Disable</strong>: Runs the disableUser query</p><p><strong>View</strong>: Opens a user modal and sets row data into a parentData state</p><p>Lastly, we clear the table&#x2019;s &#xA0;changesetArray to prevent stale state<br></p><figure class="kg-card kg-image-card"><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXf58DzHXyRUfVexJIb9u8i3CLxX4YZDIqU1ab-xpQ6oIJOqZzXThTJK2RTknFFaW7aibsRUUEGOptID2xtN9H7T7YvQpNn-Q_5jrCID6x3qaK7n0F9EFluyyojI1LZlwDLNBDvH?key=9yv7UAmcaEnDSKDTiEbY5cKx" class="kg-image" alt="UI tips: Creating dropdown actions in Retool" loading="lazy" width="672" height="376"></figure><p><br>Now, when a user selects an option from the <strong>Actions</strong> dropdown, the system will dynamically update and trigger the correct and expected action<br></p><h2 id="best-practices-for-forms-dynamic-createedit">Best practices for forms: dynamic create/edit</h2><p>Since building in Retool is so quick and easy, it&#x2019;s also very easy to create more elements than you need and forget coding best practices. As most Add and Edit forms contain the same values, it&#x2019;s best to build a single form that changes dynamically (where needed) according to the action you are looking to execute.</p><p>We already have our &#x2018;update&#x2019; functionality, so next, add a Button component and name it clearly, like &quot;addUser&quot;, and configure the event handler to:</p><ul><li>Open the modal using: addAndEditModal.show() - just like we did for our update action</li><li>Reset the form&#x2019;s data by setting it to an empty object {}<br></li></ul><figure class="kg-card kg-image-card"><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXeVDGjhLlLQ4_vZjVxWp6oP-d4QQ1bPfe9WayAT39b4jU8LMhL1iDuCp4dIUitSias7IlmwMgLJAvGGTFV-N0iK3nBQISfmy5NGbLQk_GHo_PlWWQzXT8BeVTt6d4Wzd82SVfjH?key=9yv7UAmcaEnDSKDTiEbY5cKx" class="kg-image" alt="UI tips: Creating dropdown actions in Retool" loading="lazy" width="672" height="339"></figure><p><br>In the title of your modal, you can use the markdown &#x201C; ### {{ addAndUpdateForm.initialData?.id != null ? &quot;Update&quot; : &quot;Add&quot; }} User&#x201D;. This ensures that the title will dynamically display to match the selected action.</p><p>Now, to set up our form modal, pull in a form component and click <strong>Generate Form from Table</strong> to take advantage of Retool&#x2019;s automated form generator to quickly create your form.</p><figure class="kg-card kg-image-card"><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXepsw5yc3AJUhQfyJecwZQH6hVtqnaLOZwrcGiUm0yWNgAfmIXCkvZewLPex8NGFI55D3yC9yJNAXecVk_B--a33b20aun3FQqH1KBXrJB7B82qoDbTH0cdONwjhA2MUxh4QIWiUw?key=9yv7UAmcaEnDSKDTiEbY5cKx" class="kg-image" alt="UI tips: Creating dropdown actions in Retool" loading="lazy" width="672" height="248"></figure><p>Select <strong>sourceTable</strong> as the data source and choose the fields you would like to include in your form.</p><figure class="kg-card kg-image-card"><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXcKr0E-YHG7PAOZ49qZIMnx9t1np5RNEpEb65TqC66JBO--oOfKCYcSLSwPLj53gkDFwjKBFxIEclTadUUQcr08ywyebhVufrFe50TqA9LEoVCkhru3uHvpxC5zxe8Cek_zvTEDYw?key=9yv7UAmcaEnDSKDTiEbY5cKx" class="kg-image" alt="UI tips: Creating dropdown actions in Retool" loading="lazy" width="672" height="300"></figure><p><br>Congratulations! You have successfully generated your form.</p><p>In the same way, you can also customize the Submit button to change its text based on formState.value, i.e. whether it&#x2019;s Adding or Updating a user. Use the following expression to update the button text when the form is opened for updating a user: {{ addAndUpdateForm.initialData?.id != null ? &quot;Update&quot; : &quot;Submit&quot; }}.</p><p>Next, we&#x2019;ll need two event handlers to trigger our Edit and Create queries respectively. Once you&#x2019;ve set up two queries to either add or update a row in your database, add an <strong>Event Handler</strong> to the Submit button. Set the event type to <strong>Submit</strong>, choose <strong>Control Query</strong> as the action, and select updateData.trigger() to update user details.</p><p>Use an <strong>Only run when</strong> condition to ensure this action runs specifically for updates: {{ !addAndUpdateForm.initialData?.id }}</p><figure class="kg-card kg-image-card"><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXcYSoqhr1H4_sXNX3CI9q84GsSXxbwc4QJbPA4vpcOa7sku5L6LISy8NwdD6--R4v6YY-aMiW1cQ1SajjhsxD5gWho4ZA_c4eggrs0t3SV2sDPutJSuaLPgJbOQX_ynQPNod6FE?key=9yv7UAmcaEnDSKDTiEbY5cKx" class="kg-image" alt="UI tips: Creating dropdown actions in Retool" loading="lazy" width="672" height="383"></figure><p>Similarly, add another <strong>Event Handler</strong> for new data entries. Set the event to <strong>Submit</strong>, choose <strong>Control Query</strong> as the action, and select the appropriate query (e.g., addData.trigger()).</p><p>Use an <strong>Only run when</strong> condition to ensure that the event runs only when &quot;Add&quot; is selected: &#xA0;{{ addAndUpdateForm.initialData?.id }}. Now, the correct query will also fire depending on whether the form is the add or update version. <br></p><hr><p>With these steps, you have successfully implemented <strong>Dropdown Actions</strong> in Retool! &#x1F389;<br><br>Now, when users select an option from the <strong>Actions dropdown</strong>, the system dynamically updates <strong>formState</strong>, and the corresponding modal or function is triggered automatically.</p><p>Happy Retooling! &#x1F680;</p><div class="kg-card kg-callout-card kg-callout-card-blue"><div class="kg-callout-emoji">&#x1F4A5;</div><div class="kg-callout-text">At <a href="www.boldtech.dev">Bold Tech,</a> we specialize in building great internal tools, fast. We are obsessed with building apps that make your teams happier and more productive. In our <a href="blog.boldtech.dev">blog</a>, you can learn all about how to build better business software for more satisfied employees, or <a href="www.boldtech.dev/contact">get in contact</a> to chat to us about what you&apos;re looking to build.</div></div>]]></content:encoded></item><item><title><![CDATA[Advanced permissions in Retool: The Fundamentals (Retool for Enterprises)]]></title><description><![CDATA[Permissioning for large-scale deployments can be complex, so in this article we break down the fundamentals of how Permissions work in Retool, and share some essential tips.]]></description><link>http://143.198.97.195:2369/advanced-permissions-retool-fundamentals/</link><guid isPermaLink="false">6765531fdbece927645cdfb9</guid><category><![CDATA[Retool Enterprise]]></category><category><![CDATA[Retool]]></category><category><![CDATA[Internal Tools]]></category><dc:creator><![CDATA[Joey Karczewski]]></dc:creator><pubDate>Fri, 20 Dec 2024 12:15:56 GMT</pubDate><media:content url="http://143.198.97.195:2369/content/images/2024/12/Bold-tech-blog-thumb--5-.png" medium="image"/><content:encoded><![CDATA[<img src="http://143.198.97.195:2369/content/images/2024/12/Bold-tech-blog-thumb--5-.png" alt="Advanced permissions in Retool: The Fundamentals (Retool for Enterprises)"><p><br>Managing permissions in complex systems is notoriously challenging, and <a href="http://143.198.97.195:2369/what-is-retool/">Retool</a> can be no different. If approached without a deeper understanding of how Retool permissions work, it&apos;s easy to get your apps, resource and user access in a tangle. We&apos;ve worked with many organizations struggling to regain control over convoluted permissioning setups, particularly when their app infrastructure has scaled faster than they first expected. </p><p>For this reason, we always advocate for companies to - where possible - implement a Retool-friendly permissions structure from the very beginning that allows for scale. Careful planning and a better knowledge of the intricacies of the Retool Permissions settings is essential for Enterprise deployments. </p><p>In our next few <a href="http://143.198.97.195:2369/tag/retool-enterprise/">Retool for Enterprise articles</a>, we will be focusing specifically on permissions, covering the fundamentals here first, before discussing the different approaches you can take and how you can apply them in Retool. </p><p>Need more help than this article? <a href="https://www.boldtech.dev/contact?ref=143.198.97.195">Reach out</a> to us! </p><div class="kg-card kg-callout-card kg-callout-card-grey"><div class="kg-callout-emoji">&#x1F4A1;</div><div class="kg-callout-text">Key note: We&#x2019;ve tried our utmost to make this guide as clear and comprehensive as possible, but, as with anything, there are nuances with these settings and their various possible combinations that could always have unexpected results. For that reason, it&#x2019;s essential that you use this as a guide only, and thoroughly test all your apps with different user profiles before deployment to ensure that all apps and resources are secure.&#xA0;</div></div><p></p><h2 id="retool-pricing-plans-and-permissions-features">Retool pricing plans and permissions features<br></h2><p>Firstly, it&apos;s important to know that your permission features depends on your <a href="http://143.198.97.195:2369/retool-pricing-calculator/">Retool pricing plan</a>. </p><p><strong>For small teams:</strong> The Free and Teams plans are suitable for smaller teams who don&#x2019;t have a significant need for granular permissions. The Free plan does not offer permission features, so each user has full access, meaning all users can build and edit apps without role distinctions. </p><p>This article is written for larger organizations on Retool who need more complex permissioning structures, so we&#x2019;ll be assuming readers have the Business plan or Enterprise. Here are the key distinctions between those plans when it comes to permissions:</p><p><strong>Business Plan:</strong> Suited for larger organizations, the business plan allows you to create new permission groups instead of relying on the Viewer, Editor and Admin groups. This is the minimum plan that we would recommend for teams with more granular permissions requirements. </p><p><strong>Enterprise Plan: </strong>For those on Enterprise plans, you get access to enterprise-grade features like pushing groups from Okta and environment-level source control. The ability to differentiate environment permissions is particularly important for QA teams to have access only to staging resources. <br></p><p></p><h2 id="permissioning-in-retool-the-fundamentals">Permissioning in Retool: The fundamentals<br></h2><p>For you to make the right choice when choosing a permissioning pattern (which we&apos;ll talk more about in Permissions Part II), it&apos;s essential to understand Retool&#x2019;s multiple layers of permissions. Though the Permissions UI in the environment settings can seem straightforward, it&#x2019;s important to understand the nuances of each setting as you use them. </p><p>The apps, resources and workflow tabs allow you to define &#x2018;Use&#x2019;, &#x2018;Edit&#x2019;, and &#x2018;Own&#x2019; access for users, but these settings mean different things for each tab, and these settings impact each other. </p><blockquote>An example. If you give someone &#x2018;use&#x2019; access to an app, but they don&apos;t have &#x2018;use&#x2019; access to the resource inside of it, the queries that use that resource will not execute and will produce an error response. So, if a user has &#x2018;use&#x2019; access to 2 out of 3 resources that are used in an app, the first two will work as expected, but the third (without &#x2018;use&#x2019; access) will consistently fail. </blockquote><p>To give you a better understanding of these granular settings, we&#x2019;ll quickly run through what each of these permission types mean, as well as what settings to look out for in the &#x2018;additional&#x2019; tab. </p><div class="kg-card kg-callout-card kg-callout-card-yellow"><div class="kg-callout-emoji">&#x26A0;&#xFE0F;</div><div class="kg-callout-text">Watch out! We would recommend avoiding using the Viewer, Editor and Admin groups for large Enterprise deployments, and certainly the All User group. We&#x2019;ll talk more about this later.&#xA0;</div></div><h3 id="resource-permissions"><br><br>Resource permissions</h3><p>In custom groups (outside of the editor, viewer and admin groups), you can specify exactly what type of access the group has to each resource in your environment. Although there are three boxes to toggle between, there are technically four states, as none selected means &#x2018;no access&#x2019;. You can only select one permission type, as <strong>each type builds on the permission access of the former.</strong> </p><figure class="kg-card kg-image-card"><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXdCKWnv88kn4LL2GbXlxBKRYELabFivGejpblcVdM2Vk44y1GIzFO2CzEgzb1IeOoVqSR6DeSYxyBscNyTkO42qkaEYI_uiUtjGDo6TlGPN6653sDBgaTzr6wMDFKf_ylEflYhg2A?key=yYv6ublKvZyX5fEsgZ07Aw" class="kg-image" alt="Advanced permissions in Retool: The Fundamentals (Retool for Enterprises)" loading="lazy" width="624" height="304"></figure><p></p><p>Here&#x2019;s what those permission types really mean when it comes to working with or using resources:</p><ul><li><strong>Nothing toggled state -</strong> the user can&#x2019;t run the resource even if they have access to an application that uses it. When performing an action like reading or writing data that is contingent on the resource, it will display an error message similar to: &#x201C;you do not have access to &#xA0;{{uuid}} resource&#x201D;.</li><li><strong>Use</strong> - if the resource setting is toggled to <em>Use</em>, this means that the user,<strong> </strong>if they have access to an app, can run any queries connected to that resource within the application. Importantly - though they can run queries connected to the resource in &#x2018;User&#x2019; mode, they cannot perform any edits on the query in &#x2018;Edit&#x2019; mode, even if they have edit access to the app it uses. </li><li><strong>Edit</strong> - the <em>Edit </em>toggle includes the same access as <em>Use</em> but also allows the user to edit and create queries for the resource in the &#x2018;Editor&#x2019; mode inside of Retool. Here, they can create, edit and delete<em> </em>any queries made against the resource within an application they have edit access to. Something to note here is that they can also see the resource&#x2019;s configuration inside the resource page inside Retool (though cannot edit them). </li><li><strong>Own</strong> - Own includes all access in <em>Use</em> and <em>Edit</em> but also allows the user to edit the configuration of the resource (the connection settings), rename, and move the resource around into different folders. This means effectively giving this group managerial access over the resource. </li></ul><p>When managing resource permissions, it&#x2019;s essential to be wary of the &#x2018;Query library&#x2019; setting in the Additional tab, as this can potentially overwrite resource access. We talk more about this in the &#x2018;Additional tab&#x2019; section below.<br></p><h3 id="app-permissions">App permissions</h3><p>Similarly to the resource permissioning, the application section allows No access, Use, Edit and Own permissions, but note that the ability to use the applications &#xA0;also depends on the access these users have to the resources included in apps.<br></p><figure class="kg-card kg-image-card"><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXevKiqTir9O7I4uMkzkcWi3d4G8MRE3h2Pe4G8NUt6Ozk1z7Dp0C4Qa15-UoxPGv0WuL5QKKlVg8A9axSx9u-0j6A3jXSApE1Fm9DJONMRv4w_MykO4bxJFauw7dRkNkfZoAYFzbA?key=yYv6ublKvZyX5fEsgZ07Aw" class="kg-image" alt="Advanced permissions in Retool: The Fundamentals (Retool for Enterprises)" loading="lazy" width="624" height="165"></figure><p></p><ul><li><strong>Nothing toggled state - </strong>if the user gets routed to this app or page, they will get an error message that says they don&#x2019;t have access to the app. They will not see the app in the root directory.</li><li><strong>Use -</strong> The <em>Use</em> toggle means that the user group can only open the application in &#x2018;User mode&#x2019;. However, they will also need the correct permissioning (at least <em>Use</em>) to the app&apos;s respective resources to perform the queries within the app.</li><li><strong>Edit -</strong> This gives the same access as <em>Use</em>, but the edit toggle here means that this group can also access the application in &#x2018;Editor mode&#x2019;. This means that in &#x2018;User mode&#x2019; they will see the black Retool header bar and the toggle to <em>Edit</em> the app in the right-hand corner. Once in &#x2018;Editor mode&#x2019; they can run queries in the code tab for the resources for which they have <em>Use </em>access, and edit the ones for which they have <em>Edit</em> access. They can also delete these applications.</li><li><strong>Own -</strong> &#xA0;similarly to the resources, <em>Own </em>is predominantly the administrative toggle for applications. &#x2018;Owners&#x2019; have all access from <em>Use </em>and <em>Edit, </em>but this setting allows these users to rename these apps, reorganize them in the Retool directory folders and export them to JSON or Toolscript. <br></li></ul><p></p><h3 id="workflow-permissions">Workflow permissions<br></h3><p>Workflow permissions work similarly to the App and Resource permissions, with a few small but crucial differences. Ultimately, Workflows are typically a chain of actions with a single trigger, and this trigger determines the access to run the workflow. If a user has some kind of access to trigger it, the workflow will execute regardless of the other permissions that user may have.</p><blockquote>Keep in mind: users who have Use access to an application as well as Use access to a Workflow, but who might not have underlying resource access, can still trigger and run a workflow that includes those resources. </blockquote><p></p><ul><li><strong>Nothing toggled state -</strong> The Workflow is not visible in the Workflow section, they cannot run the Workflow from within the queries section of the Retool editor, nor can they trigger the workflow.</li><li><strong>Use -</strong> groups with <em>Use </em>access can press the play button to execute the Workflow or trigger it from an app, but cannot edit any part of the workflow in &apos;Editor mode&apos;. As noted above, they do not also need resource access to trigger a workflow that uses a resource.</li><li><strong>Edit -</strong> groups with <em>Edit </em>access can trigger the workflow but they can also edit it. Importantly however, <em>Editors </em>can&#x2019;t edit or create any steps including resources they don&#x2019;t have access to edit. So, in order to properly create and edit Workflows, <em>Editors </em>need <em>Edit </em>access to all resources involved.</li><li><strong>Own -</strong> &apos;Owners&apos;<em> </em>have all the permissions above, but can also rename or delete Workflows. <br></li></ul><h3 id="additional-tab-essential-errors-to-avoid">Additional tab: Essential errors to avoid<br></h3><p>&#x26A0;&#xFE0F; Beware: Often overlooked, the &#x2018;Additional&#x2019; tab section has a few potential security risks. </p><p>The first is the <strong>Query Library.</strong> If this Query Library checkbox is toggled on for a group, this means that they can perform shared queries and potentially run queries from within the query library page that they don&#x2019;t necessarily have access to via the resource permissions we went through above. <br></p><figure class="kg-card kg-image-card"><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXc_7HciGZHT8t-TxMOVuWdobpLJSZ-9YwHfyKupF1svXjW-GX08X5I6SRsV7n6POmkZQhnDRDRmVKx12Q3jCxCCcMC7DnIYu3Ew--vMxzVW5ddCYixOtVwLXz66d9cc-aX0FMhN?key=yYv6ublKvZyX5fEsgZ07Aw" class="kg-image" alt="Advanced permissions in Retool: The Fundamentals (Retool for Enterprises)" loading="lazy" width="624" height="43"></figure><p><br><br><strong>&#x2018;Allow access to unpublished releases&#x2019;</strong> is the one of the riskiest settings in the Additional settings tab that often goes unnoticed. Allowing access to unpublished releases allows a user to go back in history and potentially run previously deleted queries from previous versions of the application. By default this is toggled on and often goes unchecked when launching an application. For large orgs it&#x2019;s very easy for this to cause a large security issue, especially as users can accidentally gain access to older releases without realizing. <br></p><figure class="kg-card kg-image-card"><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXfziT0DJX4Gyg_abvIBx8fk34Td9_aRCnTAVlrqZTqh_LTDd1z64xRGyRSkNE01S3SmAi6fNCwn6Y6SNcLl41XjFDOST7728ZRUYr72HNQwTLib0wfuVIMW0IxXh6jiDNUcXGRVqw?key=yYv6ublKvZyX5fEsgZ07Aw" class="kg-image" alt="Advanced permissions in Retool: The Fundamentals (Retool for Enterprises)" loading="lazy" width="424" height="76"></figure><p><br>Finally, and probably most importantly is the <strong>&#x2018;View audit logs&#x2019; toggle</strong>. If switched on, this allows a user to go to the audit log page and query the audit logs. The <strong>audit logs include the data that has been returned from the query,</strong> which means they can show PII and other sensitive data to users auditing, without recording what data was shown to them. It&apos;s essential that this toggle is toggled off for end users so that they can&#x2019;t access secure data without this being logged. <br><br>We talk a little more about security tips like these in the <a href="https://docs.retool.com/center-of-excellence/Customer-Assets/security-checklist?ref=143.198.97.195">Enterprise Security Checklist</a> we recently released with the Retool Center of Excellence team. </p><p></p><h2 id="essential-tips-for-permissioning-in-retool">Essential tips for permissioning in Retool</h2><p>Now we&apos;ve run through the fundamentals of Permissions in the Retool UI, here are six essential tips for working with the system best.<br></p><ol><li><strong>All Users:</strong> When you add a new user to your Retool environment, they will automatically be added to the All Users group. This is why it&#x2019;s best practice to not set any permissions via this group, as it can be hard to maintain securely. The All Users group should only give access to the platform and should have all settings in &#x2018;Additional&#x2019; (as mentioned previously) toggled off.</li><li><strong><strong><strong>Editor and Viewer groups: </strong></strong></strong>These groups should also be avoided for large deployments as the permissions and security becomes difficult to manage as engineering teams and users grow. <br>- If any user is in the Editor group, they have edit access to all apps and resources, which is generally unsuitable as your infrastructure grows. This actually also gives them <em>Own </em>settings for all resources, exposing the resource configuration and connection settings.<br>- Likewise, anyone in the Viewer default group has full access to apps and resources, and can therefore perform any action across any app in that environment. These groups are often used at the beginning of Retool buildouts as they allow for simpler structures, but it&#x2019;s best to move away from them as soon as you can.</li><li><strong>Release versions toggled off: </strong>We already mentioned the &#x2018;Release versions&#x2019; toggle in the &#x2018;Additional&#x2019; section, but we&#x2019;ll put it here again for good measure as this setting is toggled on by default. When making any new group, always ensure this has been switched off before continuing.</li><li><strong><strong><strong>Retool Enterprise plan</strong>: </strong></strong>For those on the Enterprise plan, you can also configure all of these permissions on the environment level. In the permissions settings you can therefore click the &#x2018;show&#x2019; toggle for each resource or app and decide the specific environment resource (e.g. staging vs production). This is particularly useful for QA teams because they can be given access to staging resources without exposing production data.</li><li><strong><strong><strong>User group admins: </strong></strong></strong>A group admin can add or remove users (members) in their groups, but they can&#x2019;t change any of the actual granular access settings to apps, workflows or resources. Therefore, it makes most sense to use the User group admin role to assign non-technical managers the ability to manage their team, not to engineers who need to access the permissions settings themselves.</li><li><strong><strong><strong>Folders</strong>:</strong> </strong>be wary with giving access on a folder-level, as any new app added to that folder will inherit those permissions, and this is where mistakes can easily be made. When applications, resources or workflows are placed within folders, you can define access to the parent folder or the nested objects specifically within them. We suggest sticking to a single pattern: either sticking to folder level access or single page access. If you do apply permissions via folders, you must have a rigid folder organization system to ensure no mistakes are made. &#xA0;<br></li></ol><p>That&#x2019;s it for the fundamentals of Permissions in Retool - but we have plenty more to say! In Part II, we&#x2019;ll offer some suggestions for approaches to permissions in Retool that Enterprise organizations can use to ensure watertight internal app infrastructures. We&#x2019;ll specifically focus on the importance of formatting your permissions groups carefully. Stay tuned!<br></p><div class="kg-card kg-callout-card kg-callout-card-blue"><div class="kg-callout-emoji">&#x1F4A1;</div><div class="kg-callout-text">Need help with your Enterprise deployment on Retool? We work with dozens of Enterprise companies to build and scale their internal tools. We specialize in building out large-scale deployments on developer platforms like Retool. <a href="https://www.boldtech.dev/contact?ref=143.198.97.195">Reach out</a> to discuss how we can help you.</div></div>]]></content:encoded></item><item><title><![CDATA[Building the Steam UI on Retool (Retool UI & Inspiration)]]></title><description><![CDATA[In the final release of our Retool UI inspiration series, we recreated the Steam interface. Newsletter members can download the template for free!]]></description><link>http://143.198.97.195:2369/building-the-steam-ui-on-retool/</link><guid isPermaLink="false">674881b0dbece927645cdeaf</guid><category><![CDATA[UI inspiration]]></category><category><![CDATA[Retool Template]]></category><dc:creator><![CDATA[Sophie Becker]]></dc:creator><pubDate>Thu, 28 Nov 2024 15:05:36 GMT</pubDate><media:content url="http://143.198.97.195:2369/content/images/2024/11/Bold-tech-blog-thumb--4-.png" medium="image"/><content:encoded><![CDATA[<img src="http://143.198.97.195:2369/content/images/2024/11/Bold-tech-blog-thumb--4-.png" alt="Building the Steam UI on Retool (Retool UI &amp; Inspiration)"><p>In the final release of our <a href="http://143.198.97.195:2369/tag/ui-inspiration/">Retool UI inspiration series</a>, we recreated the dark and moody Steam interface using just Retool (and a touch of CSS). </p><p>It&#x2019;s quite uncommon to see dark modes in Retool, and Steam&#x2019;s dark, layered design and functional layout inspired us to explore how Retool&#x2019;s features can bring a similar interface to life. </p><p>You can play with his <a href="https://sandbox.practicemode.retool.com/embedded/public/da35594f-aa2c-4315-98b0-cf6151c62261?ref=143.198.97.195">Retool version of the Steam UI</a> yourself. <br></p><!--kg-card-begin: html--><!--ARCADE EMBED START--><div style="position: relative; padding-bottom: calc(44.72222222222222% + 41px); height: 0; width: 100%;"><iframe src="https://demo.arcade.software/wbfIpOuYIaV1Wu7ClpJw?embed&amp;embed_mobile=inline&amp;embed_desktop=inline&amp;show_copy_link=true" title="Steam Clone" frameborder="0" loading="lazy" webkitallowfullscreen mozallowfullscreen allowfullscreen allow="clipboard-write" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; color-scheme: light;"></iframe></div><!--ARCADE EMBED END--><!--kg-card-end: html--><p>There are four key features that are particularly unique about this UI design in Retool: <br></p><ol><li>Using a container to create a sticky footer for the whole Retool page</li><li>Using custom CSS to eliminate the repeated scroll bars on Window (a particular Bold Tech pet peeve)</li><li>Applying gradient backgrounds to containers to create a more three-dimensional graphic design</li><li>Double top navigation bars for primary and secondary menu<br></li></ol><div class="kg-card kg-callout-card kg-callout-card-blue"><div class="kg-callout-emoji">&#x1F4A5;</div><div class="kg-callout-text">Interested in testing it out in your environment? <em>The</em> <em>Toolbox</em> newsletter members can download the typescript for free and import it directly into Retool to use immediately. <br><br>Subscribe to <em>The Toolbox</em> for free to skip the tutorial and download the JSON at the <a href="#download-the-sample-toolscript">end of this article </a>&#x2B07;&#xFE0F;</div></div><p></p><h2 id="creating-a-sticky-footer">Creating a sticky footer <br></h2><p>One of our favorite elements of this UI design is the sticky footer at the bottom of the page. This isn&#x2019;t something that Retool natively offers in the main canvas, and can be a really useful addition to many Retool apps with the need for additional navigation options. </p><p>To do this, we used a container within the body of the canvas and ticked the &#x2018;expand content to fit&#x2019; to avoid padding from shifting everything about. <br></p><figure class="kg-card kg-image-card"><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXcn5rD7gZ4kaWLY64RoaHMw0_7zkbYESFMRFP1DqDp3TTsYSa0hNGxm_b_jqe_gY2DVogvVV92MFPrJ-nTbbkxRRsOidXK0kpoZJflU7GaFAl1tQAhRGnh8uw5rvUvYIlErfVW_04vEvsfBDDfr9WtKucY?key=U1SfsN5VGpZ-SRV3-5vXmGmY" class="kg-image" alt="Building the Steam UI on Retool (Retool UI &amp; Inspiration)" loading="lazy" width="484" height="343"></figure><p><br>We then set up the container with a footer option and added some necessary buttons.</p><figure class="kg-card kg-image-card"><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXd13elV6ni-lYCTfnsgpiI1HKnJFvKscuzaHdia83_hPHDWjI8zOgNKZZ4QR8aGYD-yCTujioCuNrBUfq-TJUkzLyAhQ4Wng4LHp1S3esMUniOGpMC0vKsZRVa3vm5XnqrKn7qkEDjxgdc8pntZTKDMxZ4?key=U1SfsN5VGpZ-SRV3-5vXmGmY" class="kg-image" alt="Building the Steam UI on Retool (Retool UI &amp; Inspiration)" loading="lazy" width="624" height="364"></figure><p><br>We also love this unique design of having a photo background and near-transparent container on top - this could be a great option for profile pages where it&#x2019;s nice to add a personal touch for users. <br><br>Here&#x2019;s the custom CSS we used to get it:<br></p><figure class="kg-card kg-image-card"><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXe5vLvyQxENoz8h_0l1_MwoZYYjQ87KfTff6Vdb0WgOVcEIxtiJ-EtESFSyr3r16bqis89bfX4OC6w23aL0VWdBTXirBhNW9CLM-lAhq1Vt9pcmAVolPp2g3GNUCWF6_8RPD3mT?key=U1SfsN5VGpZ-SRV3-5vXmGmY" class="kg-image" alt="Building the Steam UI on Retool (Retool UI &amp; Inspiration)" loading="lazy" width="624" height="209"></figure><pre><code class="language-CSS">}
._retool-profileContainer {
background-image: url(&quot;https://picsum.photos/id/301/800/600&quot;);
background-repeat: no-repeat;
background-size: cover;
}</code></pre><p><br></p><h2 id="using-custom-css-to-adapt-windows-scrollbars">Using Custom CSS to adapt Windows Scrollbars</h2><p></p><p>Bold Tech does a collective sigh when we hear our clients work on Windows&#x2026; not because we&#x2019;re Apple fanatics, but because Windows doesn&#x2019;t properly hide scrollbars when they&#x2019;re not in use. This means that containers and tables appear cluttered with multiple scroll bars all showing simultaneously and often confusing the user. </p><p></p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="http://143.198.97.195:2369/content/images/2024/11/image.png" class="kg-image" alt="Building the Steam UI on Retool (Retool UI &amp; Inspiration)" loading="lazy" width="1875" height="837" srcset="http://143.198.97.195:2369/content/images/size/w600/2024/11/image.png 600w, http://143.198.97.195:2369/content/images/size/w1000/2024/11/image.png 1000w, http://143.198.97.195:2369/content/images/size/w1600/2024/11/image.png 1600w, http://143.198.97.195:2369/content/images/2024/11/image.png 1875w" sizes="(min-width: 720px) 720px"><figcaption>Windows doesn&apos;t hide the scrollbar when the mouse isn&apos;t hovered - so apps can often look much messier and more confusing.&#xA0;</figcaption></figure><p></p><p>But thank the heavens for Mitchel, because with this Steam design, he figured out a way to hide these additional scrollbars with a little CSS trick. </p><p>This custom CSS adjusts the scrollbar&#x2019;s width, track, and color, improving the look and feel across the app.</p><pre><code class="language-CSS">/* width */
::-webkit-scrollbar {
width: 5px;
}
/* Track */
::-webkit-scrollbar-track {
box-shadow: clear;
border-radius: 10px;
}
/* Handle */
::-webkit-scrollbar-thumb {
background: #606774;
border-radius: 10px;
}
/* Handle on hover */
::-webkit-scrollbar-thumb:hover {
background: #BCBCBC;
}</code></pre><p><br></p><h2 id="applying-gradient-backgrounds-to-containers">Applying Gradient Backgrounds to Containers</h2><p></p><p>Steam&#x2019;s design includes subtle gradients and background visuals, which gives a sleek look we don&#x2019;t often see in apps in Retool. We replicated this in Retool by applying radial gradients with a little custom CSS. </p><p>As well as looking great, this is a subtle yet effective way of drawing the user&#x2019;s eye to the most important elements of the app that they need to interact with. You&#x2019;ll notice that the areas of the app without this glow seem to disappear more into the background, which is a great way to decentralize those secondary features and allow users to focus on primary actions. </p><p>With this code you can tweak the colors and percentages to get the effect you&#x2019;re looking for.</p><pre><code class="language-CSS">/* News Container */
._retool-newsContainer {
background-image: radial-gradient(
ellipse 60% 50% at 60% 110%,
steelblue 50%,
#464B53 95%
);
}
._retool-achievementsContainer {
background-image: radial-gradient(
circle farthest-side at 40% 150%,
steelblue 40%,
transparent 60%
);
}
._retool-underglowContainer {
background-image: radial-gradient(
circle farthest-side at 40% 250%,
steelblue 40%,
transparent 80%
);</code></pre><p><br></p><h2 id="double-navigation-bar">Double navigation bar</h2><p></p><p>Steam&#x2019;s interface uses a primary and secondary navigation bar at the top of the page, which creates a structured way to organize lots of navigation options without being overwhelming. We replicated this in Retool with stacked navigation containers. <br></p><figure class="kg-card kg-image-card"><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXfDh3AcZ8KoPLWfv-sF6_aRpbtNILHA8KKsD834xpDieBvSQGIYa5kcrA3BOfq5VnScdQpgTl-QIXqmyvK6fyzDA0daPLU0ujbJRl_yUDK7htHFnaviWauHH7kTM5Of9u7vyOrC_y2-DMslS1C60e4AEU8?key=U1SfsN5VGpZ-SRV3-5vXmGmY" class="kg-image" alt="Building the Steam UI on Retool (Retool UI &amp; Inspiration)" loading="lazy" width="624" height="136"></figure><p><br>The use of a larger font for the lower navigation is also a unique design choice that can be really useful for certain UIs - particularly when the secondary navigation is actually more important than the higher-level options in the first, top one. &#xA0;<br><br>That&#x2019;s the last in our quick series of <a href="http://143.198.97.195:2369/tag/ui-inspiration/">UI-inspiration</a> buildouts in Retool! While we don&#x2019;t expect you to go building the next <a href="http://143.198.97.195:2369/youtube-in-retool-ui-inspiration/">YouTube</a>, Steam, <a href="http://143.198.97.195:2369/hubspot-inspired-retool-crm-template/">Hubspot </a>(or even <a href="http://143.198.97.195:2369/creating-retool-in-retool-ui/">Retool</a>) on Retool itself anytime soon, we hope you enjoyed the exercise of pushing the limits of Retool for some cool out-of-the-box UI thinking - we certainly have!</p><p></p><div class="kg-card kg-callout-card kg-callout-card-blue"><div class="kg-callout-emoji">&#x1F4A5;</div><div class="kg-callout-text">At <a href="https://www.boldtech.dev/?ref=blog.boldtech.dev">Bold Tech,</a> we specialize in building great internal tools, fast. We are obsessed with building apps that make your teams happier and more productive. In our <a href="http://143.198.97.195:2369/">blog</a>, you can learn all about how to build better business software for more satisfied employees, or <a href="https://www.boldtech.dev/contact?ref=blog.boldtech.dev">get in contact</a> to chat to us about what you&apos;re looking to build.</div></div><p></p><h2 id="download-the-sample-toolscript">Download the sample toolscript</h2><p>The Toolbox newsletter members can download the JSON and import it directly into their Retool environment to test it out &#x2B07;&#xFE0F;&#x2B07;&#xFE0F;&#x2B07;&#xFE0F;</p>]]></content:encoded></item><item><title><![CDATA[Retool for Enterprises Part 1: The Basics]]></title><description><![CDATA[Retool is a powerful tool for enterprises yet many still struggle to build for scale. In this first article, we’ll cover essentials for enterprises, like how they can use Retool best, pricing plans and self-hosted vs cloud.]]></description><link>http://143.198.97.195:2369/retool-for-enterprises-basics/</link><guid isPermaLink="false">6728e380dbece927645cdd05</guid><category><![CDATA[Retool Enterprise]]></category><category><![CDATA[What is...]]></category><category><![CDATA[Retool]]></category><dc:creator><![CDATA[Stefan Cvrkotic]]></dc:creator><pubDate>Wed, 20 Nov 2024 14:00:17 GMT</pubDate><media:content url="http://143.198.97.195:2369/content/images/2024/11/Bold-tech-blog-thumb--1-.png" medium="image"/><content:encoded><![CDATA[<img src="http://143.198.97.195:2369/content/images/2024/11/Bold-tech-blog-thumb--1-.png" alt="Retool for Enterprises Part 1: The Basics"><p>With an ever-expanding portfolio of prominent enterprise clients, Retool has firmly established itself as a powerful platform uniquely suited to meet the complex needs of large organizations looking to accelerate the development of their business software.<br></p><p>Nevertheless, it&apos;s remarkable how many large, technical Enterprises today use Retool for their internal tools yet still rely on guidance from dispersed Retool forum threads to manage their instances. <br></p><p>As a <a href="https://www.boldtech.dev/what-we-do?ref=143.198.97.195">Retool-focused development agency</a>, we talk to Enterprise teams each day who are unsure of how to create scalable application infrastructures in Retool. While Retool is an incredible tool that has enabled their teams to build fast and iterate even faster, engineering managers often find their teams losing control of a disorganized web of applications, with no real accountability for maintenance, nor consistent organization. &#xA0;<br></p><p>Since we&#x2019;ve worked with dozens of Enterprise companies to manage and improve their Retool app infrastructure, in <a href="http://143.198.97.195:2369/tag/retool-enterprise/">this series of blog posts</a> we hope to demystify some of the most Retool misunderstandings and paint a clearer picture of how to manage your instance properly, avoiding common anti-patterns we see in large-scale Retool deployments.<br></p><p>To start, we&#x2019;re going to focus on the basics of <a href="http://143.198.97.195:2369/tag/retool-enterprise/">Retool for Enterprises</a>, including what solutions Retool provides for Enterprise companies, what pricing plan they might need (hint: it&#x2019;s not always Enterprise), and whether or not cloud or self-hosting is more suitable for large infrastructures.<br></p><p>Let&#x2019;s dive in.<br><br></p><h2 id="how-does-retool-cater-to-the-needs-of-enterprise-businesses">How does Retool cater to the needs of enterprise businesses?</h2><p>Contrary to some expectations, and unlike most no- or low-code tools, Retool is very well-suited to large-scale Enterprise use cases and even mission-critical tools. </p><p>Retool has long targeted the needs of large tech companies to ensure their product is suitable for larger-scale deployments with increased security needs. Some of these features include Okta support, SCM provider support, and audit trails. &#xA0;</p><p>But, most importantly, Retool&#x2019;s core philosophy is to provide a tool that expedites development time <em>for developers, </em>not to provide a low-code tool for business users, an essential consideration for Enterprise teams.</p><p>So what can Enterprise companies expect from using Retool? &#xA0;<br></p><p></p><h3 id="a-space-for-engineers-to-interact-with-resources-quickly-and-securely">A space for engineers to interact with resources quickly and securely</h3><p><br>For enterprises, Retool greatly reduces friction when creating and interacting with business resources and integrations. <br></p><p>Retool simplifies connecting to enterprise resources by configuring database and API connections with a single, secure authentication setup, which minimizes the need for manual connection management. <br></p><p>Thanks to Retool&#x2019;s centralized configuration, developers can quickly access data across different sources without setting up application-specific authentication layers or repeatedly managing credentials across all of their internal tools. <br></p><p>Retool also provides an intuitive interface for managing detailed permissions, making it easy to access resources in a compliant and secure way. Managers can adjust permissions quickly and flexibly as needed across each Retool Space.<br></p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="http://143.198.97.195:2369/content/images/2025/04/uno.png" class="kg-image" alt="Retool for Enterprises Part 1: The Basics" loading="lazy" width="1600" height="408" srcset="http://143.198.97.195:2369/content/images/size/w600/2025/04/uno.png 600w, http://143.198.97.195:2369/content/images/size/w1000/2025/04/uno.png 1000w, http://143.198.97.195:2369/content/images/2025/04/uno.png 1600w" sizes="(min-width: 720px) 720px"><figcaption>Retool permissions allow for granular control over access to both resources and applications.</figcaption></figure><p></p><h3 id="an-opportunity-to-reduce-saas-seats-and-sprawl">An opportunity to reduce SaaS seats and sprawl<br></h3><p>A successful approach for many large enterprises using Retool is to leverage the platform to reduce the number of SaaS licenses required across their teams. By consolidating applications, companies can avoid paying for multiple seats on platforms that some employees rarely use directly. Instead of maintaining individual licenses for tools like Airtable, Salesforce, and Zendesk, enterprises can streamline access and control costs.<br></p><p>With Retool, teams can pull data from these external platforms via APIs and present it in custom-built applications tailored to specific job functions. This means that employees who don&#x2019;t need to work directly within each tool can still access the necessary data to perform their tasks efficiently&#x2014;all within Retool. This approach not only reduces expenses but also simplifies workflows, enabling better focus on essential operations.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="http://143.198.97.195:2369/content/images/2025/04/dos.png" class="kg-image" alt="Retool for Enterprises Part 1: The Basics" loading="lazy" width="1244" height="700" srcset="http://143.198.97.195:2369/content/images/size/w600/2025/04/dos.png 600w, http://143.198.97.195:2369/content/images/size/w1000/2025/04/dos.png 1000w, http://143.198.97.195:2369/content/images/2025/04/dos.png 1244w" sizes="(min-width: 720px) 720px"><figcaption>Data from a number of external platforms like Salesforce, Google Sheets and Airtable, amongst others, can be pulled into Retool.</figcaption></figure><h3 id="a-platform-to-expedite-development-speed-and-cut-engineering-costs">A platform to expedite development speed and cut engineering costs<br><br></h3><p>Instead of relying on traditional development methods, like a Django Admin portal or a custom internal application built with PHP, teams can use Retool to build such apps much faster and maintain them more easily. Retool offers an excellent way to modernize outdated legacy software with more agile, iterative solutions, while also consolidating your tech stack into a single, centralized, and highly manageable system. For enterprises, Retool also significantly lowers the cost of building temporary internal apps for short-term projects. <br></p><p>What&#x2019;s more, Retool is packed with security features that meet most requirements of Enterprise deployments, including self-hosting, Git source control, custom SSO, testing options, and more. <br></p><p>Now we&#x2019;ve covered some of the principal benefits of Retool for Enterprise companies, let&#x2019;s take a closer look at the pricing plans and the considerations for Enterprises with potentially large deployments. <br><br></p><h2 id="what-retool-plan-do-i-need-business-vs-enterprise-plans">What Retool plan do I need? Business vs Enterprise plans</h2><p>First things first, ignore the label: Enterprise companies aren&#x2019;t obliged to pay for an Enterprise plan straight away. For larger companies with higher security concerns, it boils down to a couple of core features that determine whether you&#x2019;ll need to be on either the Business or Enterprise plan. These features mostly revolve around security, Retool support level and data compliance requirements. <br></p><p>Regardless of your long-term needs, however, we typically suggest to our clients in an early adoption phase with Retool to start on the business plan. The business plan has all of Retool&#x2019;s core features, and starting on a lower plan will give you a better understanding of how the platform is structured before committing to a larger investment. Retool will always be on hand to help upgrade you to Enterprise when the time comes, so there&#x2019;s no real loss in gaining a base-level understanding of the platform and ensuring the best product fit before seeking out Enterprise pricing from their sales team.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="http://143.198.97.195:2369/content/images/2025/04/tres.png" class="kg-image" alt="Retool for Enterprises Part 1: The Basics" loading="lazy" width="1090" height="1074" srcset="http://143.198.97.195:2369/content/images/size/w600/2025/04/tres.png 600w, http://143.198.97.195:2369/content/images/size/w1000/2025/04/tres.png 1000w, http://143.198.97.195:2369/content/images/2025/04/tres.png 1090w" sizes="(min-width: 720px) 720px"><figcaption>A summary of Retool&apos;s Business and Enterprise plans including respective prices and service offerings.</figcaption></figure><p><br>It&#x2019;s important to note here that the Business plan has all the in-app permission levels of the Enterprise plan, aside from environment permissioning. This means that even before you make the jump to the Enterprise plan, you can begin implementing these permissions from the offset whilst on the business plan. Starting with this basic structure will put you in the best place to implement more complex permissioning infrastructure if you move to the Enterprise tier (which can be overwhelming at first). </p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="http://143.198.97.195:2369/content/images/2025/04/cuatro.png" class="kg-image" alt="Retool for Enterprises Part 1: The Basics" loading="lazy" width="1170" height="568" srcset="http://143.198.97.195:2369/content/images/size/w600/2025/04/cuatro.png 600w, http://143.198.97.195:2369/content/images/size/w1000/2025/04/cuatro.png 1000w, http://143.198.97.195:2369/content/images/2025/04/cuatro.png 1170w" sizes="(min-width: 720px) 720px"><figcaption>A list of Retool&apos;s default grouping list used to separate users based on their access requirements.</figcaption></figure><div class="kg-card kg-callout-card kg-callout-card-grey"><div class="kg-callout-emoji">&#x1F4A1;</div><div class="kg-callout-text">Permissioning tip: Make sure to use Retool&#x2019;s default groupings to separate your users from the offset. When they are added to the environment, users will land in the all-users group. The &#x2018;End users&#x2019; group is for users that shouldn&#x2019;t be able to edit apps, but will just be using them without edit access. For devs that will need edit access to apps, put them in the &#x2018;Editor&#x2019; groups. This is the most basic permissioning that you need.<br><br>In a future article in this Enterprise series, we will dive deeper into advanced permissioning in Retool.&#xA0;</div></div><p></p><p>Even if you start using Retool on the business tier, it&#x2019;s important to be aware of the Enterprise-only features that you may require in the future, to make sure you&#x2019;re best prepared for an eventual upgrade if needed. Let&#x2019;s take a closer look at the most commonly required Enterprise features.<br><br></p><h3 id="key-features-that-push-companies-to-the-retool-enterprise-plan">Key features that push companies to the Retool Enterprise Plan</h3><p>In our experience, here are the most common limitations of the business plan that typically force a company to seek out the Enterprise plan in Retool.<br></p><p><strong>100 user limit on Self-Hosted - </strong>For on-prem deployments, Retool is limited to a maximum of 100 users on both the Teams and Business plans. If your company requires your deployment to be managed on-prem, you&#x2019;ll need to consider if and when you&#x2019;ll hit that 100 user limit. We&#x2019;ll dig more into Cloud vs Self-hosted in the next section. <br></p><p><strong>Custom SSO - </strong>If your company needs to integrate with Okta or any other <a href="https://docs.retool.com/sso/tutorials/custom/saml?ref=143.198.97.195">SAML SSO provider</a>, you will have to upgrade to a Retool Enterprise plan.<br></p><p><strong>Source Control through your SCM Provider - </strong>Retool<strong> </strong>offers native versioning, which you can read more about <a href="http://143.198.97.195:2369/release-manager-versioning-explained-how-to-develop-together-best-in-retool/">here</a>. But, you do have to be on Enterprise to manage your versioning through Github or your company&apos;s SCM provider.<br></p><p><strong>Resource environment permissions - </strong>A common development pattern for high-security deployments is to give certain developers access only to a secure staging environment, thereby not exposing any PII or production data whilst they are developing. On the business plan, it&#x2019;s possible to configure different <a href="https://docs.retool.com/org-users/guides/environments?ref=143.198.97.195">resource environments</a>, but you can&#x2019;t manage permissions on an environment level. To do this kind of environment permissioning on the business plan, you would need a multi-instance deployment.<br><br><strong>Retool Spaces - </strong>Retool recently released <a href="https://docs.retool.com/org-users/guides/configure-spaces?ref=143.198.97.195">Retool Spaces</a> as a way of segmenting your teams into separate instances, whilst still managing them through a single, overarching admin instance. It&#x2019;s still possible to create a similar effect on other plans through proper permission management, but Spaces makes these full team separations straightforward and easier to manage. <br></p><p>Now that we&#x2019;ve run through the essentials, what are some additional features on the Retool Enterprise plan that may be beneficial to companies?</p><p></p><h3 id="nice-to-have-enterprise-retool-features">Nice-to-have Enterprise Retool features</h3><p>We wouldn&#x2019;t really consider these features necessities that should dictate your upgrade to an Enterprise plan, but they can certainly be useful additions if you are already on the plan. <br></p><p>We call these features the &#x2018;Nice-to-haves&#x2019;:<br></p><p><strong>Analytics &amp; audit Logs - </strong>Retool has created a usage analytics page where admins can see app saves and views. This is useful for tracking adoption of apps across teams. Nevertheless, at this time we find this page to be quite limited. You can actually create your own analytics and audit log pages on-prem by querying the audit trail events table. We&#x2019;ll be writing about this in another article in the series.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="http://143.198.97.195:2369/content/images/2025/04/cinco.png" class="kg-image" alt="Retool for Enterprises Part 1: The Basics" loading="lazy" width="1600" height="1020" srcset="http://143.198.97.195:2369/content/images/size/w600/2025/04/cinco.png 600w, http://143.198.97.195:2369/content/images/size/w1000/2025/04/cinco.png 1000w, http://143.198.97.195:2369/content/images/2025/04/cinco.png 1600w" sizes="(min-width: 720px) 720px"><figcaption>A usage analytics page in Retool.</figcaption></figure><p>As self-hosted plans with 100+ users are the most common feature that pushes Enterprises into the Enterprise plan, let&#x2019;s dive a little deeper into the pros and cons of each.</p><p><strong>Full Retool API Access- </strong>Retool API is a way to programmatically manage different parts of your Retool environment. It&#x2019;s technically in Beta as of November 2024, but several of our enterprise clients have been using it for the past six months. Through the API, the individual responsible for the deployment can manage themes, source control, spaces, as well as user permissions through an API endpoint. This can be extremely useful for having full operational control over your environment. But we&#x2019;ve noted that since you can still interact with all of these environment level features without API access, this is more of a nice-to-have. <br><br></p><h2 id="cloud-vs-self-hosted-deployment-of-retool-migration-challenges">Cloud vs Self Hosted Deployment of Retool: Migration challenges<br></h2><p>Enterprises typically know from the outset whether they&#x2019;ll need to host their Retool deployment on the cloud or on-prem. The real question is often whether they need to start with on prem immediately, and making the right choice here is crucial.</p><p>If at any point, Retool is likely to become a large deployment and a high level of security is essential to you, we would highly suggest<strong> starting with the self-hosted version </strong>of Retool from the beginning. Starting with Retool already On-prem (even before upgrading to Enterprise) prevents you from facing a long and complicated migration period from Cloud to Self-hosted when the time does come. </p><p>We ourselves have helped Enterprises manage large-scale migrations from Retool Cloud to Self-hosted deployments, and these projects often transpire into months of complication. &#xA0; Starting with self-hosted Retool from the offset is a great way to reduce complexities and tech-debt if you are certain that you will need it in the future. </p><p>Retool provides set-up documentation for deploying within your VPC or whatever format that abides to your company&#x2019;s standard. If you start with this from the offset, it will save you the struggle of matching versioning, recreating permission sets, and migrating between the instances.</p><p>As of 2024, Retool introduced <a href="https://docs.retool.com/releases/?ref=143.198.97.195">Retool &#x2018;Stable Releases&#x2019; to self-hosted</a>. Stable releases are quarterly releases that trail behind their cloud deployments by a couple of versions and promote application stability since they have been more thoroughly tested on the cloud&#x2019;s most recent release. For mission-critical workloads, having a stable release on self-hosted provides more peace of mind that a new release won&#x2019;t break your application, and for such usecases we would suggest an on-prem deployment. On Cloud versions of Retool you don&#x2019;t have the choice to upgrade your environment as this is done automatically, which can cause problems if bugs occur. <br></p><hr><p>So there were some of the basics of Retool for Enterprise. In the <a href="http://143.198.97.195:2369/tag/retool-enterprise/">rest of the series</a> we&#x2019;ll be discussing topics like: <br></p><ul><li>Advanced, scalable permissions</li><li>Resource handling</li><li>Complex deployment handling</li><li>Source control</li><li>Multipage apps</li><li>Environment variables<br></li></ul><p>And more. Keep an eye on our blog for more info or sign up to our newsletter to be the first to know.</p><div class="kg-card kg-button-card kg-align-center"><a href="#/portal/signup/free" class="kg-btn kg-btn-accent">Sign up to the Toolbox newsletter</a></div><div class="kg-card kg-callout-card kg-callout-card-blue"><div class="kg-callout-emoji">&#x1F4A5;</div><div class="kg-callout-text">At <a href="https://www.boldtech.dev/?ref=blog.boldtech.dev">Bold Tech,</a> we specialize in building great internal tools, fast. We are obsessed with building apps that make your teams happier and more productive. In our <a href="http://143.198.97.195:2369/">blog</a>, you can learn all about how to build better business software for more satisfied employees, or <a href="https://www.boldtech.dev/contact?ref=blog.boldtech.dev">get in contact</a> to chat to us about what you&apos;re looking to build.</div></div><p></p><p></p>]]></content:encoded></item><item><title><![CDATA[Creating Retool in Retool (Retool UI inspiration & template)]]></title><description><![CDATA[In this UI inspiration piece, we created Retool-ception. Retool, built on Retool. Check it out! Newsletter members can download the template too.]]></description><link>http://143.198.97.195:2369/creating-retool-in-retool-ui/</link><guid isPermaLink="false">672225a5dbece927645cd9cc</guid><category><![CDATA[UI inspiration]]></category><category><![CDATA[UX / UI Guides]]></category><category><![CDATA[Retool]]></category><category><![CDATA[Templates]]></category><dc:creator><![CDATA[Joey Karczewski]]></dc:creator><pubDate>Wed, 13 Nov 2024 15:00:15 GMT</pubDate><media:content url="http://143.198.97.195:2369/content/images/2024/11/Bold-tech-blog-thumb--3-.png" medium="image"/><content:encoded><![CDATA[<img src="http://143.198.97.195:2369/content/images/2024/11/Bold-tech-blog-thumb--3-.png" alt="Creating Retool in Retool (Retool UI inspiration &amp; template)"><p>We&#x2019;re not entirely sure if the <a href="http://143.198.97.195:2369/what-is-retool/">Retool</a> community is ready for this&#x2026; but we&#x2019;re doing it anyway. In the next of our <a href="http://143.198.97.195:2369/tag/ui-inspiration/">Retool UI-inspiration series</a> (where we use Retool to replicate well-known UIs we like) we created the ultimate Retool UI dupe - it&#x2019;s Retool. On Retool. No guts, no glory.</p><p>Here&#x2019;s what it looks like:</p><!--kg-card-begin: html--><!--ARCADE EMBED START--><div style="position: relative; padding-bottom: calc(54.78515625% + 41px); height: 0; width: 100%;"><iframe src="https://demo.arcade.software/hu1UOKtFDql1ImzAmWha?embed&amp;embed_mobile=inline&amp;embed_desktop=inline&amp;show_copy_link=true" title="Retool in Retool UI" frameborder="0" loading="lazy" webkitallowfullscreen mozallowfullscreen allowfullscreen allow="clipboard-write" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; color-scheme: light;"></iframe></div><!--ARCADE EMBED END--><!--kg-card-end: html--><p></p><p>Don&#x2019;t believe us that this isn&#x2019;t just&#x2026; Retool? <a href="https://sandbox.practicemode.retool.com/p/retool?ref=143.198.97.195">Have a play around</a> and see for yourself.</p><p>And, if you&#x2019;re feeling really daring, members of our newsletter can download the JSON to blow their minds in edit mode too.</p><div class="kg-card kg-callout-card kg-callout-card-blue"><div class="kg-callout-emoji">&#x1F4A5;</div><div class="kg-callout-text">Interested in testing it out in your environment? <em>The</em> <em>Toolbox</em> newsletter members can download the typescript for free and import it directly into Retool to use immediately. <br><br>Subscribe to <em>The Toolbox</em> for free to skip the tutorial and download the JSON at the <a href="#download-the-sample-toolscript">end of this article </a>&#x2B07;&#xFE0F;</div></div><p>Once you&#x2019;ve got your head around the Retool-ception, keep reading for some key UI pattern takeaways from this most monumental UI endeavor yet. </p><p>Key disclaimer: Yes, this was Stefan, and no, he cannot be stopped.</p><p></p><h2 id="closable-notification-containers">Closable Notification Containers</h2><p></p><p>Why not have notifications in your Retool apps? Using the Retool style of container you can set up notifications for your users that alert them to new features, important announcements and updates, that can quickly be closed away when read. This is particularly useful for the Home pages of multi-page dashboards. </p><figure class="kg-card kg-image-card"><img src="http://143.198.97.195:2369/content/images/2025/04/1.png" class="kg-image" alt="Creating Retool in Retool (Retool UI inspiration &amp; template)" loading="lazy" width="916" height="900" srcset="http://143.198.97.195:2369/content/images/size/w600/2025/04/1.png 600w, http://143.198.97.195:2369/content/images/2025/04/1.png 916w" sizes="(min-width: 720px) 720px"></figure><p>In Retool, (real Retool, not Retool on Retool) you can natively perform this use experience by using the setHidden event handler and the close button. You can use a listview with a setHidden event handler on each container to surface and hide notifications that might be relevant to the end user. </p><figure class="kg-card kg-image-card"><img src="http://143.198.97.195:2369/content/images/2025/04/2.png" class="kg-image" alt="Creating Retool in Retool (Retool UI inspiration &amp; template)" loading="lazy" width="1260" height="748" srcset="http://143.198.97.195:2369/content/images/size/w600/2025/04/2.png 600w, http://143.198.97.195:2369/content/images/size/w1000/2025/04/2.png 1000w, http://143.198.97.195:2369/content/images/2025/04/2.png 1260w" sizes="(min-width: 720px) 720px"></figure><p></p><h2 id="minimalistic-and-well-styled-listviews">Minimalistic and well-styled listviews</h2><p></p><p>We bet you didn&#x2019;t think that our app menu was a built in a listview! The Listview is a little neglected as a component: we often find that, since listviews take longer to configure, people don&#x2019;t fully stylize them and their Listviews end up looking like clunky cards rather than tidy lists.</p><figure class="kg-card kg-image-card"><img src="http://143.198.97.195:2369/content/images/2025/04/3.png" class="kg-image" alt="Creating Retool in Retool (Retool UI inspiration &amp; template)" loading="lazy" width="1600" height="574" srcset="http://143.198.97.195:2369/content/images/size/w600/2025/04/3.png 600w, http://143.198.97.195:2369/content/images/size/w1000/2025/04/3.png 1000w, http://143.198.97.195:2369/content/images/2025/04/3.png 1600w" sizes="(min-width: 720px) 720px"></figure><p>In this app we used all kinds of stylistic tricks to hide the fact that this list is made of a list view component - download the app to find out how! Listviews can be more flexible than tables, since you can use any component within them and there can be more options for editability. Plus, a well-styled Listview can look very beautiful too.</p><figure class="kg-card kg-image-card"><img src="http://143.198.97.195:2369/content/images/2025/04/4.png" class="kg-image" alt="Creating Retool in Retool (Retool UI inspiration &amp; template)" loading="lazy" width="1600" height="666" srcset="http://143.198.97.195:2369/content/images/size/w600/2025/04/4.png 600w, http://143.198.97.195:2369/content/images/size/w1000/2025/04/4.png 1000w, http://143.198.97.195:2369/content/images/2025/04/4.png 1600w" sizes="(min-width: 720px) 720px"></figure><p></p><h2 id="subtle-user-feedback-container-hovers">Subtle user feedback: container hovers</h2><p></p><p>One of our favorite things to do when developing in Retool is to use design patterns that are 99% invisible but still highly effective in guiding the user experience. In the top right-hand corner you can see the outline change on hover. There&#x2019;s a reason Retool uses this: this kind of subtle feedback helps users understand the UI intuitively without needing instructions or feeling overwhelmed with repetitive buttons or text. They might realize something is clickable that wasn&#x2019;t obvious before or notice a button better.</p><figure class="kg-card kg-image-card"><img src="http://143.198.97.195:2369/content/images/2025/04/5.png" class="kg-image" alt="Creating Retool in Retool (Retool UI inspiration &amp; template)" loading="lazy" width="782" height="372" srcset="http://143.198.97.195:2369/content/images/size/w600/2025/04/5.png 600w, http://143.198.97.195:2369/content/images/2025/04/5.png 782w" sizes="(min-width: 720px) 720px"></figure><p>To achieve this, we can write a short snippet in the button&#x2019;s &#x2018;border&#x2019; styling, to change the border color on hover. </p><figure class="kg-card kg-image-card"><img src="http://143.198.97.195:2369/content/images/2025/04/6.png" class="kg-image" alt="Creating Retool in Retool (Retool UI inspiration &amp; template)" loading="lazy" width="952" height="532" srcset="http://143.198.97.195:2369/content/images/size/w600/2025/04/6.png 600w, http://143.198.97.195:2369/content/images/2025/04/6.png 952w" sizes="(min-width: 720px) 720px"></figure><p>The &#x2018;hovered&#x2019; attribute can be so useful in Retool apps and deserves much more usage: drop shadows on containers and buttons, background color changes, and more. <br><br>Interested in playing around with how we did this in your own environment? Members can download the Toolscript below to import it directly into their Retool environment.</p><p>In the rest of this <a href="http://143.198.97.195:2369/tag/ui-inspiration/">UI inspiration series</a>, we recreate some of our favorite application UI&apos;s, like Steam, <a href="http://143.198.97.195:2369/reddit-inspired-ui-in-retool/">Reddit</a>, <a href="http://143.198.97.195:2369/youtube-in-retool-ui-inspiration/">YouTube</a> and even <a href="http://143.198.97.195:2369/creating-retool-in-retool-ui/">Retool</a> itself. Make sure to check them out!</p><div class="kg-card kg-callout-card kg-callout-card-blue"><div class="kg-callout-emoji">&#x1F4A5;</div><div class="kg-callout-text">At <a href="https://www.boldtech.dev/?ref=blog.boldtech.dev">Bold Tech,</a> we specialize in building great internal tools, fast. We are obsessed with building apps that make your teams happier and more productive. In our <a href="http://143.198.97.195:2369/">blog</a>, you can learn all about how to build better business software for more satisfied employees, or <a href="https://www.boldtech.dev/contact?ref=blog.boldtech.dev">get in contact</a> to chat to us about what you&apos;re looking to build.</div></div><h2 id="download-the-sample-toolscript">Download the sample toolscript</h2><p>The Toolbox newsletter members can download the JSON and import it directly into their Retool environment to test it out &#x2B07;&#xFE0F;&#x2B07;&#xFE0F;&#x2B07;&#xFE0F;</p>]]></content:encoded></item><item><title><![CDATA[How we built YouTube in Retool (Retool UI inspiration & template)]]></title><description><![CDATA[In this UI inspiration template, we have recreated the YouTube UI using Retool! Newsletter members can download the template for free.]]></description><link>http://143.198.97.195:2369/youtube-in-retool-ui-inspiration/</link><guid isPermaLink="false">67234077dbece927645cd9d3</guid><category><![CDATA[UI inspiration]]></category><category><![CDATA[Retool]]></category><category><![CDATA[Templates]]></category><category><![CDATA[Retool Template]]></category><dc:creator><![CDATA[Milan Kalem]]></dc:creator><pubDate>Wed, 06 Nov 2024 15:00:02 GMT</pubDate><media:content url="http://143.198.97.195:2369/content/images/2024/10/Bold-tech-blog-thumb--1-.jpg" medium="image"/><content:encoded><![CDATA[<img src="http://143.198.97.195:2369/content/images/2024/10/Bold-tech-blog-thumb--1-.jpg" alt="How we built YouTube in Retool (Retool UI inspiration &amp; template)"><p>We&#x2019;re back once again to bust the myth that <a href="http://143.198.97.195:2369/tag/ui-inspiration/">cool and complex UIs</a> aren&#x2019;t possible in <a href="http://143.198.97.195:2369/what-is-retool/">Retool</a>. With this week&#x2019;s release, we&#x2019;re sharing one of our proudest UI replicas: YouTube, but - you guessed it - in Retool.</p><p>You might not be looking to take on the Google giant with a video platform competitor built on Retool any time soon, but this example does show that there are some really unique UI features that you can build with a little tweaking of Retool&#x2019;s native components.</p><figure class="kg-card kg-video-card kg-card-hascaption"><div class="kg-video-container"><video src="http://143.198.97.195:2369/content/media/2024/10/Arcade-Flow--Wed-Oct-30-2024-.mp4" poster="https://img.spacergif.org/v1/1280x766/0a/spacer.png" width="1280" height="766" playsinline preload="metadata" style="background: transparent url(&apos;http://143.198.97.195:2369/content/images/2024/10/media-thumbnail-ember2275.jpg&apos;) 50% 50% / cover no-repeat;"></video><div class="kg-video-overlay"><button class="kg-video-large-play-icon"><svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24"><path d="M23.14 10.608 2.253.164A1.559 1.559 0 0 0 0 1.557v20.887a1.558 1.558 0 0 0 2.253 1.392L23.14 13.393a1.557 1.557 0 0 0 0-2.785Z"/></svg></button></div><div class="kg-video-player-container"><div class="kg-video-player"><button class="kg-video-play-icon"><svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24"><path d="M23.14 10.608 2.253.164A1.559 1.559 0 0 0 0 1.557v20.887a1.558 1.558 0 0 0 2.253 1.392L23.14 13.393a1.557 1.557 0 0 0 0-2.785Z"/></svg></button><button class="kg-video-pause-icon kg-video-hide"><svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24"><rect x="3" y="1" width="7" height="22" rx="1.5" ry="1.5"/><rect x="14" y="1" width="7" height="22" rx="1.5" ry="1.5"/></svg></button><span class="kg-video-current-time">0:00</span><div class="kg-video-time">/<span class="kg-video-duration"></span></div><input type="range" class="kg-video-seek-slider" max="100" value="0"><button class="kg-video-playback-rate">1&#xD7;</button><button class="kg-video-unmute-icon"><svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24"><path d="M15.189 2.021a9.728 9.728 0 0 0-7.924 4.85.249.249 0 0 1-.221.133H5.25a3 3 0 0 0-3 3v2a3 3 0 0 0 3 3h1.794a.249.249 0 0 1 .221.133 9.73 9.73 0 0 0 7.924 4.85h.06a1 1 0 0 0 1-1V3.02a1 1 0 0 0-1.06-.998Z"/></svg></button><button class="kg-video-mute-icon kg-video-hide"><svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24"><path d="M16.177 4.3a.248.248 0 0 0 .073-.176v-1.1a1 1 0 0 0-1.061-1 9.728 9.728 0 0 0-7.924 4.85.249.249 0 0 1-.221.133H5.25a3 3 0 0 0-3 3v2a3 3 0 0 0 3 3h.114a.251.251 0 0 0 .177-.073ZM23.707 1.706A1 1 0 0 0 22.293.292l-22 22a1 1 0 0 0 0 1.414l.009.009a1 1 0 0 0 1.405-.009l6.63-6.631A.251.251 0 0 1 8.515 17a.245.245 0 0 1 .177.075 10.081 10.081 0 0 0 6.5 2.92 1 1 0 0 0 1.061-1V9.266a.247.247 0 0 1 .073-.176Z"/></svg></button><input type="range" class="kg-video-volume-slider" max="100" value="100"></div></div></div><figcaption>YouTube in Retool... using native components you can build some cool UIs for your internal applications.&#xA0;</figcaption></figure><p>You can play with the Re<em>tube</em> <a href="https://sandbox.practicemode.retool.com/embedded/public/78d7cf44-200e-4e4b-aa4f-4466336172cb?ref=143.198.97.195">here</a>. </p><div class="kg-card kg-callout-card kg-callout-card-blue"><div class="kg-callout-emoji">&#x1F4A5;</div><div class="kg-callout-text">Interested in testing it out in your environment? <em>The</em> <em>Toolbox</em> newsletter members can download the toolscript for free and import it directly into Retool to use immediately. <br><br>Subscribe to <em>The Toolbox</em> for free to skip the article and download the JSON at the <a href="#download-the-sample-toolscript">end of this article </a>&#x2B07;&#xFE0F;</div></div><p>Let&#x2019;s go through some of our highlights and discuss how we might apply them to other Retool apps.</p><p></p><h2 id="retool-popovers">Retool &apos;popovers&apos;</h2><p></p><p>Our favorite UI feature in this replica is the popover effect on menu items. A &#x2018;popover&#x2019; is a technical view, often a summary or a menu, that appears over other content when people click it. It&#x2019;s a great way to optimize screen space with information that doesn&#x2019;t need to be used at all times and is also very familiar to people as a common UI pattern across many highly used web apps like YouTube.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="http://143.198.97.195:2369/content/images/2025/04/one.png" class="kg-image" alt="How we built YouTube in Retool (Retool UI inspiration &amp; template)" loading="lazy" width="914" height="892" srcset="http://143.198.97.195:2369/content/images/size/w600/2025/04/one.png 600w, http://143.198.97.195:2369/content/images/2025/04/one.png 914w" sizes="(min-width: 720px) 720px"><figcaption>Using Retool, optimize UI and screen space with a popover effect on your app&apos;s menu items.</figcaption></figure><p>This is not a UI style that we see in Retool very often, and that&#x2019;s because frankly, this is a really sneaky hack. In short (we&#x2019;ll share a more detailed tutorial in the next few weeks), the way you can achieve this style of UI is by placing your summary into a container body, with a toggle button set to show/hide the body, and then placing that into another container&#x2019;s header box. In this app, you can see this effect in the notifications section, add new video button, and the search bar.</p><p>It&#x2019;s not a perfect option yet, and some additional tweaks need to be made to make this as seamless a user experience as possible, but it can nevertheless be a great option in many Retool app UIs.</p><p></p><h2 id="centralized-search-bar">Centralized search bar</h2><p></p><p>We see a lot of Retool apps with the same search bar style: placed to the top-left side of a table with several dropdown filters. Shake it up! Placing a centered search with filters underneath as tabs is a common UI pattern in web applications outside of Retool, and one that ought to be used more in Retool apps too. &#xA0;This style of search and filter is easy to achieve using the tabs component (set to pills) and can be more intuitive for users who use platforms like AirBnb or YouTube often.</p><p>In terms of<a href="http://143.198.97.195:2369/ui-tips-efficient-dashboards-retool/#filters"> filtering views</a>, tabs are a great way to create a single-click style of common filters that doesn&#x2019;t require users to constantly scroll through long dropdown lists. As you can see in the YouTube replica, even having more than a dozen options can still look tidy when presented in the right way. Note, this is best reserved for UIs where filtering is one of the key functions users will be performing (as in YouTube) since otherwise, this style of UI can be overly busy.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="http://143.198.97.195:2369/content/images/2025/04/two.png" class="kg-image" alt="How we built YouTube in Retool (Retool UI inspiration &amp; template)" loading="lazy" width="1600" height="421" srcset="http://143.198.97.195:2369/content/images/size/w600/2025/04/two.png 600w, http://143.198.97.195:2369/content/images/size/w1000/2025/04/two.png 1000w, http://143.198.97.195:2369/content/images/2025/04/two.png 1600w" sizes="(min-width: 720px) 720px"><figcaption>Improve UI by opting for tabbed and centred filters to keep your app&apos;s screen tidy.</figcaption></figure><h2 id="creating-a-collapsible-sidebar-in-retool">Creating a collapsible sidebar in Retool</h2><p></p><p>Another one of our features to highlight in this YouTube replica is the <a href="http://143.198.97.195:2369/5-great-sidebar-layouts-in-retool-ux-ui/">collapsible sidebar</a>. This option to dynamically hide or show the sidebar navigation by the hamburger icon is a really familiar UI style that users will typically instinctively recognize, and can be a great way to give users the option for more screen space when needed. Don&#x2019;t forget to place the toggle button in the header frame to ensure it&#x2019;s always shown!</p><figure class="kg-card kg-video-card"><div class="kg-video-container"><video src="http://143.198.97.195:2369/content/media/2024/10/Screen-Recording-2024-10-30-at-15.47.52.mp4" poster="https://img.spacergif.org/v1/1432x1076/0a/spacer.png" width="1432" height="1076" loop autoplay muted playsinline preload="metadata" style="background: transparent url(&apos;http://143.198.97.195:2369/content/images/2024/10/media-thumbnail-ember954.jpg&apos;) 50% 50% / cover no-repeat;"></video><div class="kg-video-overlay"><button class="kg-video-large-play-icon"><svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24"><path d="M23.14 10.608 2.253.164A1.559 1.559 0 0 0 0 1.557v20.887a1.558 1.558 0 0 0 2.253 1.392L23.14 13.393a1.557 1.557 0 0 0 0-2.785Z"/></svg></button></div><div class="kg-video-player-container kg-video-hide"><div class="kg-video-player"><button class="kg-video-play-icon"><svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24"><path d="M23.14 10.608 2.253.164A1.559 1.559 0 0 0 0 1.557v20.887a1.558 1.558 0 0 0 2.253 1.392L23.14 13.393a1.557 1.557 0 0 0 0-2.785Z"/></svg></button><button class="kg-video-pause-icon kg-video-hide"><svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24"><rect x="3" y="1" width="7" height="22" rx="1.5" ry="1.5"/><rect x="14" y="1" width="7" height="22" rx="1.5" ry="1.5"/></svg></button><span class="kg-video-current-time">0:00</span><div class="kg-video-time">/<span class="kg-video-duration"></span></div><input type="range" class="kg-video-seek-slider" max="100" value="0"><button class="kg-video-playback-rate">1&#xD7;</button><button class="kg-video-unmute-icon"><svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24"><path d="M15.189 2.021a9.728 9.728 0 0 0-7.924 4.85.249.249 0 0 1-.221.133H5.25a3 3 0 0 0-3 3v2a3 3 0 0 0 3 3h1.794a.249.249 0 0 1 .221.133 9.73 9.73 0 0 0 7.924 4.85h.06a1 1 0 0 0 1-1V3.02a1 1 0 0 0-1.06-.998Z"/></svg></button><button class="kg-video-mute-icon kg-video-hide"><svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24"><path d="M16.177 4.3a.248.248 0 0 0 .073-.176v-1.1a1 1 0 0 0-1.061-1 9.728 9.728 0 0 0-7.924 4.85.249.249 0 0 1-.221.133H5.25a3 3 0 0 0-3 3v2a3 3 0 0 0 3 3h.114a.251.251 0 0 0 .177-.073ZM23.707 1.706A1 1 0 0 0 22.293.292l-22 22a1 1 0 0 0 0 1.414l.009.009a1 1 0 0 0 1.405-.009l6.63-6.631A.251.251 0 0 1 8.515 17a.245.245 0 0 1 .177.075 10.081 10.081 0 0 0 6.5 2.92 1 1 0 0 0 1.061-1V9.266a.247.247 0 0 1 .073-.176Z"/></svg></button><input type="range" class="kg-video-volume-slider" max="100" value="100"></div></div></div></figure><p></p><p>To build this in Retool, we simply set the sidebar frame&#x2019;s <em>hidden</em> attribute by the true/false value of the hamburger toggle button. The toggle button is the best component to use in boolean functionality since these values are natively built into the component&#x2019;s settings and therefore require less messing around. </p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="http://143.198.97.195:2369/content/images/2025/04/three-four.png" class="kg-image" alt="How we built YouTube in Retool (Retool UI inspiration &amp; template)" loading="lazy" width="2000" height="1203" srcset="http://143.198.97.195:2369/content/images/size/w600/2025/04/three-four.png 600w, http://143.198.97.195:2369/content/images/size/w1000/2025/04/three-four.png 1000w, http://143.198.97.195:2369/content/images/size/w1600/2025/04/three-four.png 1600w, http://143.198.97.195:2369/content/images/2025/04/three-four.png 2076w" sizes="(min-width: 720px) 720px"><figcaption>Setting guidelines for collapsible sidebars in Retool.</figcaption></figure><p>Interested in playing around with how we did this in your own environment? Members can download the Toolscript below to import it directly into their Retool environment.</p><p>In the rest of this <a href="http://143.198.97.195:2369/tag/ui-inspiration/">UI inspiration series</a>, we recreate some of our favorite application UI&apos;s, like Steam, <a href="http://143.198.97.195:2369/reddit-inspired-ui-in-retool/">Reddit</a>, <a href="http://143.198.97.195:2369/youtube-in-retool-ui-inspiration/">YouTube</a> and even <a href="http://143.198.97.195:2369/creating-retool-in-retool-ui/">Retool</a> itself. Make sure to check them out!</p><div class="kg-card kg-callout-card kg-callout-card-blue"><div class="kg-callout-emoji">&#x1F4A5;</div><div class="kg-callout-text">At <a href="https://www.boldtech.dev/?ref=blog.boldtech.dev">Bold Tech,</a> we specialize in building great internal tools, fast. We are obsessed with building apps that make your teams happier and more productive. In our <a href="http://143.198.97.195:2369/">blog</a>, you can learn all about how to build better business software for more satisfied employees, or <a href="https://www.boldtech.dev/contact?ref=blog.boldtech.dev">get in contact</a> to chat to us about what you&apos;re looking to build.</div></div><p></p><h2 id="download-the-sample-toolscript">Download the sample toolscript</h2><p>The Toolbox newsletter members can download the JSON and import it directly into their Retool environment to test it out &#x2B07;&#xFE0F;&#x2B07;&#xFE0F;&#x2B07;&#xFE0F;</p>]]></content:encoded></item><item><title><![CDATA[Reddit-inspired UI in Retool (Retool UI inspiration & template)]]></title><description><![CDATA[In this UI inspiration template, we have recreated the Reddit UI using Retool! Newsletter members can download the template for free!]]></description><link>http://143.198.97.195:2369/reddit-inspired-ui-in-retool/</link><guid isPermaLink="false">66f6d8fbdbece927645cd8b7</guid><category><![CDATA[UI inspiration]]></category><category><![CDATA[Retool]]></category><dc:creator><![CDATA[Stefan Cvrkotic]]></dc:creator><pubDate>Fri, 27 Sep 2024 16:37:32 GMT</pubDate><media:content url="http://143.198.97.195:2369/content/images/2024/09/Bold-tech-blog-thumb--2-.png" medium="image"/><content:encoded><![CDATA[<img src="http://143.198.97.195:2369/content/images/2024/09/Bold-tech-blog-thumb--2-.png" alt="Reddit-inspired UI in Retool (Retool UI inspiration &amp; template)"><p>In the next of our <a href="http://143.198.97.195:2369/tag/ui-inspiration/">Retool UI inspiration series</a>, we&#x2019;ve built a Reddit replica that would be sure to fool any keen Redditor (until they clicked something at least!). Reddit&#x2019;s UX/UI design is super minimalistic, allowing users to focus on the content over functionality. While you may be unlikely to build a social media platform in <a href="http://143.198.97.195:2369/what-is-retool/">Retool</a>, this style of UI might be most useful when building business software that revolves around information, such as sales CRMs or customer support tools. </p><p>Play around with it <a href="https://sandbox.practicemode.retool.com/p/reddit?ref=143.198.97.195">here</a>!</p><figure class="kg-card kg-image-card"><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXfWwyRHyPpcCOsACPd9h-rUBrk3H1n88Fi8OCIkU6zAwoc1jaac3AQBVfp2kJuZ2KNIkTrvCgpcvWM5VSKAO9roBQz91ijnM4S7IAxnuTXdyv8LEplZ6W350iaVoI7-62lkLdAQfdSAT0HpbR6PF_5vHZcm?key=mvMCsVM1if4ick0y6LrhFw" class="kg-image" alt="Reddit-inspired UI in Retool (Retool UI inspiration &amp; template)" loading="lazy" width="624" height="280"></figure><p><br>Let&#x2019;s break down this UI style a little and see how this might be useful when building in Retool. <br></p><h3 id="dark-mode-styling">Dark mode styling<br></h3><p>Dark mode is a relatively under-utilized way of styling apps in Retool, but using an example like Reddit shows how slick it can look when used effectively. Using the orange as an accent color for key action buttons and tags is also an effective color palette. </p><p>Here is the theme we used for this example which you can copy directly to your app theme settings:<br></p><p><em>Primary: D93900</em></p><p><em>Secondary text: 758791</em></p><p><em>Canvas &amp; primary surface: 0F1113</em></p><p><em>Secondary surface: 2B3236</em><br></p><p>We also used high-pixel border radiuses to create rounded inputs for buttons and the search bar for example. </p><p>The font type here is Open Sans, but we used custom CSS to change the appearance of the nav text for instance: <br></p><figure class="kg-card kg-image-card"><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXeICJQdj8wITn1m5Yr_O2iL0-w3HMIrNZZLJogJ_RKTzUOtGnv33gtRFCMKdODbkI1Eo5Lsywz-Llekj3wvcjitrARcVCt2zd3Uaa4No3UrWTiuNMddTsyjOSN2XA0AzovUZj885mJG9PSggSrTgyXgJVI?key=mvMCsVM1if4ick0y6LrhFw" class="kg-image" alt="Reddit-inspired UI in Retool (Retool UI inspiration &amp; template)" loading="lazy" width="598" height="430"></figure><p><br><br></p><h3 id="columns-of-scrollable-information">Columns of scrollable information <br></h3><p>One UI element we particularly enjoy about Reddit - like other social media platforms - is its ability to show different areas of functionality and data on the same page without overwhelming them. </p><p>The three columns of functionality (navigation, forum content, and forum info overview) are visually distinct and individually scrollable to improve navigation of different data without leaving the page. </p><p>Okay - disclaimer - there&#x2019;s a little cheating in here when it comes to the comments section, where this kind of UI is just not possible without extensive custom code. Nevertheless, some of the styling was easily replicated in Retool, such as the highlighted content in the right column which we built with a listview component, using a combination of avatar, link and text components.<br></p><figure class="kg-card kg-image-card"><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXfQAheyR6BldJd084Tp8gZRzIgxTCQpeFgXKFBk88_eaK18eJd_rxUIKZUDc4mSb0yvttcT5o-JynEnIIGn-QpCRXIFbVnKSvKepXB0ekoO_LBe9qJ1Lf1gyk8DBp5lwVyRbl-iOj7W2-iCdkWb-csV-44?key=mvMCsVM1if4ick0y6LrhFw" class="kg-image" alt="Reddit-inspired UI in Retool (Retool UI inspiration &amp; template)" loading="lazy" width="452" height="475"></figure><p><br>We did something a little like this column layout in our <a href="http://143.198.97.195:2369/hubspot-inspired-retool-crm-template/">Hubspot UI inspiration piece</a>, using three columns to show company and deal data on the same page, but designed in a way to be easily hidden and ignored if not necessary.<br></p><h3 id="navigation-bar">Navigation bar</h3><p>Retool&#x2019;s native navigation bar is a little limited in terms of styling, so we had to get creative with this neat style of organization for site pages. To create this dropdown menu we simply used a collapsible container that allowed us greater control over text spacing and additional components like icons if needed. <br></p><figure class="kg-card kg-image-card"><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXear0jAFDSeQ1119yZl_MJxD_3D0kofs8LN5gC2lLKgrgr0UIafVWoL9GQsdeR3I3k0j1EvJ2D8RhFIYje_u_SsoMWJblo5oku3hurmcN9h4QRjJ-r-YDNxL2OuHgrLgD6CRl1XG6OaXroAKxqOgQD2f2k?key=mvMCsVM1if4ick0y6LrhFw" class="kg-image" alt="Reddit-inspired UI in Retool (Retool UI inspiration &amp; template)" loading="lazy" width="395" height="532"></figure><p><br>The <em>Home </em>and <em>Popular </em>items are composed of text components and HTML for the icons, which you can group to set an event handler &#x2018;on click&#x2019;, effectively turning anything into a clickable &#x2018;button&#x2019; in Retool. </p><p>One key style feature we used throughout this UI was the .hovered attribute on components like the collapsible container. This attribute allows you to change the &#x2018;Background&#x2019; styling according to whether the user hovers on the component, mimicking a lot of commonly-used UX design across the web and creating a highly professional-looking app.</p><figure class="kg-card kg-image-card"><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXcBDrhFiFzyPE0LaMfR8wYT6TXUwSjmHG5xqwuH1Qupt6_16wVpDHudk7DzNqguPcnDjp-yVLXO9z0Vb8Quc81F80GmH3wvsxoK2w6mIpCDrspB1-YPpcI9WFk3QN_WYLvNkvyTJu2ZNhUtlWJoPcvUIksy?key=mvMCsVM1if4ick0y6LrhFw" class="kg-image" alt="Reddit-inspired UI in Retool (Retool UI inspiration &amp; template)" loading="lazy" width="624" height="269"></figure><p>Interesting in playing around with how we did this in your own environment? Members can download the JSON below to import it directly into their Retool. </p><p>In the rest of this <a href="http://143.198.97.195:2369/tag/ui-inspiration/">UI inspiration series</a>, we recreate some of our favorite application UI&apos;s, like Steam, <a href="http://143.198.97.195:2369/reddit-inspired-ui-in-retool/">Reddit</a>, <a href="http://143.198.97.195:2369/youtube-in-retool-ui-inspiration/">YouTube</a> and even <a href="http://143.198.97.195:2369/creating-retool-in-retool-ui/">Retool</a> itself. Make sure to check them out!<br></p><div class="kg-card kg-callout-card kg-callout-card-blue"><div class="kg-callout-emoji">&#x1F4A5;</div><div class="kg-callout-text">At <a href="https://www.boldtech.dev/?ref=blog.boldtech.dev">Bold Tech,</a> we specialize in building great internal tools, fast. We are obsessed with building apps that make your teams happier and more productive. In our <a href="http://143.198.97.195:2369/">blog</a>, you can learn all about how to build better business software for more satisfied employees, or <a href="https://www.boldtech.dev/contact?ref=blog.boldtech.dev">get in contact</a> to chat to us about what you&apos;re looking to build.</div></div><h2 id="download-the-sample-toolscript">Download the sample toolscript</h2><p>The Toolbox newsletter members can download the JSON and import it directly into their Retool environment to test it out &#x2B07;&#xFE0F;&#x2B07;&#xFE0F;&#x2B07;&#xFE0F;</p>]]></content:encoded></item><item><title><![CDATA[Building interactive maps with OpenStreetMap API in Retool]]></title><description><![CDATA[The native Mapbox component in Retool offers powerful capabilities for building interactive maps, giving users the ability to visualize and work with geospatial data.]]></description><link>http://143.198.97.195:2369/building-interactive-maps-retool/</link><guid isPermaLink="false">66e48816dbece927645cd80f</guid><category><![CDATA[Tutorials]]></category><category><![CDATA[Retool]]></category><dc:creator><![CDATA[Joey Karczewski]]></dc:creator><pubDate>Fri, 13 Sep 2024 19:14:24 GMT</pubDate><media:content url="http://143.198.97.195:2369/content/images/2024/09/Bold-tech-blog-thumb--1-.png" medium="image"/><content:encoded><![CDATA[<img src="http://143.198.97.195:2369/content/images/2024/09/Bold-tech-blog-thumb--1-.png" alt="Building interactive maps with OpenStreetMap API in Retool"><p>In this tutorial, we&#x2019;ll show you how to set up a map inside Retool that allows you to highlight general location boundaries using the OpenStreetMap API.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXePTock3Zl1lktk9vMNvj_olCiZujLFMHD4Vn6wt5FEQ5yQTCMt6kjJJbsmjJyj3qGgnF8dXtbLRwwYgdHwZAd4ETE3jzg4808ikNsVQrFpBAeR-0E9snS7s9QjPQ717KUq5HrXwbZKHAYYA2dmahgRKLqN?key=IZzuxzQe07BDMgEtXsIPyA" class="kg-image" alt="Building interactive maps with OpenStreetMap API in Retool" loading="lazy" width="624" height="220"><figcaption>Interactive map built using OpenStreetMap API and Retool interface.</figcaption></figure><p>While this might seem like some highly complex functionality, in Retool it&#x2019;s a 3-step process to get this up and running.</p><p><strong>In this guide, we&#x2019;ll cover how to:</strong></p><ol><li>Integrate a map component within Retool.</li><li>Use the OpenStreetMap API to fetch and display GEOJSON data based on user input.</li><li>Define map center points and zoom levels dynamically, making the map both interactive and user-responsive.</li></ol><p>You can play with the <a href="https://sandbox.practicemode.retool.com/embedded/public/c798c22e-4854-4d3f-a4aa-549ea540781e?ref=143.198.97.195">example app in our environment</a>. </p><p>While we chose to use the OpenStreetMap API for this example, the ways in which we format the GEOJSON and employ the mapbox component can be extended to your own personal business usecase. </p><p>Example internal tools that could make use of the mapbox:</p><ul><li>Logistics teams can use maps to track real-time fleet locations in their internal tools to optimize delivery routes, and identify bottlenecks.</li><li>In retail, store managers might employ a map in Retool to visualize customer demographics or sales data across different regions to tailor marketing strategies.</li><li>Field service teams can assign technicians to jobs based on proximity of a Retool Mobile app, and real estate teams can analyze property locations alongside zoning or demographic data.</li></ul><p><br></p><h2 id="the-mapbox-component-in-retool-pros-and-cons">The Mapbox component in Retool: Pros and Cons</h2><p>The native <a href="https://docs.retool.com/apps/reference/components/integrations/mapbox-map?ref=143.198.97.195">Mapbox component</a> in Retool offers powerful capabilities for building interactive maps, giving users the ability to visualize and work with geospatial data. Built on top of the <a href="https://www.mapbox.com/mapbox-gljs?ref=143.198.97.195">Mapbox Library</a>, you can fully extend your applications to include complex map related workflows., you can display various map styles (such as satellite, streets, or custom themes) and overlay markers, shapes, and GEOJSON data. The component comes with some default variables and supports custom center points and zoom levels, allowing you to tailor the view based on user input or dynamic data sources.</p><p>You can also trigger interactions like clicking on map features to reveal detailed information, making it useful for use cases like visualizing real-time asset locations, plotting routes, or highlighting regions on a map. Mapbox&apos;s flexibility in Retool also extends to integrating with external APIs, enabling advanced geospatial data analysis directly within your internal tools.</p><p>The Mapbox component in Retool, while powerful, does have some limitations to consider:</p><ol><li><strong>Limited customization via Retool UI</strong>: Although you can adjust aspects like center point, zoom level, and map style, more advanced Mapbox configurations&#x2014;such as detailed control over map layers or specific styling options&#x2014;require custom JavaScript or external configuration, which might not be fully accessible through Retool&apos;s interface alone. Though, you can implement a simple Mapbox functionality inside of Retool&#x2019;s custom component to get around this limitation.</li><li><strong>No direct Tile layer customization</strong>: While the Mapbox component supports different map styles (e.g., streets, satellite), customizing tile layers beyond the provided Mapbox options may be challenging. You would need to implement a custom Retool component using the Mapbox to customize this yourself.</li><li><strong>Performance concerns</strong>: Loading large amounts of geospatial data (e.g., numerous markers or complex GEOJSON files) can affect performance, leading to slower map rendering or user experience lags, especially in applications that require real-time data updates.</li></ol><p>Now we know a bit more about the component, let&#x2019;s get started with building out our map app. <br><br></p><h2 id="step-1-generating-geojson-data-for-the-map">Step 1: Generating GEOJSON Data for the Map</h2><p>First things first, you need data to display on your map. We&#x2019;ll use OpenStreetMap&apos;s API, a robust, open-source platform that supports global location data.</p><p>The key to getting this data is making an API call to OSM that retrieves GEOJSON data based on user input. Back in your app, first pull in a mapbox component and a text input.</p><p>Now, here&#x2019;s the API call you&#x2019;ll be using in Retool:</p><figure class="kg-card kg-image-card"><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXdTNtyZKfPnRBzzoV9WPcCCupREUOedO47jPKkvtGYFqZXtHBAHC_ZGbga08AM7r9spT64gn4UnWb__m4lI2LMdiaYOxSCOFviwKPoWk9ksLHKgSe9Nj6SMU_CB13HdVRIXrkY4gddjgyfi8QVWL0Nujrjw?key=IZzuxzQe07BDMgEtXsIPyA" class="kg-image" alt="Building interactive maps with OpenStreetMap API in Retool" loading="lazy" width="624" height="269"></figure><p><br></p><p>Copy code:</p><figure class="kg-card kg-code-card"><pre><code>https://nominatim.openstreetmap.org/search?q={{ textInput1.value }}&amp;format=geojson&amp;polygon_geojson=1</code></pre><figcaption>Code example for API call to OpenStreetMap, retrieving GEOJSON data for map visualization</figcaption></figure><p>The query (q) parameter will be linked to a text input box in your Retool app ({{ textInput1.value }}). The response format is set to GEOJSON, which will give us the data we need to display location information on the map. polygon_geojson=1 ensures that we also receive polygon data, which is important for visualizing boundaries and areas on the map.</p><p>You can now use this GEOJSON response to start building your map.</p><p>Next we&#x2019;ll show you how we set the latitude and longitude for the center point. <br><br></p><h2 id="step-2-defining-the-center-point-and-zoom-level">Step 2: Defining the Center Point and Zoom Level</h2><p>The next step is to dynamically set the map&apos;s center point and zoom level in the Mapbox component. This ensures that the map displays the location based on what the user inputs.</p><p>To achieve this, you&#x2019;ll need a JavaScript query in Retool. Now, the code for this is fairly complex, but luckily for you we&#x2019;ve sorted that out for you already:</p><p></p><figure class="kg-card kg-image-card"><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXcr53jrFTaw3x1wRcUVHFXe0au2kIiuJ6UC4He2ws7jYDP9ulz-Vc9rEqhQjBvpGDmuEMiJ2Ses9SnK01H4yFK08vg8ZDLekoHwj66udBjXCANEoTInYo0aaF1pg9HM7yX79O2adeQrUNydaY9NjTKAAsKL?key=IZzuxzQe07BDMgEtXsIPyA" class="kg-image" alt="Building interactive maps with OpenStreetMap API in Retool" loading="lazy" width="624" height="249"></figure><p>Here&#x2019;s the full JS query:</p><figure class="kg-card kg-code-card"><pre><code class="language-JavaScript">var geojson = generateGeoJson.data
function calculateBoundingBox(geojson) {
let minLat = Infinity, maxLat = -Infinity;
let minLng = Infinity, maxLng = -Infinity;
geojson.features.forEach(function(feature) {
const coords = feature.geometry.coordinates;
if (feature.geometry.type === &quot;Point&quot;) {
const [lng, lat] = coords;
if (lat &lt; minLat) minLat = lat;
if (lat &gt; maxLat) maxLat = lat;
if (lng &lt; minLng) minLng = lng;
if (lng &gt; maxLng) maxLng = lng;
} else if (feature.geometry.type === &quot;Polygon&quot;) {
coords[0].forEach(function([lng, lat]) {
if (lat &lt; minLat) minLat = lat;
if (lat &gt; maxLat) maxLat = lat;
if (lng &lt; minLng) minLng = lng;
if (lng &gt; maxLng) maxLng = lng;
});
}
});
return {
southwest: [minLng, minLat],
northeast: [maxLng, maxLat]
};
}
// Function to calculate the center point
function calculateCenter(bounds) {
const centerLng = (bounds.southwest[0] + bounds.northeast[0]) / 2;
const centerLat = (bounds.southwest[1] + bounds.northeast[1]) / 2;
return [centerLng, centerLat];
}
// Function to estimate zoom level based on the bounding box
function calculateZoom(bounds, mapWidth, mapHeight) {
const WORLD_DIM = { height: 256, width: 256 };
const ZOOM_MAX = 20;
function latRad(lat) {
const sin = Math.sin(lat * Math.PI / 180);
const radX2 = Math.log((1 + sin) / (1 - sin)) / 2;
return Math.max(Math.min(radX2, Math.PI), -Math.PI) / 2;
}
function zoom(mapPx, worldPx, fraction) {
return Math.floor(Math.log(mapPx / worldPx / fraction) / Math.LN2);
}
const latFraction = (latRad(bounds.northeast[1]) - latRad(bounds.southwest[1])) / Math.PI;
const lngDiff = bounds.northeast[0] - bounds.southwest[0];
const lngFraction = (lngDiff &lt; 0 ? lngDiff + 360 : lngDiff) / 360;
const latZoom = zoom(mapHeight, WORLD_DIM.height, latFraction);
const lngZoom = zoom(mapWidth, WORLD_DIM.width, lngFraction);
return Math.min(latZoom, lngZoom, ZOOM_MAX);
}
// Calculate the bounding box
const bounds = calculateBoundingBox(geojson);
// Calculate the center point of the bounding box
const center = calculateCenter(bounds);
// Calculate zoom level (for example, assuming a map size of 800x600 pixels)
const mapWidth = 800;
const mapHeight = 600;
const zoomLevel = calculateZoom(bounds, mapWidth, mapHeight);
return {&apos;center&apos;:center, &apos;zoomLevel&apos;:zoomLevel}</code></pre><figcaption>JavaScript code for setting map center points and zoom levels dynamically in Retool.</figcaption></figure><p><br>This script pulls the coordinates from the first feature in your GEOJSON response and uses them as the map&#x2019;s center point.</p><p>We then referenced these as the center point in the mapbox component.</p><p>The zoom level is hardcoded to 16 in this example, but you can make it dynamic based on the size or type of the location.</p><p>To ensure the data updates when new text is searched, we set a success handler on the JS query to set the mapbox center values:</p><figure class="kg-card kg-image-card"><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXfbBkcA2cP3iyeS3GFlm5X9YoQpjuNB73fv5sqW1Cjh76hbux_P9eF9PAJ3fnYAqHEcuqSqtk4hT68oA4ZyY0k7N0Rdv3HzORHTTXsi4k3oZ7PKu6OfDrDi06UMKEn2Din3timaXwBHmtCQ2kIdXcVHgIDW?key=IZzuxzQe07BDMgEtXsIPyA" class="kg-image" alt="Building interactive maps with OpenStreetMap API in Retool" loading="lazy" width="624" height="461"></figure><p><br></p><h2 id="step-3-connecting-the-values-to-the-mapbox-component">Step 3: Connecting the values to the Mapbox component</h2><p>Now that we have both the GEOJSON data and the dynamic center point, it&#x2019;s time to configure the map itself. Here&#x2019;s what you need to do:</p><ol><li><strong>Reference the Center Point</strong> &#x2013; In your Mapbox component, set the center point latitude and longitude to the centerPoint values you defined in the JavaScript query.</li></ol><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXew97o2Nx5bTD-ZCRL7xgBlHXz_AdwScDpUMYkxqA916tJ6u2wGH2DgXhZP9rcOfKPQ7FDxwvTYe3L8QtzLBmpamdY168xk5APdoP9HtfBGRgPxbhkqtXPb70fdSVsT_ou_x77nVd7_xA8nGtNB-wYZg1XX?key=IZzuxzQe07BDMgEtXsIPyA" class="kg-image" alt="Building interactive maps with OpenStreetMap API in Retool" loading="lazy" width="624" height="396"><figcaption>Instructions on connecting center points and zoom levels to the Mapbox component in Retool.</figcaption></figure><p></p><p><strong>2. Load the GEOJSON</strong> &#x2013; Use the GEOJSON data fetched from the OpenStreetMap API to display boundaries, markers, or other geographic features on the map.</p><figure class="kg-card kg-image-card"><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXfojQMHelrt4N_dDh1i4Ir6qXULaYktxmupRr-LtX5PeFs9whJv5M_D2RBgbvYH1_DWJ6Sje4TaTsAI75o_mNTFB6UFvnFH3evCrIQuv31emGxct7B0BgdQzebAkr4SPgdCfRifOBdj6lizQpPzH1_By_I1?key=IZzuxzQe07BDMgEtXsIPyA" class="kg-image" alt="Building interactive maps with OpenStreetMap API in Retool" loading="lazy" width="624" height="300"></figure><p></p><p><strong>3. Set Zoom Level</strong> &#x2013; Link the zoom level from your JavaScript query to your map component to ensure that the map adjusts according to the user&apos;s input.</p><figure class="kg-card kg-image-card"><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXdCBaq4l1yKQsMaYDGwWL_2hOAgP5ykCVh0dpL7TipczPFMdIoPVJj61AC4EMK4S8ifjPG9hpTEp0j0l1BM9VMSemvrI6Fwz1gdE4wwDDlh4zCBQEeJ4Sa613zhRd-upuBgc-kp73EaqiCKAGIb-kVaLfvP?key=IZzuxzQe07BDMgEtXsIPyA" class="kg-image" alt="Building interactive maps with OpenStreetMap API in Retool" loading="lazy" width="624" height="564"></figure><p><br></p><p><strong>Putting it all together</strong></p><p>At this point, you should have:</p><ul><li>A text input field where users can type a location (e.g., &quot;New York&quot;).</li><li>A JavaScript query that pulls GEOJSON data from the OSM API based on that input.</li><li>Dynamic center points and zoom levels that adjust the map based on user searches.</li></ul><p>This makes your map highly interactive and customized, perfect for internal tools that need to visualize location-based data in real-time.</p><p>By following these steps, you can build a dynamic map in Retool using the OpenStreetMap API. Retool&#x2019;s Mapbox component is a powerful tool that allows you to go far beyond basic mapping, making it easy to overlay GEOJSON data, set zoom levels, and center points dynamically. Try it out for your next project to see how seamlessly you can integrate maps into your internal applications.</p><p></p><div class="kg-card kg-callout-card kg-callout-card-blue"><div class="kg-callout-emoji">&#x1F4A5;</div><div class="kg-callout-text">At <a href="https://www.boldtech.dev/?ref=blog.boldtech.dev">Bold Tech,</a> we specialize in building great internal tools, fast. We are obsessed with building apps that make your teams happier and more productive. In our <a href="http://143.198.97.195:2369/">blog</a>, you can learn all about how to build better business software for more satisfied employees, or <a href="https://www.boldtech.dev/contact?ref=blog.boldtech.dev">get in contact</a> to chat to us about what you&apos;re looking to build.</div></div>]]></content:encoded></item><item><title><![CDATA[Hubspot-inspired UI: CRM Template (Retool UI inspiration & template)]]></title><description><![CDATA[We built a Hubspot-inspired CRM UI in Retool with some super useful features. Members can download the template for free!]]></description><link>http://143.198.97.195:2369/hubspot-inspired-retool-crm-template/</link><guid isPermaLink="false">66bdeba0dbece927645cd49c</guid><category><![CDATA[UI inspiration]]></category><category><![CDATA[UX / UI Guides]]></category><category><![CDATA[Retool]]></category><category><![CDATA[Retool Template]]></category><dc:creator><![CDATA[Joey Karczewski]]></dc:creator><pubDate>Thu, 05 Sep 2024 13:15:39 GMT</pubDate><media:content url="http://143.198.97.195:2369/content/images/2024/09/Bold-tech-blog-thumb.png" medium="image"/><content:encoded><![CDATA[<img src="http://143.198.97.195:2369/content/images/2024/09/Bold-tech-blog-thumb.png" alt="Hubspot-inspired UI: CRM Template (Retool UI inspiration &amp; template)"><p>There&apos;s a tendency with <a href="http://143.198.97.195:2369/what-is-retool/">Retool</a> to think that it&apos;s only possible to create basic, unpolished internal apps (read: ugly apps with default Retool-blue buttons). While it&apos;s certainly not yet a pixel-perfect builder, with every release of new features it&apos;s getting easier and easier to create beautiful apps that just look like the favorites you use every day. What&apos;s even better is that implementing these practical, sleek features is still really fast.</p><p>For that reason, we&apos;ve been working on some <a href="http://143.198.97.195:2369/tag/ui-inspiration/">simple UI inspiration templates</a> that prove just how beautiful and functional Retool can be with just a few creative uses of components. </p><p>For our first template: a Hubspot-inspired CRM UI (play with it <a href="https://sandbox.practicemode.retool.com/embedded/public/2cf86550-f63e-4a5e-b4a6-a9bb5c3f99ae?ref=143.198.97.195">here</a>!). </p><figure class="kg-card kg-embed-card"><iframe src="https://demo.arcade.software/tuZx0PmfIvhzBAKsgXa1" allowfullscreen width="1024" height="478" title="Hubspot UI"></iframe></figure><p>Here are some of our favorite parts of this UI and how you can implement them with Retool.</p><p></p><h2 id="columns-of-information-with-a-clean-design">Columns of information with a clean design</h2><p></p><p>Since sales agents often need quick access to lots of info on the same screen, we recreated the Hubspot vertical view functionality with a mixture of the sidebar frame, split pane frame and containers, with the ability to hide these away too. </p><figure class="kg-card kg-image-card"><img src="http://143.198.97.195:2369/content/images/2024/09/image.png" class="kg-image" alt="Hubspot-inspired UI: CRM Template (Retool UI inspiration &amp; template)" loading="lazy" width="2000" height="777" srcset="http://143.198.97.195:2369/content/images/size/w600/2024/09/image.png 600w, http://143.198.97.195:2369/content/images/size/w1000/2024/09/image.png 1000w, http://143.198.97.195:2369/content/images/size/w1600/2024/09/image.png 1600w, http://143.198.97.195:2369/content/images/size/w2400/2024/09/image.png 2400w" sizes="(min-width: 720px) 720px"></figure><p></p><p>One of the things we particularly like about the Hubspot UI is how clean and simple the design and color choice is. The varied colors across columns helps visually differentiate the sections but also gives a clean and practical look to the app. </p><p></p><h2 id="categorizing-and-hiding-data">Categorizing and hiding data</h2><p></p><p>For the card-like functionality of client task tracking and touchpoints, we used a listview component. For the toggle information on the right-hand side panel, we used toggle containers to hide away information until necessary. </p><figure class="kg-card kg-image-card"><img src="http://143.198.97.195:2369/content/images/2024/11/Screenshot-2024-11-27-at-16.34.51.png" class="kg-image" alt="Hubspot-inspired UI: CRM Template (Retool UI inspiration &amp; template)" loading="lazy" width="2000" height="782" srcset="http://143.198.97.195:2369/content/images/size/w600/2024/11/Screenshot-2024-11-27-at-16.34.51.png 600w, http://143.198.97.195:2369/content/images/size/w1000/2024/11/Screenshot-2024-11-27-at-16.34.51.png 1000w, http://143.198.97.195:2369/content/images/size/w1600/2024/11/Screenshot-2024-11-27-at-16.34.51.png 1600w, http://143.198.97.195:2369/content/images/2024/11/Screenshot-2024-11-27-at-16.34.51.png 2210w" sizes="(min-width: 720px) 720px"></figure><p>This gives the user full control over how much data they see at once and allows fast, organized access to related information in one place, without needing to switch tabs or pages.</p><p></p><h2 id="varied-button-types-for-actions">Varied button types for actions</h2><p></p><p>One thing we particularly like about the Hubspot interface is the ease with which you can take action on an account. So we made an effort to replicate some of Hubspot&apos;s intuitive action features such as the icon button row, with simple icons that are obvious to users and reduce the amount of space used up by action buttons for these primary actions. Secondary actions are tucked away in the actions dropdown. </p><p></p><figure class="kg-card kg-image-card"><img src="http://143.198.97.195:2369/content/images/2024/11/Screenshot-2024-11-27-at-16.35.29.png" class="kg-image" alt="Hubspot-inspired UI: CRM Template (Retool UI inspiration &amp; template)" loading="lazy" width="1166" height="628" srcset="http://143.198.97.195:2369/content/images/size/w600/2024/11/Screenshot-2024-11-27-at-16.35.29.png 600w, http://143.198.97.195:2369/content/images/size/w1000/2024/11/Screenshot-2024-11-27-at-16.35.29.png 1000w, http://143.198.97.195:2369/content/images/2024/11/Screenshot-2024-11-27-at-16.35.29.png 1166w" sizes="(min-width: 720px) 720px"></figure><p></p><p>We also played with notification feature options in the navbar. Adding simple elements like notifications icons or captions to dropdowns with further information can be a great way to make apps feel more well-rounded and intuitive.</p><p></p><figure class="kg-card kg-image-card"><img src="http://143.198.97.195:2369/content/images/2024/11/Screenshot-2024-11-27-at-16.29.24.png" class="kg-image" alt="Hubspot-inspired UI: CRM Template (Retool UI inspiration &amp; template)" loading="lazy" width="858" height="360" srcset="http://143.198.97.195:2369/content/images/size/w600/2024/11/Screenshot-2024-11-27-at-16.29.24.png 600w, http://143.198.97.195:2369/content/images/2024/11/Screenshot-2024-11-27-at-16.29.24.png 858w" sizes="(min-width: 720px) 720px"></figure><hr><p></p><p>This app is a UI wireframe template inspired by Hubspot and created in Retool. You can adapt the template as you see fit for your CRM or Retool project. </p><p>Want to download the source code? <strong>Sign up to our newsletter below!</strong></p><p>In the rest of this <a href="http://143.198.97.195:2369/tag/ui-inspiration/">UI inspiration series</a>, we recreate some of our favorite application UI&apos;s, like Steam, <a href="http://143.198.97.195:2369/reddit-inspired-ui-in-retool/">Reddit</a>, <a href="http://143.198.97.195:2369/youtube-in-retool-ui-inspiration/">YouTube</a> and even <a href="http://143.198.97.195:2369/creating-retool-in-retool-ui/">Retool</a> itself. Make sure to check them out!</p><p></p><div class="kg-card kg-callout-card kg-callout-card-blue"><div class="kg-callout-emoji">&#x1F4A5;</div><div class="kg-callout-text">At <a href="https://www.boldtech.dev/?ref=143.198.97.195">Bold Tech</a>, we specialize in building great internal tools, fast. We are obsessed with building apps that make your teams happier and more productive. In our <a href="http://143.198.97.195:2369/">blog</a>, you can learn all about how to build better business software for more satisfied employees, or <a href="https://www.boldtech.dev/contact?ref=143.198.97.195">get in touch</a> to chat to us about what you&apos;re looking to build.</div></div>]]></content:encoded></item><item><title><![CDATA[Plotly AI helper - Generate Plotly charts in Retool in seconds!]]></title><description><![CDATA[We built an AI chatbot to quickly generate Plotly charts inside of Retool according to user prompts. Newsletter members can download the chatbot module TypeScript for free!]]></description><link>http://143.198.97.195:2369/plotly-ai-helper-retool/</link><guid isPermaLink="false">66c70abddbece927645cd519</guid><category><![CDATA[Plotly Guides]]></category><category><![CDATA[Retool]]></category><category><![CDATA[Retool Template]]></category><dc:creator><![CDATA[Stefan Cvrkotic]]></dc:creator><pubDate>Fri, 23 Aug 2024 17:21:27 GMT</pubDate><media:content url="http://143.198.97.195:2369/content/images/2024/08/Bold-tech-blog-thumb.jpg" medium="image"/><content:encoded><![CDATA[<img src="http://143.198.97.195:2369/content/images/2024/08/Bold-tech-blog-thumb.jpg" alt="Plotly AI helper - Generate Plotly charts in Retool in seconds!"><p><br>In the final instalment (for now) of our <a href="http://143.198.97.195:2369/tag/plotly-guides/">Charting in Retool with Plotly</a> series, we want to share our final tip to beat them all: a little AI chatbot helper that can get all your next Plotly endeavors off the ground, really fast. </p><p>We have already built a super <a href="http://143.198.97.195:2369/build-ai-chatbot-custom-knowledge-base-retool/">useful AI chatbot</a> that helps our team solve Retool problems quickly, using Retool Vectors to gather together resources for more informed and contextualized AI responses. We pull information in from the Retool Docs, Community, and our own blog. </p><p>Since charts can be such useful tools in internal business software, it&#x2019;s always advantageous to build them fast. We use this AI tool to expedite the initial setup of charts we aren&#x2019;t familiar with, as well as to generate quick lines of code to add customization features that make these charts stand out.</p><p></p><div class="kg-card kg-callout-card kg-callout-card-blue"><div class="kg-callout-emoji">&#x1F4A5;</div><div class="kg-callout-text">Interested in testing it out in your environment? <em>The</em> <em>Toolbox</em> newsletter members can download the typescript for free and import it directly into Retool to use immediately. <br><br>Subscribe to <em>The Toolbox</em> for free to skip the tutorial and download the JSON at the <a href="#download-the-sample-toolscript">end of this article </a>&#x2B07;&#xFE0F;</div></div><p>Members will get guides, tutorials and internal tool tips in 1-2 emails every month.</p><p></p><h3 id="how-to-use-the-plotly-chatbot">How to use the Plotly chatbot<br></h3><p>The Plotly AI helper is a simple chatbot in a drawer frame in Retool. We set it up as a module so the chatbot can be pulled into multiple applications and used all over your apps when building. </p><p>The user simply prompts the chatbot with the kind of charts they need and, using our system prompts and connected vectors, the chatbot returns the code and the chart itself to preview. </p><p>You can ask the chatbot for different chart types, colors, annotations and code snippets to improve your charts. You can make the prompts even more specific by checking the <a href="https://plotly.com/javascript/reference?ref=143.198.97.195">Plotly docs</a> first and making sure you use the correct terms. <br></p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXcxKW_ZDWeKpexuualDgGMyb8p-epkNQ4aiEjVhRY8cXOWqrk0K9b3FPObXfaY1yEb4hK-0VbnI4MixbATVXgytA5DaGcxsRy0quL5D-Tv6s9HQuLGbXlR8ymYntrnl1uIAhSK6F2KJbdigiU8_L74fjs13?key=JVA8TsfPrkL-aDucPOTn3w" class="kg-image" alt="Plotly AI helper - Generate Plotly charts in Retool in seconds!" loading="lazy" width="439" height="504"><figcaption>In our version, we also built in a &apos;Rate the response&apos; option to further improve answers.</figcaption></figure><p><br>Users can then copy the data object and layout object to their clipboards and paste them directly into the respective parts of the chart component in their app. And it&#x2019;s really as simple as that!<br><br></p><h3 id="how-did-we-build-it">How did we build it?<br></h3><p>We built this much like our original AI chatbot, starting first with the Vectors to contextualize the information. In this case, we set up a vector to scan the Plotly docs online - you can see how to to do this to set up the module in your own environment. We also set up a vector to scrape the Retool docs.</p><p>Inside our Ai query, we made sure to include a specific prompt which we tested and refined to get the perfect result each time: </p><blockquote>&#x201C;You are a plotly chart assistant that will return a JSON object with 2 keys: &apos;data&apos; and &apos;layout&apos; ALWAYS between &lt;code&gt; and &lt;/code&gt; tags.<br>If data is not provided please generate data so the chart can be rendered.<br>Provide additional tips how to enhance chart if asked for.&#x201D;</blockquote><p>We then connected the query to our Plotly and Retool Docs. <br></p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXcfmvs-QdlQxnJK-h9VuOzWDxdpbMqRzxJyT4-nyCLSeTRQ6CUR5msoKB5tMnhp2cedy2h8n60KO75VZoLD-NhL2d6-ebrE-MtRiYEfkK94VzLgG96Tkzl-FzUkS5hIRSiOmnbExqaT3xkdT_T-6zn-S30?key=JVA8TsfPrkL-aDucPOTn3w" class="kg-image" alt="Plotly AI helper - Generate Plotly charts in Retool in seconds!" loading="lazy" width="430" height="477"><figcaption>Connecting Retool AI with Plotly, setting the vectors to use Retool and Plotly docs online and populating the system prompt with the AI query.</figcaption></figure><p><br>Once we get a response, we need to parse the data and use this to present the preview of the chart, and separate the data and layout objects to be copied into the chart component. We pulled in a chart component to the chatbot to present the preview. This is what our data object looks like, as it parses out the response from the AI bot. <br></p><figure class="kg-card kg-code-card"><pre><code class="language-JavaScript">(() =&gt; {  // Start of an Immediately Invoked Function Expression (IIFE)
try {  // Start of a try block to handle any potential errors
return JSON.parse( // Parse a JSON string into an object
bold_tech_plotly_helper.data // Access the data property from bold_tech_plotly_helper
?.split(&quot;&lt;code&gt;&quot;)?.[1] // Split the data string at &lt;code&gt; and take the second part
?.split(&quot;&lt;/code&gt;&quot;)[0] // Split that part at &lt;/code&gt; and take the first part
?.replaceAll(&quot;&apos;&quot;, &apos;&quot;&apos;) // Replace all single quotes with double quotes to make it valid JSON
).data; // Return the &apos;data&apos; property of the parsed object
} catch {  // If any error occurs in the try block, this catch block runs
return [ // Return a fallback data array with two scatter plots
{
&quot;type&quot;: &quot;scatter&quot;, // First scatter plot
&quot;x&quot;: [1,1,2,2,1.5,1.5], // x-coordinates of the plot
&quot;y&quot;: [2,3,3,2,2,1], // y-coordinates of the plot
&quot;mode&quot;: &quot;lines&quot; // Display the plot as lines
},
{
&quot;type&quot;: &quot;scatter&quot;, // Second scatter plot
&quot;x&quot;: [1.5,1.5], // x-coordinates of the plot
&quot;y&quot;: [0,0.5], // y-coordinates of the plot
&quot;mode&quot;: &quot;lines&quot; // Display the plot as lines
}
];
}
})() // Immediately invoke the function</code></pre><figcaption>A data object after the AI bot response has been parsed.&#xA0;</figcaption></figure><p></p><p>And the layout object, which parses for the layout object, and sets the background to transparent, as well as allowing for an error option:<br></p><figure class="kg-card kg-code-card"><pre><code class="language-JavaScript">(() =&gt; {  // Start of an Immediately Invoked Function Expression (IIFE)
try {  // Start of a try block to handle any potential errors
return Object.assign( // Merge the parsed layout object with new properties
JSON.parse( // Parse a JSON string into an object
bold_tech_plotly_helper.data // Access the data property from bold_tech_plotly_helper
?.split(&quot;&lt;code&gt;&quot;)?.[1] // Split the data string at &lt;code&gt; and take the second part
?.split(&quot;&lt;/code&gt;&quot;)[0] // Split that part at &lt;/code&gt; and take the first part
?.replaceAll(&quot;&apos;&quot;, &apos;&quot;&apos;) // Replace all single quotes with double quotes to make it valid JSON
).layout, // Access the layout property of the parsed object
{
&quot;paper_bgcolor&quot;: &quot;rgba(0,0,0,0)&quot;, // Set the background color of the paper to transparent
&quot;plot_bgcolor&quot;: &quot;rgba(0,0,0,0)&quot; // Set the background color of the plot to transparent
}
);
} catch {  // If any error occurs in the try block, this catch block runs
return { // Return a fallback layout configuration
&quot;xaxis&quot;: {
&quot;showgrid&quot;: false, // Hide the grid on the x-axis
&quot;zeroline&quot;: false, // Hide the zero line on the x-axis
&quot;visible&quot;: false // Make the x-axis invisible
},
&quot;yaxis&quot;: {
&quot;showgrid&quot;: false, // Hide the grid on the y-axis
&quot;zeroline&quot;: false, // Hide the zero line on the y-axis
&quot;visible&quot;: false // Make the y-axis invisible
},
&quot;title&quot;: {
&quot;text&quot;: &quot;Error - chart not generated&quot;, // Display an error message as the title
&quot;font&quot;: {
&quot;color&quot;: &quot;red&quot; // Set the color of the error message to red
}
},
&quot;showlegend&quot;: false // Hide the legend
}
}
})() // Immediately invoke the function</code></pre><figcaption>A layout object in Retool specifying layout and background settings.&#xA0;</figcaption></figure><p><br>Inside our chat window we have two buttons that appear to allow you to copy the objects to your clipboard. <br></p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXcLyaPA9qZTLIHjOt4VFBHqThfPjr1XeqEFFxz6x2h_3eNcQJdbSTd7M_sv1keIDZ5lJ4bYFk3ElaxtDIqC6CgOuK8snfPt5Yi1mHLjsovIJRBjmdD_zkyL7SSbVeftnwPKJTQ6JS490w5cTpaiFIsrU7fH?key=JVA8TsfPrkL-aDucPOTn3w" class="kg-image" alt="Plotly AI helper - Generate Plotly charts in Retool in seconds!" loading="lazy" width="624" height="347"><figcaption>Copy to clipboard buttons enhancing UI for the helper.&#xA0;</figcaption></figure><p></p><pre><code class="language-JavaScript">{{JSON.stringify(JSON.parse(bold_tech_plotly_helper.data?.split(&quot;&lt;code&gt;&quot;)?.[1]?.split(&quot;&lt;/code&gt;&quot;)?.[0]?.replaceAll(&quot;&apos;&quot;,&apos;&quot;&apos;))?.data)}}</code></pre><p></p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXfaNTKgcUp_HAeIY-uTX8bvho-nvKsRLQxi_qieyBpPejiwDMOjxYI74MPWR_wiqsrchEgCA8VeCfePBootBODArIyMLzUIKJf7YIkjNagZriUZp3vn1EKJLM6__UUZvAf9yziUqTIAGszRmkyQEAVHvt6q?key=JVA8TsfPrkL-aDucPOTn3w" class="kg-image" alt="Plotly AI helper - Generate Plotly charts in Retool in seconds!" loading="lazy" width="624" height="475"><figcaption>JS script for the copy to clipboard buttons.&#xA0;</figcaption></figure><pre><code class="language-JavaScript">{{JSON.stringify(JSON.parse(bold_tech_plotly_helper.data?.split(&quot;&lt;code&gt;&quot;)?.[1]?.split(&quot;&lt;/code&gt;&quot;)?.[0]?.replaceAll(&quot;&apos;&quot;,&apos;&quot;&apos;))?.layout)}}</code></pre><p></p><p>Our Should_hide variable checks if the AI query is fetching and shows the buttons and chart component once complete. This query also makes sure that the chart preview has an error value option if the AI query doesn&apos;t work properly. <br></p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXd7L5MF8jIOzWH7OJVTPzgWr3q0q6m_FFiA890k-Af0As6iDWa4MaShrbpkUljHzTUvAK_tZODEzHpXytEuOe402ZWj3isoVAhsXPhQJ7PEAw6cvQxpJCaSX248KBbA7c_jBOFhVuJI7hLhC2xOa918EX3M?key=JVA8TsfPrkL-aDucPOTn3w" class="kg-image" alt="Plotly AI helper - Generate Plotly charts in Retool in seconds!" loading="lazy" width="624" height="340"><figcaption>Should_hide variable checks show chart component when complete or an error value if the query was unsuccessful.&#xA0;</figcaption></figure><p><br>To make sure they stay hidden until the AI query is complete, we added this value to each component in the &#x2018;hidden&#x2019; value: <br></p><figure class="kg-card kg-image-card"><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXfRoW9hw0w7vdYvNZAPjbm8Q4oEdoRc67lZFkDXT8KEIU838rGOPar71ndVAa8rx-GdKb2-SB1ZaY39ZbkicDrtdHfqP3_7IT02qylryLfy4hhKTUulREQIEv4WPhHVuIydQkbt5GX0MZLVAjYgBK8D6GH7?key=JVA8TsfPrkL-aDucPOTn3w" class="kg-image" alt="Plotly AI helper - Generate Plotly charts in Retool in seconds!" loading="lazy" width="516" height="196"></figure><p><br></p><h3 id="how-to-set-it-up-in-your-environment">How to set it up in your environment<br></h3><p>Setting up the Plotly AI helper in your own environment is as simple as downloading the typescript and importing it into your environment as a module. All you have to do to make sure it works is set up a Retool Vector to scan the Plotly docs by adding the URL &#x2018;Plotly.com&#x2019;. Like we did, you can also set up a Retool Docs vector that scans the Retool documentation too. <br></p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXfsh-L8eFX_4WhbELBdNz4rp7YELN_NovnrrCaBUZ8yqyhcuUjJFl3ViqJfSVztDKfY7p_eMBOwlRYWFzyYaklBZ6wdHtequB8K_VT-X5xQG4OlMsUnNMP_H74kbpq5Bc1ghpn3roXnRx_AOoSa7yX0TeQT?key=JVA8TsfPrkL-aDucPOTn3w" class="kg-image" alt="Plotly AI helper - Generate Plotly charts in Retool in seconds!" loading="lazy" width="624" height="353"><figcaption>Adding the url Plotly.com will ensure the Plotly AI is set up correctly.&#xA0;</figcaption></figure><p></p><p>This will then crawl the domain for all URLs to formulate an accurate response.<br></p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXc4Px3dJ0DBO1-ao2Pi3WZyVHbQVyYKBT5fa4j2LFd0bjsBFT9knXvoTEOrzlC6tKS9cLX_DE0wZF8rYQVnvIhSMWQqzHgGi7NfRKCwBcN_NodFsCPwurzQoyRfuu5E4Y22GVfnXO5fGS-FbZfv9T_cqPc?key=JVA8TsfPrkL-aDucPOTn3w" class="kg-image" alt="Plotly AI helper - Generate Plotly charts in Retool in seconds!" loading="lazy" width="624" height="331"><figcaption>List of Plotly docs&#xA0;</figcaption></figure><p><br>Once that&#x2019;s done, simply connect the Vectors in the AI query and you&#x2019;re ready and raring to go! </p><p></p><div class="kg-card kg-callout-card kg-callout-card-blue"><div class="kg-callout-emoji">&#x1F4A5;</div><div class="kg-callout-text">At <a href="https://www.boldtech.dev/?ref=blog.boldtech.dev">Bold Tech,</a> we specialize in building great internal tools, fast. We are obsessed with building apps that make your teams happier and more productive. In our <a href="http://143.198.97.195:2369/">blog</a>, you can learn all about how to build better business software for more satisfied employees, or <a href="https://www.boldtech.dev/contact?ref=blog.boldtech.dev">get in contact</a> to chat to us about what you&apos;re looking to build.</div></div><p></p>
        <div class="kg-card kg-file-card ">
            <a class="kg-file-card-container" href="http://143.198.97.195:2369/content/files/2024/08/Plotly-20module.zip" title="Download" download>
                <div class="kg-file-card-contents">
                    <div class="kg-file-card-title">Plotly chatbot module</div>
                    <div class="kg-file-card-caption">Use this module to generate Plotly charts fast in Retool using ChatGPT. </div>
                    <div class="kg-file-card-metadata">
                        <div class="kg-file-card-filename">Plotly%20module.zip</div>
                        <div class="kg-file-card-filesize">19 KB</div>
                    </div>
                </div>
                <div class="kg-file-card-icon">
                    <svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24"><defs><style>.a{fill:none;stroke:currentColor;stroke-linecap:round;stroke-linejoin:round;stroke-width:1.5px;}</style></defs><title>download-circle</title><polyline class="a" points="8.25 14.25 12 18 15.75 14.25"/><line class="a" x1="12" y1="6.75" x2="12" y2="18"/><circle class="a" cx="12" cy="12" r="11.25"/></svg>
                </div>
            </a>
        </div>
        <h2 id="download-the-sample-toolscript">Download the sample toolscript</h2><p>The Toolbox newsletter members can download the JSON and import it directly into their Retool environment to test it out &#x2B07;&#xFE0F;&#x2B07;&#xFE0F;&#x2B07;&#xFE0F;</p>]]></content:encoded></item><item><title><![CDATA[Charting in Plotly part III - Interactive charts]]></title><description><![CDATA[In part III of our Plotly guides, we’ll be focusing on creating not only useful charts, but highly interactive ones too. We'll also be making our chart functionality into a module. ]]></description><link>http://143.198.97.195:2369/charting-in-plotly-part-iii-interactive-charts/</link><guid isPermaLink="false">66a397aadbece927645cd348</guid><category><![CDATA[Plotly Guides]]></category><category><![CDATA[Tutorials]]></category><category><![CDATA[Retool]]></category><dc:creator><![CDATA[Stefan Cvrkotic]]></dc:creator><pubDate>Fri, 26 Jul 2024 16:27:12 GMT</pubDate><media:content url="http://143.198.97.195:2369/content/images/2024/07/Bold-tech-blog-thumb--13-.jpg" medium="image"/><content:encoded><![CDATA[<img src="http://143.198.97.195:2369/content/images/2024/07/Bold-tech-blog-thumb--13-.jpg" alt="Charting in Plotly part III - Interactive charts"><p>In <a href="http://143.198.97.195:2369/charting-in-retool-with-plotly-part-i/">Part I </a>and <a href="http://143.198.97.195:2369/charting-retool-with-plotly-sankey/">Part II </a>of our Charting in Retool with Plotly series, we explained how to go from basic charting options on a line chart (and how to add some cool features) to a <a href="http://143.198.97.195:2369/charting-retool-with-plotly-sankey/">complex Sankey chart generator</a> - all in Retool. </p><p>In this part III, we&#x2019;ll be focusing on leveraging the power of both platforms to create not only useful charts, but highly interactive ones that integrate seamlessly with your internal app toolset. Using the selectedPoints attribute of the chart component is a brilliant way to make your charts more understandable and more actionable.</p><p>We&#x2019;ll be building this funnel chart for a sales app that tracks the number of deals in each status tag. Users can simply click into a bar in the funnel and a modal will show them detailed data for that status group. They can even highlight and select multiple statuses to see all data. <br></p><figure class="kg-card kg-video-card"><div class="kg-video-container"><video src="http://143.198.97.195:2369/content/media/2024/07/Funnel-app-tutorial-_-Bold-Tech--2-.mp4" poster="https://img.spacergif.org/v1/1280x602/0a/spacer.png" width="1280" height="602" playsinline preload="metadata" style="background: transparent url(&apos;http://143.198.97.195:2369/content/images/2024/07/media-thumbnail-ember421.jpg&apos;) 50% 50% / cover no-repeat;"></video><div class="kg-video-overlay"><button class="kg-video-large-play-icon"><svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24"><path d="M23.14 10.608 2.253.164A1.559 1.559 0 0 0 0 1.557v20.887a1.558 1.558 0 0 0 2.253 1.392L23.14 13.393a1.557 1.557 0 0 0 0-2.785Z"/></svg></button></div><div class="kg-video-player-container"><div class="kg-video-player"><button class="kg-video-play-icon"><svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24"><path d="M23.14 10.608 2.253.164A1.559 1.559 0 0 0 0 1.557v20.887a1.558 1.558 0 0 0 2.253 1.392L23.14 13.393a1.557 1.557 0 0 0 0-2.785Z"/></svg></button><button class="kg-video-pause-icon kg-video-hide"><svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24"><rect x="3" y="1" width="7" height="22" rx="1.5" ry="1.5"/><rect x="14" y="1" width="7" height="22" rx="1.5" ry="1.5"/></svg></button><span class="kg-video-current-time">0:00</span><div class="kg-video-time">/<span class="kg-video-duration"></span></div><input type="range" class="kg-video-seek-slider" max="100" value="0"><button class="kg-video-playback-rate">1&#xD7;</button><button class="kg-video-unmute-icon"><svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24"><path d="M15.189 2.021a9.728 9.728 0 0 0-7.924 4.85.249.249 0 0 1-.221.133H5.25a3 3 0 0 0-3 3v2a3 3 0 0 0 3 3h1.794a.249.249 0 0 1 .221.133 9.73 9.73 0 0 0 7.924 4.85h.06a1 1 0 0 0 1-1V3.02a1 1 0 0 0-1.06-.998Z"/></svg></button><button class="kg-video-mute-icon kg-video-hide"><svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24"><path d="M16.177 4.3a.248.248 0 0 0 .073-.176v-1.1a1 1 0 0 0-1.061-1 9.728 9.728 0 0 0-7.924 4.85.249.249 0 0 1-.221.133H5.25a3 3 0 0 0-3 3v2a3 3 0 0 0 3 3h.114a.251.251 0 0 0 .177-.073ZM23.707 1.706A1 1 0 0 0 22.293.292l-22 22a1 1 0 0 0 0 1.414l.009.009a1 1 0 0 0 1.405-.009l6.63-6.631A.251.251 0 0 1 8.515 17a.245.245 0 0 1 .177.075 10.081 10.081 0 0 0 6.5 2.92 1 1 0 0 0 1.061-1V9.266a.247.247 0 0 1 .073-.176Z"/></svg></button><input type="range" class="kg-video-volume-slider" max="100" value="100"></div></div></div></figure><p></p><p>We also made this chart into a module that can be reused across multiple apps. </p><p>Let&#x2019;s jump into how we built this.<br></p><div class="kg-card kg-callout-card kg-callout-card-blue"><div class="kg-callout-emoji">&#x1F4A5;</div><div class="kg-callout-text">Interested in testing it out in your environment? <em>The</em> <em>Toolbox</em> newsletter members can download the typescript for free and import it directly into Retool to use immediately. <br><br>Subscribe to <em>The Toolbox</em> for free to skip the tutorial and download the JSON at the <a href="#download-the-sample-toolscript">end of this article </a>&#x2B07;&#xFE0F;</div></div><p></p><h2 id="building-a-funnel-chart-in-plotly">Building a funnel chart in Plotly <br></h2><p>This is what the Plotly data object for a basic funnel chart looks like: <br></p><figure class="kg-card kg-code-card"><pre><code class="language-JavaScript">[
{
&quot;name&quot;: &quot;sales&quot;,
&quot;x&quot;: [
65,
29,
7,
3
],
&quot;y&quot;: [
&quot;Prospect&quot;,
&quot;Negotiation&quot;,
&quot;Contract&quot;,
&quot;Won&quot;
],
&quot;type&quot;: &quot;funnel&quot;
}
]</code></pre><figcaption>JavaScript code snippet showing how to set up a mock data query for a sales funnel component in Retool.</figcaption></figure><p><br>We&#x2019;re going to expand on this basic format with some more complex and dynamic data and interactivity. </p><p>For our sales funnel, we started by creating some mock data in a JS query. This defines data keys such as stages, owners, deal names and then sets a deal date and calculates the days in that stage. The <em>for</em> loop creates the full dataset according to the counts defined for each stage. </p><p>This JS query is the data we use for testing, and also allows us to export the full module as a JSON for you to download below and use straight away. <br></p><figure class="kg-card kg-image-card"><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXd6cg5J5YcH_Xx17Zp8SC2BclE3jb8qVqSX7kUmPoBK_koFn2FnrwDPiHM4OryyZ6_0j0WFlYn2BePTaBgyH9GA1Un0JCl6uPNlfuedASSiQdFbP75qXWdt3OzcN4Aj7Q1zKGXHTXzDyq_I2JLQNJhrR2BS?key=-rORuAQrA3PZcXsyLT3qpA" class="kg-image" alt="Charting in Plotly part III - Interactive charts" loading="lazy" width="494" height="484"></figure><p><br>We also added a segmented control component above our chart to allow users to switch between number of deals (#) and the dollar value ($): <br></p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXe-H6sEKS1tmC0NKN38Z7C4VLiRIsX85jME9BCBg0rF9p611dHMsim8o1u8n7GTBRjSqnttwK8f-lR0a7Tldeh1PIf3pQYhbJY8ICmWbb_ehNDlh_m_rMCYRPuIvzcoVotfJsp5x5plWwO6DtmbvP3U2WU?key=-rORuAQrA3PZcXsyLT3qpA" class="kg-image" alt="Charting in Plotly part III - Interactive charts" loading="lazy" width="624" height="141"><figcaption>Segmented control in Retool interface, allowing users to toggle between displaying number of deals and dollar value in the funnel chart.</figcaption></figure><p><br>Next, we connected the data in our JS query and the switch functionality to the chart component in the data object. This is what it looks like: <br></p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXdoYkSVbSUQH_ImUbx5L8cPms5zu83D0l6MEbg-baXdy1J_jLZnLkSMdb9i1RjM-OmGci-qwD6p_f5ZNoqgD2SGvbluXtDn5h6n4C-gcVEVNmJJLtgL5HuUvNw_xrm99CCbvUBSCks_Qqnom7V_GvI8jNU?key=-rORuAQrA3PZcXsyLT3qpA" class="kg-image" alt="Charting in Plotly part III - Interactive charts" loading="lazy" width="624" height="224"><figcaption>Retool interface displaying a basic funnel chart with stages labeled on the Y-axis and deal count on the X-axis.</figcaption></figure><p><br>This formats the deals data into grouped stages for the &#x2018;x&#x2019; axis of the chart. If the segmented control value (sgMetric) is set to the number of deals (#), it groups the values by the stages defined, and counts the number of values in each group using .length. If the sgMetric is set to Value rather than the deal number, it groups and then sums the values in each stage to display the total dollar amount. <br></p><p>The keys are defined by the stage_order variable we defined, which looks like this: <br></p><pre><code class="language-JavaScript">{&apos;Prospect&apos;:0,
&apos;Negotiation&apos;:1,
&apos;Contract&apos;:2,
&apos;Won&apos;:3
}</code></pre><p><br>Then, the layout object of the chart is straightforward and principally defines the colors, as well as the ability to select and drag on the chart: <br></p><pre><code>{&quot;title&quot;: {
&quot;text&quot;: &quot;&quot;,
&quot;font&quot;: {
&quot;color&quot;: &quot;#3D3D3D&quot;,
&quot;size&quot;: 16
}
},
&quot;autosize&quot;:true,
&quot;height&quot;:1000,
&quot;font&quot;: {
&quot;family&quot;: &quot;var(--default-font, var(--sans-serif))&quot;,
&quot;color&quot;: &quot;#979797&quot;
},
&quot;showlegend&quot;: false,
&quot;margin&quot;: {
&quot;l&quot;: 72,
&quot;r&quot;: 0,
&quot;t&quot;: 0,
&quot;b&quot;: 0,
},
&quot;hovermode&quot;: &quot;closest&quot;,
&quot;hoverlabel&quot;: {
&quot;bgcolor&quot;: &quot;#000&quot;,
&quot;bordercolor&quot;: &quot;#000&quot;,
&quot;font&quot;: {
&quot;color&quot;: &quot;#fff&quot;,
&quot;family&quot;: &quot;var(--default-font, var(--sans-serif))&quot;,
&quot;size&quot;: 12
}
},
&quot;clickmode&quot;: &quot;select+event&quot;,
&quot;dragmode&quot;: &quot;select&quot;,
}</code></pre><p><br>By adding &#xA0;<em>&quot;clickmode&quot;: &quot;select+event&quot;, &#xA0;&quot;dragmode&quot;: &quot;select&quot; </em>to the layout object, we make it possible to open the modal and display a table filtered off the data. <br><br></p><h3 id="chart-details-modal">Chart details modal<br></h3><p>For the next steps, we set up the modal and detailed table view. </p><p>In the chart component, we set an event handler to trigger the modal to open on select. <br></p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXdnJ2_NqoKU5AL7r2fbmsyF-HPt7xAycXU075IiRzctQsmwC-WIFUO4Vj-qZM02RmkgUywMVHvVWFBIsK6pB-tQp5C-IR0JpZZcqWeBtRoQZi1BNNadnr9w4GsFOrJGJRtNvJXsiEK8B8iTG-YcVqOCrKk?key=-rORuAQrA3PZcXsyLT3qpA" class="kg-image" alt="Charting in Plotly part III - Interactive charts" loading="lazy" width="624" height="363"><figcaption>Event handler setup in Retool to trigger a modal when a bar in the funnel chart is clicked.</figcaption></figure><p><br>In the modal, we added a table, search bar, titles and more. For the table, we filter the data from the selected points in the chart. The table reflects the data we set up in the JS query at the beginning, and we have formatted these to be currencies, avatars, and dates in the column settings.<br></p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXcKCG7ULH8PkitpHtfaaNNfBuP2LTXcnERl6rao0ZI8i3JxCHXyegmn-NhpRm-bFIUm4emp6IVdnJJlLUokzX-i_b-Au2554iz-Q28nGrHs-4RW5KhGkSFmd03fcdLgrchOwFlne1U8FtnHHp1gPsMMzCE?key=-rORuAQrA3PZcXsyLT3qpA" class="kg-image" alt="Charting in Plotly part III - Interactive charts" loading="lazy" width="624" height="283"><figcaption>Event handler setup in Retool to trigger a modal when a bar in the funnel chart is clicked.</figcaption></figure><p><br>The search bar searches all records in the table and is connected to the &#x2018;search term&#x2019; value in the table component. </p><p>Using this filter will also apply multiple selected points, so users can drag over and select multiple stages at once and see all data for those tags. <br></p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXdw6N5UiSyTyHI2EGZ7BIMs8qIp2S2q0C9zm_emade2ElAtQCqz6HiETumirlKzeDXqwTQ-EmGXk1KcOIH0Y-Aq-bNzlegMQzDFAihqrxLryFhyU3BuzDhdEwPFuquzuFNu-nNdiPposuK2MrihmSjiLk93?key=-rORuAQrA3PZcXsyLT3qpA" class="kg-image" alt="Charting in Plotly part III - Interactive charts" loading="lazy" width="624" height="280"><figcaption>Retool table interface with a search bar at the top, filtering through selected data from the funnel chart.</figcaption></figure><p></p><h3 id="grouping-functionality">Grouping functionality<br></h3><p>We also used the recently-added grouping functionality to this modal, so that users can group the data in the table by the owner of that sales account. </p><p>To do this, we first had to figure out the column ID of the &#x2018;owners&#x2019; column. You can inspect this in the State section and copying the code - the order of these columns is reflected in the order in which they are listed in the table component inspector.<br></p><figure class="kg-card kg-image-card"><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXexn32g9k6Up-DbqHDPgA1-3SMAbWe4-lKvOy8IhQiJbT1CaFJayK3O_KvGqjQna8tSdRj_c-yCuWwu_BAmcwzg-wLP5OodSH-93Qcij5_mFxrhsxzikc6hlSdK9BmVGm2JvKPmuTphsvtLilHEY3KBVwr8?key=-rORuAQrA3PZcXsyLT3qpA" class="kg-image" alt="Charting in Plotly part III - Interactive charts" loading="lazy" width="293" height="300"></figure><p><br></p><p>We then added two event handlers to set and reverse this grouping. The first sets the grouping of the table by the &#x2018;Owner&#x2019; column. This only runs if they aren&#x2019;t grouped already using this code: <em>{{!tblDeals.groupByColumns.map(x=&gt;x.columnId).includes(&apos;6585e&apos;)}}</em><br></p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXckV79qpUOryIlhLL4E-SXNEYBSSEN7bK-ghCsPL-4Le-T1NEDkHZiMQGZK6LhWOuqSjwNu3L0Nfr50BOm-rTBCNIzb2DJblbd5ioLQnhjrmzCtQeV5cMalrLsL76xFIeTnBazzi-_P9qnqCiBCmUvC0QHY?key=-rORuAQrA3PZcXsyLT3qpA" class="kg-image" alt="Charting in Plotly part III - Interactive charts" loading="lazy" width="624" height="312"><figcaption>JavaScript code in Retool to apply grouping to the table data by &apos;Owner&apos; column, triggered by an event handler.</figcaption></figure><p><br>The other event handler performs the opposite and clears the grouping, if the groupByColumns value of the table is already set to Owners: <br></p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXeJunHbqgXsh5stio0S9yiwGrfKPHFIYkOoiuXW8Smz8a-NJ-wlNBDkZFlBmeVlTlQAzfT9Gw7pxOOAkDmHvhnOlbx_hKCOZTZgieA2XsVMwXh1a3DLcgxXoMKIF1soabBWyxKml2AC1BOSe4rs_vZc7NA?key=-rORuAQrA3PZcXsyLT3qpA" class="kg-image" alt="Charting in Plotly part III - Interactive charts" loading="lazy" width="441" height="314"><figcaption>JavaScript code to remove grouping from the table data in the Retool interface when a toggle is clicked.</figcaption></figure><p><br>We also set the text and icon of the button to switch according to whether the grouping has been set. <br></p><p>Text: <em>{{ tblDeals.groupByColumns.map(x=&gt;x.columnId).includes(&apos;6585e&apos;)?&apos;Clear Grouping&apos;:&apos;Group by Owner&apos;}}</em><br></p><p>Prefix icon: <em>{{ tblDeals.groupByColumns.map(x=&gt;x.columnId).includes(&apos;6585e&apos;)?&quot;/icon:bold/interface-edit-select-area-circle-dash&quot;:&quot;/icon:bold/interface-user-king-crown&quot;}}</em><br><br></p><h3 id="statistics">Statistics<br></h3><p>Finally, to add additional info to the modal, we set up some statistics to summarize the data. </p><p>For the <em>Deals in stage</em>, this JS filters for the selected points and counts the length of the array it returns, to show the number of entries under this stage selection. <br></p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXe98ZRIqF7gWHWdSnevB1nhRxtAGUHSzL03He_Yr0VoTkrg5qwNbOh4Om9nGNUmI-A00A4i-UxSkfyXMQCOuHDYKLE8JIT6CCsMKzyHyxEFB_LryxWantCmegNbrPqI4RXZuSTuLDBmP9fb_iJrUOMohYHY?key=-rORuAQrA3PZcXsyLT3qpA" class="kg-image" alt="Charting in Plotly part III - Interactive charts" loading="lazy" width="624" height="319"><figcaption>Statistic in the Retool modal showing the total number of deals in the selected sales funnel stages.</figcaption></figure><p><br>For the average size, the first JS script filters by the selected stage, and uses _.mean to find the average of the returned values. </p><p><em>{{_.mean(deals.data.filter(x=&gt;x.stage==Object.keys(stage_order.value)[chartFunnel.selectedPoints[0].indices]).map(x=&gt;x.value))}}</em></p><p>As in the first, the caption changes depending on whether one or more stages are selected.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXdTy49k6tqlMgmNELZsuxSODL0ao5lGJF34IWoRdJbsTjsVyUnOTAQvLM5gNJaHjBr4rZMdWxYQUMoKk77ayoQUJJJj25zbUA7l8FogXzLFQ8pG3GR0nJdpxX0dOzi_M9gKGS0iA4sfYsVO-fwqDZS66ji8?key=-rORuAQrA3PZcXsyLT3qpA" class="kg-image" alt="Charting in Plotly part III - Interactive charts" loading="lazy" width="496" height="515"><figcaption>Statistic in the Retool modal calculating the average deal size for the selected stages in the funnel chart.</figcaption></figure><p><br>The third statistic counts the number of days in the stage(s) selected. The code is very similar to the previous, but instead finds the mean of the &#x2018;daysInStage&#x2019; value.</p><p></p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXfaSykWllm5EiBXFGFa8R11VywrCsv15GJc1NNf0KoXZLbdh54Y1iGIQRrgggKKG_wypBE_LbS6XFlOihILUJ9MBT57Ih3TauqNsXLPTEH_yAwRaRzi8facjEIwDCMI-C7OErGkg0R65WLeQf30ZNVW61Q?key=-rORuAQrA3PZcXsyLT3qpA" class="kg-image" alt="Charting in Plotly part III - Interactive charts" loading="lazy" width="544" height="488"><figcaption>Statistic in the Retool modal calculating the average number of days deals spent in the selected funnel stages.</figcaption></figure><p><br></p><p>Finally we want to return the oldest deal in this stage and present how many days it has been there. For this we use the _.max Lodash function to find the highest value in the data and return it.</p><p></p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXfUlpL9aLOxNBChdxmIcwHkYU9Rn0-EkpFJ1UivU-i32oSR-3bCDHcS6sYFdvOw43iCrJYMVGWHPMEfsUDmMZarnDz3h_Fqp1t6r-xlVyfPwi7wwsac1eO2UBRnNeaBAY1-_Bs7nTp8RPFYuYjgGs2VwC_h?key=-rORuAQrA3PZcXsyLT3qpA" class="kg-image" alt="Charting in Plotly part III - Interactive charts" loading="lazy" width="534" height="544"><figcaption>JavaScript code in Retool to calculate and display the oldest deal in a selected sales stage.</figcaption></figure><p><br>And with those final touches - we have a fully functioning funnel chart with an interactive data modal. Since we want to reuse this exact same UI in more of our apps (as we recognize the value of consistent UI!), for our next step, we will make this chart into a module that simply needs to be connected to data to be easily reused.</p><p></p><h2 id="creating-a-module">Creating a module<br></h2><p>Using modules effectively is essential for building great applications in Retool. While caution should be exercised when it comes to which modules to build (we typically aim for navbars, forms and non mission-critical features such as this one) since performance can slow with too many modules in each app, using them well can make your internal app ecosystem much more scalable and easy to maintain in Retool. <br></p><p>Next, we&#x2019;ll show you how simple it was to make this feature a module. <br></p><p></p><h3 id="making-a-chart-into-a-reusable-module">Making a chart into a reusable module<br></h3><p>This works much the same way as the normal app did, but instead we have defined values for the inputs that can be configured and reused across our Retool environment.<br></p><p>When you set up a module, it gives you the global option to define inputs and outputs for this module. In this case, most importantly we have the deal_input - our deal data. We also have the option to set the title and the default input. <br></p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXfccxwwoNlmqKUjDV15pC4w_VFtPCFHXdAKcWA52i8OBfGk-mmhZpXFCB-4cAECzKA5zsLc2aZRV_9dDq77LlSA9edzamGPKFEUIXmphdqlAOM8MciodM2Lj5hyvV-zAjxZZBjZk7ddRaKweU2MA0kQVeE5?key=-rORuAQrA3PZcXsyLT3qpA" class="kg-image" alt="Charting in Plotly part III - Interactive charts" loading="lazy" width="624" height="351"><figcaption>Retool module interface showing options to define inputs and outputs, including deal data and title for reuse in different apps</figcaption></figure><p><br>With modules, you can also connect test data in these places to make sure everything is working correctly. You can access these test values by selecting the moduleContainer in the component tree in the left-hand panel.<br></p><p>In our case, we set up another JS query with some mock data and connected this test data to the demo data as data_input:<br></p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXdjY1P8h7iMpN1gs9flPC-CZBg-eFJ5xvMm5eX1hQB3CkjFZPUjgj4ilY_AIiI4bBv5goLwwRgZrzko9m3KA1uIK26wsnMo1wlT2TgpRxntk2k7BazAcFusfitfCYnjhFvaN4sATZD-xVzr4vNT-3y643AK?key=-rORuAQrA3PZcXsyLT3qpA" class="kg-image" alt="Charting in Plotly part III - Interactive charts" loading="lazy" width="624" height="371"><figcaption>Retool interface showing JavaScript code with mock data, connected to test the reusable module for the funnel chart</figcaption></figure><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXe-ZNydXysxczAO9yupEECId5xu0V1M7_A3rRubF6UdwhH1ODl4gRuxCKStqJMKKD5Lbb2U7vWaDF1_pXGn0VJhaY02X503k1Ik66qeaJA5rawcGVk3ULIFmVD3TEDKlac004CdeiVsSkw2wrPcaPdOb7s?key=-rORuAQrA3PZcXsyLT3qpA" class="kg-image" alt="Charting in Plotly part III - Interactive charts" loading="lazy" width="624" height="196"><figcaption>Test data setup in Retool, connected to the module&apos;s input to test funnel chart functionality.</figcaption></figure><p><br>This data is the same as we used in the first tutorial above, so all that we changed in the module was switching the references from deal.data, our previous demo data query, to deals_input.data, the name of our module input value. This way the data in the funnel chart input will automatically switch to whatever data it is connected to in each app. <br></p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXc55e65sEdEESWio75j-OCWhyVgWDPYn7A3O-l_v4hMTvVvYJyx-aBn8APOTh8KzAzGCUp7PqnZU6IDHDEg9pmrntjVRFhF_qYvM8kvTMaNLXe5_P9t_tOiGJEO5_MMrsTqUCVTYburzVzDRy2oE7v1HqwS?key=-rORuAQrA3PZcXsyLT3qpA" class="kg-image" alt="Charting in Plotly part III - Interactive charts" loading="lazy" width="624" height="211"><figcaption>Retool app interface showing a reusable funnel chart module, with data connected to the module&apos;s input and dynamic title setup.</figcaption></figure><p><br>Here you can see the module in use within an app. All we needed to do was pull in the module, and connect our chart data to the deal_input value in the module component. We set the title manually, but this could also be connected to dynamic data or inputs in the app. <br></p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXfXuh8mbfMPIp_wePEtueU9SrcwkDDzIAF0Bow3yviWbiRP7EwOMZbD7J3tlk_iDfcp5rZQ-puv_7i63m9V6oKOA7avZDr9ux6uIwPr0W_GHqukgyui_5wVQVHTIWDwC0ZxXGmAGRh0cS9SuLJPHgoJqIIu?key=-rORuAQrA3PZcXsyLT3qpA" class="kg-image" alt="Charting in Plotly part III - Interactive charts" loading="lazy" width="624" height="177"><figcaption>Final funnel chart module in use within a Retool app, displaying connected data and title dynamically.</figcaption></figure><p><br>This is a great example of using modules to create repeatable patterns in Retool development that ensure consistency and that code is not constantly repeated throughout apps (and therefore becomes hard to maintain). <br></p><h2 id="download-the-sample-toolscript">Download the sample toolscript</h2><p>The Toolbox newsletter members can download the JSON and import it directly into their Retool environment to test it out &#x2B07;&#xFE0F;&#x2B07;&#xFE0F;&#x2B07;&#xFE0F;</p><div class="kg-card kg-button-card kg-align-center"><a href="#/portal/signup/free" class="kg-btn kg-btn-accent">Sign up to the Toolbox newsletter</a></div><p>Members will get guides, tutorials and internal tool tips in 1-2 emails every month.</p><div class="kg-card kg-callout-card kg-callout-card-blue"><div class="kg-callout-emoji">&#x1F4A5;</div><div class="kg-callout-text">At <a href="https://www.boldtech.dev/?ref=143.198.97.195">Bold Tech</a>, we specialize in building great internal tools, fast. We are obsessed with building apps that make your teams happier and more productive. In our <a href="http://143.198.97.195:2369/">blog</a>, you can learn all about how to build better business software for more satisfied employees, or <a href="https://www.boldtech.dev/contact?ref=143.198.97.195">get in touch</a> to chat to us about what you&apos;re looking to build.</div></div>]]></content:encoded></item><item><title><![CDATA[Charting in Retool with Plotly. Part II: The Sankey Diagram]]></title><description><![CDATA[In Part II, we share a case study of how we used Plotly to build a complex Sankey generator with a super user-friendly interface.]]></description><link>http://143.198.97.195:2369/charting-retool-with-plotly-sankey/</link><guid isPermaLink="false">668e81d6dbece927645cd2a4</guid><category><![CDATA[Plotly Guides]]></category><category><![CDATA[Retool]]></category><dc:creator><![CDATA[Joey Karczewski]]></dc:creator><pubDate>Wed, 17 Jul 2024 15:41:47 GMT</pubDate><media:content url="http://143.198.97.195:2369/content/images/2024/07/Sankey-thumb.png" medium="image"/><content:encoded><![CDATA[<img src="http://143.198.97.195:2369/content/images/2024/07/Sankey-thumb.png" alt="Charting in Retool with Plotly. Part II: The Sankey Diagram"><p>As part of our <a href="http://143.198.97.195:2369/tag/plotly-guides/"><em>Charting in Retool</em> series</a>, we&#x2019;re stretching the limits of Plotly to create some incredible and functional charts to use in our apps in Retool. </p><p>In <a href="http://143.198.97.195:2369/charting-in-retool-with-plotly-part-i/">Part I</a>, we reviewed some of the Plotly basics and how to set up some functionality around the line/scatter graph type of chart. We showed you how, by coding with Plotly, it&#x2019;s possible to create highly custom charts, with built-in functionality like <a href="http://143.198.97.195:2369/charting-in-retool-with-plotly-part-i/#scatter-plotline-graph-step-by-step">range sliders, buttons, and annotations</a>. Integrating these with your existing Retool apps makes these charts even more useful and interactive.</p><p>In Part II, we&#x2019;ll be sharing a case study of how we built a complex Sankey generator with a super user-friendly interface. You can use it yourself at <a href="http://sankeygenerator.com/?ref=143.198.97.195">sankeygenerator.com</a>. <br></p><p></p><h2 id="building-complex-charts-in-retool-with-plotlybuilding-a-sankey-generator">Building complex charts in Retool with Plotly - building a Sankey generator<br></h2><p>So from the simple charts in Part 1, we&#x2019;re now moving to some much more advanced graphing, to share an app we built to create <strong>complex Sankey charts</strong>. </p><p>If you aren&#x2019;t already familiar, Sankey charts are a way of visualizing flows of data across various stages, presenting a clear representation of the movement of numerical values (such as amounts of money) from a source to a target. Each stage of the process is represented by a node proportional to the numerical value.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://lh7-us.googleusercontent.com/docsz/AD_4nXerUFSEtZ0CFvsHU1FhwwT3gmfjMJ1s53T4bfAMcXt-euFWGgXJkaSvlMxv76Ho_bZh1ejwoL4P02fXmhnYfTOriVVl4jJYQj7lvRe5yJUulYQg5svtiM855Yq552W3MNYAz68f5ntpxssNN3g7Wpvl7Cs?key=J28ZIkzsTFt-5kxkJu6vag" class="kg-image" alt="Charting in Retool with Plotly. Part II: The Sankey Diagram" loading="lazy" width="574" height="316"><figcaption>Sankey diagram generator app in Retool</figcaption></figure><p></p><p>You may see various Sankey diagrams used for visualizing personal finance, job searches, or breaking down complex budget flows within a company. </p><p><a href="https://www.sankeygenerator.com/?ref=143.198.97.195">Play around with it yourself</a> and see!</p><p>Note: Data is saved only on the front end and isn&#x2019;t exposed to us internally. <br><br></p><h2 id="how-do-sankey-diagrams-work">How do Sankey Diagrams work?<br></h2><p>There are many options out there for building Sankey diagrams, but few of them are intuitive to use and most offer a complex UI that requires a bit of a learning curve. For this reason, we focused on building a Sankey option with a UI that even a beginner could understand. </p><p>Sankey diagrams are often simple to understand, but it&#x2019;s easy to hit some mental roadblocks once you start building one yourself. <br><br>Sankey diagrams can get really complex too - if we take a look at the Sankey diagram below from user <a href="https://www.reddit.com/r/dataisbeautiful/comments/191l5r8/oc_my_2023_spending_visualized_aerospace_us/?ref=143.198.97.195">ArciticDrag0n</a> on Reddit as an example. There are tons of data points here, but at first glance it&#x2019;s still easy to interpret the flow of this salary budget. <br></p><figure class="kg-card kg-image-card"><img src="https://lh7-us.googleusercontent.com/docsz/AD_4nXdf27OG5B11GyDI1ogEs55bnwyfAnltMoXOJhjeTBOPO67OA0BDHWlU3XaCRBQltVrY6cvLr9WPL2PioW-cBOYUXkdGpUOi_GgSeafQhQtf320R7GQikqWVP7azCrDeR-jdJ_D7gBRj0iAfqw9tap6OH1o?key=J28ZIkzsTFt-5kxkJu6vag" class="kg-image" alt="Charting in Retool with Plotly. Part II: The Sankey Diagram" loading="lazy" width="624" height="475"></figure><p><br><br>The style shown above is a common way of presenting data flow in a Sankey Diagram: on the left-hand side we show specific inputs or <em>nodes</em> that flow to the right. Gross Pay, Tax Return &amp; Employer Match are all sources of income, and this total income is then broken down into its separate parts, in this case - taxes, net income, and a few other sub-nodes. </p><p>When programming a Sankey diagram, it&#x2019;s easiest to think of the source as the <em>from</em>, the target as the <em>to,</em> and then the <em>value</em> is how much value flows between them. </p><p>This is not the only style of Sankey chart out there. Sankey chart flows can double back on themselves and represent more abstract flows of resources and values. <br><br></p><h2 id="how-did-we-build-sankeygeneratorcom">How did we build SankeyGenerator.com? <br></h2><p>The Sankey generator consists of three sections and a Sankey canvas. The first section is a &#xA0;home page where users can select and preview sample diagrams to be introduced to the tool. </p><figure class="kg-card kg-image-card"><img src="http://143.198.97.195:2369/content/images/2024/07/Screenshot-2024-07-17-at-16.48.23.png" class="kg-image" alt="Charting in Retool with Plotly. Part II: The Sankey Diagram" loading="lazy" width="2000" height="891" srcset="http://143.198.97.195:2369/content/images/size/w600/2024/07/Screenshot-2024-07-17-at-16.48.23.png 600w, http://143.198.97.195:2369/content/images/size/w1000/2024/07/Screenshot-2024-07-17-at-16.48.23.png 1000w, http://143.198.97.195:2369/content/images/size/w1600/2024/07/Screenshot-2024-07-17-at-16.48.23.png 1600w, http://143.198.97.195:2369/content/images/size/w2400/2024/07/Screenshot-2024-07-17-at-16.48.23.png 2400w" sizes="(min-width: 720px) 720px"></figure><p></p><p>The &#x2018;Generate my Sankey&#x2019; button leads to the <em>Create</em> page, where users can configure their own Sankey diagram using a simple table layout, download their Sankey as a PDF or upload a previously configured Sankey diagram. </p><p></p><figure class="kg-card kg-image-card"><img src="http://143.198.97.195:2369/content/images/2024/07/Screenshot-2024-07-17-at-16.48.54.png" class="kg-image" alt="Charting in Retool with Plotly. Part II: The Sankey Diagram" loading="lazy" width="2000" height="894" srcset="http://143.198.97.195:2369/content/images/size/w600/2024/07/Screenshot-2024-07-17-at-16.48.54.png 600w, http://143.198.97.195:2369/content/images/size/w1000/2024/07/Screenshot-2024-07-17-at-16.48.54.png 1000w, http://143.198.97.195:2369/content/images/size/w1600/2024/07/Screenshot-2024-07-17-at-16.48.54.png 1600w, http://143.198.97.195:2369/content/images/size/w2400/2024/07/Screenshot-2024-07-17-at-16.48.54.png 2400w" sizes="(min-width: 720px) 720px"></figure><p></p><p>Finally, we have a canvas settings page where users can define font sizes, give their chart a title &amp; more.</p><p></p><figure class="kg-card kg-image-card"><img src="http://143.198.97.195:2369/content/images/2024/07/Screenshot-2024-07-17-at-16.49.21.png" class="kg-image" alt="Charting in Retool with Plotly. Part II: The Sankey Diagram" loading="lazy" width="2000" height="894" srcset="http://143.198.97.195:2369/content/images/size/w600/2024/07/Screenshot-2024-07-17-at-16.49.21.png 600w, http://143.198.97.195:2369/content/images/size/w1000/2024/07/Screenshot-2024-07-17-at-16.49.21.png 1000w, http://143.198.97.195:2369/content/images/size/w1600/2024/07/Screenshot-2024-07-17-at-16.49.21.png 1600w, http://143.198.97.195:2369/content/images/size/w2400/2024/07/Screenshot-2024-07-17-at-16.49.21.png 2400w" sizes="(min-width: 720px) 720px"></figure><p></p><p>Let&#x2019;s run through some of the core features of this app and talk a little about how we built it out. <br></p><p></p><h3 id="plotly-code">Plotly Code<br></h3><p>Sankey diagrams are natively included in Plotly using the &#x2018;Sankey&#x2019; chart type, and they already offer some great built-in features. </p><p>Below is an example of a very basic Sankey diagram from the <a href="https://plotly.com/javascript/sankey-diagram/?ref=143.198.97.195">Plotly docs</a>.<br></p><pre><code class="language-JavaScript">var data = {
type: &quot;sankey&quot;,
orientation: &quot;h&quot;,
node: {
pad: 15,
thickness: 30,
line: {
color: &quot;black&quot;,
width: 0.5
},
label: [&quot;A1&quot;, &quot;A2&quot;, &quot;B1&quot;, &quot;B2&quot;, &quot;C1&quot;, &quot;C2&quot;],
color: [&quot;blue&quot;, &quot;blue&quot;, &quot;blue&quot;, &quot;blue&quot;, &quot;blue&quot;, &quot;blue&quot;]
},
link: {
source: [0,1,0,2,3,3],
target: [2,3,3,4,4,5],
value:  [8,4,2,8,4,2]
}
}
var data = [data]
var layout = {
title: &quot;Basic Sankey&quot;,
font: {
size: 10
}
}
return {data, layout};</code></pre><p><br>You can import this directly into a JS query in your Retool app, and set it up by linking to the data and object values in the chart component - as we showed in Part 1. &#xA0;</p><p>What&#x2019;s particularly nice about the Plotly code is that the node positions within the generator are completely dynamic, so you can move the nodes around to suit the presentation you are looking for. This kind of interactivity built-in is something we love about Plotly. </p><p>This is how the base data object of our Plotly code looks. Due to all the functionality in our app, our Plotly code is very complex, and we defined several variables and set functions above. </p><p>However, you can see that most importantly, under the &#x2018;Link&#x2019; object, we define the sources, targets, and values of our nodes which we have mapped from our table.</p><p></p><figure class="kg-card kg-image-card"><img src="https://lh7-us.googleusercontent.com/docsz/AD_4nXdgUVlo-XMJrjXC4K213Wx1l344jFGHj4mbL8oRg39EY0j5yc82o9tGK9IVQGatZZ58GcsFp34hjAexyM9IWsbz4hWCY_9SD7_0UcNpj1AXPLohH7lVgwnSwOm7ue5b9VNuNbqib99ZENSLMuFdVsN0t4bC?key=J28ZIkzsTFt-5kxkJu6vag" class="kg-image" alt="Charting in Retool with Plotly. Part II: The Sankey Diagram" loading="lazy" width="406" height="446"></figure><p><br>We&#x2019;ll explain this code as we show you some more features.<br></p><p></p><h3 id="user-interface">User interface<br></h3><p>What&#x2019;s most important about this app, is the ability for any user &#x2013; whether familiar or unfamiliar with Sankey diagrams or code &#x2013; to jump in and use it right away. That&#x2019;s why we set the configuration interface up as a simple table. <br></p><figure class="kg-card kg-image-card"><img src="https://lh7-us.googleusercontent.com/docsz/AD_4nXfMun8St5_46gL5-m2DF9KfWgbTbsTelw9ejq6_6tWvI-Je9H22fzNzhgV5lXnSXHmcULgt83Q1GPKu6x9mFUMBz8deC-97mBFatMFHk4TTNU85vl9QGBVOfJHQNEKvUNaKF9SgpKBrzMxe-4suN7L5h-t8?key=J28ZIkzsTFt-5kxkJu6vag" class="kg-image" alt="Charting in Retool with Plotly. Part II: The Sankey Diagram" loading="lazy" width="624" height="395"></figure><p><br>The table that is shown is based on the values in the &#x2018;sankey_input.value&#x2019;, which defaults to the values in the selected template. This value is how we create actions such as adding and deleting nodes.<br></p><figure class="kg-card kg-image-card"><img src="https://lh7-us.googleusercontent.com/docsz/AD_4nXdPco3s6jiQA0Nx1gcrndrWt7veRMvQh3zsAnUBNXy9GUISYgdtq4F4eFDdr030CWvbK1Zo_4slG7LGzPkKhuPSFAtQCQ6HEu1ryizsUIwsxa5Niy9djSEjz7UocLXgT153awZLn_I-9YZSqLWPJwaJw4Z2?key=J28ZIkzsTFt-5kxkJu6vag" class="kg-image" alt="Charting in Retool with Plotly. Part II: The Sankey Diagram" loading="lazy" width="624" height="217"></figure><p><br></p><p>Users can add new nodes to this table and chart by selecting the <em>from </em>and <em>to </em>inputs and defining a value. The dropdown (select) components are defined by the values already in the table, but custom values are also allowed so that new sources and targets can be created.<br><br></p><figure class="kg-card kg-image-card"><img src="https://lh7-us.googleusercontent.com/docsz/AD_4nXcNh1r165q0R0hToaMYwpf_AbLblGfm1yxuJGK5mY5f0arUU36k1mgBFX0GnMrWBLnqfQbNAQMttzIJdIJkMfu6dhrBaUgPmjzA0F1kv49OQ1M_q9CErX1qK2-iNmzEQe_mOlDOMaYs_15sMYlczr_nqc4?key=J28ZIkzsTFt-5kxkJu6vag" class="kg-image" alt="Charting in Retool with Plotly. Part II: The Sankey Diagram" loading="lazy" width="283" height="533"></figure><p><br></p><p>When &#x2018;Add node&#x2019; is clicked, the node is defined as a new value in the sankey_input variable and it will then appear in the table and Sankey diagram. <br></p><figure class="kg-card kg-image-card"><img src="https://lh7-us.googleusercontent.com/docsz/AD_4nXeMyyIZDiCNnXYvHr8lrxSs5_LNXtuwQCQwuXdmnoedwFBEAGvggKOIIN36ku-Bhk6oCy_nQNb1nOMwicYSlmMCSixL9HMxW-VwJ9TIsMGYT5nwBJ6GFFOLkHhUfn-fLLrh7zvwjN8g04UngvSvT8j-3X0?key=J28ZIkzsTFt-5kxkJu6vag" class="kg-image" alt="Charting in Retool with Plotly. Part II: The Sankey Diagram" loading="lazy" width="332" height="273"></figure><p><br></p><p>Users can delete a node by clicking the trash can in-line in the table. This is set as a row action in Retool. <br></p><figure class="kg-card kg-image-card"><img src="https://lh7-us.googleusercontent.com/docsz/AD_4nXcK-80hb85lRDcl3bK8a09MoLHAkLF3LljVExcautS9r4TNnhoyfKbJZQh-eXkoDVv9kf0mw1M1_0WqPMfdmYB8lJUQ9pe46WbeIQhtGvpUmtUu3m1P3qb7SAFqEVY4z-Rt0XXX-6kO8Dab6qm_csJakaU?key=J28ZIkzsTFt-5kxkJu6vag" class="kg-image" alt="Charting in Retool with Plotly. Part II: The Sankey Diagram" loading="lazy" width="443" height="343"></figure><p><br>Hovering over a row pulls up a row action and clicking on this action will delete the entire row and all of its parts. Deleting a row will also reevaluate all target node values to account for the deleted node and readjust the proportions of the nodes.</p><p>By clicking &#x2018;More actions&#x2019; users can clear the entire table and start from scratch, and also view the table rows grouped by their source node to help them understand more complex tables. This simply switches a tabbed container to a different table view which is grouped by default. <br></p><figure class="kg-card kg-image-card"><img src="https://lh7-us.googleusercontent.com/docsz/AD_4nXcjremcBaRrNHT8Rr_MgJIDhop_meTlDY0-xQmEEYwHqJ-__fLsHPixi6GftZV4FhyxFHlMj0Pu-Vdgjz42yRPeSWoHhaoDjR6p7lbkqZwYA0deLpPRCwWo2VCvxaFbGkpkuZVVEdLWCbOS6ou9IO6byo90?key=J28ZIkzsTFt-5kxkJu6vag" class="kg-image" alt="Charting in Retool with Plotly. Part II: The Sankey Diagram" loading="lazy" width="624" height="327"></figure><p><br>Now let&#x2019;s look at some more features that we built in to make this app more user-friendly.<br></p><h3 id="downloading-the-csv-template">Downloading the CSV template<br></h3><p>If a user doesn&#x2019;t have the chance to complete their chart, or wants to save their Sankey to edit later, they can click &#x2018;download as template&#x2019; in the top right hand corner. </p><p>Download as template will save the Sankey configuration as a simple CSV which can then be reimported.<br></p><figure class="kg-card kg-image-card"><img src="https://lh7-us.googleusercontent.com/docsz/AD_4nXcYtIwSPQ2qD9iSfS559yGzVpXNZrtCvtROCe3gOzQZ3gC4W1m0KKxzmKIXv7_THAVSBOkUv2oT11LLq14yotkKvEbrIdBCU_bWVUvHghE5RG1zCAAonEd4tFe90Vv1cRnyiR2ZTN7BQbJHDLOlTRz4svk-?key=J28ZIkzsTFt-5kxkJu6vag" class="kg-image" alt="Charting in Retool with Plotly. Part II: The Sankey Diagram" loading="lazy" width="624" height="345"></figure><p><br></p><p>To upload a template, users just click on &#x2018;More actions&#x2019; once more and select Upload. This opens a modal with a file dropzone.<br><br></p><figure class="kg-card kg-image-card"><img src="https://lh7-us.googleusercontent.com/docsz/AD_4nXcYxInSRQlrQMIZliANmbvehgqYDdd50yFBLVUYE0msB7ECpeCVz6SccflmGM1fw5DcUeJvkaonvQ_f_a9NxD3xgiZ1B2wHv1GVttmNliat8JSVAK3kQAy2t_SpJ_pFM4YOtPJU7gIyZQZ-exZXS3Cb7SIU?key=J28ZIkzsTFt-5kxkJu6vag" class="kg-image" alt="Charting in Retool with Plotly. Part II: The Sankey Diagram" loading="lazy" width="624" height="215"></figure><p><br>Once a user drops their CSV file template here, a script uses this to set the value of sankey_input once more, clear the dropzone and close the modal. Then the user will have the same Sankey chart in their app once more.</p><p></p><figure class="kg-card kg-image-card"><img src="https://lh7-us.googleusercontent.com/docsz/AD_4nXfIRIOTSy1UPMcu_iloxG038QnJN4aNOyazYTrLdW8xN9nb7kb4plbnV2Z-7VZ6Nm9vWckU0wxVEXrB3aBTgLCC_3VVfweM-vUxxAfTqPtMpFh6YUrCmL2-82SrGq8fRet_ZOT-4xhwb1ipKhdTgpL0TEsY?key=J28ZIkzsTFt-5kxkJu6vag" class="kg-image" alt="Charting in Retool with Plotly. Part II: The Sankey Diagram" loading="lazy" width="624" height="393"></figure><p><br><br><br></p><h3 id="exporting-the-sankey-to-pdf">Exporting the Sankey to PDF<br></h3><p>While users can take a screenshot of their Sankey chart, it can be really useful to have as a handy PDF. So, in the top corner of the configuration we added an &#x2018;Export Sankey as PDF&#x2019; button. This uses the Retool utils.downloadPage option. You can learn more about PDFs in Retool in our PDF guide.<br><br></p><figure class="kg-card kg-image-card"><img src="https://lh7-us.googleusercontent.com/docsz/AD_4nXfND4wV5WKkHq0IDhngzbl_KQpFZkXqELeCnCDHzv1ZfE7RSdfUHPKiD1RNHCWFABLgjOPxI0uFELSPsISYNffb4QCEK4qZA_uZucDwqvbjJaeL04skNIuEdO5nVffNB4OjwWRH44EeeB3Xb7pH2iHCb3S4?key=J28ZIkzsTFt-5kxkJu6vag" class="kg-image" alt="Charting in Retool with Plotly. Part II: The Sankey Diagram" loading="lazy" width="624" height="309"></figure><p><br>This will automatically download the chart to a single-page PDF and set the file title to the title of the Sankey.<br><br></p><h3 id="customizing-the-sankey-diagram">Customizing the Sankey diagram<br></h3><p>Finally, it&#x2019;s obviously important to most people that their Sankey diagrams suit their personal style, so that&#x2019;s why we added some detailed configuration options.<br></p><p>On the design tab of the application, you can set the title, the background color, font height and color theme for the actual diagram itself. The title text and font size is then set in the Layout object of the Plotly chart.<br></p><figure class="kg-card kg-image-card"><img src="https://lh7-us.googleusercontent.com/docsz/AD_4nXcZXrRn0h46Q2faOe2TMJox7Gp9OFcbtkHBVPldPfdSF7gvl80qn-bjE3qukoc1YEVSxLRjwePtlhPTAY2q6RyxoRPh5egKHLirA_d83lgJqyyTrFrlowB68yKgV22KJ-Fqk_zWziSeQIq8sXk3ya5YVtEk?key=J28ZIkzsTFt-5kxkJu6vag" class="kg-image" alt="Charting in Retool with Plotly. Part II: The Sankey Diagram" loading="lazy" width="624" height="264"></figure><p><br><br>We also added options to change the orientation and flip the data. The orientation is a simple boolean value inside the Plotly docs (see our first code image) and the flip option simply inverts the data throughout.<br></p><figure class="kg-card kg-image-card"><img src="https://lh7-us.googleusercontent.com/docsz/AD_4nXdmvkk1cnkdyH2IAxJIsq5vcMCzSoEtvwVY8-J4G9gDxLc8WJlPn32HOHq474d-coilhh5uqOfF4bpZIQ12SD-BDQH2BPUU9WBX1Yo6K9NTlMjWvmVWg-NE2y0U2M-mpHMH1tUFIFIZnKhGeOjvlxSYODpw?key=J28ZIkzsTFt-5kxkJu6vag" class="kg-image" alt="Charting in Retool with Plotly. Part II: The Sankey Diagram" loading="lazy" width="624" height="147"></figure><p><br></p><p>We set the color options using some color palettes. We start with three default palettes, which are defined in the color_v variable and presented in a Listview with a repeating color input component.<br></p><figure class="kg-card kg-image-card"><img src="https://lh7-us.googleusercontent.com/docsz/AD_4nXcZgNx0_FEHPeBOsFNltU_cwCc9koZTJMhDp_-4P8vpd_2msu9vd3kf8U02FT9TR7RiVCtEEZ5g6R0IgC_tiADLWaBh65o8XHoKAMIwQg1T8CT0DrwVPsILJyFdDc61IS5nFmVJKl2PrNhxBacemU9mH-NP?key=J28ZIkzsTFt-5kxkJu6vag" class="kg-image" alt="Charting in Retool with Plotly. Part II: The Sankey Diagram" loading="lazy" width="624" height="297"></figure><p><br><br></p><p>When a different color is selected from the color inputs, this sets the new value in the color_v variable. Finally, in our Sankey code, we defined the color variable as an array based on this variable called &#x2018;color&#x2019; and, with a little tweaking, mapped this as the color options in the Sankey code. <br><br></p><figure class="kg-card kg-image-card"><img src="https://lh7-us.googleusercontent.com/docsz/AD_4nXcVjbNdwIBbQF4Rlpmm_r1lc1zYIC3QO80Ef2iNlRWWVwzB0PKJnEwaFCdTo9i6STIsgz_Jx6xjiIsfZd89-qR8NvJx2dfsNnw5SGDycws53kM5utuIZVP-0OCRm9_FG9lBwtWKjCnLqtPpDaeKcWBGhNFC?key=J28ZIkzsTFt-5kxkJu6vag" class="kg-image" alt="Charting in Retool with Plotly. Part II: The Sankey Diagram" loading="lazy" width="624" height="189"></figure><p><br>Now, not only is it possible to build functional Sankey diagrams fast, they can be beautiful too!<br></p><hr><p>While Retool is often seen as a product with limited charting options, we hope this proves the scope of what can be done with a little creativity in the Plotly code. Retool is a great platform for building intuitive, flexible UIs that can be quickly adjusted to user feedback and experience.</p><p>In the next part of our <a href="http://143.198.97.195:2369/tag/plotly-guides/">Plotly series</a>, we&#x2019;ll be sharing some more unexpected charting options that you can include in Retool to make your internal apps (or even external ones) even more powerful.</p><p></p><div class="kg-card kg-callout-card kg-callout-card-blue"><div class="kg-callout-emoji">&#x1F4A5;</div><div class="kg-callout-text">At <a href="https://www.boldtech.dev/?ref=143.198.97.195">Bold Tech</a>, we specialize in building great internal tools, fast. We are obsessed with building apps that make your teams happier and more productive. In our <a href="http://143.198.97.195:2369/">blog</a>, you can learn all about how to build better business software for more satisfied employees, or <a href="https://www.boldtech.dev/contact?ref=143.198.97.195">get in touch</a> to chat to us about what you&apos;re looking to build.</div></div>]]></content:encoded></item><item><title><![CDATA[Charting in Retool with Plotly. Part I: Line graphs step-by-step beginners guide]]></title><description><![CDATA[In this first part of the Plotly in Retool series, we’re going back to basics with the line/scatter chart and how to add more useful features like trend lines and annotations. ]]></description><link>http://143.198.97.195:2369/charting-in-retool-with-plotly-part-i/</link><guid isPermaLink="false">6682f2fadbece927645cd1ff</guid><category><![CDATA[Plotly Guides]]></category><category><![CDATA[Retool]]></category><category><![CDATA[Guides]]></category><dc:creator><![CDATA[Sophie Becker]]></dc:creator><pubDate>Mon, 08 Jul 2024 17:43:46 GMT</pubDate><media:content url="http://143.198.97.195:2369/content/images/2024/07/Ploltly-part-1-thumb.jpg" medium="image"/><content:encoded><![CDATA[<img src="http://143.198.97.195:2369/content/images/2024/07/Ploltly-part-1-thumb.jpg" alt="Charting in Retool with Plotly. Part I: Line graphs step-by-step beginners guide"><p>At <a href="www.boldtech.dev">Bold Tech</a>, we think that Plotly Charts are a criminally underrated option in <a href="http://143.198.97.195:2369/what-is-retool/">Retool</a>. For that reason, we&#x2019;ve spent some time digging into all the options available with Plotly and have come up with a whole series of design choices, ranging from simple to complex, to help Retool users integrate better data into their apps. </p><p>In this first part of the series, we&#x2019;ll strip it back to basics with the line/scatter chart and add various features to make it more useful. This will also help to illustrate the structure of the data/layout objects in Plotly, which is often the biggest struggle for developers using it in Retool. </p><p>In the rest of this series of Plotly guides, we&#x2019;ll show you how to make more advanced graphs and charts that might just rival those of your favorite BI tools. <br><br></p><h2 id="plotly-in-retool-pros-and-cons">Plotly in Retool: Pros and Cons<br></h2><h3 id="pros">Pros<br></h3><ol><li>Plotly is hugely flexible and with a little tweaking you can get most of the results that you are looking for. This is very useful for consolidating your tech stack and removing costly BI seats for your organization.</li><li>You can build out niche use cases for your team based on interactive data already available in your apps.</li><li>Simple charts are <em>really</em> easy to build - and these tend to be the majority of use cases we see. For presenting these simple charts, paying for PowerBI or similar products might be overkill and Retool is a great alternative.</li><li><a href="https://plotly.com/javascript/text-and-annotations/?ref=143.198.97.195">Annotations</a> help add a lot of contextual information to chart formats.</li><li>The flexibility of Retool means you can build your charts specifically for the end user. For example, you might see that operations teams want to see data in a more action-focused format than team leaders, or even marketing teams, who might prefer detailed charts. With Retool you can present the data exactly how it suits these teams.<br></li></ol><h3 id="cons">Cons </h3><ol><li>Development speed using Plotly is the major limitation compared to standard BI tools, and is typically slower than the speed of development you&#x2019;d be used to in Retool too.</li><li>Nevertheless, Business Intelligence tools like Tableau are usually very expensive, so if you only use a limited selection of charts, you might find using Plotly in Retool a good way to save money.</li><li>Plotly can take a little time to get into and truly understand, and there is a steep learning curve to mastering the system that may not pay off if you are only looking to make a single chart.<br><br></li></ol><p></p><h2 id="plotly-essentials">Plotly Essentials<br></h2><p>Retool has built in a UI layer for working with Plotly in Retool, but they are mostly limited to simple charts like bar graphs, line and pie charts, and scatter plots. Working with these options is simple and Retool does a lot of the heavy lifting for you, automatically offering the data as available in your data resource, and allowing you to sum, average, median your data, and more.<br></p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://lh7-us.googleusercontent.com/docsz/AD_4nXc_LB0WfYfkbKw2cm5ueDGyNABbSnjjeT20ypn6zyb8IkIRPLAXuCE9GAUQ7vX7hTHKYZ1hKCxvXD6y50WJwAwsiPbrUXiUlu7mquPcVXUVR6Ne4A1VmhHwZCUGCSO5S3iWYW44o-QnpNSgzQSMhr1BeDNL?key=DYBZ1Fhvhcb3ihta1uO1ow" class="kg-image" alt="Charting in Retool with Plotly. Part I: Line graphs step-by-step beginners guide" loading="lazy" width="311" height="386"><figcaption>An example of the UI layer with Plotly showing the dataset for a line chart in Retool</figcaption></figure><p><br>With more complex datasets, however, it can be tricky to format the data correctly in the spaces provided. In this case it can be more straightforward to format into a JavaScript query. The Retool UI also doesn&#x2019;t leave much space for customization with the built-in options.</p><p>The key to learning how to use Plotly in Retool is understanding how to transfer their <a href="https://plotly.com/javascript?ref=boldtech">detailed documentation</a> into the <em>data </em>and <em>layout </em>objects used in Retool. </p><p>Luckily, there is a simple trick that can help you get started with this for all the <a href="https://plotly.com/javascript/line-and-scatter?ref=boldtech">demo charts</a> and their code that are available in the Plotly docs. All you need to do is copy and paste the example code into a JavaScript query and change the final line from <em>Plotly.newPlot(&apos;myDiv&apos;, data, layout);</em> to <em>return {data, layout};. </em></p><p>You can then refer to these objects in the respective value boxes in the Retool chart component - switching the option to PlotlyJSON instead of the UI form, and referring to the attributes in your query.<br></p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://lh7-us.googleusercontent.com/docsz/AD_4nXdWTnHBka7dC5Ji0H70fslQy8L2wb5SH3OtgIS7f9X-89InDq5TouZhG6FnE0kqGqUqoIIa5AfaI8_M0N3roWwnMcnympNfIP10lgwoj0aKeDi3E3PQeubmFPn7bhztBlwyKl18yt-g29VJM9sbs0n5ysc?key=DYBZ1Fhvhcb3ihta1uO1ow" class="kg-image" alt="Charting in Retool with Plotly. Part I: Line graphs step-by-step beginners guide" loading="lazy" width="177" height="363"><figcaption>Layout and data value boxes in Retool</figcaption></figure><p><br>This gives you a great starting point from which to understand how to manipulate the example charts that Plotly provides. <br></p><p>Here is an example of how the Plotly attributes are organized within the object. <br></p><figure class="kg-card kg-code-card"><pre><code class="language-JavaScript">data = [
{
type: &apos;scatter&apos;,  // all &quot;scatter&quot; attributes: https://plotly.com/javascript/reference/#scatter
x: [1, 2, 3],     // more about &quot;x&quot;: https://plotly.com/javascript/reference#scatter-x
y: [3, 1, 6],     // #scatter-y
marker: {         // marker is an object, valid marker keys:https://plotly.com/javascript/reference #scatter-marker
color: &apos;rgb(16, 32, 77)&apos; // more about &quot;marker.color&quot;:https://plotly.com/javascript/reference#scatter-marker-color
}
},
{
type: &apos;bar&apos;,      // all &quot;bar&quot; chart attributes: https://plotly.com/javascript/reference#bar
x: [1, 2, 3],     // more about &quot;x&quot;: https://plotly.com/javascript/reference#bar-x
y: [3, 1, 6],     // https://plotly.com/javascript/reference#bar-y
name: &apos;bar chart example&apos; // https://plotly.com/javascript/reference#bar-name
}
];
layout = {                     // all &quot;layout&quot; attributes: https://plotly.com/javascript/reference#layout
title: &apos;simple example&apos;,  // more about &quot;layout.title&quot;: https://plotly.com/javascript/reference#layout-title
xaxis: {                  // all &quot;layout.xaxis&quot; attributes: https://plotly.com/javascript/reference#layout-xaxis
title: &apos;time&apos;         // more about &quot;layout.xaxis.title&quot;: https://plotly.com/javascript/reference#layout-xaxis-title
},
annotations: [            // all &quot;annotation&quot; attributes: https://plotly.com/javascript/reference#layout-annotations
{
text: &apos;simple annotation&apos;,    // https://plotly.com/javascript/reference#layout-annotations-text
x: 0,                         // https://plotly.com/javascript/reference#layout-annotations-x
xref: &apos;paper&apos;,                // https://plotly.com/javascript/reference#layout-annotations-xref
y: 0,                         //https://plotly.com/javascript/reference #layout-annotations-y
yref: &apos;paper&apos;                 // https://plotly.com/javascript/reference#layout-annotations-yref
}
]
}
return {data, layout}; // which formats this to be easily referenced from Retool.</code></pre><figcaption>An example of Plotly attributes within the object</figcaption></figure><p><br>Something that many developers using Plotly are unaware of, is the &#x2018;Annotations&#x2019; options it offers. These annotations need to go in the &#x2018;Layout&#x2019; object of the Plotly code as you can see in the example above. This can be helpful for adding useful contextual customizations to any chart. </p><p>Features such as subplot annotations can be particularly useful for highlighting certain data points. You can read more in their <a href="https://plotly.com/javascript/text-and-annotations/?ref=143.198.97.195">annotations section</a>.<br></p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://lh7-us.googleusercontent.com/docsz/AD_4nXcoj2-hfGemKvcjFlow663Eg1zf1aC8cHwZJG_Wd8iFb3w8rKV4cWnMUQo51v6_ZY8AhWMi3U-BEY5hY0nzMtFNCf90YtZHmweykESpDBxnSgIRyI8LKNGm9a2aR9vGc36OIgKqkUBBaaPxY3Cqu8q3KpJ2?key=DYBZ1Fhvhcb3ihta1uO1ow" class="kg-image" alt="Charting in Retool with Plotly. Part I: Line graphs step-by-step beginners guide" loading="lazy" width="624" height="365"><figcaption>Annotation subplots showing certain data points in Retool</figcaption></figure><p><br></p><h2 id="scatter-plotline-graph-step-by-step">Scatter plot/line graph step-by-step<br></h2><p>For this demonstration, we&#x2019;ve used the scatter plot option as an illustration, as this trace type includes line charts, scatter charts, text charts, and bubble charts and the code can easily be used to create any of these examples. </p><p>Line charts are set by changing the &#x2018;mode&#x2019; type from &#x2018;markers&#x2019;, a scatter plot, to &#x2018;line&#x2019;, or &#x2018;lines+markers&#x2019; to combine the two. Bubble charts are achieved by setting &#x2018;marker.size&#x2019; and/or &#x2018;marker.color&#x2019; to numerical arrays.<br><br></p><h3 id="chart-1-basic-chart">Chart 1: Basic chart<br></h3><p>To get started, we set up a simple line chart with some social media analytics data. In the code below, we have annotated the purpose and some of the customization options of this chart.</p><p>As you can see, the data object is where you&#x2019;ll format your X and Y values, the type of graph and some of the color scheme (including the color of the line/scatter plots), as well as the format of the text in the hover label. <br></p><p><strong>Data object: </strong></p><figure class="kg-card kg-code-card"><pre><code class="language-JavaScript">// Format the data object from the dataset &#x2018;YouTubeTotals&#x2019;
let formattedData = formatDataAsObject({{youtubeTotals.data}});
// Create the chart data array
let chartData = [
{
&quot;name&quot;: &quot;Subscribers gained&quot;, // The name of the data series shown in the legend
&quot;x&quot;: formattedData.Date, // X-axis data: array of dates from the formatted data object
&quot;y&quot;: formattedData[&apos;subscribers_gained&apos;], // Y-axis data: array of subscribers gained from the formatted data object
&quot;type&quot;: &quot;scatter&quot;, // Plot type: scatter plot
&quot;mode&quot;: &quot;line&quot;, // Display mode: &#x2018;line&#x2019; for line chart, &#x2018;markers&#x2019; displays points only, &#x2018;lines+markers&#x2019; for both
&quot;marker&quot;: {
&quot;color&quot;: &quot;#1E3A8A&quot; // Marker color: blue shade
},
&quot;hovertemplate&quot;: &quot;&lt;b&gt;Date:&lt;/b&gt; %{x}&lt;br&gt;&lt;b&gt;Subscribers Gained:&lt;/b&gt; %{y}&lt;extra&gt;&lt;/extra&gt;&quot; // Hover template: customizes the information shown when hovering over points
}
];
// Return the chart data array for Plotly
return chartData;</code></pre><figcaption>An example of a data object in Retool</figcaption></figure><p><br>Now, in the layout object, we can define more customization options. These typically include the title, legend, labels and their respective design options, such as font and color, and define the margins of the plot.<br></p><p>You can also define whether it&#x2019;s possible to select points on the chart. This can be useful when using a chart to filter data in a table for instance, which is possible in Retool using the chart.selectedPoints attribute. Note, this is straightforward with scatter plots and bubble charts with clearly-defined markers, but requires some more complex code for line charts. </p><p></p><p><strong>Layout object: </strong></p><figure class="kg-card kg-code-card"><pre><code class="language-JavaScript">// Define the layout for the chart
let layout = {
&quot;title&quot;: {
&quot;text&quot;: &quot;Daily Subscribers Gained&quot;, // Title text for the chart
&quot;font&quot;: {
&quot;color&quot;: &quot;#3D3D3D&quot;, // Color of the title text
&quot;size&quot;: 16 // Font size of the title text
}
},
&quot;font&quot;: {
&quot;family&quot;: &quot;var(--default-font, var(--sans-serif))&quot;, // Default font family for the chart
&quot;color&quot;: &quot;#979797&quot; // Default font color for the chart
},
&quot;showlegend&quot;: true, // Display the legend
&quot;legend&quot;: {
&quot;xanchor&quot;: &quot;center&quot;, // Anchor point for the x position of the legend
&quot;x&quot;: 0.45, // X position of the legend
&quot;y&quot;: -0.2, // Y position of the legend
&quot;orientation&quot;: &quot;h&quot; // Orientation of the legend (horizontal)
},
&quot;margin&quot;: {
&quot;l&quot;: 16, // Left margin
&quot;r&quot;: 24, // Right margin
&quot;t&quot;: 24, // Top margin
&quot;b&quot;: 32, // Bottom margin
&quot;pad&quot;: 2 // Padding
},
&quot;hovermode&quot;: &quot;closest&quot;, // Hover mode: show information for the closest data point
&quot;hoverlabel&quot;: {
&quot;bgcolor&quot;: &quot;#000&quot;, // Background color of the hover label
&quot;bordercolor&quot;: &quot;#000&quot;, // Border color of the hover label
&quot;font&quot;: {
&quot;color&quot;: &quot;#fff&quot;, // Font color of the hover label
&quot;family&quot;: &quot;var(--default-font, var(--sans-serif))&quot;, // Font family of the hover label
&quot;size&quot;: 12 // Font size of the hover label
}
},
&quot;clickmode&quot;: &quot;select+event&quot;, // Click mode: allow selection and trigger events
&quot;dragmode&quot;: &quot;select&quot;, // Drag mode: allow selection of data points
&quot;xaxis&quot;: {
&quot;title&quot;: {
&quot;text&quot;: &quot;Date&quot;, // Title text for the x-axis
&quot;standoff&quot;: 6, // Standoff distance for the x-axis title
&quot;font&quot;: {
&quot;size&quot;: 12 // Font size for the x-axis title
}
},
&quot;type&quot;: &quot;-&quot;, // Axis type (default)
&quot;tickformat&quot;: &quot;&quot;, // Tick format (default)
&quot;automargin&quot;: true, // Automatically adjust margins
&quot;fixedrange&quot;: true, // Fixed range for the x-axis (no zooming)
&quot;gridcolor&quot;: &quot;#fff&quot;, // Grid color for the x-axis
&quot;zerolinecolor&quot;: &quot;#fff&quot; // Zero line color for the x-axis
},
&quot;yaxis&quot;: {
&quot;title&quot;: {
&quot;text&quot;: &quot;Number of subscribers&quot;, // Title text for the y-axis
&quot;standoff&quot;: 6, // Standoff distance for the y-axis title
&quot;font&quot;: {
&quot;size&quot;: 12 // Font size for the y-axis title
}
},
&quot;type&quot;: &quot;linear&quot;, // Axis type: linear
&quot;tickformat&quot;: &quot;&quot;, // Tick format (default)
&quot;automargin&quot;: true, // Automatically adjust margins
&quot;fixedrange&quot;: true, // Fixed range for the y-axis (no zooming)
&quot;zerolinecolor&quot;: &quot;#DEDEDE&quot; // Zero line color for the y-axis
}
};
// Return the layout for Plotly
return layout;</code></pre><figcaption>An example of a layout object in Retool</figcaption></figure><p><br><br><br></p><h3 id="chart-2-basic-chart-with-trend-line">Chart 2: Basic chart with trend line<br></h3><p>For this chart version we have the same chart but have added a trendline that summarizes the values as an average of each month. To set up the trendline, you need to make these changes in the <strong>data</strong> object. In this chart, the layout object is exactly the same as in the first. </p><p>This trendline is just another line on the chart, so this method can also be used for adding a second line to the chart to represent different data. <br></p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://lh7-us.googleusercontent.com/docsz/AD_4nXdJsHGMfvP2Lpd6tquXNvOh0p1ba6I89CK2UwAmxrV8XUW8veqyd8xkSYPjGG3h75cx4n-X8GDqRUQ5jNkJQ35Y-DvbM3EQ9KmJ6fQhMsfgJ6i3CSICXkCzJEXOYKEWgKXhfih59GuymmXQo02Kq8esq5Y_?key=DYBZ1Fhvhcb3ihta1uO1ow" class="kg-image" alt="Charting in Retool with Plotly. Part I: Line graphs step-by-step beginners guide" loading="lazy" width="624" height="305"><figcaption>A trend line on a graph in Retool summarising average values in the month.</figcaption></figure><p>In our case, we needed to first group months and calculate averages of each, so we initially had to define these variables and number formats and calculate the averages:<br><br><strong>Data object:</strong></p><figure class="kg-card kg-code-card"><pre><code class="language-JavaScript">// Format the data object
let data = formatDataAsObject({{youtubeTotals.data}});
// Convert dates and subscriber gains
let dates = data.Date.map(date =&gt; new Date(date)); 
// Convert subscriber gains to numbers
let subscribersGained = data.subscribers_gained.map(Number); // Ensures values are numbers
// Group data by month and year
let monthlyData = {};
dates.forEach((date, index) =&gt; {
let monthYear = `${date.getFullYear()}-${date.getMonth() + 1}`; // Format as YYYY-M
if (!monthlyData[monthYear]) {
monthlyData[monthYear] = [];
}
monthlyData[monthYear].push(subscribersGained[index]);
});
// Calculate the average for each month
let monthlyAverages = {};
for (let monthYear in monthlyData) {
monthlyAverages[monthYear] = _.mean(monthlyData[monthYear]);
}
// Prepare the data for the trend line
let trendLineX = [];
let trendLineY = [];
for (let monthYear in monthlyAverages) {
let [year, month] = monthYear.split(&quot;-&quot;);
let date = new Date(year, month - 1, 1); // Start of the month
trendLineX.push(date);
trendLineY.push(monthlyAverages[monthYear]);
}
// Main data series (scatter plot)
let plotData = [
{
name: &quot;Subscribers gained&quot;,
x: dates,
y: subscribersGained,
type: &quot;scatter&quot;,
mode: &quot;line&quot;,
marker: {
color: &quot;#1E3A8A&quot;
},
hovertemplate: &quot;&lt;b&gt;%{x}&lt;/b&gt;&lt;br&gt;%{fullData.name}: %{y}&lt;extra&gt;&lt;/extra&gt;&quot;
}
];
// Conditional trend line addition with switch toggle
if ({{ trendlineChart2Switch.value }}) {
plotData.push({
name: &quot;Monthly Average Line&quot;,
x: trendLineX,
y: trendLineY,
type: &quot;scatter&quot;,
mode: &quot;lines&quot;,
line: {
dash: &quot;solid&quot;,
color: &quot;#FF5733&quot;
},
hoverinfo: &quot;skip&quot;
});
}
// Return the data for Plotly
return plotData;</code></pre><figcaption>Data object showing coding to create averages for the trend line</figcaption></figure><p><br></p><h3 id="chart-3-annotations">Chart 3: Annotations<br></h3><p>For this chart, we have replaced the trendline with an annotation that alerts the user to an event on the chart. For the sake of clarity in this first code, we manually coded in the annotation label and value, but you could use the annotations options to set dynamic values to automatically indicate values such as the highest or lowest with some JavaScript calculations.<br><br></p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://lh7-us.googleusercontent.com/docsz/AD_4nXcnfE3NCFS1wqed_GL748Wn5nk0RrcMLsDtgUlP-IzzA87foVpYWDAYUq6KUFAX2OdkAqvZKef5dnAEx27lZfYwLNPRKn5KiKSDLHTnKOkdfxmOogG2YYYYHy-yQLa9sf2SB-zuoR_ths5l8gfFRz7Cn7U?key=DYBZ1Fhvhcb3ihta1uO1ow" class="kg-image" alt="Charting in Retool with Plotly. Part I: Line graphs step-by-step beginners guide" loading="lazy" width="624" height="275"><figcaption>An Annotation chat showing highest and lowest values in Retool.</figcaption></figure><p><br></p><p>The data object is the same as in the first chart, but we&#x2019;ve changed the layout object by adding the &#x2018;Annotations&#x2019; object within it. This &#x2018;Annotations&#x2019; object comes in right at the end of our layout object code, after all the other code. <br><br></p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://lh7-us.googleusercontent.com/docsz/AD_4nXeo66EqZXKeHUq7LeZ0njPWixmN-zV2Bp-RqPn7Zqu4A3gLF5bJbHl7XkMk-gKAfkGl7yzypFRjvoSDeSJeWq03RlEUKlEatubn2KyWRuS0APjJ-7OzGk-cahkuJ46Le8jMoYEmXA557px-CzV1CPGyQOHo?key=DYBZ1Fhvhcb3ihta1uO1ow" class="kg-image" alt="Charting in Retool with Plotly. Part I: Line graphs step-by-step beginners guide" loading="lazy" width="419" height="319"><figcaption>An example of a data object in Retool&#xA0;</figcaption></figure><p><br>This is the annotations object to be added to the layout:<br></p><figure class="kg-card kg-code-card"><pre><code class="language-JavaScript">&quot;annotations&quot;: [ // Unique to this chart: Annotations section
{
&quot;x&quot;: &quot;2023-06-03&quot;, // X position of the annotation
&quot;y&quot;: 1691, // Y position of the annotation
&quot;xref&quot;: &quot;x&quot;, // X-axis reference
&quot;yref&quot;: &quot;y&quot;, // Y-axis reference
&quot;text&quot;: &quot;Special event&quot;, // Text of the annotation
&quot;showarrow&quot;: true, // Show an arrow pointing to the annotation
&quot;arrowhead&quot;: 7, // Arrowhead style
&quot;ax&quot;: 150, // X offset of the arrow
&quot;ay&quot;: 10, // Y offset of the arrow
&quot;hovertext&quot;: &quot;Special event on 2023-06-03: This event caused a significant increase in subscribers.&quot;, // Hover text for the annotation
&quot;hoverlabel&quot;: {
&quot;bgcolor&quot;: &quot;#fff&quot;, // Background color of the hover label
&quot;bordercolor&quot;: &quot;#1E3A8A&quot;, // Border color of the hover label
&quot;font&quot;: {
&quot;color&quot;: &quot;#1E3A8A&quot; // Font color of the hover label
}
}
}
]</code></pre><figcaption>Annotations object within the layout in Retool.</figcaption></figure><p><br>To take these annotations one step further, we&#x2019;ve made some dynamic options based on some calculations. We included a multi-select component (named <em>selectedAnnotations</em> here) where users can decide which features to highlight. <br></p><p>When any of these are selected, a marker will show on the chart to point out the relevant value. <br><br></p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://lh7-us.googleusercontent.com/docsz/AD_4nXfnYKiunfRPMFvGrSROal3IVPOC0m_eI7I5WclCr9lkdFJ9sU0436EG0g4Nq4OCCGrx5vH-96fhzYAODkVlDaTJNgOuOfAf_F1UBPjDKyhB288PvwuDRGoQRUXvIC8AXJpcr220FqIozd82iLO_Pb5fo92d?key=DYBZ1Fhvhcb3ihta1uO1ow" class="kg-image" alt="Charting in Retool with Plotly. Part I: Line graphs step-by-step beginners guide" loading="lazy" width="624" height="267"><figcaption>An example of a chart point showing certain values.&#xA0;</figcaption></figure><p><br></p><p>These are calculated in JavaScript queries that look for the minimum and maximum values using _.<em>minBy</em> and _.<em>maxBy. </em>These queries can be triggered to run on the value selection. <br></p><p><strong>Min:</strong></p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://lh7-us.googleusercontent.com/docsz/AD_4nXeUbpsamK_-TMWH3Xe1h4LGHMIl0EFZbYp8VGA-qrMeInPAipcCPse73DPiUC0oK1_ED3VGIICPRA9A8shLGgLvqWdMg3G0a6epqFc9mmxtsGYrjhZZRXWNVJy5-zwQu-ZxCUTWPw_plsNJMhAvqSqFgaxD?key=DYBZ1Fhvhcb3ihta1uO1ow" class="kg-image" alt="Charting in Retool with Plotly. Part I: Line graphs step-by-step beginners guide" loading="lazy" width="298" height="329"><figcaption>JavaScript queries that mark out the lowest values in the Retool graph.</figcaption></figure><p><br></p><p><strong>Max:</strong></p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://lh7-us.googleusercontent.com/docsz/AD_4nXfXtS_BxjSpwDvl0LPdlsB5NbkVRUQYbrdKDk-0noJeVl9UpGTD_nlycz53BVwHRszDS0BO1fOMwpDbfRoQOmLXza8R5jMLxrV-eY4B8Phw0-I-U3ZqwOSDoe0gcGCHHgH2vKOgbyqsrPwHUVjOLCU37_Q?key=DYBZ1Fhvhcb3ihta1uO1ow" class="kg-image" alt="Charting in Retool with Plotly. Part I: Line graphs step-by-step beginners guide" loading="lazy" width="203" height="228"><figcaption>JavaScript queries that mark out the highest values in the Retool graph.</figcaption></figure><p><br>In the Plotly code, we then check if the multiselect (<em>selectedAnnotations</em>) includes the selected value, and then if so, sets that annotation on the chart. As before, this code is right at the end of our layout object. <br></p><figure class="kg-card kg-code-card"><pre><code class="language-JavaScript">if (selectedAnnotations.includes(&apos;maxSubscription&apos;)) {
annotations.push({
x: {{ findMaxSubscriptionDay.data.Date }},
y: {{ findMaxSubscriptionDay.data[&apos;subscribers_gained&apos;] }},
xref: &quot;x&quot;,
yref: &quot;y&quot;,
text: &quot;Max Subscription Event&quot;,
showarrow: true,
arrowhead: 4,
ax: 200,
ay: -20,
hovertext: &quot;Max subscription on  + {{ findMaxSubscriptionDay.data.Date }} + : This event caused a significant increase in subscribers.&quot;,
hoverlabel: {
bgcolor: &quot;#fff&quot;,
bordercolor: &quot;#1E3A8A&quot;,
font: {
color: &quot;#1E3A8A&quot;
}
}
});
}
if (selectedAnnotations.includes(&apos;minSubscription&apos;)) {
annotations.push({
x: {{ findMinSubscriptionDay.data.Date }},
y: {{ findMinSubscriptionDay.data[&apos;subscribers_gained&apos;] }},
xref: &quot;x&quot;,
yref: &quot;y&quot;,
text: &quot;Lowest Subscription Event&quot;,
showarrow: true,
arrowhead: 4,
ax: 25,
ay: -100,
hovertext: &quot;This was the day with the least subscribers on  + {{ findMinSubscriptionDay.data.Date }} + .&quot;,
hoverlabel: {
bgcolor: &quot;#fff&quot;,
bordercolor: &quot;#1E3A8A&quot;,
font: {
color: &quot;#1E3A8A&quot;
}
}
});
}</code></pre><figcaption>A layout object showing code for the annotations graph in Retool.</figcaption></figure><p></p><p></p><h3 id="chart-4-color-scale">Chart 4: Color scale<br></h3><p>In chart 4, we&#x2019;re getting a little funky with our color scheme and have used the built-in color scale to add some interest to the chart. It&#x2019;s not a major lift, but color can go a long way to making data easier to understand with a single glance. This might be particularly useful for bubble maps.<br></p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://lh7-us.googleusercontent.com/docsz/AD_4nXf5BPFzcWKy2PAGRof2OKld06ELicycScvKqLyGwt_Pyn3oPgN_dgci9zWLQ0gVpPJjM5NZCbX2gdDJgUARF5arPoaXQ-cFLjRVyELtSsGqLrI7PhPkLthKAy9TkmgNj14aL2cVTcRoezEvMAceSG1vRFHC?key=DYBZ1Fhvhcb3ihta1uO1ow" class="kg-image" alt="Charting in Retool with Plotly. Part I: Line graphs step-by-step beginners guide" loading="lazy" width="624" height="295"><figcaption>An example of color scale added to a Retool graph.&#xA0;</figcaption></figure><p><br></p><p>The color scale is defined in the data object under &quot;colorscale&quot;: &quot;Viridis&quot;.<br></p><figure class="kg-card kg-code-card"><pre><code class="language-JavaScript">return [
{
&quot;name&quot;: &quot;Subscribers gained&quot;,
&quot;x&quot;: {{formatDataAsObject(youtubeTotals.data).Date}},
&quot;y&quot;: {{formatDataAsObject(youtubeTotals.data)[&apos;subscribers_gained&apos;]}},
&quot;type&quot;: &quot;scatter&quot;,
&quot;mode&quot;: &quot;markers&quot;,
&quot;marker&quot;: { // Marker customization
&quot;color&quot;: {{formatDataAsObject(youtubeTotals.data)[&apos;subscribers_gained&apos;]}}, // Marker color based on subscribers gained
&quot;colorscale&quot;: &quot;Viridis&quot;, // Color scale for the markers
&quot;showscale&quot;: true // Display color scale
},
&quot;hovertemplate&quot;: &quot;&lt;b&gt;%{x}&lt;/b&gt;&lt;br&gt;%{fullData.name}: %{y}&lt;extra&gt;&lt;/extra&gt;&quot;
}
]</code></pre><figcaption>A data object in Retool with the colorscale defined for the gragh.</figcaption></figure><p><br><br></p><h3 id="chart-5-range-slider-and-time-buttons">Chart 5: Range slider and time buttons<br></h3><p>For our last addition, we&#x2019;re adding a handy range-slider feature and some buttons to adjust the time span. <br></p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://lh7-us.googleusercontent.com/docsz/AD_4nXfL61CNf_IjoNQP-RdHOQPZSWmZIZbxfjvm17j3meL647OuMKRmEsBJhMPtpMvmpLN-IgdZ3Kl9KZnlc-4YJfk8qY-l_0MkkYW0lBPdl8dgnNr4BAHHRFy9ycMtQ6i7ELc3uAXNAYtSHgOeLhlfTugQ1ISy?key=DYBZ1Fhvhcb3ihta1uO1ow" class="kg-image" alt="Charting in Retool with Plotly. Part I: Line graphs step-by-step beginners guide" loading="lazy" width="624" height="184"><figcaption>Range slider and button features on a Retool graph.</figcaption></figure><p><br><br>The data object is the same as in chart 1. For the layout object, everything we need here is under the &#x2018;x-axis&#x2019; object. The range slider is a built-in option, and can be activated simply by setting &#x2018;rangeslider&#x2019; to visible. </p><p>The integrated buttons are an additional UI feature that can save some screen real estate by keeping buttons on a Retool app to a minimum. It&#x2019;s important to note however that the state of these buttons are not exposed to Retool, so can&#x2019;t be used to filter more data in the app if needed. To filter data in both a chart and table, for instance, the buttons would need to be configured in Retool itself. <br></p><figure class="kg-card kg-code-card"><pre><code class="language-JavaScript">X-axis object: 
&quot;xaxis&quot;: { // X-axis configuration
&quot;rangeslider&quot;: {
&quot;visible&quot;: true // Display range slider
},
&quot;rangeselector&quot;: { // Range selector configuration
&quot;buttons&quot;: [
{
&quot;count&quot;: 7, // Number of units to go back
&quot;label&quot;: &quot;1w&quot;, // Button label
&quot;step&quot;: &quot;day&quot;, // Unit of time (e.g., &quot;day&quot;, &quot;month&quot;)
&quot;stepmode&quot;: &quot;backward&quot; // Step mode (backward in time)
},
{
&quot;count&quot;: 1,
&quot;label&quot;: &quot;1m&quot;,
&quot;step&quot;: &quot;month&quot;,
&quot;stepmode&quot;: &quot;backward&quot;
},
{
&quot;step&quot;: &quot;all&quot; // Button to view all data
}
]
}
},</code></pre><figcaption>A layout object to include a range slider and buttons into the Retool graph.&#xA0;</figcaption></figure><p><br><br></p><h3 id="candlestick-chart">Candlestick chart<br></h3><p>Another similar option to the line and scatter graphs is the Candlestick chart. This chart gives you a clear overall trend line of values, and up close users can get a better understanding of the positive and negative values and their min/max values. <br></p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://lh7-us.googleusercontent.com/docsz/AD_4nXesiNyEIn-c_ciqBRSS-0Gj2FoQXG_pO_DFVWy_KuHuy2izYm9QmI8LOcUnFyUh4z9i7Px8oAP_XEyLvP2bhEOAeJKmojzsKPL_LO_613b341DzxDPJooB6vFDZyEZLW51VYL1HEu2-rP5wAYoixLXazdE?key=DYBZ1Fhvhcb3ihta1uO1ow" class="kg-image" alt="Charting in Retool with Plotly. Part I: Line graphs step-by-step beginners guide" loading="lazy" width="624" height="368"><figcaption>A candlestick chart in Retool.</figcaption></figure><p><br></p><p>It&#x2019;s a particularly common format in financial charts.</p><p></p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://lh7-us.googleusercontent.com/docsz/AD_4nXfSp7vrg7dIVicL53aY0oJ7nO9NnIqg9-fwxenJJrRroGpdadZctWBK2ojwomkAKEB_2JKcSxY7eTFVBkHyg_ukY5qHIxJ3wFg41NF_ALTocjIJIfZUBoGVyQ9iHw0YCXcGdwM6FjtvYGNJqEnxik0PYSUs?key=DYBZ1Fhvhcb3ihta1uO1ow" class="kg-image" alt="Charting in Retool with Plotly. Part I: Line graphs step-by-step beginners guide" loading="lazy" width="624" height="361"><figcaption>A candlestick chart showing price variations in Retool.</figcaption></figure><p></p><p>To illustrate this chart, we used the publicly available Bitcoin price data. <br><br></p><p><strong>Data </strong><br></p><figure class="kg-card kg-code-card"><pre><code class="language-JavaScript">// Accesses the nested historical data for BTC from the API response
let btcData = {{ getHistoricalData4BTC.data }};
// Converts timestamps to ISO date strings in &apos;YYYY-MM-DD&apos; format
let btcDates = btcData.Data.Data.map(item =&gt; new Date(item.time * 1000).toISOString().split(&apos;T&apos;)[0]);
// Extracts the &apos;open&apos; prices for each data point
let btcOpen = btcData.Data.Data.map(item =&gt; item.open);
// Extracts the &apos;high&apos; prices for each data point
let btcHigh = btcData.Data.Data.map(item =&gt; item.high);
// Extracts the &apos;low&apos; prices for each data point
let btcLow = btcData.Data.Data.map(item =&gt; item.low);
// Extracts the &apos;close&apos; prices for each data point
let btcClose = btcData.Data.Data.map(item =&gt; item.close);
// Constructs a data series object for a candlestick chart
let btcDataSeries = {
x: btcDates,
open: btcOpen,
high: btcHigh,
low: btcLow,
close: btcClose,
type: &apos;candlestick&apos;,
name: &apos;BTC Price&apos;,
hovertemplate: `
&lt;b&gt;%{x}&lt;/b&gt;&lt;br&gt;
Open: %{open}&lt;br&gt;
High: %{high}&lt;br&gt;
Low: %{low}&lt;br&gt;
Close: %{close}&lt;extra&gt;&lt;/extra&gt;
`
};
// Returns the data series object as an array
return [btcDataSeries];</code></pre><figcaption>A Retool data object using the Bitcoin price data.</figcaption></figure><p><br></p><p><strong>Layout</strong><br></p><p>In this case, our layout object is very straightforward and mainly defines the labels, legends and color scheme. The range slider is set to visible as default, but can be added as in chart 5 and set to false if not required.<br></p><figure class="kg-card kg-code-card"><pre><code class="language-JavaScript">return {
title: {
text: &quot;BTC Price Chart&quot;,
font: {
color: &quot;#3D3D3D&quot;,
size: 16
}
},
font: {
family: &quot;var(--default-font, var(--sans-serif))&quot;,
color: &quot;#979797&quot;
},
showlegend: true,
legend: {
xanchor: &quot;center&quot;,
x: 0.45,
y: -0.2,
orientation: &quot;h&quot;
},
margin: {
l: 72,
r: 24,
t: 80,
b: 72,
pad: 2
},
hovermode: &quot;closest&quot;,
hoverlabel: {
bgcolor: &quot;#000&quot;,
bordercolor: &quot;#000&quot;,
font: {
color: &quot;#fff&quot;,
family: &quot;var(--default-font, var(--sans-serif))&quot;,
size: 12
}
},
xaxis: {
title: {
text: &quot;Date&quot;,
font: {
size: 12
}
},
type: &quot;date&quot;,
automargin: true
},
yaxis: {
title: {
text: &quot;Price (USD)&quot;,
standoff: 6,
font: {
size: 12
}
},
type: &quot;linear&quot;,
automargin: true,
zerolinecolor: &quot;#DEDEDE&quot;
}
};</code></pre><figcaption>A layout object in Retool set for a candlestick chart.</figcaption></figure><p><br>There you have several variations to improve your scatter/line charts in Retool with just a few simple tweaks! For our subscribers we&#x2019;ve included links to these charts in Retool below.<br></p><p>In the next part of this series, we&#x2019;ll be sharing how we built out a complex Sankey diagram in Retool. </p><p></p><div class="kg-card kg-callout-card kg-callout-card-blue"><div class="kg-callout-emoji">&#x1F4A5;</div><div class="kg-callout-text">At <a href="https://www.boldtech.dev/?ref=143.198.97.195">Bold Tech</a>, we specialize in building great internal tools, fast. We are obsessed with building apps that make your teams happier and more productive. In our <a href="http://143.198.97.195:2369/">blog</a>, you can learn all about how to build better business software for more satisfied employees, or <a href="https://www.boldtech.dev/contact?ref=143.198.97.195">get in touch</a> to chat to us about what you&apos;re looking to build.</div></div><p><br></p>]]></content:encoded></item><item><title><![CDATA[What is Retool Storage? How to upload and store files in Retool]]></title><description><![CDATA[Retool Storage offers a native option for uploading and storing files within the Retool environment. In this guide, we discuss the advantages and disadvantages of Retool Storage and how else you can store documents in Retool. ]]></description><link>http://143.198.97.195:2369/what-is-retool-storage/</link><guid isPermaLink="false">66695f7edbece927645cd102</guid><category><![CDATA[What is...]]></category><category><![CDATA[Retool]]></category><dc:creator><![CDATA[Sophie Becker]]></dc:creator><pubDate>Thu, 13 Jun 2024 18:50:19 GMT</pubDate><media:content url="http://143.198.97.195:2369/content/images/2024/06/Bold-tech-blog-thumb--8--1.png" medium="image"/><content:encoded><![CDATA[<img src="http://143.198.97.195:2369/content/images/2024/06/Bold-tech-blog-thumb--8--1.png" alt="What is Retool Storage? How to upload and store files in Retool"><p><br>Retool offers a native option for uploading and storing files within its environment. This works a little like an AWS S3 bucket and can be useful for integrating file storage into your business software and internal tools for no extra cost, though it does come with some limitations.</p><p>In this guide, we&apos;ll walk through the opportunities and limitations of Retool Storage, and how we recommend uploading, previewing, and removing files.<br><br></p><h2 id="what-is-retool-storage">What is Retool Storage? <br></h2><p>Here are the basics:</p><ul><li>Retool storage allows for document storage and predominantly supports saving images and PDFs.</li><li>It&#x2019;s only available for cloud-hosted Retool instances.</li><li>Retool Storage includes up to 5 GB of storage per organization. Files can be up to 40 MB each. They do seem to have a hard limit here and you&#x2019;d have to request more storage from the team rather than just pay for more.</li><li>Files are only available to users by default, but can be made <a href="https://docs.retool.com/queries/guides/files?ref=143.198.97.195">publicly available</a>.<br></li></ul><h3 id="benefits">Benefits</h3><ul><li>Retool Storage is free up to 5GB, which makes it a great solution for low-level storage requirements or simple add-ons to Retool applications that won&#x2019;t cost a penny.</li><li>Retool Storage works a lot like an AWS S3 bucket, but is easier to set up, cheaper, and easier to shut down too. Many people struggle to manage AWS buckets and accounts and find themselves overpaying for storage, so this can be a good option for &#x2018;light&#x2019; document storage. <br></li></ul><h3 id="limitations">Limitations</h3><ul><li>When uploading to Retool storage, the data saved against the file is quite limited: only name, type, sizeBytes, value, url. It&#x2019;s not possible to save custom values such as the ID of the record you&#x2019;d like to save it against (e.g. saving a profile picture against a user ID in your table). This means that in order to save additional data against a file, you need to save this in a separate DB, which can get disorganized quickly if not set up correctly. You would probably expect that this kind of connection would be a native experience so using Retool Storage might not be the fully-integrated time saver you would expect.</li><li>Once uploaded, it can be confusing to retrieve the files again. When uploading multiple files, it&#x2019;s not necessarily straightforward to pull these files back into the app to preview, you need to save they keys somewhere in your app or in your database to retrieve files again once uploaded.</li><li>Permissioning is not as well developed for Retool Storage as for other aspects of the Retool environment, so it can be difficult to limit access for certain users to this storage, meaning almost anyone could upload, read and delete files. With S3, on the other hand, you can set up a connector with scoped access (like read-only) for certain users.</li><li>Given the lack of organization around uploads, it works more like an S3 bucket where you can dump files into folders and retrieve all of them when needed. Organizing these files properly requires some pre-planning and additional scripts. <br><br></li></ul><p>Overall, while Retool Storage works for simple use-cases, it does feel like an addition to the Retool ecosystem that would benefit from some TLC in order to be suitable for larger or more complex usecases, nor is it particularly enterprise-ready as a product. For this reason, we would recommend using Retool Storage more for smaller, side usecases (like storing logos, or non-essential product photos), rather than anything mission-critical. <br></p><p>For more mission-critical file storage or for storing larger files, we would probably still recommend using Amazon S3 or even consider using our Retool Database workaround for smaller files, which we explain below. <br><br></p><h2 id="how-to-use-retool-storage">How to use Retool Storage<br></h2><p>Retool Storage is relatively simple to work: all you need to do is connect a query to the Storage resource in your app, select an action and then connect it to your UI with event handlers. <br></p><p>You can even use the File button, upload and input to connect directly to Retool storage without creating a query, by selecting the <strong>Upload file to Retool Storage </strong>option. <br></p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://lh7-us.googleusercontent.com/docsz/AD_4nXeSItr7ZYZKsiiCzHFPWcweYCtwVCgWQ8AIZkLXEsPQQ_nskObWV3KLx6JVZV0_Huav7aGw1VvChDNLWjas5W5giX0kNZpeT8WsIttRApsY_R5TF_LmY_HemqdoSWcspoMb5fLFGz1M0sbWQDdTYglMktY?key=ONs0eD47G5Y61Y5gdBJfvg" class="kg-image" alt="What is Retool Storage? How to upload and store files in Retool" loading="lazy" width="405" height="685"><figcaption>Use the File button to connect with Retool Storage&#xA0;</figcaption></figure><p><br>The GetAllFiles action type with retrieve metadata such as file names, IDs, sizes, types, URLs, and created and modified dates. Using this query, it&#x2019;s very simple to create a list of all available files for a user to select, for instance with a dropdown or to present them in a Listview. <br></p><p>Uploading files is also simple, and they can easily be organized into folders too. This can be organized dynamically by toggling the <em>fx </em>option and using JS. &#xA0;<br></p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://lh7-us.googleusercontent.com/docsz/AD_4nXdQi3e5CN_7qS--fNm6E-hLVTQ0lvoWkkR_dRE0peEatpsMxHfltzl31h-5pRugDgC6BtnZQ3yUaK-mXQc9SpLcweko-_zDLay9gguD-A1X7NPMMNt36nscaCuKwPnWx5cliuP75QBJOAgnSp5x_d-JzeRW?key=ONs0eD47G5Y61Y5gdBJfvg" class="kg-image" alt="What is Retool Storage? How to upload and store files in Retool" loading="lazy" width="624" height="508"><figcaption>Uploading and organizing files within Retool</figcaption></figure><p>While the file is automatically uploaded into the Retool Storage without creating a separate query, there is no automatic behavior to pull the file back into the app and preview it if needed. One way to do this is using the fileID which is available in the fileButton component value. Note, this value will refresh on page load. <br></p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://lh7-us.googleusercontent.com/docsz/AD_4nXffp0vYrwa5-Tf-9LOSVr_jAIU0UHRkbYpKoRC_6b49mP_9P-wIbToTDG2d11oyW4PfT9BfhZKqy8ltLSn-tq1PtgD2EV4nmN6dDI5drfm_jj12w0kUMoNJZXWwTtpkMso61cS3ntuekvQpd2FBvsGmvgTO?key=ONs0eD47G5Y61Y5gdBJfvg" class="kg-image" alt="What is Retool Storage? How to upload and store files in Retool" loading="lazy" width="364" height="254"><figcaption>Using fileID in Retool will pull the upload file into the app&#xA0;</figcaption></figure><p><br></p><p>You can then retrieve the file ID from the file button once uploaded using {{fileButton1.value[0].fileId}}, or replace 0 with the index you need.<br></p><figure class="kg-card kg-image-card"><img src="https://lh7-us.googleusercontent.com/docsz/AD_4nXdHzjEsFgo8Dsk1SttApAS2m2XdUfkZlUoxWSrj7kJy_eEg7QrIqwl_0ZeJvjP5V_f3Wk26xoy0ZYMHM9SckzM3CCxSaO8Prjd2fuvPkwZkJJgpPaW3xAzv1Q5NH5mNl71fOkiEeaIHy0ubqLmWC-NcaIw?key=ONs0eD47G5Y61Y5gdBJfvg" class="kg-image" alt="What is Retool Storage? How to upload and store files in Retool" loading="lazy" width="536" height="514"></figure><p><br></p><p>In order to permanently associate a file with a record in a table &#x2013; which is a common pattern in Retool apps &#x2013; you would need to add the file name or ID to a record in the database by creating a separate query. This can be done by triggering another query with an event handler in the fileButton to trigger a database update query with the file ID. <br></p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://lh7-us.googleusercontent.com/docsz/AD_4nXdXP5Vx7MUk-pBsFvlrv-MemXPLVgK9O6Odgh6lO9HCr1aTCHfxM6UdQEP-wwrRbvUsv56BzKpP8tbxSAX4ZKo3Dvc8t-jsGNmLxpw8aNeLGTMZi2gejnS88uUcONSyH1WYhgbM-1tDQe48IvLjk7GgAtE?key=ONs0eD47G5Y61Y5gdBJfvg" class="kg-image" alt="What is Retool Storage? How to upload and store files in Retool" loading="lazy" width="624" height="341"><figcaption>Adding a file name to a record will create a permanent association within the internal application</figcaption></figure><p><br></p><p>So, given the current limitations of Retool Storage and the relatively small max storage limit, we would suggest using it as an option predominantly to extend the free storage availability of Retool Database, which is currently set to 5GB max. Storing images and heavier files in Retool storage reduces the likelihood of maxing the RetoolDB limit, but the additional scripting needed to organize and filter files makes it less suitable for <br></p><p>If you&#x2019;re looking to give it a go, Retool has a couple of detailed tutorials for creating a document storage CRUD using Retool Storage on their docs page. <br></p><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://docs.retool.com/data-sources/quickstarts/retool-storage?ref=boldtechblog"><div class="kg-bookmark-content"><div class="kg-bookmark-title">Retool Storage quickstart | Retool Docs</div><div class="kg-bookmark-description">Learn how to build apps for managing files using Retool Storage.</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://docs.retool.com/apple-touch-icon.png" alt="What is Retool Storage? How to upload and store files in Retool"><span class="kg-bookmark-author">Docs</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://docs.retool.com/img/logo-black.svg" alt="What is Retool Storage? How to upload and store files in Retool"></div></a></figure><p><br><br></p><h2 id="how-to-save-files-against-a-record-in-retool">How to save files against a record in Retool</h2><p></p><p>Since the current state of Retool Storage means that you need to write a separate query to associate a saved file to a record, it might make more sense for some users to just use the JSON column type in their database to store the document or image instead. <br><br>This is useful for organising files that are specifically associated to a single record in your database, but be aware that it might max out your Retool DB storage limit quickly if storing heavier files. <br><br></p><h3 id="setting-up-your-database">Setting up your database <br></h3><p>You&#x2019;ll need to set up a column type in your Retool Database table to save these files. This will just be made of one column - a JSON field type - which will save all of the necessary data for your file, including the base64 data which encodes your file. <br></p><p>Before proceeding with the file upload process, you need to add a JSON field type column to your table. Set the default value to be an empty array by using the box brackets &#x2018;[]&#x2019;. This setup allows for seamless storage of uploaded files within your database since all data will be included in this JSON object.<br></p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://lh7-us.googleusercontent.com/docsz/AD_4nXcDtHMrPowOxl6p0uDE481xrrLqIg45asJLT6we3r3-60zvote556zaqWr3LTzX5nwRhHWFH4xpwXxJXAkpZPPryU9RU-v7VjqbXDdMjck2Vo1Ynf9Ze-2Cfq5D7AxdRoybfDBb49ipiAD7DD8cs3bZJT76?key=ONs0eD47G5Y61Y5gdBJfvg" class="kg-image" alt="What is Retool Storage? How to upload and store files in Retool" loading="lazy" width="198" height="216"><figcaption>Adding a JSON file (null entry) type column to a Retool table to enable file upload</figcaption></figure><p><br></p><p>You will define the JSON value from your app, but using this method you can save custom values against the document that might be useful, such as: <br></p><ul><li>Record ID - e.g. number (whatever you are saving the file against, e.g. a user)</li><li>Date updated</li><li>Tags</li><li>Associated Retool user</li><li>And more. <br><br></li></ul><h3 id="setting-up-your-app">Setting up your app<br></h3><p>Now that you have the JSON column type available in your table, you just need to connect this to your Retool app. In this walkthrough, we have a simple table with products, against which we&#x2019;d like to save both an invoice and a product image. <br><br></p><h3 id="upload-process">Upload process<br></h3><p>First, we need a component that allows for file upload. You can either use the file button, file input, or the file dropzone.<br></p><p>In our table component, we added a custom column with the button type which triggers an upload/view modal to open.<br></p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://lh7-us.googleusercontent.com/docsz/AD_4nXdVN5j0jok1E2NQ4yOsEWSmhofd-DAV6YNDf71qnB_X_mFnv4vbzEpPdLPcs5tylkYQDxUEdVr_3sO29nk0-D43cd-H4glCk0vRwSZdRsp83aCcuuxL9u227ssh3ffQ7KmfCJ8ScbhUPIb0LTVzLH-3pk8?key=ONs0eD47G5Y61Y5gdBJfvg" class="kg-image" alt="What is Retool Storage? How to upload and store files in Retool" loading="lazy" width="212" height="320"><figcaption>A custom column with the button type triggers an upload/view modal to open</figcaption></figure><p><br></p><p>In this modal we have a tabbed container which switches between the two previews, and the file upload sections, where we have a file dropzone to select the files to upload. <br></p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://lh7-us.googleusercontent.com/docsz/AD_4nXdg2XEzbzc6Nfnf7YAwYdY6yIV8bIpnjHh-NOz_bCpGXz3yahxX9Dpibg2IxKmrNUQJt8qXLiMGfTgcIUwZTMWRaFnOB7Uso5EqWgdWCTH00Pxks4UqDL_xyfmX_QmmEqUoWL5AOBYNog5VRZCKxqPtQC4T?key=ONs0eD47G5Y61Y5gdBJfvg" class="kg-image" alt="What is Retool Storage? How to upload and store files in Retool" loading="lazy" width="624" height="259"><figcaption>A tabbed container with a file upload section within Retool</figcaption></figure><p><br>The upload button triggers our &#x2018;upload&#x2019; query, which saves the document data back to the database in our JSON object.</p><p>First, we set up the apend data object as a separate script, which we called &#x2018;apend_file&#x2019;. Here, we pull in any existing data, then retrieved the values from the app that we would like to save to our new file data, and formatted them as an object. This object value is the one that we will use to save the document data back to our database. If no file exists, it will create a new one. With this query, the apend_file query is set up to save multiple documents per record, and saving a document will simply add it to the JSON. <br></p><figure class="kg-card kg-image-card"><img src="https://lh7-us.googleusercontent.com/docsz/AD_4nXdzTEbR6OwE1PcL_ZI4ekn6nfpCjQmR8V7pUDUkYPIIAvZd4B82F5q8M29fst03DI63Y14-dsA3-RstlvlSpvK6f4PGWdQCWkHOXnTgF8FKdpRntjAfwBdj7y1w8hR0fPfGcwVwyHeA1gaTSNRm7wfVvLP9?key=ONs0eD47G5Y61Y5gdBJfvg" class="kg-image" alt="What is Retool Storage? How to upload and store files in Retool" loading="lazy" width="487" height="302"></figure><pre><code class="language-JavaScript">const existingData =  get_file.data.files[0] 
const newFileData = {
&quot;name&quot;: fileDropzone1.value[0].name,
&quot;type&quot;: fileDropzone1.value[0].type,
&quot;base64Data&quot;: fileDropzone1.value[0].base64Data,
&quot;date&quot;: moment().format(&apos;YYYY-MM-DD&apos;),
&quot;product_id&quot;: table1.selectedSourceRow.product_id,
&quot;user_uploaded&quot;: current_user.fullName
};
existingData.push(newFileData);
return existingData;</code></pre><p><br>Setting up our apend query is now really simple, we just need to filter by the selected row ID, and pass in this data to the &#x2018;files&#x2019; column.<br></p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://lh7-us.googleusercontent.com/docsz/AD_4nXdKfkREbWg5UamTtc6qEAZWamvPi4laaMutdcv_ZDw3XlEVtiZCAh0Q4GZsbbQtMTZNqShiv5sbWYwVAP7W3NGqjDe45Xch_LOjgmutgSAhoJbK_bD_r5iHCUSCe2v8qHMcwec_NwEIIxaFN5mIuCVFDF_A?key=ONs0eD47G5Y61Y5gdBJfvg" class="kg-image" alt="What is Retool Storage? How to upload and store files in Retool" loading="lazy" width="389" height="349"><figcaption>Setting up the apend query in Retool</figcaption></figure><p><br>On success, we set up two event handlers: one to trigger the get files query to refresh the data, and then cleared the dropzone value. <br></p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://lh7-us.googleusercontent.com/docsz/AD_4nXeZgoTfGyH7VRI96R5ofqHmbZ3gUOF_sQXYeIpXN-FyXYUoARMwB_cL1SyczVveSSbjbO6EDsAnOh_Old0BLqdJppY1Bi3jEILtoTBG0G4gICjtWUG7dzhn99EBLMB8AlgzpME8affq5sLHhnE6TuyXyCvM?key=ONs0eD47G5Y61Y5gdBJfvg" class="kg-image" alt="What is Retool Storage? How to upload and store files in Retool" loading="lazy" width="624" height="348"><figcaption>Event handlers trigger a data refresh in Retool</figcaption></figure><p><br>Our get_file query is very basic, simply pulling in the &#x2018;files&#x2019; JSON object by the selected row: <br></p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://lh7-us.googleusercontent.com/docsz/AD_4nXcxxd-tdqJqs9k3RfpCCghi9QKYEn0-FBNm0dMjGLrkSwWpxaRmV-MsIQTK09lzoz_A-d3dvAgvKogclkDCfgMEgRky0nfRup2P3khiYCx9NXZdoV-Lr61aLUOSrfo6pbcoFmxqsb6Qox2EkDNG-db1sHI?key=ONs0eD47G5Y61Y5gdBJfvg" class="kg-image" alt="What is Retool Storage? How to upload and store files in Retool" loading="lazy" width="542" height="303"><figcaption>A get_file query in Retool</figcaption></figure><pre><code class="language-SQL">SELECT files FROM orders WHERE id = {{ table1.selectedSourceRow.id }}</code></pre><p></p><h3 id="connecting-to-the-preview">Connecting to the preview<br></h3><p>Connecting to the preview is now really simple. Now, when a user clicks the &#x2018;See files&#x2019; button in the table, we also set it up trigger the get_files query to run and refresh the data.<br></p><p>Now, inside our tabbed container we have one tab that allows users to preview PDF components (in this usecase, our invoices), and one with an image component to preview any images. <br></p><p>Users can select the available files from the dropdown. Our dropdown gives additional information about the files which would not be possible with the Retool Storage option, without additional scripts.<br></p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://lh7-us.googleusercontent.com/docsz/AD_4nXcBwq0dv_lCBWpMGfUQAa9cTVnNwPMfpoAv4xX5cJgF4XgfMXoUPl9uMvbVm5e1nz8T75f1MumejXQI-0_JLDiXOwZk1Q0_J0XKlWGrcGUdJk8yoFCiVVNMyLcaaePpG_QBVtfknXtTUAiXDSQYW-_GgjOe?key=ONs0eD47G5Y61Y5gdBJfvg" class="kg-image" alt="What is Retool Storage? How to upload and store files in Retool" loading="lazy" width="624" height="233"><figcaption>A dropdown box in the tabbed container shows information about available files</figcaption></figure><p></p><p>The data source filters the documents saved in the &#x2018;files&#x2019; column by the &#x2018;image/jpeg&#x2019; type. The image file object is then connected to the value of the dropdown (select) component.<br></p><figure class="kg-card kg-image-card"><img src="https://lh7-us.googleusercontent.com/docsz/AD_4nXcSC90SYMWohEU7GD58ngn8NekSfYajyPyeIHVIjvsxiamj51mLxhsyji4cQqMPi6l6rj8Qzv67MiNeOjDayfzsI16OBFcDfIBFe61lMdjhn0CS6nm5S-TBebguP7du7Bzl-upXzvEU8dVr3jvAvZbpbVhC?key=ONs0eD47G5Y61Y5gdBJfvg" class="kg-image" alt="What is Retool Storage? How to upload and store files in Retool" loading="lazy" width="624" height="449"></figure><p><br>The PDF works in the same way, but instead filters the data by type: application/pdf.<br><br></p><h3 id="delete-files">Delete files<br></h3><p>Finally, we need the ability to delete files when needed. For this we added a button to the tabbed container that runs a script and then triggers the delete_file query.</p><pre><code class="language-JavaScript">await delete_file.trigger({additionalScope:{passed_name:select1.selectedItem.name}})</code></pre><p>This query filters the selected item out of the JSON (in case there are multiple files) and removes it removes it from the JSON.</p><p></p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="http://143.198.97.195:2369/content/images/2024/06/image.png" class="kg-image" alt="What is Retool Storage? How to upload and store files in Retool" loading="lazy" width="2000" height="818" srcset="http://143.198.97.195:2369/content/images/size/w600/2024/06/image.png 600w, http://143.198.97.195:2369/content/images/size/w1000/2024/06/image.png 1000w, http://143.198.97.195:2369/content/images/size/w1600/2024/06/image.png 1600w, http://143.198.97.195:2369/content/images/size/w2400/2024/06/image.png 2400w" sizes="(min-width: 720px) 720px"><figcaption>A button in the tabbed container that runs script and triggers delete_file query</figcaption></figure><pre><code class="language-JavaScript">{{get_data.data.files[0].filter(obj =&gt; obj.name != passed_name) }}</code></pre><hr><p><br>If you would like to learn more about Retool, you can read more on <a href="http://143.198.97.195:2369/">our blog</a>. </p><p>More in the What is... series:</p><ul><li><a href="http://143.198.97.195:2369/what-is-retool/">What is Retool?</a></li><li><a href="http://143.198.97.195:2369/what-is-retool-database/">What is Retool Database?</a></li></ul><p></p><div class="kg-card kg-callout-card kg-callout-card-blue"><div class="kg-callout-emoji">&#x1F4A5;</div><div class="kg-callout-text">At <a href="https://www.boldtech.dev/?ref=143.198.97.195">Bold Tech</a>, we specialize in building great internal tools, fast. We are obsessed with building apps that make your teams happier and more productive. In our <a href="http://143.198.97.195:2369/">blog</a>, you can learn all about how to build better business software for more satisfied employees, or <a href="https://www.boldtech.dev/contact?ref=143.198.97.195">get in touch</a> to chat to us about what you&apos;re looking to build.</div></div>]]></content:encoded></item></channel></rss>