TRANSCRIPCIÓN 🔗
WEBVTT
00:00:00.001 --> 00:00:04.060
Do you find yourself for your team building internal apps frequently for your company?
00:00:04.060 --> 00:00:06.980
Are you familiar with the term forms over data?
00:00:06.980 --> 00:00:12.260
They can be super empowering for your organization, but they can also be pretty repetitive.
00:00:12.260 --> 00:00:18.920
And you might find yourself spending more time than you like working on them rather than core products and services.
00:00:18.920 --> 00:00:27.280
I've invited Jimmy Chan from Dropbase to tell us about their services, whose tagline is build internal web apps with just Python.
00:00:27.280 --> 00:00:29.900
It's a cool service and a fun conversation.
00:00:30.480 --> 00:00:35.940
This is Talk Python To Me, episode 460, recorded March 12, 2024.
00:00:35.940 --> 00:00:37.980
Are you ready for your host?
00:00:37.980 --> 00:00:38.600
Please.
00:00:38.600 --> 00:00:42.260
You're listening to Michael Kennedy on Talk Python To Me.
00:00:42.260 --> 00:00:45.940
Live from Portland, Oregon, and this segment was made with Python.
00:00:45.940 --> 00:00:53.320
Welcome to Talk Python To Me, a weekly podcast on Python.
00:00:53.320 --> 00:00:55.060
This is your host, Michael Kennedy.
00:00:55.060 --> 00:01:02.560
Follow me on Mastodon, where I'm @mkennedy, and follow the podcast using @talkpython, both on fosstodon.org.
00:01:02.560 --> 00:01:07.640
Keep up with the show and listen to over seven years of past episodes at talkpython.fm.
00:01:08.480 --> 00:01:11.980
We've started streaming most of our episodes live on YouTube.
00:01:11.980 --> 00:01:19.520
Subscribe to our YouTube channel over at talkpython.fm/youtube to get notified about upcoming shows and be part of that episode.
00:01:20.680 --> 00:01:25.620
This episode is sponsored by Mailtrap, an email delivery platform that developers love.
00:01:25.620 --> 00:01:28.860
Try for free at mailtrap.io.
00:01:28.860 --> 00:01:32.840
And it's brought to you by us over at Talk Python Training.
00:01:32.840 --> 00:01:36.320
Did you know that we have over 250 hours of Python courses?
00:01:36.320 --> 00:01:37.260
Yeah, that's right.
00:01:37.260 --> 00:01:40.680
Check them out at talkpython.fm/courses.
00:01:42.140 --> 00:01:42.860
Hey, Jimmy.
00:01:42.860 --> 00:01:43.400
Hey, Michael.
00:01:43.400 --> 00:01:43.820
How are you doing?
00:01:43.820 --> 00:01:44.800
I'm doing well.
00:01:44.800 --> 00:01:46.620
Welcome to Talk Python To Me.
00:01:46.620 --> 00:01:47.840
It's fantastic to have you here.
00:01:47.840 --> 00:01:48.240
Thank you.
00:01:48.240 --> 00:01:48.700
I'm really excited.
00:01:48.700 --> 00:01:49.660
Yeah, I am too.
00:01:49.660 --> 00:01:51.040
I saw DropBase.
00:01:51.040 --> 00:01:51.920
I saw what you all were building.
00:01:51.920 --> 00:01:54.440
I'm like, that is pretty darn interesting.
00:01:54.440 --> 00:01:56.540
I think people will want to check it out.
00:01:56.540 --> 00:02:03.040
So we'll dive into this app and this platform that you made for app building, basically.
00:02:03.040 --> 00:02:04.060
We'll have a lot of fun.
00:02:04.060 --> 00:02:08.280
Now, before we get into that, though, just give us a quick bit of background on yourself.
00:02:08.280 --> 00:02:09.440
How'd you get into programming?
00:02:09.600 --> 00:02:13.020
How'd you find yourself writing a Python building platform?
00:02:13.020 --> 00:02:13.440
Awesome.
00:02:13.440 --> 00:02:15.060
Yeah, I went to school for engineering.
00:02:15.060 --> 00:02:17.100
This was actually back in Canada.
00:02:17.100 --> 00:02:20.360
I studied in Montreal at a little school called McGill University.
00:02:20.360 --> 00:02:20.720
Nice.
00:02:20.720 --> 00:02:21.540
We started then.
00:02:21.540 --> 00:02:26.000
I used to intern, by the way, at this company called Research in Motion that used to make
00:02:26.000 --> 00:02:27.780
BlackBerrys way back in the time.
00:02:27.780 --> 00:02:28.680
Oh, yeah.
00:02:28.680 --> 00:02:29.420
Awesome.
00:02:29.420 --> 00:02:30.660
In the heyday?
00:02:30.660 --> 00:02:31.480
In the heyday.
00:02:31.480 --> 00:02:36.960
I remember when they said we had 50% of the US smartphone market share.
00:02:36.960 --> 00:02:38.900
But the platform was actually built on Java.
00:02:39.260 --> 00:02:39.720
No, Python.
00:02:39.720 --> 00:02:41.420
Python was something afterwards.
00:02:41.420 --> 00:02:44.940
Actually, my co-founder is the Python programmer.
00:02:44.940 --> 00:02:47.360
And I picked up Python after we started working together.
00:02:47.360 --> 00:02:47.640
Cool.
00:02:47.640 --> 00:02:50.100
You got any fun stories from your time at BlackBerry?
00:02:50.100 --> 00:02:50.920
Did you enjoy it?
00:02:50.920 --> 00:02:51.480
How long were you there?
00:02:51.640 --> 00:02:52.840
I was there as an intern only.
00:02:52.840 --> 00:02:56.780
Spent about 16 to 20 months of internships.
00:02:56.780 --> 00:02:57.220
Yeah.
00:02:57.220 --> 00:02:59.320
At the time, I was, I think, in my third year of school.
00:02:59.320 --> 00:03:05.360
And we were just working on these little Java apps for the smartphones and just making sure
00:03:05.360 --> 00:03:06.540
everything was working.
00:03:06.540 --> 00:03:12.720
The cool thing is when you work at a company that's making devices, devices have a very long
00:03:12.720 --> 00:03:14.000
development cycle.
00:03:14.000 --> 00:03:16.380
So imagine, for example, you worked at Apple today.
00:03:16.380 --> 00:03:20.060
Like the iPhone, what, 15, whichever one's coming next.
00:03:20.060 --> 00:03:23.020
Like they've been working on it for at least a year, probably longer.
00:03:23.020 --> 00:03:26.860
Do you get access to all these prototypes that you get to use?
00:03:26.860 --> 00:03:28.740
Because like you're building for it, you're testing it.
00:03:28.740 --> 00:03:30.840
That was a really nice, nice, nice thing.
00:03:30.840 --> 00:03:32.540
But you actually couldn't tell anybody about it.
00:03:32.540 --> 00:03:35.000
But it was really cool
Load full transcript
to know that you're on the last thing.
00:03:35.000 --> 00:03:38.140
And you couldn't lose it in a bar or anything like that, right?
00:03:38.140 --> 00:03:39.680
You remember those stories, right?
00:03:39.680 --> 00:03:40.800
Yes, exactly.
00:03:40.800 --> 00:03:41.640
A few times.
00:03:41.640 --> 00:03:46.280
Somebody got a hold of a lost phone and it was sold and there was all sorts of drama.
00:03:46.280 --> 00:03:46.980
It was a big deal.
00:03:46.980 --> 00:03:51.760
That was around an iPhone 4, 3, 4, 5 sort of time frame.
00:03:51.760 --> 00:03:53.520
Yeah, I remember that very clearly.
00:03:53.520 --> 00:03:53.860
Yeah.
00:03:53.860 --> 00:03:55.420
So you didn't want to be that.
00:03:55.500 --> 00:03:57.060
You wanted to make sure you hung on to it.
00:03:57.060 --> 00:03:57.440
Oh, yeah.
00:03:57.440 --> 00:03:57.680
No.
00:03:57.680 --> 00:04:02.360
Yeah, I think working for a company like that would have been awesome, at least in the heyday.
00:04:02.360 --> 00:04:09.380
It's cool to work for a tech company that's got a lot of wind that it's back and a lot of people using it.
00:04:09.380 --> 00:04:10.400
It's kind of neat.
00:04:10.400 --> 00:04:11.000
I was very happy.
00:04:11.000 --> 00:04:14.300
We had a lot of other interns that they hired at the time.
00:04:14.300 --> 00:04:17.020
So you just had a blast to work in there over the summer.
00:04:17.020 --> 00:04:19.200
Yeah, a lot of excited people to do stuff.
00:04:19.200 --> 00:04:19.880
Excellent.
00:04:19.880 --> 00:04:20.520
Cool.
00:04:20.520 --> 00:04:24.560
And so then you picked up Python, I guess, when you started this project.
00:04:24.560 --> 00:04:25.000
Is that right?
00:04:25.080 --> 00:04:26.020
Just a little bit before.
00:04:26.020 --> 00:04:30.100
So when we started our startup, this was back in 2020.
00:04:30.100 --> 00:04:32.980
My co-founder had been using Python.
00:04:32.980 --> 00:04:38.260
He did a master's degree, computer science, focused on machine learning, actually.
00:04:38.260 --> 00:04:42.320
In that field, Python is really the main language you use.
00:04:42.320 --> 00:04:42.800
Yeah, it is.
00:04:42.900 --> 00:04:44.460
And so he was very familiar with it.
00:04:44.460 --> 00:04:49.200
And so he set our stack, basically, to be a Python backend.
00:04:49.580 --> 00:04:56.540
And then just through that process, just looking at things and designing features, we just all got involved with Python.
00:04:56.540 --> 00:04:58.140
So it kind of just became the same.
00:04:58.480 --> 00:05:04.480
And this is actually the reason why we're working on a Python builder is we're kind of building a product for ourselves.
00:05:04.480 --> 00:05:08.720
It's something where it fits our own needs, that works with our mental models.
00:05:09.120 --> 00:05:10.660
So that's pretty much it.
00:05:10.660 --> 00:05:16.140
So today, I spent a lot of time building apps with DropBase, so internal tools.
00:05:16.140 --> 00:05:18.720
And that's most of the app building
I do now.
00:05:18.720 --> 00:05:22.880
So building demos, testing the product, making sure everything is working.
00:05:23.280 --> 00:05:27.300
And then just finding other ways to make the developer experience more convenient.
00:05:27.300 --> 00:05:32.980
It seems like something you could really take care of a bunch of internal automation type of apps.
00:05:32.980 --> 00:05:40.580
You don't have to create full-on web apps to secretize this data or get that dashboard or whatever, right?
00:05:40.580 --> 00:05:43.420
You just fire up your own platform and win at your data sources.
00:05:43.420 --> 00:05:44.380
That's right, yeah.
00:05:44.380 --> 00:05:51.380
So the big difference with other frameworks is that you're going to use these frameworks to build your customer-facing applications.
00:05:52.000 --> 00:05:56.440
And customers, they have expectations about what they need.
00:05:56.440 --> 00:05:59.740
Interactions sometimes make a big difference for them.
00:05:59.740 --> 00:06:03.180
UI components, the way models come up.
00:06:03.180 --> 00:06:04.740
It's all part of the experience.
00:06:04.740 --> 00:06:09.100
And so for that, you really need a lot of extra components complexity.
00:06:09.100 --> 00:06:14.140
For internal tools, it's not to say that internal users don't have high expectations.
00:06:14.140 --> 00:06:19.220
But the kinds of things that you do with those tools tend to be very, very similar.
00:06:19.220 --> 00:06:20.580
You search for data.
00:06:21.020 --> 00:06:23.960
You get context about that.
00:06:23.960 --> 00:06:26.500
So for example, you search for a transaction or for a user.
00:06:26.500 --> 00:06:30.980
You get some more context to make sure that that's the user or the transaction that you want to act on.
00:06:30.980 --> 00:06:32.340
And then you just act on it, right?
00:06:32.340 --> 00:06:37.200
Like you trigger an action on that item or that resource or that person.
00:06:37.200 --> 00:06:39.460
It helps you simplify the kind of things you need.
00:06:39.460 --> 00:06:44.560
And so for that, having a framework, a builder to make this happen is super convenient.
00:06:45.260 --> 00:06:50.880
This is a little bit of a tool.
00:06:50.880 --> 00:07:01.940
And when I think of internal web apps or even traditionally, if you look back a ways, there was VB6 and Windows Forms and those types of things that were kind of playing the same role.
00:07:02.340 --> 00:07:03.880
So same basic idea.
00:07:03.880 --> 00:07:08.520
There was a lot of people who referred to that as forms over data.
00:07:08.720 --> 00:07:16.280
It kind of the not quite a negative term, but kind of like we're sort of doing the same basic architecture over and over.
00:07:16.400 --> 00:07:18.120
But it's a different problem every time.
00:07:18.120 --> 00:07:22.420
And so we kind of got to write code, create these projects from scratch every time.
00:07:22.420 --> 00:07:25.020
But they're the kind of same kind of thing.
00:07:25.020 --> 00:07:36.700
And so, you know, I think that's probably why VB6 with its kind of visual drag and droppy experience became real popular because you could drag a table on there and drag a data source, bind it to that and make a button click when somebody touches this thing.
00:07:36.700 --> 00:07:45.580
And that didn't create something that would rival, say, Airbnb.com or, you know, these really dynamic design sites.
00:07:45.960 --> 00:07:47.200
But that's not what they need.
00:07:47.200 --> 00:07:50.820
The company says, look, we need this week.
00:07:50.820 --> 00:07:55.180
I need our salespeople to be able to answer this question and make this change.
00:07:55.180 --> 00:07:57.120
That's what we need you to build this week.
00:07:57.120 --> 00:08:00.780
And if it's from scratch every time, that's a ton of rework.
00:08:00.780 --> 00:08:01.920
It's a lot of work.
00:08:01.920 --> 00:08:04.300
It's funny you mentioned the forms over data.
00:08:04.300 --> 00:08:10.960
It is true that a lot of the, well, if you take it at a very high level, all apps are forms over data.
00:08:10.960 --> 00:08:12.400
In some sense, yeah.
00:08:12.520 --> 00:08:17.680
All SaaS apps are forms over a database in some sense.
00:08:17.680 --> 00:08:25.160
And then you start to hear also about the similar things with, you've heard about the GPT wrappers, right?
00:08:25.460 --> 00:08:30.140
It's the same concept where it's like an oversimplification of what's happening.
00:08:30.140 --> 00:08:32.720
But at the same time, it is kind of core to what's happening.
00:08:32.720 --> 00:08:36.460
And for internal tooling, at least, is exactly what you need.
00:08:36.460 --> 00:08:38.400
Forms over data, but very quickly.
00:08:38.620 --> 00:08:44.280
So that developers don't have to spend a lot of time basically doing the same things over and over again.
00:08:44.280 --> 00:08:48.460
You want to make their lives easier to support their internal users.
00:08:48.460 --> 00:08:51.060
So people in customer support, operations.
00:08:51.060 --> 00:08:54.540
And I think sometimes even supporting other engineers as well.
00:08:54.540 --> 00:08:54.720
Yeah.
00:08:54.720 --> 00:09:00.740
And it's not that people in companies don't have expectations of nice apps and nice interactions.
00:09:01.060 --> 00:09:02.880
It's just that it's more utilitarian.
00:09:02.880 --> 00:09:11.800
Like so many of these big enterprises, when you kind of think of them, maybe the right way to think of them is there's a massive Postgres or Microsoft SQL server at the center.
00:09:11.800 --> 00:09:20.980
And like it almost connects the business divisions, like the sales team and the marketing team and the product team and all that.
00:09:20.980 --> 00:09:33.500
And if you can get into the database and answer questions, expose data, expose relationships, put a UI to some aspect of that, you're really right at the heart of the company in some sense, you know?
00:09:33.500 --> 00:09:35.580
Yeah, it's definitely
about effectiveness.
00:09:36.140 --> 00:09:51.000
One way we think about what these kinds of tools should do, you have to enable developers to very quickly build apps that have maximal value, that lets you get the job done as effectively as possible.
00:09:51.000 --> 00:09:54.440
But also that's easy to use for the end users.
00:09:54.440 --> 00:10:01.480
So, you know, if it's like a business operator or someone in the operations team, they also need to be able to learn quickly how to use it and trigger actions.
00:10:01.960 --> 00:10:07.740
And so we call that sort of effectiveness of the apps, some sort of like effectiveness score.
00:10:07.740 --> 00:10:08.040
Yeah.
00:10:08.040 --> 00:10:09.400
It just combines these components.
00:10:09.400 --> 00:10:19.520
And that's really the, like, if you can get to the essence of it and create a framework or a tool builder that maximizes for that, I think you're in a really good place.
00:10:19.520 --> 00:10:22.080
And this is something we're trying to do with DropBase.
00:10:22.080 --> 00:10:23.780
The components are simple.
00:10:24.240 --> 00:10:29.140
The kinds of apps that you can build look roughly the same, but they look really nice.
00:10:29.140 --> 00:10:31.660
And they're also quite simple to understand.
00:10:31.660 --> 00:10:39.680
They're modeled after, but it's in a way where you have data, a greater table in the middle, and then there's a sidebar from where you can trigger actions.
00:10:40.180 --> 00:10:55.600
And this ties back to this concept of when you ask people in operations what they do, like sales, marketing, business operations, essentially it ties back to the previous comments, which was you search for something, you get context about it, and you trigger action.
00:10:55.600 --> 00:11:03.640
And so the way we translated that insight about what people just end up doing over and over again, we said, well, then you really just need some sort of search bar.
00:11:03.640 --> 00:11:11.020
You need a grid and you need a sidebar with some buttons or some other drop downs and other components.
00:11:11.020 --> 00:11:15.160
And then you realize, okay, this is kind of what spreadsheets I've been trying to do for a long time.
00:11:15.160 --> 00:11:15.760
Yeah, that's true.
00:11:15.760 --> 00:11:17.560
Except we like to trigger actions.
00:11:17.560 --> 00:11:17.940
Yeah.
00:11:17.940 --> 00:11:22.900
People do oddly connect Excel to, like, external data sources and all sorts of weird things as well.
00:11:22.900 --> 00:11:23.300
Yeah.
00:11:23.300 --> 00:11:25.660
Or write VBA that makes some change.
00:11:25.660 --> 00:11:27.300
They probably should just not be doing that.
00:11:27.300 --> 00:11:27.540
Yeah.
00:11:27.540 --> 00:11:29.520
There's a lot of, it's actually a big use case.
00:11:29.520 --> 00:11:32.480
One of our previous product, we actually did exactly that.
00:11:32.480 --> 00:11:32.740
Okay.
00:11:32.740 --> 00:11:39.440
We let you connect any database source to your Google Sheets and just kind of run that on a schedule.
00:11:39.440 --> 00:11:48.380
So you'd imagine in a business setting, you have sort of these, like, weekly, daily reports that analysts end up working on, right?
00:11:48.380 --> 00:11:52.640
And what you want is for the data to be fresh, up to date.
00:11:52.640 --> 00:12:02.320
And so people just wanted a way to, on, at 7 a.m., 8 a.m. on Monday morning, basically automatically pull data from a database, load it up to your spreadsheet.
00:12:02.320 --> 00:12:11.120
And then all your tables and calculations, which is sort of updated because they're referencing a tab, a sheet, basically, that has fresh data.
00:12:11.120 --> 00:12:13.620
It's very interesting, the evolution of all these tools.
00:12:13.620 --> 00:12:14.380
It is really interesting.
00:12:14.380 --> 00:12:21.480
Maybe one of the big differences is the interactivity here versus what you might do in that story, right?
00:12:21.560 --> 00:12:22.920
That's read-only, really.
00:12:22.920 --> 00:12:29.420
And then here, what we're doing is letting you trigger actions, perform actions, basically outside the app.
00:12:29.420 --> 00:12:35.540
So you might call an API or you might trigger an internal endpoint or just trigger some action in the UI.
00:12:37.240 --> 00:12:44.140
This portion of Talk Python To Me is brought to you by Mailtrap, an email delivery platform that developers love.
00:12:44.140 --> 00:12:55.580
An email sending solution with industry-best analytics, SMTP, and email API SDKs for major programming languages and 24-7 human support.
00:12:55.580 --> 00:12:58.540
Try for free at mailtrap.io.
00:12:59.920 --> 00:13:04.360
I think we'll get to this more later, but I want to maybe touch on it since there's a good question.
00:13:04.360 --> 00:13:06.620
Also, it might be a question a lot of people have.
00:13:06.620 --> 00:13:08.860
So what's the pricing model for this?
00:13:08.860 --> 00:13:13.020
And basically, more broadly, what is the business model around here?
00:13:13.020 --> 00:13:18.080
Luis says, already amazed by it, would like to compare it.
00:13:18.080 --> 00:13:20.980
First thought, there's nothing like this available in open source.
00:13:20.980 --> 00:13:22.180
So very neat.
00:13:22.180 --> 00:13:29.120
The business model is we're going to sell the product on a per-user, per-month basis.
00:13:29.220 --> 00:13:31.000
So it's a B2B SaaS app product.
00:13:31.000 --> 00:13:38.320
Now, developers need to be able to play around with products before they can decide whether that's something they want.
00:13:38.320 --> 00:13:48.520
And so we have a free version of the products that you can set up locally, like in your own machine, or you can just put it up on EC2.
00:13:48.520 --> 00:13:50.620
And you can just build apps for yourself.
00:13:50.620 --> 00:13:54.700
If you want to automate personal tasks, you can totally use this for it.
00:13:55.000 --> 00:14:10.460
And then the way that we, in a way, layer
the pricing is like, if you need very complex permission systems, so like you build an app and you want it accessible by this person, by person A, but not person B, then you'll need very granular permission systems.
00:14:10.460 --> 00:14:15.040
And so that's an indicator that you're probably like a corporate user, you're a business user.
00:14:15.040 --> 00:14:17.560
And so we do the pricing based on that.
00:14:17.560 --> 00:14:19.680
The source is open, at least.
00:14:19.680 --> 00:14:21.260
People can go and check it out, right?
00:14:21.260 --> 00:14:21.980
Is that true?
00:14:21.980 --> 00:14:22.900
Let me clarify that.
00:14:22.900 --> 00:14:24.300
So you can self-host it.
00:14:24.300 --> 00:14:24.600
Yes.
00:14:24.760 --> 00:14:26.540
You know, you can look at the repo.
00:14:26.540 --> 00:14:30.620
Behind the scenes, it's a Docker image that you set.
00:14:30.620 --> 00:14:41.160
So the code for draw base is not immediately, you know, you can't just browse it through the file system, but the code is basically sitting in your machine when you set this up locally.
00:14:41.160 --> 00:14:45.920
Now, the difference here is if you look at the directory where you have the workspace.
00:14:45.920 --> 00:14:52.580
So the workspace directory is where all your apps files would be generated as you build the apps.
00:14:53.240 --> 00:14:58.220
That's really nice because you can essentially version control this from day one.
00:14:58.220 --> 00:14:59.260
You can build apps.
00:14:59.260 --> 00:15:01.000
You can check it in GitHub.
00:15:01.000 --> 00:15:02.320
You can just keep your code.
00:15:02.320 --> 00:15:03.040
You can version it.
00:15:03.040 --> 00:15:05.520
And so it's really, it's not open source.
00:15:05.520 --> 00:15:08.020
It's clarified that, but you can self-host it.
00:15:08.020 --> 00:15:16.160
It's on GitHub, but the licensing is really not like just straight up GPL open source type of thing, right?
00:15:16.160 --> 00:15:16.720
That's correct.
00:15:16.720 --> 00:15:17.120
Yes.
00:15:17.120 --> 00:15:17.460
Okay.
00:15:17.460 --> 00:15:22.820
And it's on GitHub because you need to, you do need to clone the repo and then you need to send it out and install it.
00:15:22.920 --> 00:15:29.540
The free tier doesn't allow self-hosting, but if you pay for one of the versions, then it does have a self-hosting option.
00:15:29.540 --> 00:15:40.000
So when you, just to wrap this up on the price, when you say it's $10 per user per month, is that per person that makes the project, that builds the apps?
00:15:40.000 --> 00:15:43.220
Or is that per person that interacts with the web app?
00:15:43.440 --> 00:15:46.140
This is currently per member of your workspace.
00:15:46.140 --> 00:15:51.340
So we're not yet differentiating between someone who is building the app or using the app.
00:15:51.340 --> 00:15:54.540
Although that might be something that we'll have to add later on.
00:15:54.540 --> 00:15:54.760
Sure.
00:15:54.860 --> 00:16:03.240
So if you had say four salespeople and one developer in quotes, maybe developer, that would be five users under this story.
00:16:03.240 --> 00:16:03.560
Correct.
00:16:03.560 --> 00:16:04.940
Under the current pricing, yes.
00:16:04.940 --> 00:16:05.220
Okay.
00:16:05.440 --> 00:16:08.520
You know, even if it's not just pure open source, take it and run with it.
00:16:08.520 --> 00:16:22.720
I do like the self-hosting aspect of it because if you've got private data or maybe even more important than any of that is I want to connect it to data sources that are, I don't want to give your cloud access to my company database, for example.
00:16:22.720 --> 00:16:23.860
I can expand on that, actually.
00:16:23.860 --> 00:16:29.520
So we built this specifically with that comment in mind.
00:16:29.520 --> 00:16:41.180
So when you're using internal tools, it's very, well, let's say it's almost all the cases you are interacting with production, at least one production database, right?
00:16:41.180 --> 00:16:48.040
Like if you're supporting customers and you're issuing them a refund, you don't do that in tests and then take it to staging and then deploy it, right?
00:16:48.040 --> 00:16:51.680
You basically, you act on it on your production data.
00:16:51.680 --> 00:17:06.180
And so we thought, okay, people are probably going to be very hesitant to basically say, let me load up all my creds, all my API keys into some new player, new cloud, and then like hope for the best, right?
00:17:06.180 --> 00:17:11.600
So when we designed DropBase, we call it the worker or the worker's server.
00:17:11.600 --> 00:17:19.620
The way you connect to data sources is you basically go to your .env file and you just add your database creds.
00:17:20.020 --> 00:17:27.520
And that .env file sits in the same directory that that workspace directory sits, the one that we saw on GitHub.
00:17:27.520 --> 00:17:30.220
And that's completely on your side.
00:17:30.220 --> 00:17:32.720
And that's in your VPC or in your local machine.
00:17:32.720 --> 00:17:39.240
And the same server is the one that triggers the task to query your database.
00:17:39.240 --> 00:17:43.140
So, and that's also sitting on your side in your machine.
00:17:43.140 --> 00:17:54.680
And so the entire part of the product that processes, queries, touches your data, your data sources, your credentials, that's completely on the user side.
00:17:54.680 --> 00:17:59.520
And the only part that we manage is really just the permission system.
00:17:59.520 --> 00:18:04.180
So that controlling the workspace and controlling the like the app permissions.
00:18:04.180 --> 00:18:06.680
That's the layer that we control.
00:18:06.680 --> 00:18:10.720
And that's really like the part where we can do the pricing on to begin with.
00:18:10.720 --> 00:18:15.180
Like that's the, that's the feature set thing that helps us say, okay, this is going to be paid customers.
00:18:15.180 --> 00:18:18.940
And these are going to be developers who
are just going to learn how to code in Python.
00:18:18.940 --> 00:18:22.480
They just want to build little apps for their own personal use.
00:18:22.480 --> 00:18:22.780
All right.
00:18:22.780 --> 00:18:23.240
That makes sense.
00:18:23.240 --> 00:18:27.040
You know, let's maybe talk through an example.
00:18:27.040 --> 00:18:35.020
If you go to dropbase.io, there's a, right at the top, there's a sort of tutorial or a demo video of you using it.
00:18:35.020 --> 00:18:42.380
Obviously, I don't want to just play the video, but maybe just talk us through the steps of what this app is and what are the steps to build it.
00:18:42.380 --> 00:18:49.420
And just for people who are listening, haven't watched that video, maybe I think it's 12 minutes long and you're like, let's create a new project.
00:18:49.760 --> 00:18:52.160
And here it is published at the end, right?
00:18:52.160 --> 00:18:52.920
Which is really nice.
00:18:52.920 --> 00:18:53.720
So yeah, talk us through.
00:18:53.720 --> 00:18:58.100
I'm going to try to recreate the exact same one that's, that you have on the, on the screen, right?
00:18:58.100 --> 00:19:04.880
So it looks like an app that has two tables and you can somehow perform an action with up on the sidebar.
00:19:04.880 --> 00:19:11.060
Basically, it just notifies, either notifies a user or it performs some sort of permissions.
00:19:11.060 --> 00:19:18.460
I think what this one does is it has a workspaces and then users are in a workspace and you can make them admins or not admins of that workspace.
00:19:18.620 --> 00:19:19.400
Gotcha.
00:19:19.400 --> 00:19:19.840
Perfect.
00:19:19.840 --> 00:19:20.340
Okay.
00:19:20.340 --> 00:19:21.260
Okay.
00:19:21.260 --> 00:19:22.980
So I'll describe how you build this app.
00:19:22.980 --> 00:19:26.280
So you go to our app studio and it's going to be a blank canvas.
00:19:26.280 --> 00:19:29.120
In that canvas, you can add tables.
00:19:29.120 --> 00:19:36.560
So the first thing you do is you add table one, you add the first table, and then you add table two, which is the second table.
00:19:36.960 --> 00:19:39.460
And then you add a widget on the sidebar.
00:19:39.460 --> 00:19:44.340
You just click on add button and then it just places a button on the screen for you.
00:19:44.340 --> 00:19:46.460
That will be sort of a shell of the application.
00:19:46.460 --> 00:19:48.700
It'll be just the UI part.
00:19:48.700 --> 00:19:50.980
At this point, it's just a few mouse clicks.
00:19:50.980 --> 00:19:54.080
There's no JavaScript code or Python code that you're writing.
00:19:54.340 --> 00:19:57.960
The next step is to add the sort of the logic behind the scenes.
00:19:57.960 --> 00:20:03.580
The first thing we need to do is to populate the first table with data about your workspaces.
00:20:03.580 --> 00:20:08.920
And essentially what we do is you click on create new, you create a new function.
00:20:09.340 --> 00:20:12.740
And in that function, it could be a SQL function or a Python function.
00:20:12.740 --> 00:20:16.780
Because that's just a table, you can just create a new SQL function.
00:20:16.780 --> 00:20:21.920
So you do create a new function, select everything from workspaces, let's say that's the table.
00:20:21.920 --> 00:20:26.600
And then you can see a little preview of what that select statement will result in.
00:20:26.600 --> 00:20:29.120
So you can verify that that's the data that you want to show.
00:20:29.120 --> 00:20:34.760
Once you've done that, you just save that file, that query, and you do something we call binding.
00:20:34.760 --> 00:20:40.120
So in the UI, you can select table one, and it'll present you with the table's properties.
00:20:40.120 --> 00:20:46.080
And one of the properties is which SQL file, which SQL script it's bound to.
00:20:46.080 --> 00:20:51.040
So you just click bind to the SQL file that you just wrote, and then it just automatically
00:20:51.040 --> 00:20:53.720
populates it with data for your workspace.
00:20:53.720 --> 00:20:59.680
Now, the second table is a little bit more interesting because the second table will update
00:20:59.680 --> 00:21:02.620
depending on what row you've selected in the first table.
00:21:02.620 --> 00:21:07.200
When you click on a workspace in the first table, it should load all of the users that
00:21:07.200 --> 00:21:08.940
are part of a particular workspace.
00:21:08.940 --> 00:21:14.660
And so we do this, we have a feature called dependent tables, and that's exactly what it
00:21:14.660 --> 00:21:14.820
does.
00:21:14.820 --> 00:21:19.160
So for the second table, you would still write a SQL query, and the query would just say,
00:21:19.160 --> 00:21:27.620
select everything from users where the workspace ID is the selected row workspace ID from the
00:21:27.620 --> 00:21:28.140
first table.
00:21:28.140 --> 00:21:32.380
And we used to sort of a Jinja, I'm not sure, maybe the audience will be familiar with Jinja,
00:21:32.380 --> 00:21:37.640
it's sort of like Jinja templating style where you say, select everything from users where
00:21:37.640 --> 00:21:41.520
workspace ID is double curly brace.
00:21:41.520 --> 00:21:43.720
And then we have something called state.
00:21:43.720 --> 00:21:48.520
State basically gives you the state of the UI at any point in time when you've clicked something.
00:21:48.520 --> 00:21:50.880
And it's really, we made it into a class.
00:21:50.880 --> 00:21:56.020
So you can say state.tables.table1.workspaceID.
00:21:56.240 --> 00:22:01.720
We resolve that into the value that's the workspace ID from the first table.
00:22:01.720 --> 00:22:03.620
And so that's, and then you do the same thing.
00:22:03.620 --> 00:22:07.060
You save that SQL query, you bind it to the second table.
00:22:07.060 --> 00:22:12.340
And then we automatically infer that whenever you need, whenever you select a different row
00:22:12.340 --> 00:22:17.960
in the first table, the second table will update the workspace ID value, rerun the
query,
00:22:17.960 --> 00:22:19.420
and then show you the data for it.
00:22:19.500 --> 00:22:19.740
That's cool.
00:22:19.740 --> 00:22:21.100
I was wondering how that happened.
00:22:21.100 --> 00:22:26.080
I thought you must have to wire some on change event, clicks over here, then it triggers that.
00:22:26.080 --> 00:22:27.720
But you just have that all automatic, right?
00:22:27.720 --> 00:22:31.360
The UI actually knows that which tables are related.
00:22:31.360 --> 00:22:37.780
The UI sends a payload to the backend saying, this table was clicked and this other table is related
00:22:37.780 --> 00:22:38.180
to it.
00:22:38.180 --> 00:22:41.700
And so we kind of know that we need to process those again.
00:22:42.040 --> 00:22:49.060
And so that's how we do this dependent table for the getting the value of the workspace ID in the
00:22:49.060 --> 00:22:49.700
first table.
00:22:49.700 --> 00:22:56.560
We basically, we resolve the sort of the variables in the backend and then pass the value so that
00:22:56.560 --> 00:22:57.680
we can update the query.
00:22:57.680 --> 00:23:00.160
So let's say that you stop at that point, right?
00:23:00.160 --> 00:23:01.960
And then you say preview the app.
00:23:01.960 --> 00:23:07.860
The app would look like two tables where it's really just lets you see all the users for each
00:23:07.860 --> 00:23:10.860
workspace that you have in your database.
00:23:10.860 --> 00:23:16.440
And then a few more things to make that very useful is you might want to search for a workspace
00:23:16.440 --> 00:23:18.740
before you know who to support.
00:23:18.740 --> 00:23:22.260
So let's say each workspace is associated with one of your customers.
00:23:22.260 --> 00:23:27.180
So let's say company A is your customer and company A gives you a call, a support call and
00:23:27.180 --> 00:23:31.160
says, hey, can you make John in our company an admin?
00:23:31.160 --> 00:23:35.180
So the first thing you want to do is you want to find, you search for company A and
00:23:35.180 --> 00:23:35.920
then find John.
00:23:35.920 --> 00:23:40.520
So we have this nice feature that basically automatically creates searches for you.
00:23:40.520 --> 00:23:46.080
So let's say in the first table, you can click on a button to convert it to a smart table.
00:23:46.080 --> 00:23:50.700
And when you do that, we basically generate filters for you.
00:23:50.700 --> 00:23:56.360
So you can then just say, I'd like to search by company name and you can select the filter
00:23:56.360 --> 00:23:58.760
and you can pin the filter into the table.
00:23:58.760 --> 00:24:01.600
And that automatically performs the search for you.
00:24:01.600 --> 00:24:03.280
So it's just pretty neat that way.
00:24:03.440 --> 00:24:05.780
It reminds me a little bit of Notion, Notion tables.
00:24:05.780 --> 00:24:07.180
I don't know if you play with Notion any.
00:24:07.180 --> 00:24:07.620
Yes.
00:24:07.620 --> 00:24:11.560
You know, you have got those pinned swords and
those pinned filters and different things
00:24:11.560 --> 00:24:14.840
you can kind of put at the top of the, I guess their databases are called in Notion.
00:24:14.840 --> 00:24:16.080
A little like that.
00:24:16.160 --> 00:24:21.640
It's very similar to that in the sense that you're not writing any code to be able to search
00:24:21.640 --> 00:24:26.760
through tables, but you can still modify what you let people search by pinning certain filters.
00:24:26.760 --> 00:24:34.120
The really interesting thing that we've done here is that we let you do joins and still provide
00:24:34.120 --> 00:24:34.820
you that feature.
00:24:34.940 --> 00:24:39.300
So in Notion, for example, you would just have one database and you can filter and sort
00:24:39.300 --> 00:24:40.180
that database.
00:24:40.180 --> 00:24:45.560
With DropBase, what we have is, let's say you have a table called users and a table called
00:24:45.560 --> 00:24:46.180
roles.
00:24:46.180 --> 00:24:53.960
And then they're related by an ID where, let's say, ID 1 is users, ID 2 is developers, ID 3 is
00:24:53.960 --> 00:24:54.400
admins.
00:24:54.400 --> 00:24:54.700
Yeah.
00:24:54.740 --> 00:24:56.600
You might have to join those two tables first.
00:24:56.600 --> 00:25:02.260
And so that same smart table feature, you can just write that SQL statement, that join
00:25:02.260 --> 00:25:06.440
statements, and we can still generate sort of the right filters for you.
00:25:06.440 --> 00:25:08.920
And we'll actually let you edit those tables as well.
00:25:08.920 --> 00:25:15.760
What we do is we take your SQL statement and then we infer all the SQL required to search
00:25:15.760 --> 00:25:18.840
or edit any column within the SQL statement.
00:25:18.840 --> 00:25:19.500
That sounds awesome.
00:25:19.500 --> 00:25:25.260
That's a really neat feature, especially for the people who are used to using something
00:25:25.260 --> 00:25:31.580
like Django admin in the sense that it helps you very quickly build an admin panel with very
00:25:31.580 --> 00:25:33.380
little developer work.
00:25:33.380 --> 00:25:33.660
Yeah.
00:25:33.660 --> 00:25:36.640
You can just write a SQL statement and then we give you an admin panel.
00:25:36.640 --> 00:25:36.940
Yeah.
00:25:36.940 --> 00:25:37.860
So that's really neat.
00:25:37.860 --> 00:25:42.260
The final thing with the app here in the demo is the little button on the right side.
00:25:42.260 --> 00:25:42.500
Yeah.
00:25:42.500 --> 00:25:44.020
That is a Python function.
00:25:44.020 --> 00:25:52.220
So you create a new Python function and you essentially write a database update to update
00:25:52.220 --> 00:25:56.580
the role from whatever it was, let's say from developer to an admin.
00:25:56.580 --> 00:26:03.300
So it's just really a select statement, update, table, set, column, something on this particular
00:26:03.300 --> 00:26:03.620
ID.
00:26:03.620 --> 00:26:05.300
And so that's just a Python function.
00:26:05.300 --> 00:26:10.040
And the final thing is just to connect that button to run this Python function.
00:26:10.040 --> 00:26:14.880
You click on the button, we run the function, and then we perform a database update to update
00:26:14.880 --> 00:26:16.600
the role to whichever role you want.
00:26:16.600 --> 00:26:19.440
And that really is just the gist of the demo.
00:26:19.440 --> 00:26:22.820
So a couple of things about that Python function that's pretty interesting.
00:26:22.820 --> 00:26:25.880
When you create it, you can say, I want to create a function and it says, do you want SQL
00:26:25.880 --> 00:26:28.680
or do you want Python, which is pretty interesting.
00:26:28.680 --> 00:26:32.460
The Python function has access to the UI widgets.
00:26:32.460 --> 00:26:37.540
Like in the actual video, not the screenshot of the video, I think you've got a dropdown select
00:26:37.540 --> 00:26:38.220
box.
00:26:38.220 --> 00:26:41.680
And so the Python function go, well, what did the user select?
00:26:41.680 --> 00:26:45.720
And then we'll make the change to the person in the workspace along those lines.
00:26:45.720 --> 00:26:47.700
So that's pretty cool, right?
00:26:47.700 --> 00:26:51.600
That you interact with this UI in kind of an object-oriented way, I suppose.
00:26:51.600 --> 00:26:53.320
That's exactly how it works.
00:26:53.320 --> 00:26:56.360
So behind the scenes, we have two classes.
00:26:56.360 --> 00:26:59.300
One is called state and one is called context.
00:26:59.500 --> 00:27:06.000
So the state class just lets us access all of the UI state at any point in time.
00:27:06.000 --> 00:27:12.300
Anything you enter in an input component or any row you select in the tables, you can see
00:27:12.300 --> 00:27:14.860
the currently selected values of it.
00:27:14.860 --> 00:27:22.400
And so whenever you click on a button or you perform an action, that state is passed to the
00:27:22.400 --> 00:27:24.800
backend just as a payload, just like a dictionary.
00:27:25.180 --> 00:27:31.300
And the backend, we generate all the classes, all the objects related to state and context.
00:27:31.300 --> 00:27:36.560
So we just have to pass the values in and then execute the function with those values as the
00:27:36.560 --> 00:27:36.860
input.
00:27:36.860 --> 00:27:40.760
And so that's how we're able to do the state thing with Python.
00:27:41.080 --> 00:27:45.560
If you've seen how you would do it in Python, it is very much a dot notation, right?
00:27:45.560 --> 00:27:52.040
So you would say to get the value of column one in table one, you basically just say state dot
00:27:52.040 --> 00:27:57.380
tables, which gives you all the tables, dot table one, dot column one.
00:27:57.380 --> 00:28:04.860
And that basically resolves into the value of the table, of the row in that table for that column.
00:28:05.000 --> 00:28:05.500
Yeah, that's cool.
00:28:05.500 --> 00:28:08.240
I can imagine the implementation of that thing.
00:28:08.240 --> 00:28:11.120
It's like dot, dot, dot, dot, git
adder.
00:28:11.120 --> 00:28:15.140
And if you ask for the thing, you look in the dictionary and you traverse the thing.
00:28:15.140 --> 00:28:23.200
But with that in mind, what I thought was really nice about this is you had pretty decent autocomplete in your little embedded Python editor.
00:28:23.200 --> 00:28:24.000
How did you pull that off?
00:28:24.000 --> 00:28:24.700
I did that you noticed.
00:28:24.700 --> 00:28:25.080
Yeah.
00:28:25.080 --> 00:28:26.720
We spent a lot of time on it.
00:28:26.720 --> 00:28:28.040
I bet you did.
00:28:28.040 --> 00:28:28.400
Yeah.
00:28:28.480 --> 00:28:28.900
How's that work?
00:28:28.900 --> 00:28:32.560
When we were designing this, we were thinking, damn, VS Code is really nice.
00:28:32.560 --> 00:28:36.120
You have all the plugins, all the autocomplete and everything.
00:28:36.120 --> 00:28:38.200
But we had two choices, right?
00:28:38.200 --> 00:28:47.760
Either we build this whole UI builder into VS Code, or we kind of take some of the things that make VS Code great and then bring it into the DropAce Studio.
00:28:47.760 --> 00:28:50.960
We don't know sort of the final eventually where this will be.
00:28:51.300 --> 00:29:05.840
But the current version of this is we thought, you know what, I think we need to give users an editor, like a built-in editor, so they can just quickly, they can have the best experience building the app and the access to UI and context and state really quickly.
00:29:05.840 --> 00:29:12.260
We just did it that way where we added in LSP, so like a language server.
00:29:12.260 --> 00:29:23.040
So anytime you type code in your Python function, it's basically over a WebSocket connection, basically streaming the code changes and saving them in your file system.
00:29:23.040 --> 00:29:28.960
That's the only way we can do this, this like object-oriented Python dot notation access.
00:29:28.960 --> 00:29:32.260
And so we need to have access to all the files.
00:29:32.260 --> 00:29:41.000
And so we set this up so that not only you can do autocomplete, but also that we can actually do the state and context approach to the web framework.
00:29:41.000 --> 00:29:45.980
It was a bit complicated because we hadn't been really exposed to LSPs before.
00:29:45.980 --> 00:29:53.100
And so we had to learn how to use LSPs, and we had to sort of hijack sort of the WebSocket connection in a way.
00:29:53.100 --> 00:29:56.460
So like we intercept the code, and then we save it in your file system.
00:29:56.460 --> 00:29:59.220
So we had to customize it a little bit to do this.
00:29:59.220 --> 00:30:03.000
And it's really nice because now you can do autocomplete for your files.
00:30:03.000 --> 00:30:04.100
It's just a need.
00:30:04.100 --> 00:30:05.880
It's so hard to develop now.
00:30:05.880 --> 00:30:07.360
We're so used to these tools.
00:30:07.360 --> 00:30:12.780
And now with things like Copilot, like we're used to even more than just autocomplete, right?
00:30:12.780 --> 00:30:16.380
It's like autocomplete the function, not just the variable, right?
00:30:16.380 --> 00:30:21.640
I feel like autocomplete is just table stakes, you know, especially in this kind of thing.
00:30:21.700 --> 00:30:28.020
There's somebody who's just done Python forever, and they'd rather get it out of the way, and it's fine.
00:30:28.020 --> 00:30:31.300
It's not my way of working, but it's fine for people who want to do that.
00:30:31.300 --> 00:30:40.800
But if you're working with somebody who might not be a full-time developer, but they want to use your framework, your service to build some app, it seems like this could really empower them.
00:30:41.060 --> 00:30:46.040
But if you give them something with zero autocomplete, zero highlighting, you're going to be having a rough time, you know?
00:30:46.040 --> 00:30:50.580
Yeah, even for a more experienced developer, I think it's still a hard time.
00:30:50.580 --> 00:30:53.620
Even if you can do it, it's just less productive to go like, oh, yeah.
00:30:53.620 --> 00:30:54.580
Way less productive.
00:30:54.780 --> 00:30:55.880
Yeah, way less productive.
00:30:55.880 --> 00:31:03.660
I think AI gets added to apps a lot just to kind of check a box, but the result of it is not that great.
00:31:03.660 --> 00:31:11.340
To get on my email client that has AI integrated, but it almost always seems like, well, that's not something I'd, yeah, something I want to read.
00:31:11.340 --> 00:31:14.460
Like, I don't really want to read that, and I don't need to summarize it.
00:31:14.460 --> 00:31:15.760
It's not emails, you know?
00:31:15.760 --> 00:31:19.420
It just seems like a lot of energy goes into it when it's not that big of a value.
00:31:19.420 --> 00:31:22.040
But maybe something like Copilot could be here.
00:31:22.040 --> 00:31:24.660
This is something we've talked about, me and my co-founder.
00:31:24.660 --> 00:31:37.300
So one of the things that we didn't get to cover, because we're not going to go through all the demos, but the way that we render data in these tables is we basically format it as a pandas data frame.
00:31:37.300 --> 00:31:37.540
Okay.
00:31:37.540 --> 00:31:43.500
So what that means is that, let's say that you query data from Stripe, right?
00:31:43.500 --> 00:31:46.060
Like you get all your customers from Stripe.
00:31:46.060 --> 00:31:48.020
Stripe is not going to return a data frame for you.
00:31:48.020 --> 00:31:50.380
It's going to return like an object, right?
00:31:50.380 --> 00:31:51.000
A dictionary.
00:31:51.480 --> 00:31:56.000
And then you basically have to take that dictionary and then basically convert it into a data frame.
00:31:56.000 --> 00:31:58.400
And then we automatically know how to render everything else from there.
00:31:58.400 --> 00:31:59.740
So we've thought about this.
00:31:59.740 --> 00:32:13.700
And like, wouldn't it be cool if as soon as you get the response from an endpoint, let's say as a JSON dictionary, that we suggest that we can just take it
at next step for you, which is just to like convert it into a data frame.
00:32:13.700 --> 00:32:15.560
And then you wouldn't have to hustle with it.
00:32:15.560 --> 00:32:15.720
Yeah.
00:32:15.720 --> 00:32:16.440
We've done that with it.
00:32:16.440 --> 00:32:18.780
But in theory, that sounds very, very helpful.
00:32:19.140 --> 00:32:22.920
If you're proficient in pandas and using data frames,
00:32:22.920 --> 00:32:24.360
it's actually not that hard.
00:32:24.360 --> 00:32:25.880
It's a very quick thing for you.
00:32:25.880 --> 00:32:28.720
But if you just know Python but not exposed
00:32:28.720 --> 00:32:32.240
to the whole data frame ecosystem,
00:32:32.240 --> 00:32:35.100
then maybe it would be really nice if you just said, OK,
00:32:35.100 --> 00:32:36.740
we just started to data frame for you,
00:32:36.740 --> 00:32:38.660
and then that's all you have to care about.
00:32:38.660 --> 00:32:39.580
So we've thought about this.
00:32:39.580 --> 00:32:40.560
We haven't added this yet.
00:32:40.560 --> 00:32:41.860
MARK MANDEL: I think it's fine without.
00:32:41.860 --> 00:32:43.320
But it's kind of one of those things,
00:32:43.320 --> 00:32:45.420
like you're in there, and you've got these data sources,
00:32:45.420 --> 00:32:47.080
and maybe you're not super familiar with them.
00:32:47.080 --> 00:32:48.700
Maybe you can pull them together somehow.
00:32:48.700 --> 00:32:50.940
One of the things that I find myself struggling with
00:32:50.940 --> 00:32:52.760
is, let's say I want to build a demo.
00:32:52.760 --> 00:32:56.200
Let's say I haven't been exposed to the SendGrid API
00:32:56.200 --> 00:32:57.780
or the HubSpot API.
00:32:57.780 --> 00:33:00.820
Then I have to go to their documentation
00:33:00.820 --> 00:33:05.340
to figure out what's the package name so I can install it.
00:33:05.340 --> 00:33:06.960
How do I authenticate in?
00:33:06.960 --> 00:33:09.740
How do I call a few endpoints to do what I need to do?
00:33:09.740 --> 00:33:11.380
And I think in that case where it's
00:33:11.380 --> 00:33:13.360
not about your knowledge of Python,
00:33:13.360 --> 00:33:16.220
it really is about your knowledge of this other thing
00:33:16.220 --> 00:33:17.260
that you're using.
00:33:17.260 --> 00:33:21.600
In those cases, it seems that it could be extremely helpful for someone to build apps very quickly
00:33:21.600 --> 00:33:27.640
if they somehow had access to either quick documentation or you just suggested what you might want to do.
00:33:27.640 --> 00:33:29.500
MARK MANDEL: Yeah, that's kind of what I was thinking as well.
00:33:29.500 --> 00:33:35.840
If you're a regular listener of the podcast, you surely heard about Talk Python's online courses.
00:33:35.840 --> 00:33:37.840
But have you had a chance to try them out?
00:33:37.840 --> 00:33:41.740
No matter the level you're looking for, we have a course for you.
00:33:41.740 --> 00:33:48.080
Our Python for Absolute Beginners is like an introduction to Python plus that first year computer science course that you never took.
00:33:48.080 --> 00:33:54.860
Our data-driven web app courses build a full PyPI.org clone along with you right on the screen.
00:33:54.860 --> 00:33:58.080
And we even have a few courses to dip your toe in with.
00:33:58.080 --> 00:34:03.120
See what we have to offer at training.talkpython.fm or just click the link in your podcast player.
00:34:03.120 --> 00:34:09.460
MARK MANDEL: So speaking of that sort of external resources, you've got this Python function.
00:34:09.460 --> 00:34:10.960
And what can I put in there?
00:34:10.960 --> 00:34:12.960
Can I use external packages?
00:34:12.960 --> 00:34:18.160
Can I call out on the network to talk to some API endpoints?
00:34:18.160 --> 00:34:19.460
Can I spin up threads?
00:34:19.460 --> 00:34:21.380
Like what can I do?
00:34:21.380 --> 00:34:23.000
How much Python can I do there?
00:34:23.000 --> 00:34:24.440
MARK MANDEL: Pretty much all of the above.
00:34:24.440 --> 00:34:26.400
MARK MANDEL: So I'll elaborate what I mean by that.
00:34:26.400 --> 00:34:34.780
So the standard way that you would connect to some of these services, these third party services, is you'll make like an HTTP request.
00:34:34.780 --> 00:34:36.660
Like get requests, post requests.
00:34:36.660 --> 00:34:39.720
So you can just like import requests, basically.
00:34:39.720 --> 00:34:44.900
PIP install requests and then just do it over the standard Python, basically Python package.
00:34:44.900 --> 00:34:50.300
Now, it is way more convenient when you use an SDK provided by one of these third parties.
00:34:50.300 --> 00:34:54.300
So if you want to use Stripe, if you're able to just import Stripe, it'll make your life
00:34:54.300 --> 00:34:58.340
a lot easier, very nicely, Pythonic, everything set up.
00:34:58.340 --> 00:35:03.480
So in DropBase, you can install anything that you can install via PyPI.
00:35:03.480 --> 00:35:06.880
We have a file called custom requirements.
00:35:06.880 --> 00:35:12.620
And if you just list them out, when you set up DropBase, we'll basically install all those for you.
00:35:12.620 --> 00:35:17.620
And then when you write a function, you can just basically import Stripe directly in the function
00:35:17.620 --> 00:35:20.920
without pip installing it again, and then you just use it.
00:35:20.920 --> 00:35:22.120
So that's really nice.
00:35:22.120 --> 00:35:23.000
But basically anything.
00:35:23.000 --> 00:35:25.540
I think you were doing a previous uv.
00:35:25.540 --> 00:35:26.040
You were talking.
00:35:26.040 --> 00:35:27.040
Yeah, yeah.
00:35:27.040 --> 00:35:29.040
I was talking to Charlie Marsh about uv earlier today.
00:35:29.040 --> 00:35:29.040
Yeah.
00:35:29.040 --> 00:35:30.800
We haven't looked into it yet.
00:35:30.800 --> 00:35:36.920
But anything you can pip install from PyPI, you can install in DropBase, which makes it really,
00:35:36.920 --> 00:35:37.720
really powerful.
00:35:37.720 --> 00:35:38.280
Yeah, nice.
00:35:38.280 --> 00:35:39.560
There's a database connections.
00:35:39.560 --> 00:35:42.920
I mean, you could use SQLAlchemy or you can import whatever else you want.
00:35:42.920 --> 00:35:48.520
But we make those a bit more native because we know that you're going to connect to databases.
00:35:48.520 --> 00:35:50.760
So we want to make it a bit more convenient.
00:35:50.760 --> 00:35:51.560
So.
00:35:51.560 --> 00:35:55.420
And your tables need sort of direct access to it as well, right?
00:35:55.420 --> 00:36:01.220
Not just the output of some access to the database, but you've got to figure out the columns and all that kind of stuff, right?
00:36:01.220 --> 00:36:01.760
That's correct.
00:36:01.760 --> 00:36:11.140
So we created a little library, like a utility slash helper that lets you perform database operations very quickly.
00:36:11.140 --> 00:36:22.700
So if you've added your database credentials to the .env file, then you can quickly perform, you know, like a select statement or, you know, make an update to that database via functions.
00:36:22.700 --> 00:36:32.380
But without, you know, the standard thing where you do, if you use SQLAlchemy, for example, where you like start a session, start a connection, you know, like all those steps, we kind of abstract that for you.
00:36:32.380 --> 00:36:37.480
But you can totally use SQLAlchemy in its full glory if you, you know, if that's what you're used to.
00:36:37.600 --> 00:36:43.560
Nice. Can I write Python files, like separate Python scripts and stuff, and then just import and call them from there?
00:36:43.560 --> 00:36:45.080
Or does it have to be done through the UI?
00:36:45.080 --> 00:36:45.400
Totally.
00:36:45.400 --> 00:36:45.700
Yeah.
00:36:45.700 --> 00:36:57.960
There's actually one of the biggest advantages of DropBase is that if you have like a Python script lying around and you want to sort of use it in DropBase, you can add it to that file system somewhere in the workspace directory.
00:36:57.960 --> 00:37:01.080
And you can just import it in via your function.
00:37:01.080 --> 00:37:06.320
So you just like from your file, you can import a specific function in that file, for example.
00:37:06.580 --> 00:37:14.460
And so the implication of this is that you can set up DropBase in a way that it just lives in your existing Python code base.
00:37:14.460 --> 00:37:20.820
So imagine you're already, you know, you've set up your company, you've got product market fit, you know, things are running, right?
00:37:20.820 --> 00:37:22.140
And you have a Python backend.
00:37:22.140 --> 00:37:25.900
And now you're starting to scale and you need to build tools.
00:37:25.900 --> 00:37:29.460
So your first option would be to do all custom, obviously.
00:37:29.460 --> 00:37:33.260
The second option is to use some sort of tools builder.
00:37:33.340 --> 00:37:40.040
But every single action you take is done over an HTTP request with authentication, with everything.
00:37:40.040 --> 00:37:42.340
So just like a standard internet communication.
00:37:42.340 --> 00:37:54.400
But if you wanted to just interact with an existing functions or internal endpoints, then you'd have to either set up an RPC server or you might want to use some other way to get in there.
00:37:55.220 --> 00:38:00.340
DropBase, you basically just set up DropBase in the same directory as your app.
00:38:00.340 --> 00:38:03.540
And you can then import selectively what functions you need.
00:38:03.880 --> 00:38:14.060
It's sort of like a window into your code base that it's like a plug into that code base where you can now expand and build a lot of internal tools that leverages everything that you've already built.
00:38:14.060 --> 00:38:14.360
Yeah.
00:38:14.360 --> 00:38:15.320
That's it, by the way.
00:38:15.320 --> 00:38:15.720
Yeah.
00:38:15.720 --> 00:38:17.780
When you've got, yeah, there's the requirements at custom, right?
00:38:17.780 --> 00:38:20.360
So you've got your Docker compose file.
00:38:20.360 --> 00:38:28.140
I mean, could you set it up just so as you build, maybe even better, just set up a volume so that it can directly find.
00:38:28.140 --> 00:38:30.440
I mean, I guess that's what you're kind of showing right here, right?
00:38:30.440 --> 00:38:38.380
Is that you can sort of map, mount a volume just directly into, say, your Git repo for your big project code.
00:38:38.380 --> 00:38:40.800
And then you can just start importing that and doing stuff with it, right?
00:38:40.800 --> 00:38:44.740
We still need to do some tweaks because of the relative paths.
00:38:44.740 --> 00:38:48.400
But the idea is that you can do that with a little bit of customization.
00:38:48.400 --> 00:38:56.020
But yeah, our workspace server, basically, you mount files or directories, and then we can look into those to execute.
00:38:56.020 --> 00:38:58.260
Yeah, manage those files with Git or something like that.
00:38:58.260 --> 00:39:02.280
A good example of this is, are you familiar with Django and Django Admin?
00:39:02.280 --> 00:39:04.820
Not super, as I do every day, but I'm aware, sure.
00:39:04.820 --> 00:39:07.480
Django, it's a great web framework.
00:39:07.480 --> 00:39:08.580
It's used by a lot of companies.
00:39:08.580 --> 00:39:11.140
It's like, if you want to build web apps, you have Django.
00:39:11.140 --> 00:39:12.700
It comes with a lot of stuff, right?
00:39:12.700 --> 00:39:21.540
And there's this thing called Django Admin that basically automatically generates admin panels for you based on your Django models.
00:39:21.680 --> 00:39:25.740
And so if you have a model for a book, right?
00:39:25.740 --> 00:39:27.060
And the book has authors.
00:39:27.060 --> 00:39:29.940
It basically exposes that to the Django admin.
00:39:29.940 --> 00:39:33.800
And then now you can edit a book without really doing anything.
00:39:33.800 --> 00:39:35.360
It all kind of comes for free.
00:39:35.360 --> 00:39:36.220
It's pretty neat.
00:39:36.220 -->
00:39:38.640
I think that's half the appeal of Django right there.
00:39:38.640 --> 00:39:39.200
It is.
00:39:39.200 --> 00:39:41.220
Yeah, I think a lot of people use it for that.
00:39:41.220 --> 00:39:42.620
Yeah, they're like, I don't want to write that stuff.
00:39:42.620 --> 00:39:43.280
I'm using Django.
00:39:43.280 --> 00:39:44.180
Yeah, for real.
00:39:44.180 --> 00:39:44.860
And it's great.
00:39:44.860 --> 00:39:58.120
Now, at some point, when your company hits a certain milestone or a certain number of customers, you will need to customize those admin panels.
00:39:58.120 --> 00:40:03.860
You might need to create admin panels for things that maybe you don't have models for yet.
00:40:03.860 --> 00:40:10.980
Or for things that combine data from your database with data from like Stripe or some other source.
00:40:10.980 --> 00:40:20.940
And so what we see when we talk to these people is that they kind of struggle to like either do I like keep using this or do I like completely rebuild everything?
00:40:20.940 --> 00:40:29.860
For those users, when we talk to them about DropBase, they get very excited because with DropBase, you can install Django and it can sit in your file system.
00:40:29.860 --> 00:40:38.760
And so essentially all the models that you've already built in Django, you can basically call them via DropBase, with DropBase function because it's all Python, right?
00:40:38.920 --> 00:40:43.180
And so it gives you this like, okay, Django admins are great up to a certain point.
00:40:43.180 --> 00:40:45.100
And then after that, what happens, right?
00:40:45.100 --> 00:40:48.440
Like you might not want to rebuild everything just so you can have internal tooling.
00:40:48.440 --> 00:41:01.760
And so I think that's quite of a nice spot for us to say, look, DropBase can live in your code base, uses everything you already have, but it gives you some extra things if you want to build internal tools very quickly.
00:41:01.760 --> 00:41:04.720
So that's something we're obviously very, very excited about.
00:41:04.720 --> 00:41:05.380
That's really cool.
00:41:05.380 --> 00:41:06.620
I like that aspect of it.
00:41:06.880 --> 00:41:12.620
So when we talk about this code, I guess there's two scenarios, the cloud version or the self-hosted version.
00:41:12.620 --> 00:41:15.600
But where and how does this Python run?
00:41:15.600 --> 00:41:17.660
Is it, it must be full CPython?
00:41:17.660 --> 00:41:20.020
Is it running in isolated Docker containers?
00:41:20.020 --> 00:41:22.160
Or in your cloud, what happens?
00:41:22.160 --> 00:41:25.200
Is it functions like AWS functions, Lambda?
00:41:25.200 --> 00:41:30.180
It just runs either on your local machine, if you've set it up as a developer.
00:41:30.180 --> 00:41:31.240
It's all running there.
00:41:31.240 --> 00:41:34.340
Obviously, if you turn off your machine, you can use your apps.
00:41:34.340 --> 00:41:42.800
And then if you set it up in a production instance, let's say you deploy
this on an EC2, your Python functions are running on that EC2.
00:41:42.800 --> 00:41:46.440
But it's running via Docker container inside.
00:41:46.540 --> 00:41:49.700
So it gets a little isolation, a little bit of protection, that kind of stuff.
00:41:49.700 --> 00:41:54.360
And we're assuming that, I mean, you're building these apps to run on your own infrastructure.
00:41:54.360 --> 00:41:56.700
It's that you would, that you know what you're doing.
00:41:56.700 --> 00:42:15.900
So this is as opposed to us having a full cloud version where all customers run untrusted code in the same sort of backend system, which would be obviously very dangerous because I'm sure there's ways a customer can somehow, you know, go through the backend and access other customers' untrusted code.
00:42:15.900 --> 00:42:17.040
And that would be a nightmare.
00:42:17.040 --> 00:42:22.740
And so if, you know, we have isolation, first layer is, well, it's in your infrastructure you're going to do.
00:42:22.740 --> 00:42:24.480
It's just your company's code.
00:42:24.480 --> 00:42:29.780
But then further, you know, we run Python in containers in that instance.
00:42:29.780 --> 00:42:33.200
That sounds more like a durability thing than anything.
00:42:33.200 --> 00:42:35.440
I mean, it is also for isolation protection.
00:42:35.440 --> 00:42:40.580
But first and foremost, just don't let bad Python code take down the whole thing, you know?
00:42:40.580 --> 00:42:52.080
The way we recommend people using DropBase or setting up their dev sort of process with DropBase is that they would clone, basically fork the for DropBase.
00:42:52.080 --> 00:42:53.740
And then they will develop locally.
00:42:54.120 --> 00:42:55.320
They will test changes.
00:42:55.320 --> 00:43:00.120
And once they're happy with the new code, you know, they'll push it back.
00:43:00.120 --> 00:43:03.640
And then they will have CI/CD into the production instance.
00:43:03.640 --> 00:43:05.460
And then they can version control everything.
00:43:05.460 --> 00:43:11.340
So that also gives you that extra layer of, okay, let's make sure that whatever we're pushing is tested.
00:43:11.340 --> 00:43:19.360
You can always add test databases that you develop locally with before you push the production, where it's going to have to act on your production data.
00:43:19.460 --> 00:43:20.500
Yeah, that's pretty interesting.
00:43:20.500 --> 00:43:22.960
I like the version control aspect of it.
00:43:23.020 --> 00:43:31.900
That gives it a much nicer touch to connection to real software rather than just it's a text input area in an app that who knows what happens.
00:43:31.900 --> 00:43:34.740
As developers, it sometimes feels a bit scary, right?
00:43:34.740 --> 00:43:39.500
Like you're building something and it's in this other framework and this other cloud.
00:43:39.500 --> 00:43:45.400
And it just feels like you can't kind of get, like if the thing goes away, like you can't even see your previous code.
00:43:45.400
--> 00:43:57.740
That was another key concept that we wanted to have is in this tool that it feels friendly for developers, that it matches your mental models and your sort of like your development process, let's call it.
00:43:57.740 --> 00:44:04.140
Like how you're used to making apps or developing code, that we keep that feeling when you're building apps for a trial phase.
00:44:04.140 --> 00:44:09.700
I want to maybe have a PR to understand if we accept this change to it, right?
00:44:09.700 --> 00:44:10.240
That's right.
00:44:10.240 --> 00:44:10.480
Yeah.
00:44:10.560 --> 00:44:10.720
Yeah.
00:44:10.720 --> 00:44:14.000
You don't normally hear that kind of stuff around these kind of tools, you know?
00:44:14.000 --> 00:44:26.280
And if you do, I think it tends to be like, yeah, okay, it's like a huge enterprise contract, you know, pay us $50,000 a year and then you get version control, which to me, it sounds scary.
00:44:26.280 --> 00:44:28.600
I mean, it just, it will make me a little bit less comfortable.
00:44:28.600 --> 00:44:35.560
Now, obviously, if I'm a big company and I just really need the tool, sure, maybe I'll just pay for it and I get version control.
00:44:35.560 --> 00:44:42.260
But, you know, getting version control, it just feels so like, like table stakes for developers, especially today.
00:44:42.260 --> 00:44:44.900
But yeah, it just wouldn't make sense otherwise for us.
00:44:44.900 --> 00:44:46.420
I mean, it's the way we're approaching this product.
00:44:46.420 --> 00:44:46.700
Yeah.
00:44:46.700 --> 00:44:49.640
Well, the other aspect is, you know, what are you version controlling?
00:44:49.640 --> 00:44:56.920
You know, do you end up with, you know, something like effectively a Jupyter Notebook, like big blob of something.
00:44:56.920 --> 00:45:00.140
And then there's an older blob of something and then you diff it.
00:45:00.140 --> 00:45:01.000
You're like, what is this?
00:45:01.000 --> 00:45:05.320
But since you end up with just these, you know, your workspace files that just live there, right?
00:45:05.320 --> 00:45:08.060
It's a real optimized, like, show me the changes.
00:45:08.060 --> 00:45:09.060
Show me what's happened here.
00:45:09.060 --> 00:45:09.420
Yeah.
00:45:09.420 --> 00:45:13.500
It all lives there, including the component properties.
00:45:13.500 --> 00:45:18.420
Like we don't store this in like a separate database or anything like that.
00:45:18.420 --> 00:45:24.480
So like, you know, like for some of their tools, they will store all the components in their database.
00:45:24.480 --> 00:45:36.380
And so what they do is, you know, when you load up their tools, like their tools builder, it'll fetch all the components from the provider's database, combine it with maybe your custom code, and then it'll do it.
00:45:36.380 --> 00:45:40.940
And so even that feels like, okay, but where's like config for my components?
00:45:40.940 --> 00:45:41.300
Yeah.
00:45:41.300 --> 00:45:42.240
Where'd this button come from?
00:45:42.240 --> 00:45:43.080
Why is it gone?
00:45:43.080 --> 00:45:43.660
That's tough.
00:45:43.660 --> 00:45:44.040
Yeah.
00:45:44.040 --> 00:45:44.420
That's tough.
00:45:44.420 --> 00:45:50.060
And then like, imagine if you wanted to like share their apps or, you know, it's just like version control makes a bit less sense.
00:45:50.060 --> 00:46:00.020
I mean, you're just version controlling, just like the individual functions, maybe like the custom part of the code that you write, which is still useful, but it still feels like you don't have the full picture of what's happening.
00:46:00.020 --> 00:46:00.340
Yeah.
00:46:00.340 --> 00:46:01.800
You don't have a full record.
00:46:01.800 --> 00:46:03.240
It could easily get out of sync.
00:46:03.240 --> 00:46:03.540
Yeah.
00:46:03.540 --> 00:46:04.260
Quite interesting.
00:46:04.260 --> 00:46:15.040
I guess one thing we touched on a little bit before I press go here in the show, you said that at one point you were considering using Jupyter in this whole mechanism.
00:46:15.040 --> 00:46:15.780
Yeah.
00:46:15.780 --> 00:46:17.340
What's the story around that?
00:46:17.340 --> 00:46:18.320
We love Jupyter.
00:46:18.320 --> 00:46:19.680
We love notebooks.
00:46:19.680 --> 00:46:21.600
And we love the experience of them.
00:46:21.600 --> 00:46:30.120
The sense that you can write some code and you can quickly test and execute the code without, basically without, without needing to write anything else.
00:46:30.120 --> 00:46:33.660
So for prototyping, for getting quick feedback, it's great.
00:46:33.660 --> 00:46:41.160
And we wanted to give our developers something like that, because when you build these apps, you're kind of iterating, right?
00:46:41.160 --> 00:46:42.180
You're like, you're testing it.
00:46:42.180 --> 00:46:48.100
A lot of times you don't even know the documentation for Drive or HubSpot or, and so like there's a lot of experimentation.
00:46:48.680 --> 00:46:50.720
And so we wanted a quick way to do that.
00:46:50.720 --> 00:46:58.520
So we considered maybe having something like a Jupyter kernel within DropBase that allowed people to do it.
00:46:58.520 --> 00:47:05.180
There were some issues with it in the sense that the kernel actually stores results from like previous blocks.
00:47:05.760 --> 00:47:10.320
And sometimes that gets in the way of you triggering an action in a later block.
00:47:10.320 --> 00:47:14.480
And so we were like, okay, maybe that's a little bit more than we need.
00:47:14.480 --> 00:47:17.480
Now, we still kind of eventually want something like that.
00:47:17.480 --> 00:47:18.660
We hacked it in a way.
00:47:18.660 --> 00:47:22.360
Like, so the way that we do it is you can write a Python function.
00:47:22.360 --> 00:47:23.820
You basically get one block.
00:47:23.820 --> 00:47:30.200
You can write a Python function and you can click on a play button to basically run that function.
00:47:30.360 --> 00:47:32.000
But it's not like a
kernel.
00:47:32.000 --> 00:47:36.200
So what we do is behind the scenes, we have like a main function.
00:47:36.200 --> 00:47:41.120
And when you trigger that function, we take the state from the client.
00:47:41.120 --> 00:47:46.520
So whatever you've selected or input it, we take the underlying file for your Python function.
00:47:46.520 --> 00:47:48.200
And then we call it from me.
00:47:48.200 --> 00:47:54.180
And so we kind of simulate that experience of like instantly testing code that you just wrote.
00:47:54.180 --> 00:47:57.760
But there is no Jupyter kernel behind the scenes.
00:47:57.760 --> 00:47:59.960
And then you can only do one block at a time.
00:47:59.960 --> 00:48:04.700
And so we said, okay, for now, as we're getting started with it, it's good enough.
00:48:04.700 --> 00:48:05.740
You can write your functions.
00:48:05.740 --> 00:48:08.820
You can run and test them immediately, which is really nice.
00:48:08.820 --> 00:48:10.440
You can do this with VS Code, by the way.
00:48:10.440 --> 00:48:13.460
Like you would have to open up the terminal and then basically run your function.
00:48:13.840 --> 00:48:19.940
And so we still wanted this feature where you can click and just see your outputs and basically debug and troubleshoot.
00:48:19.940 --> 00:48:23.860
But it would be really nice if you could get out multiple blocks and you can just build functions that way.
00:48:23.860 --> 00:48:25.200
So maybe for the future.
00:48:25.200 --> 00:48:25.700
Interesting.
00:48:25.700 --> 00:48:29.120
Did you say that you were a core developer for Jupyter?
00:48:29.120 --> 00:48:29.920
No, no.
00:48:29.920 --> 00:48:31.180
I just spoke to them.
00:48:31.180 --> 00:48:32.620
It sounds fun.
00:48:32.700 --> 00:48:34.900
I interviewed a whole bunch of them recently.
00:48:34.900 --> 00:48:41.180
And what I thought was interesting is Jupyter is such an empowering thing for Python developers.
00:48:41.180 --> 00:48:53.000
But many of the core developers are so focused on writing JavaScript and TypeScript to sort of make these interactions possible so that the rest of us don't have to write JavaScript and that kind of stuff.
00:48:53.000 --> 00:48:55.420
So I think we're getting about to the end of our time here.
00:48:56.220 --> 00:48:58.960
I'm sure that actually this is somewhat similar.
00:48:58.960 --> 00:49:01.920
It's really a dynamic interactive web app.
00:49:01.920 --> 00:49:05.960
And in that case, it probably has to have some interesting front end JavaScript stuff going on.
00:49:05.960 --> 00:49:07.420
What's the JavaScript story?
00:49:07.420 --> 00:49:07.960
Yeah.
00:49:07.960 --> 00:49:09.440
What framework are you using and stuff like that?
00:49:09.440 --> 00:49:12.220
We just react to build our components.
00:49:12.220 --> 00:49:18.360
Obviously, we abstract that away so that you as a Python developer, you're just writing Python.
00:49:18.360 --> 00:49:19.820
Well, you're writing SQL as well.
00:49:19.820 --> 00:49:20.980
But
let's call that Python.
00:49:21.300 --> 00:49:24.900
And then we deal with the components for you.
00:49:24.900 --> 00:49:32.940
And so it's not the kind of framework where you're writing Python and we're generating HTMX or something like that.
00:49:32.940 --> 00:49:35.320
So obviously, we understand React.
00:49:35.320 --> 00:49:39.540
And we know we can build some beautiful components, customize them with it.
00:49:39.540 --> 00:49:45.980
We weren't about to create a completely new framework where we somehow just generate HTML from Python.
00:49:45.980 --> 00:49:49.180
I think there's a few people working on that, actually.
00:49:49.520 --> 00:50:02.580
We already know React, so let's just build those components or customize those components and then just let people declare them and then sort of access and modify them via the context objects in your Python functions.
00:50:02.580 --> 00:50:07.660
So our stack, we use FastAPI for our backend, which is great.
00:50:07.660 --> 00:50:08.700
It's excellent, yeah.
00:50:08.700 --> 00:50:11.680
I'm not sure if you've had the creator here.
00:50:11.820 --> 00:50:16.100
Yeah, I've had Sebastian on, I think, at least three times, Sebastian Ramirez.
00:50:16.100 --> 00:50:17.440
Yeah, he's great.
00:50:17.440 --> 00:50:18.560
Yeah, he is really great, yeah.
00:50:18.560 --> 00:50:20.700
FastAPI is a fantastic app.
00:50:20.700 --> 00:50:22.080
And so, yeah, we use them.
00:50:22.080 --> 00:50:24.640
We use React or our client side.
00:50:24.640 --> 00:50:27.900
And we are a lot of our infras on AWS.
00:50:27.900 --> 00:50:29.540
Yeah, sounds really interesting.
00:50:29.540 --> 00:50:31.060
Sounds like a fun app to work on.
00:50:31.060 --> 00:50:32.940
Yeah, you should play around with it.
00:50:32.940 --> 00:50:36.840
I can help you build some apps to manage your podcast library.
00:50:37.400 --> 00:50:40.980
All right, well, Jimmy, I think we are pretty much out of time.
00:50:40.980 --> 00:50:43.060
Final thought for people listening.
00:50:43.060 --> 00:50:44.500
Maybe they're excited to try this out.
00:50:44.500 --> 00:50:45.460
What are you telling them?
00:50:45.460 --> 00:50:49.600
Yeah, just go to droppace.io and sign up for a free account.
00:50:49.600 --> 00:50:50.760
It's free for developers.
00:50:50.760 --> 00:50:51.780
You can set it up locally.
00:50:51.780 --> 00:50:54.600
If you have any issues setting it up, just reach out.
00:50:54.600 --> 00:50:56.600
I'll personally help you get it up and running.
00:50:56.600 --> 00:50:59.500
Yeah, you can look at the documentation for everything else.
00:50:59.500 --> 00:50:59.840
Yeah.
00:50:59.840 --> 00:51:00.400
Let's find it.
00:51:00.400 --> 00:51:00.860
Try it.
00:51:00.860 --> 00:51:01.560
Give us some feedback.
00:51:01.560 --> 00:51:02.700
We'd love to hear from you.
00:51:02.760 --> 00:51:03.000
Awesome.
00:51:03.000 --> 00:51:06.460
Congrats on building a cool project for people.
00:51:06.460 --> 00:51:07.640
And yeah, good luck with it.
00:51:07.640 --> 00:51:08.040
Thanks, Michael.
00:51:08.040 --> 00:51:11.420
This has been another episode of Talk Python To Me.
00:51:11.420 --> 00:51:13.220
Thank you to our sponsors.
00:51:13.220 --> 00:51:14.840
Be sure to check out what they're offering.
00:51:14.840 --> 00:51:16.280
It really helps support the show.
00:51:16.280 --> 00:51:21.160
Mailtrap, an email delivery platform that developers love.
00:51:21.160 --> 00:51:24.420
Try for free at mailtrap.io.
00:51:24.420 --> 00:51:26.820
Want to level up your Python?
00:51:26.820 --> 00:51:30.860
We have one of the largest catalogs of Python video courses over at Talk Python.
00:51:31.320 --> 00:51:36.060
Our content ranges from true beginners to deeply advanced topics like memory and async.
00:51:36.060 --> 00:51:38.720
And best of all, there's not a subscription in sight.
00:51:38.720 --> 00:51:41.620
Check it out for yourself at training.talkpython.fm.
00:51:41.620 --> 00:51:43.700
Be sure to subscribe to the show.
00:51:43.700 --> 00:51:46.480
Open your favorite podcast app and search for Python.
00:51:46.480 --> 00:51:47.780
We should be right at the top.
00:51:47.780 --> 00:51:52.960
You can also find the iTunes feed at /itunes, the Google Play feed at /play,
00:51:52.960 --> 00:51:57.140
and the direct RSS feed at /rss on talkpython.fm.
00:51:57.140 --> 00:52:00.100
We're live streaming most of our recordings these days.
00:52:00.240 --> 00:52:03.520
If you want to be part of the show and have your comments featured on the air,
00:52:03.520 --> 00:52:07.900
be sure to subscribe to our YouTube channel at talkpython.fm/youtube.
00:52:07.900 --> 00:52:10.000
This is your host, Michael Kennedy.
00:52:10.000 --> 00:52:11.300
Thanks so much for listening.
00:52:11.300 --> 00:52:12.460
I really appreciate it.
00:52:12.460 --> 00:52:14.360
Now get out there and write some Python code.
00:52:14.360 --> 00:52:35.340
We'll see you next time.