Talks

Business in the Front, Party in the Back (Office)

If you have ever built a web application, chances are that you have also had to deal with "the back office" - the chores and one-off tasks required to operate your software in production. Workflows that aren't user-facing, like creating promo codes, moderating content, or running reports, are often a janky combination of admin scripts and spreadsheets. Retool helps developers quickly and easily solve these problems with software instead. In this session, we'll show how to build a back office interface for a Ruby on Rails application using Postgres and several common API services, so you can keep your focus on the business in the front, and let Retool help throw the party in the back (office).

RubyConf 2022

00:00:00.000 ready for takeoff
00:00:17.720 all right let's go ahead and uh kick things off folks straggling that's totally fine uh what's going on folks uh
00:00:25.019 my name is Kevin wintery and I'm the head of developer experience at a company called uh ritual and today I
00:00:31.260 want to talk about uh not the mullets that you might think of when you read the title initially but actually a
00:00:38.340 phenomenon that happens a lot in software development where you have kind of two different uh very separate types
00:00:46.200 of applications that you're responsible for maintaining as a developer and I want to talk a little bit about uh you
00:00:52.559 know the relationship between kind of the the customer facing the front of the
00:00:58.379 the front of the house type of software applications that we build and also these sort of back office applications
00:01:04.739 that uh might be a little different they might serve a smaller audience but are kind of no less impactful so I will take
00:01:11.580 a look at kind of the difference between those types of applications and then I'd like to show you one approach to kind of
00:01:18.840 building out the back office side of things using the platform ritual that
00:01:24.119 I've recently joined to help build out if you have any questions along the way
00:01:29.580 I'll try to save some time at the end we can drill down into any areas that might be interesting to folks as I think we do
00:01:36.000 have a little bit of time in between the sessions so I wanted to start off by saying I are
00:01:43.259 sort of explaining a situation that I'm betting that many of you in the room have encountered at some point in your
00:01:50.100 software development career if you have as much gray hair as I do chances are good that you know maybe dozens of times
00:01:57.479 over the course of your career uh you've had you've been in a situation where you've worked on one application that is
00:02:04.140 like the main application it's the the customer facing application the consumer
00:02:09.420 facing experience that you build out for the customers of your software company
00:02:14.879 it's sort of the glossy application that uh what is what most people think of when they think of your
00:02:21.420 company in addition to that application there's also the back office the you
00:02:26.940 know the administrative interface the dashboards like the software that you build that runs behind the scenes and
00:02:33.540 helps your business actually operate either your software in production or certain like key aspects of your of of
00:02:40.440 your business and there's kind of a few like properties that distinguish these two
00:02:46.140 types of software so for the main application it's typically the thing that your users interact with on a daily
00:02:52.800 basis and in that application UI polish and differentiated ux are actually
00:02:58.260 pretty important they they differentiate your product from others in the marketplace so having a user experience
00:03:05.040 that is unique to that application is actually pretty important there are also those types of applications are also
00:03:10.920 built for a broad audience with diverse needs so you might have you know one
00:03:16.260 type of user with a very different usage pattern and then that same user has to be accommodated in the same platform by
00:03:24.060 another type of user with very different needs so you tend to be building for a very broad audience you're also
00:03:30.900 optimizing for many users that are executing small tasks so if you're
00:03:36.420 building Twitter you are optimizing for lots of people um uh sending Tweets
00:03:41.720 and in general you have to assume that most of the users of your application should have like pretty restricted
00:03:48.239 access to whatever data your application is using and you can kind of compare this to what's happening with like your
00:03:54.540 back office software which is it's typically something that's internal facing that maybe your partners or your
00:04:00.720 fellow employees use uh it's more important that the software is like
00:04:05.819 performance and utilitarian versus having like a super differentiated ux a lot of times when you're building that
00:04:12.060 back office software you tend to reach for you know material UI or bootstrap or whatever like the off the shelf like CSS
00:04:18.900 framework du jour is because like that side of the application just isn't that important it's not as important as the
00:04:26.280 as a contributor to the success of the app you're tending to build for a small audience with a very specific set of
00:04:33.060 needs sometimes that audience is as small as like the 10 people on your support team that need to interact with
00:04:39.060 a particular type of data in your infrastructure somewhere you're also kind of optimizing for a relatively
00:04:46.020 small number of users that have you know fairly complex needs like sometimes they
00:04:51.960 will have to be able to kick off hours-long data export jobs which is not
00:04:57.300 typically a thing that you'll see like in your consumer-facing application they also generally have privileged data
00:05:04.259 access so uh you know you usually protect those applications with some kind of like corporate SSO you are
00:05:11.520 pretty interested in maybe auditing the steps that are happening or like the actions that people people are taking in
00:05:17.460 that back office software because it matters for regulatory concerns or or what have you so the sort of
00:05:24.660 requirements for these two types of applications end up being pretty different but at least a lot of
00:05:31.259 companies I've worked at over the years if you're in a situation where you have both the main app and the back office
00:05:38.160 app some somebody usually loses in terms of prioritization and it's almost always
00:05:43.800 the back office applications or those internal tools largely because like the
00:05:49.199 main app is probably what's like the revenue driver for your company it's the it's the thing that is customer facing I
00:05:56.460 it's built for a larger audience so work on like the main app actually impacts a
00:06:02.039 lot more people than the back office software and like two developers like
00:06:07.080 sometimes uh that is the more exciting piece of software to work on like building a differentiated ux shipping
00:06:13.440 software that impacts customers outside the company uh sometimes can be sometimes can be a more attractive
00:06:19.199 Prospect than building that critical internal tool that everybody at the company uses every day
00:06:25.979 um and then sort of on the flip side uh the reasons why the back office side sometimes gets under invested in is
00:06:32.819 because rather than being tied to revenue internal tools usually save time it's about like making your team more
00:06:38.520 efficient and creating operational excellence uh which has massive impact
00:06:43.860 on the bottom line but it's harder to kind of directly Trace that work back to something that helps your business I
00:06:51.300 it's also because of the impact is smaller it impacts a smaller number of people can sometimes be hard to like
00:06:57.240 justify an investment in creating like really great internal tooling and then
00:07:02.520 uh one thing for me as a front-end developer I actually uh you know know and am pretty sold on the utility of
00:07:09.419 having internal tools but it's kind of boring to like build the same react UI
00:07:15.300 or like form-based UI over and over and over again that's actually you know part of why I'm at the company I'm at now is
00:07:23.160 because I'm kind of tired of doing that I've done it many dozens of times times and uh you know I think there should be
00:07:28.680 a better way of handling that and one of the big ones for that sort of disincentive disincentivize uh folks
00:07:35.460 from working on internal tools is the maintenance burden of yet another application now you might actually think
00:07:41.340 like oh it's it's just a crud application uh it's just a small web application that I can just throw
00:07:46.680 together and deploy unfortunately there's really no such thing as a small web application before I joined retool I
00:07:53.759 spent 10 years at a company called twilio and one of the big like internal engineering philosophies that we have
00:07:59.819 was uh no free puppies which means you don't like bring a new piece of technology into the technology ecosystem
00:08:06.180 like spin up a go application because you think go is cool and you wanted to try to build something with it you have
00:08:12.840 to consider like what the maintenance and sort of long-term scalability and maintainability of that application is
00:08:18.979 and internal tools are just one more potential surface area where you create you know another node.js application or
00:08:26.940 rails application where you have dependencies get out of date and the next time somebody has to touch it they
00:08:32.640 spend you know days trying to update a dependency that has some kind of critical security vulnerability so lots
00:08:39.360 of reasons why you might want to go around building these internal tools but
00:08:45.240 uh so because of that like sort of lack of investment uh oftentimes there's these like clergy workarounds that will
00:08:52.500 emerge uh in the place of like software-driven uh internal tools so there's the classic like one-off admin
00:09:00.420 script uh you know the picture here is the laptop that is actually a server that is running some kind of like
00:09:07.320 long-running ETL task that is shockingly common uh actually you would you would
00:09:13.440 be surprised at how many like very large companies are doing stuff like this where like critical business workflows
00:09:19.800 are happening on just a random laptop and oftentimes uh you know you as a
00:09:25.920 developer I'm sure like a decent chunk of folks in the room uh have been like tapped on the shoulder by a business
00:09:31.980 person to say like hey can you run this query for me real quick and like dump this data out to a CSV or what have you
00:09:39.019 and it's really annoying because you have to you know do kind of a one-off administrative task to get that person
00:09:44.940 the data that they need so these are things that happen we have you know
00:09:50.459 potentially business users trying to solve their own problems through sort of spreadsheet driven janky workflows that
00:09:57.600 you know require human processes at every step of the way or they find some software as a service that does like a
00:10:04.140 good chunk of what they want to do but not quite everything and they kind of
00:10:09.360 have to make some compromises based on what happens to be available in a particular piece of SAS
00:10:15.380 and in these cases it's almost always true that some custom built software
00:10:20.580 would work better it would actually enable teams to work a little more
00:10:25.680 efficiently a little bit closer to the actual flow of the work that they want to accomplish
00:10:32.240 and I you know you can actually build software that solves some of these problems and
00:10:39.360 because it's software improves the data Integrity of you know the information that's going into and coming out of the
00:10:45.779 system and removes that capacity for human error that can be introduced otherwise generally I you know you
00:10:53.339 should be thinking about like especially in these internal tool use cases that software custom built software
00:10:59.399 specifically can work better to serve some of these needs than these like one-off admin scripts or manual
00:11:05.579 workflows uh so what I'm going to show real quick um in the uh sort of back
00:11:10.680 half of the talk here is kind of how you can go about building the back office
00:11:16.040 side of an application using some of the tools available in the retool platform
00:11:22.380 so ritual is a platform for developers that sort of purpose build for creating
00:11:27.779 these internal tools that drive a lot of businesses so uh you know for example we
00:11:33.720 have one of our customers is stripe an API provider that's up on the screen here and they have an internal application that they're like customer
00:11:39.600 support people use every day to like process chargebacks and refunds and those types of things and there's you
00:11:47.040 know lots of businesses who create these custom interfaces that are used heavily
00:11:52.260 every single day and those use cases are what retool was built to uh built to support So in your
00:12:01.440 back office software you typically are going to be accessing all of the same data sources apis that your sort of main
00:12:09.839 production application uses but in a slightly different way you might have privileged access to those interfaces or
00:12:16.500 those resources versus some of your internal services and you probably want
00:12:21.899 to have that layer of corporate SSO and audit logging on top of some of those
00:12:27.120 privileged operations and all of that is sort of part of the of the platform that
00:12:33.540 I'm just going to show you how to work with real quick so in this particular example we're going to show how you can
00:12:40.260 build an application that talks to like your application layers apis and also
00:12:46.139 directly to some of the data sources that are used by the application in this case it's going to be a postgres database so let's stop talking and
00:12:54.600 actually see how that works so I'm going to head over here to the
00:13:00.120 browser and I I'm on retool.com so I'm going to
00:13:05.459 show you how like sort of the hosted version of retool works but retool also
00:13:10.500 can be deployed inside like your VPC with uh you know a set of Docker
00:13:15.540 containers if you need your internal tools to have access to sort of privileged data that's behind a firewall
00:13:21.019 so this is one mode of interacting with retool but not the only one
00:13:26.220 and uh most uh internal applications start with access to various resources
00:13:32.940 the internal databases and apis uh like all the like all the services that might exist in your business that drive like
00:13:39.600 various parts of the stack you'll tend to expose those as resources so in this
00:13:44.700 case in this case I'm going to actually be building an administrative interface for one of the most important Enterprise
00:13:50.220 applications that any of us has ever worked on which is the Ruby on Rails guides built-in blog with posts and
00:13:56.940 comments and those types of things so I'm going to kind of demonstrate how you can do crud operations uh kind of using
00:14:03.139 the logic that you already built in the rails application and also a pretty common use case for internal tools too
00:14:09.959 which is some kind of human in the loop workflow where there's like an approval chain that needs to happen so the one
00:14:16.500 light modification that I have made to this app is that you know when you make
00:14:22.740 a comment on the blog for the first time um it actually can only be created in a
00:14:29.160 private mode and has to be approved before it actually shows up on the page
00:14:34.440 so we'll kind of build out some tooling that will allow like our back office staff to both create content and also to
00:14:42.000 like moderate uh these comments as they're coming in and hopefully that'll give you a sense of just sort of how the
00:14:47.880 how the technology works so in the resource configuration as I said we have our postgres database set up uh this
00:14:55.560 site is actually built and deployed on render which I've found to be a nice replacement for like the free Heroku
00:15:02.820 Dyno pour one out for the free Heroku daimo so if you want you know an
00:15:08.220 environment to play around with for your rails apps I definitely do recommend it it was pretty easy to get set up so this
00:15:14.459 is the postgres database associated with my render account and then I also have
00:15:20.459 configured the uh the blog API and I have API in quotes here because I didn't
00:15:26.699 really go through and do the entire API I just removed c-surf protection from all the rails routes so that I could
00:15:33.480 just hit them with arbitrary HTTP requests so it doesn't even return Json
00:15:38.519 so but I I do want to use the API to like be able to post new blog to create
00:15:43.800 new blog posts and stuff like that so we have a couple of resources and then on
00:15:49.019 top of those sources we're going to start creating applications so retool provides a visual IDE for building out
00:15:56.880 these types of you know Common applications that are mostly like forms buttons those those types of things so
00:16:04.680 I'm going to come in here and create a new application and we'll just call it a Blog admin
00:16:13.740 and I'll uh just double check I know it's a little bit small for which I
00:16:18.959 apologize so I'll try to blow it up just a little bit but on the canvas here there's a few
00:16:26.040 things that are created for you by default like this uh I like this data table which I'm
00:16:32.639 actually just going to delete because I don't need that and I one of the uh sort of core
00:16:39.120 building blocks of a retool application is a query uh which is either a chunk of logic that's going to like hit an API
00:16:44.940 and bring some kind of data back or a literal SQL query which you can write to like pull data out of the databases that
00:16:52.740 you might be working with uh so for there is a query that's in here by by
00:16:57.839 default and I'm going to start by you know in my application I know I'm going to want to do some crud on a couple of
00:17:04.860 resources so in the default like rails blog application the primary models are
00:17:10.679 the Articles and the comments so I'm going to write some queries that'll actually help me get that data back so I
00:17:16.260 can start using it in my application so for starters I'm going to select the
00:17:22.439 data source that I need which is the postgres database associated with my
00:17:27.959 rails blog and then I can write a SQL statement so I can say a select star
00:17:33.720 from articles and then I'm going to order by
00:17:42.480 updated whoops updated at uh
00:17:48.419 because I'm going to want to get sort of in Reverse chronological order all of the blog posts that are in my in my
00:17:56.460 database so if I can save that query and if I hit this like preview button it'll actually
00:18:01.500 uh execute the query and kind of give me a sense of what the data is that's
00:18:06.780 coming back so hopefully that'll work though it's going
00:18:12.480 a little longer than it often does conference Wi-Fi for you I guess
00:18:18.059 um but here let me uh just refresh to make
00:18:23.160 sure that I am still connected to the network
00:18:33.120 a network error when attempting to fetch resource it says so that does make some sense
00:18:41.760 try to give it one more try here I'm going to kill my Wi-Fi and bring it back
00:18:48.320 probably a cautionary tale where you can actually do local development of retool as well and not use like the cloud-based
00:18:54.900 version of it you can download the docker containers that run like sort of the on-premise retool and so you can run
00:19:01.500 resale on localhost and do your development uh there as well but let's
00:19:06.600 bring that back and refresh and see if that helps us at all get back into a
00:19:13.799 functional state for our blog admin here
00:19:21.720 okay so uh there we go let's grab the resource that we need it
00:19:30.059 looks like it's maybe also not getting my list of resources either
00:19:35.160 Which is less than ideal
00:19:45.179 yeah it looks like perhaps I'm still having network problems here so I there are my resources so that's
00:19:53.100 good to see let's try to go one more time out here
00:20:00.179 and edit the app okay so there's the resource it looks
00:20:07.080 like it's going back uh which is great and if I
00:20:12.120 run the query hopefully it will actually give me the results back
00:20:18.600 in a reasonable time frame
00:20:27.179 this is a bummer because it does have to connect to the
00:20:32.940 postgres that is running for the blog right now
00:20:39.539 which it looks like I am also struggling to see so we're going to debug it live
00:20:44.820 I'm going to actually use my personal hotspot on my phone
00:20:51.059 as an emergency backup so this is going great I'm just for
00:20:58.620 those of you keeping score at home I can also try just using like the the
00:21:04.980 Hilton Wi-Fi too let's try that first
00:21:16.320 what's up oh did it uh did it come up
00:21:28.140 yeah it might be the thing that needs to happen
00:21:37.500 does often require that all right but here there's my phone
00:21:44.039 let's see if that helps at all
00:21:55.799 yeah looks like
00:22:02.159 not about it I can also try to quit Firefox occasionally that will
00:22:08.640 help too if I'm changing Networks
00:22:19.740 okay so that's positive okay blog admin
00:22:26.400 sure and there we go okay so with internet
00:22:32.220 this works a lot better and we can see some uh just the blog
00:22:37.320 post from the standard rails blog application uh showing up here so I have
00:22:43.200 this data that I can start to work with and hopefully my phone I also notice is
00:22:48.960 conveniently a 10 battery so this is going to put a lot of pressure on the seven minutes remaining in the
00:22:54.780 presentation but hopefully it'll be just enough to keep us going um so I have the data source here and I
00:23:01.500 know that like in my blog I'm going to want to show the blog post data as it
00:23:06.900 comes back because that is the sort of read of the crud application so I'll start like kind of assembling interface
00:23:13.380 on the canvas using some of these like built-in components so on the right here there's sort of a palette of built-in
00:23:20.100 controls that you can use to start assembling your application and this text field can be configured
00:23:27.059 with markdown so I can just uh you know set up an H2 tag that says uh you know
00:23:33.120 list articles and I to actually display the contents
00:23:40.080 of the blog post I'm going to use a component called a list View and if you've done any development uh
00:23:46.799 you know with rich clients before this is like the repeater element or like the iterative loop that you would do in a
00:23:52.860 react application to render out HTML elements one after the other so I'm
00:23:58.919 going to start by like giving this component a a number of rows which is like how many rows that it should expect
00:24:06.360 to render and when I specify Dynamic values like anywhere in the configuration for a
00:24:12.419 component and retool I use these double curly braces so I can sort of template
00:24:17.940 in Dynamic values into the text content anywhere so in this case I'm going to
00:24:23.900 use what's called a query one dot data and you know the autocomplete shows me
00:24:31.260 as I go along like this is you know the contents of that query and I I can reference I the first uh
00:24:41.580 like the this object actually sort of represents a SQL query result set so uh this JavaScript object contains keys for
00:24:48.600 each of the fields that are brought back by the query um so one of those uh Fields is the ID
00:24:55.140 and the length of that ID is going to be about six but six individual rows and
00:25:02.100 then within this repeating component I can put in components that will be rendered for each item in my data set
00:25:10.080 um so oops I just missed my drop Target there so um as I start to drag this together I
00:25:17.100 can see these six items being rendered but instead of this uh sort of static message I want to show maybe the title
00:25:25.860 of each individual blog post so I'm going to say query one
00:25:32.220 uh Dot data and then I'm going to look for the title
00:25:38.520 of each one and then within this repeater component I kind of have the access to this I
00:25:46.020 variable which will let me reference like the current Uh current thing in the array that I'm dealing with so I can
00:25:53.279 start to render out the title there and I can I can also grab the contents
00:25:59.460 of the blog post so I'm going to grab um just copy that and here instead of
00:26:04.980 rendering out the title I'm going to render out the body of the blog post so
00:26:10.500 you can see the content starting to pop in there so you know now now we're starting to
00:26:16.260 see like the at least the read part of the crud application um
00:26:21.840 the other bit uh that you know since we I want to try to show other bits of the platform here before I have to let you
00:26:28.500 go so what I'm going to do is create a a form to like start to actually
00:26:33.960 create some new blog posts and start adding some content into the blog so uh
00:26:39.240 probably the quickest way I can do that is you know I'll drag in some text
00:26:44.580 inputs so uh here's a text input that I can use and we'll just kind of create a
00:26:50.100 form to create a new blog post like right next to this content I can specify
00:26:55.980 a label so we have like a title and then we also have a status so if
00:27:03.000 you've gone through the rails tutorial recently you'll remember like each of
00:27:09.360 the blog posts also has a status which can be like public private or archived
00:27:15.900 so I'm going to create a drop down for you know each of those options we got
00:27:21.659 public private and
00:27:27.779 and archives
00:27:33.299 and I can set the label to status and also the default value to public so
00:27:42.720 a couple seconds here just like whipping together a few form elements that I can
00:27:48.120 use to create a new blog post and then I the for the content itself like it might
00:27:53.159 be nice actually to have a rich text editor so with the blog posts I can actually you know have HTML formatted
00:27:59.900 text so I can do a bolded content stuff like that so I'm going to actually pop
00:28:06.059 in a rich text element here and you know I can use this to actually put in the
00:28:11.760 body of the blog post and then finally um you know I'm going to need a button to actually save this so I'll pull it
00:28:19.980 down uh I'll just put it out here it's a little non-standard but that's okay and this button when clicked uh will
00:28:27.360 like save my new blog post
00:28:32.640 all right so uh yeah just really quickly I you know I'm putting together an
00:28:37.980 interface that'll let me start to create content for the blog the
00:28:44.880 uh bits to note here uh are like we I can actually uh you know directly add
00:28:53.039 the blog post to the postgres database using a SQL statement like we saw before but that's not typically something you
00:28:58.679 want to do you don't want to sort of YOLO SQL statements uh to like create data uh if you can avoid it unless uh
00:29:06.539 you know you're using a stored procedure which has some like validation logic baked in or something like that a lot of times what you'll want to do is
00:29:13.320 go through the same API that you use for the models like in your rails app specifically because you tend to have
00:29:19.860 like your validation and other logic that exists in code that you wouldn't have access to if you just did a SQL
00:29:26.580 statement directly against the database so what I'm going to do is create another query here but in this case it's
00:29:32.520 going to be actually like a rest API request to create a new resource on the
00:29:38.460 server so instead of the postgres API I'm going to select this pre-configured
00:29:44.460 API endpoint that I have in my resources tab which I showed you earlier
00:29:49.679 and the benefit of kind of pre-configuring an API endpoint like that is you can set like the base URL
00:29:56.520 here and you can also configure authentication so the default rails demo uses HTTP basic auth to protect certain
00:30:04.260 endpoints so I actually already have my like HTTP basic auth header configured for this resource so I can use that
00:30:11.279 across all of the resource or all the requests that I'm making in the application so in this case
00:30:16.740 I'm going to be making a post request to the articles
00:30:22.159 endpoint and then I can include all the uh you know any URL parameters that I
00:30:27.299 would need any headers that I would need but I also will be passing in the form data
00:30:33.720 which formatted in the right way for creating a rails model would be like article dot
00:30:40.500 or you know subscript title and this is just kind of the Rails naming convention for these fields and then I would want
00:30:49.740 to uh you know pass in uh the data from each of those components that I added to
00:30:56.580 the UI earlier so I had a text input a select and then a rich text editor so
00:31:02.640 for the title I can reference I think it was uh text input one dot value
00:31:09.960 and then I can also have my body which is going to be
00:31:17.580 that Rich Text Editor one dot value
00:31:24.240 and then finally I have the status which is in that select
00:31:33.179 that I added to the UI before as well so uh when I do that
00:31:39.000 um I'll I can submit whatever is currently in that form uh send it to my rails API where like the validation
00:31:45.480 logic that's configured in the active record models will be executed before the model is saved and then you know on
00:31:52.559 success I can handle the success in some way so like I can rerun the query to show the complete list of blog posts
00:31:59.100 which is what I'll do right now uh and then on failure I can also
00:32:05.279 configure JavaScript code that's going to be executed if I get you know 400 or 500 level error uh back from the API
00:32:12.840 so let's go ahead and save that and then for this button we can wire up
00:32:18.360 an event handler here uh to you know on uh when when the button is clicked it's
00:32:24.360 going to fire off this uh this query that I just created so if I enter a title
00:32:32.580 you know some new content and some kind of text
00:32:42.000 exciting we'll see if this works before I let you go to the next session here whoops
00:32:49.440 just uh add it to be something you know some bold text or something like that
00:32:55.320 and if I hit save I did get a 500 back so that is a bummer I was hoping I was going to be able to
00:33:01.440 stick the landing a little bit here by saving the data but let's let's see if it's something that I can quickly uh
00:33:12.179 oh which one yes
00:33:18.539 at trickle yeah that's not a thing yep there we go
00:33:24.539 so here we go save that
00:33:31.260 let's try it again and it looks like it did go through
00:33:36.659 there and we have you know the new blog post content uh coming up there so yeah
00:33:41.940 I'll I'll take the PDF I'll take the pity clap I appreciate that thank you very much uh so uh
00:33:49.620 internet notwithstanding today we learned an important lesson about making sure that your hotspot is ready as a
00:33:55.140 backup but I the idea is that you know with uh in just a few minutes like we
00:34:00.179 implemented at least two letters of the crud operations um against my data store
00:34:05.700 um but what you didn't see is that you know every retail application can be set up to work with like your company's SSO
00:34:12.179 so you can have OCTA set up to you know authenticate users of your of your applications they're sort of built-in
00:34:18.599 audit logging so you can see like which users executed which queries and you can sort of secure queries to be only
00:34:25.080 executable by certain people in your business we also didn't get to see our workflow editor which is like a way to
00:34:31.919 create cron tasks in JavaScript so instead of having the laptop open you
00:34:37.080 can actually run your background tasks and retool as well so definitely a lot of fun stuff to dig into
00:34:42.240 um I'm also going to be hanging out a little bit after the session here and at a table in the exhibit hall if you have
00:34:49.020 any questions about out retool make sure to stop by and also I have three Lego
00:34:54.359 sets that I don't want to bring home so if you just like sign up for a retool account and build something quickly you
00:35:00.300 have a chance to take home one of those very fun Lego sets so make sure you stick stick around and check that out but thank you very much I appreciate the