00:00:00.000
ready for takeoff
00:00:18.480
all right so these are some pictures that Dolly gave me of machine generated
00:00:25.260
gems so it's a machine generated images of machine generated gems and they're in
00:00:32.940
the graphic novel style I thought it was pretty fun um but I want to roll back to 2019 for a
00:00:38.880
second so I was out on a walk I was at an on-site in Seattle and I was walking sort of from The Event Center to dinner
00:00:44.940
and I was chatting with my friend Alex about this really cool tooling that he was building he was talking about how he
00:00:50.760
was using react but he was writing all these different programming languages using react and it sort of blew my mind
00:00:56.039
a little bit I was like this is really really interesting I was sort of bedazzled as uh we are when we're
00:01:01.680
talking about gems and so I have been sort of like chomping at the bit waiting to go out and talk about this and so I'm
00:01:08.280
super excited to share it with you all today um but before we talk about automatically generating some of our
00:01:14.280
sdks I want to talk about the hard version which is writing things by hand when I was going through practice one of
00:01:20.040
the people who I told we used to write our all of our Gems by hand they said by hand as if like we were actually like
00:01:26.340
pencil and paper which uh is not true so I work for a company called stripe
00:01:32.400
um the uh the only thing you need to really know about stripe today is that we have a web API and that a huge Lion
00:01:39.540
Share of the people who integrate with stripe use our official client Library so we have a bunch of different client libraries stripe Ruby is one of them
00:01:46.619
it's a very popular gem stripe uh apis are used by millions of businesses
00:01:52.079
around the world from super small startups all the way up to massive Enterprise companies to accept payments
00:01:58.079
make payouts and just generally manage their business online so again developer experience the hard
00:02:04.380
way when we talk about DX oftentimes we're either talking about the internal developer experience that we have going
00:02:10.860
out and working on our own applications building our own products that's like our own pains that we feel with CI
00:02:17.940
running slow or tests or you know the error messages that we're getting or the
00:02:23.400
the conflict and issues that we have when we're trying to like change our own systems but today I want to talk about
00:02:28.980
external DX and that is like when third-party developers try to integrate against our own apis and using our tools
00:02:35.520
maybe that's uh you know a third-party developer using an SDK a rubygem using the actual API the error messages that
00:02:42.120
they get the documentation that they read all the way down to the shape of the actual API response this type of
00:02:48.780
support you get that's all sort of external DX there's a lot that you can build into that automatically so you
00:02:54.840
don't have to do tons and tons of chore work all the time so let's talk about the hard way so in
00:03:01.800
2011 version 1.5 of the stripe gem this is sort of as far back as the public GitHub
00:03:07.800
goes for stripe Ruby uh this is when uh stripe Ruby was just basically one giant
00:03:13.260
striped RB file here that had just four resources you could interact with the
00:03:18.300
stripe API um fast forward a little bit we spent a lot of time hardening the core of strike
00:03:25.440
Ruby so if you look at the PRS between 2012 2014 this is things like cleaning
00:03:30.780
up organization making sure that we're backing into the patterns that we want to use inside of our classes or the way
00:03:36.420
that we want to implement stripe Ruby so that going forward it'll be a nice experience to use the SDK so there's
00:03:42.659
little PR's like this that are just sort of like okay let's organize our modules into their own files and things like
00:03:48.420
that going forward a little bit more the PRS that you see from 2015 to 2016 were all
00:03:55.739
of these really high effort PR's that were really just mirroring the API so
00:04:00.959
like as a new endpoint is released or a new property is released or a new whatever is released you have to go in
00:04:06.780
and make a PR to stripe Ruby but also strike python PHP node go java.net and
00:04:12.720
these are sort of like really heavy things that you have to do often costing you know hours per change or days per
00:04:20.400
change depending on how big that change was so here's an example of one uh
00:04:25.740
adding a new resource so this is a source object and if it doesn't follow
00:04:31.080
all of the exact patterns where it's just like a crud sort of rest API that
00:04:36.360
you're familiar with and if for some reason that resource has another method to it in this case verify then we're
00:04:43.979
going to add those in sort of manually but all of this is going to be a pattern that we're using across the whole SDK
00:04:50.699
in 2017 we introduced the open API spec into stripe Ruby and the whole point of
00:04:57.060
that first like dumping the open API spec into stripe Ruby was just for tests so we were using it as the fixtures that
00:05:04.320
backed our automated tests to make sure that stripe Ruby was behaving as expected and also this is the first time
00:05:10.860
that we have sort of this artifact that exactly represents what the API is that
00:05:16.620
is inside of the SDK and we're now able to use that to at least verify that what we're writing by hand is valid
00:05:23.400
so if you're unfamiliar the open API spec is a standard it used to be called Swagger so if you heard of swagger
00:05:30.300
before it got renamed to open API there's a bunch of stuff that happened around who owns things but
00:05:37.560
um at Strife we write all of our or we describe all of our apis with a ruby DSL
00:05:43.740
and then we have some homegrown tools that will spit out some yaml files and some Json files a bunch of different
00:05:49.440
versions of these specs depending on whether we're talking about you know beta beta versions of features or public
00:05:56.880
versions of features or um but at the end of the day we're giving out this open API spec and this
00:06:02.940
is actually available on GitHub so you can go to github.com stripe open API you can see all the different versions of
00:06:08.340
the open API spec that are available there still in 2019 we're seeing a lot of
00:06:14.280
these really high effort PRS that are going into all of these sdks
00:06:20.660
but if we fast forward to 2019 we'll start to see okay this is when we get a
00:06:26.400
glimmer of hope in that Cogen is going to come and rescue us and we'll no longer have to write all these high effort PR's just to mirror the API
00:06:35.100
um so again now today if you look at the repo you'll see like okay we're just
00:06:40.199
shipping one of these API updates PR's and then bumping a version and this is
00:06:45.360
all just generated now like every time the API changes it's flowing out to the open API spec that's automatically
00:06:51.660
generating the sdks and it it is super nice we're saving hundreds of hours in
00:06:59.039
engineering work per year but you might be sitting there wondering
00:07:05.220
like okay great like what alternatives did they consider how did they figure out that they need to build this tooling
00:07:11.400
and maybe it's worth talking about sort of the requirements that we had going into this so uh I already mentioned that we have
00:07:18.300
seven official sdks so we wanted to build some sort of pipeline that would support all seven of these languages we
00:07:25.560
also wanted that the we wanted the code that we were going to generate to um be almost exactly what it was when it
00:07:33.479
was handwritten there's a couple reasons for this we consider our sdks to be a
00:07:38.759
form of documentation we want them to be readable we want them to be like nice to use we want them to be something that if
00:07:44.520
for some reason if there's a bug then you can look at the code on GitHub for stripe Ruby and sort of easily figure
00:07:50.880
out what's going on why there was an error we also wanted some sort of pipeline
00:07:56.400
that was really straightforward to build and maintain for a very small set of Engineers inside of stripe who maintain
00:08:02.220
sort of this pipeline of SDK generation uh so this was kind of like our Baseline
00:08:08.400
requirements going into this so you're like sitting out there you're like okay he already said there's an
00:08:13.919
open API spec why is he using swagger code gen or the open API code generator so this open API is a standard it's uh
00:08:22.199
it's got a bunch of Open Source tools one of them is called Swagger code gen and it is a tool that will take your
00:08:28.440
spec and then you can spit out client libraries or sdks in lots of different languages
00:08:34.320
so let's take a look at what that looks like so you can Brew install Swagger code gen
00:08:43.140
and pretty simply pass a couple different options to it pass it this big
00:08:48.300
Json blob that comes from uh that's just on GitHub we want to tell it that we're going to use Ruby as the language that
00:08:54.720
we want this output and we'll just kind of like spit the files out into this directory called stripe Ruby Swagger
00:09:00.300
Cogen so this is going to go and generate tons and tons of files for us and if you are
00:09:06.120
starting today from scratch this might actually be a really good option just like go use this off-the-shelf tool that
00:09:12.600
you can Target tons and tons of different languages for really easily uh another
00:09:18.060
um reason that we wanted to do this is that or one of the reasons that we wanted to Target existing
00:09:24.540
um Target matching the existing code that was already there and already human
00:09:29.760
readable is that we wanted to minimize the breaking changes that uh third parties would have to make
00:09:34.980
um okay that didn't work as expected
00:09:40.260
doesn't like pausing in the middle when I'm trying okay all right so Swagger code gen spits out this giant
00:09:47.519
Ruby file called default api.rb and if we look at the number of lines 30 000 line files so just like a super massive
00:09:54.540
file for default API but that's not the only part of the SDK that's being generated so if we go into this models
00:10:01.320
directory which represents either sort of the params that we're sending into the API or the like results that we're
00:10:07.620
getting that are being then deserialized and bound to these Ruby objects there's over 2000 of them so it's like if there
00:10:14.760
was a bug you'd have to go dig through either these thirty thousand line files or two thousand different files so it's
00:10:21.000
like super tricky to go and debug anything and we felt like the developer experience wasn't great
00:10:28.019
um so uh this is actually one of the resources this is a customer object that
00:10:33.060
Swagger code gem wouldn't spit out for you it's actually pretty nice like there's documentation about all the different attributes and if you uh again
00:10:40.260
if you're starting today this is probably like a really good option off the shelf um
00:10:45.779
there's a couple different formatting things that were sort of bothersome and a lot of this code was repetitive so
00:10:51.540
computers are really good at generating repetitive stuff and then understanding repetitive stuff but we aren't as good
00:10:58.140
at that okay now it's no longer full screen
00:11:05.640
there was a couple different things that made using off-the-shelf tools challenging and that's because there's
00:11:10.800
some features of the stripe API that are a little bit um unique so one of them is that we have
00:11:16.560
this concept of expandable Fields so that means that by default if you make a request to the API and you get back a
00:11:22.680
Json object and somewhere in that object there's an ID to a related field then it's possible to change the parameters
00:11:29.760
that you sent for that previous request and instead of just getting the ID back you would get a fully nested object
00:11:36.000
that's like expanded in place inside of the Json that you got back and that means that you have like kind of these
00:11:41.519
polymorphic things where like oh a property could be a string or it could be like this other giant thing and so
00:11:47.100
that made it a little bit challenging but um the open API spec is really flexible and
00:11:52.680
so you can add your own sort of extensions to it so one of our extensions is expandable Fields there's
00:11:57.839
a handful of others but that made it challenging to use off-the-shelf stuff so while it is a convenience for
00:12:04.160
developers to have these different tools to in that case it's to avoid an N plus one query like to the API
00:12:11.820
um it can make it challenging to use off-the-shelf stuff so the uh this Swagger Cogen takes this
00:12:18.839
approach that uses templates they're kind of messy and if you look into the actual source of swagger Cogen it's
00:12:24.360
basically just like this giant these giant mustache templates that you then feed in the open API and fill out okay
00:12:29.760
this is the name of the class this is the name of the methods and then you will like iterate over certain results
00:12:35.160
that are in the spec and spit those out as parts of um as parts of the resulting code
00:12:41.459
we actually did a lot of this in our documentation and for a long time all of the Snippets that you saw in the docs
00:12:47.579
those were all just like written in Erb and just straight up like the raw code
00:12:52.800
was in the Erb template um and so we'll talk about how that has improved also but
00:12:58.139
um this sort of string concatenation approach or template approach was something that we want to avoid because
00:13:03.779
it's sort of just messy and toilsome on the other uh side of the world we've got these AST Builders and printers right so
00:13:10.500
like Ruby syntax tree or using a tool like that would be an option to approach
00:13:16.440
it from a different angle but one of this is like a list of reasons why we didn't take that approach oftentimes
00:13:22.800
these AST Builders and printers are very specific to the language that you're targeting and so uh as a team we would
00:13:28.920
need to go and learn all of the different AST Builders and printers for go and Java and c-sharp and all the
00:13:35.100
different languages that we want to support okay let's take an introduction to this thing
00:13:41.579
called prettier poet uh so this is one of the components that
00:13:47.459
is involved in our in our pipeline this is the one that I'm most excited about and super super pumped to share so
00:13:53.459
prettier poet is a react like tool for generating readable code in several
00:13:58.860
languages powered by the core of prettier so who's used uh react before
00:14:05.100
okay almost everyone okay at least at some point okay maybe 90 95 of the room
00:14:11.100
so um then we'll be able to spin through the Hello World stuff pretty easily so
00:14:17.760
react um we all often think about react in the context of a front-end framework right
00:14:24.899
so we're writing these components and we we at the end of the day are going to
00:14:30.000
receive back some HTML right so react is going to generate this this HTML for us but it's also going to give us some like
00:14:36.240
reactivity like you can have click events and you can listen for changes on things we don't actually use the events
00:14:42.480
or reactivity we are just using the components so what's nice about this is that we can have sort of really isolated
00:14:49.980
things that are easily testable and then we can build them up into much bigger things so in this case we have this
00:14:55.380
welcome component that is like super super isolated takes in some props and then renders out some things then we can
00:15:00.899
build an app component that is composed of these smaller bits we also get conditional rendering a
00:15:07.139
bunch of other nice features from uh just using jsx react is used for a couple of other like
00:15:14.220
really interesting use cases so react native is a way that you can write the
00:15:19.320
same sort of react code but you're building for uh like cross-platform
00:15:24.480
mobile applications you can write for IOS and Android but it's still you're you're using react
00:15:30.360
there's another example here so raycasts an alternative to Alfred or Spotlight on
00:15:36.180
your Mac there's an extension gallery for raycast and you can Implement extensions using these different react
00:15:42.180
components and tools all right so I wanted to do a live demo so
00:15:49.320
um this is prettier poet
00:15:54.360
so on the very first line here we're importing react so we can use jsx we're also importing this render to string
00:16:01.019
thing that's going to let us render out something to a string and here we're importing Ruby and this is where like I
00:16:08.339
was like whoa this is amazing so if you're feeling that I don't know like it's it's kind of crazy all right so
00:16:16.199
um we are going to build this higher order component called say hello Ruby that's going to take in some props that have a message on it and now we see this
00:16:23.100
new component or a sub component of Ruby called method call you give it a Kali and you can say whether or not you want
00:16:29.579
parentheses and then you can pass in some arguments and finally we just got
00:16:34.680
like this little helper method that's going to call render to string and that will actually like print out to
00:16:40.620
the console some some Ruby code you'll notice here when we're looking at
00:16:45.779
the render to string function it's kind of like a little yeah just like a little printing function but one of the arguments to render to string is a print
00:16:52.620
width now this is where prettier comes in really handy and that lets you depending on how wide you want to like
00:17:00.120
actually print the code it will break it at the correct line breaks and so if you're interested in the way that
00:17:05.880
prettier is implemented there is a a paper that will link to at the the end
00:17:11.280
and you can take a look at it it's only uh 20 22 pages long and there's a bunch of like fancy math in there but there's
00:17:19.799
just like a handful of functions that if you implement them you can build a tool that will make your code really
00:17:25.740
beautiful right and so we've probably um actually many folks that I have
00:17:31.080
worked with in the past are familiar with using prettier as a good way just like Auto format your code there's other Alternatives in Ruby we've got like Ruby
00:17:36.960
format and you know there's a lot of other things now but prettier is a language agnostic way to sort of build
00:17:43.440
tools that make your code look nice all right let's run it okay
00:17:50.400
so here's our output puts hello rubyconf
00:17:55.679
that's not Val I mean it is valid if we have hello and rubyconf
00:18:01.260
as constants but what okay so we wanted it to be a string right but instead we printed out just the actual like raw
00:18:08.280
contents of what was passed in as the message and so we need to use another feature of uh this Ruby like language
00:18:15.299
toolbox that we have here and that is ruby.string so here we're going to pass in as an argument ruby.string and its
00:18:22.320
value is going to be the message that we're passing in okay we can run this again
00:18:29.100
now we have quotes all right so we've got some valid Ruby code that's cool
00:18:34.500
but what if we wanted to print out uh the number 42. okay let's see how this works because I
00:18:41.280
don't know maybe it's going to do something Fancy with the string thing all right so we run it and this time we
00:18:46.679
get an exception it says what you try to call a string is actually not a hard-coded string it's something else
00:18:52.620
and so you get an exception it's like okay the props that you passed in they're not valid and so this allows you
00:18:57.720
to kind of like be really careful about what you're rendering out so they're instead of using ruby.string here we can
00:19:03.240
use ruby.literal that's another component
00:19:08.400
so we'll run this again and now we're able to say it puts 42 and if we wanted to we can put in both 42 and I don't
00:19:15.900
know uh hello run this again and we should be able to
00:19:21.780
see both options there so now we're able to like print stuff out okay
00:19:28.740
let's look at another example now we're importing Ruby and we're also importing JavaScript
00:19:36.299
so now we have this higher order component called say hello Ruby which looks exactly the same as what we just
00:19:42.000
showed we also have say hello JavaScript and here we have js. method call
00:19:49.140
and its Kali is console.log technically there are other tools I I took a couple
00:19:54.720
of shortcuts to build the demo but there's other tools that you can use if you need to like build a long method chain so you can you can say like oh I'm
00:20:01.799
in JavaScript and I need to build a like a chain of different calls that way when
00:20:07.380
prettier is rendering it if the line of method calls is too long it can sort of like split out so it has kind of like
00:20:13.980
the top level thing and then the dots on the new lines with the correct indentation
00:20:19.440
um so this is cool we're able to print out some stuff in different languages now we have the say hello function that
00:20:25.440
is just going to like sort of switch on the language that we actually want to print out so down here at the bottom
00:20:30.840
we're going to try to render hello Ruby and hello JavaScript both of those different languages so we'll say two and
00:20:37.140
now we get puts hello Ruby and we also have this console log for JavaScript so
00:20:43.080
um let's add go in here so here we can just say go you also notice that like
00:20:48.780
the say hello Ruby does not have parens but the method call in the JS component
00:20:55.140
world like has to have parents like you can't have a JS method call without parens as far as I know I mean there
00:21:01.020
might be some Edge case out there but all right so let's say const say hello go
00:21:06.360
all right thank you GitHub copilot go dot method call whatever so go it's not actually called method call the
00:21:12.059
component in uh in go it's actually called uh function call function call
00:21:18.900
and this is the right Cally format.printline and it will know that it's printing the right thing we need to
00:21:24.299
add this down here so we can say all right we want to actually print out go say hello go
00:21:31.559
all right and we also need to print out the right language hello go and we'll
00:21:38.159
just see if this works nice all right so now we're able to print out three different languages and
00:21:44.940
we're using kind of like this cool style so we'll come back to that as that's like one of the really important features that we use in the
00:21:51.179
documentation to render out like all the different languages as you're kind of like switching through and picking a
00:21:57.000
different language um okay so let's look at a third example
00:22:03.059
if I could type all right so this is another example where we're gonna have to just imagine
00:22:08.760
for a minute that this spec at the top is actually the open API spec right like the the spec that we have is so big that
00:22:14.580
GitHub won't render it so I assume it's like just really big file um and in this case we have two
00:22:19.919
resources we have a coupon and a customer and then maybe we have some operations so we can like you know send
00:22:25.080
a post request a get for a single one or a gift for a list and what we want to do is render out several different models
00:22:31.799
so here we can have a ruby module with our namespace at the top then we can have a comment with like a class level
00:22:38.820
description of what the what we've got going on this line tool here comes
00:22:44.520
directly from the core of prettier poet it is not Ruby specific but it is something that we use when you just want
00:22:50.220
to like add some some lower level formatting as you're building this stuff out so there is a set of prettier
00:22:56.280
prettier poet components that we use to build up these language specific
00:23:01.620
components and then sometimes you use them as you're building these higher order tools
00:23:07.020
next we're going to create a ruby class we do have to pass in the right strings when we're saying like okay here's the
00:23:12.480
name of the class we want to capitalize it and you can also say okay this is going to inherit from some other thing
00:23:17.880
called API resource ruby.statements so statements is a tool that lets us sort of like break up the
00:23:25.200
lines correctly otherwise they're all going to be sort of like bunched together so this gives us like gaps between all the different classes and
00:23:31.500
then because we're in react land we can just map over the list of operations and render out some other higher order
00:23:37.260
component that we can individually test and it's actually like pretty handy so let's look at that higher order
00:23:42.780
component it is this one so we're going to define a ruby method it has a specific name and then inside of that
00:23:49.799
we're just going to like do a simple assignment of some request and we're going to pass like a ruby symbol and a
00:23:55.919
ruby string and we're going to get back some response this is all just like totally fake and isn't exactly what we
00:24:01.320
use in in reality but I want to just show that you can actually like generate full classes relatively easy
00:24:08.159
um and so here at the bottom we're just going to iterate over the spec and for each of the sort of the resources in the spec we're going to generate a model and
00:24:14.280
print out the code in the terminal here so this is the third example
00:24:19.440
so here we have module we got our like namespace we've got this like top level you know documentation and then we're
00:24:27.120
printing out this customer class and inside of create it knows that it's like supposed to be splitting on these lines
00:24:32.700
like this to make a long method call but I actually want that to be printed out a little bit I don't know more like wide
00:24:40.440
and so I can come into my print with and change that to 80 and if we run this again
00:24:47.460
we're going to see that like okay now it knows that I have 80 characters and so I can like print it out in the right
00:24:52.860
format for 80 characters so that is pretty cool
00:24:57.900
let's look at another example in this case I thought this is like kind of another neat example of using jsx and
00:25:05.100
react to sort of like compose all this stuff we're going to build out a Sinatra server so some some route definitions
00:25:12.360
for a Sinatra server and we'll do the same for Express and the way that we're going to define the routes is just in
00:25:18.240
some data object again this is something that you could theoretically get directly from the open API spec it does
00:25:24.059
have like all of the um the routes and methods and sort of the arguments that it can accept
00:25:31.260
ooh warning something oh no
00:25:37.080
all right Amber Alert darn okay
00:25:43.500
inside of our Sinatra route there's going to be some children and so we can Define this higher order
00:25:48.960
component called a Sinatra route that's going to take in the name the method the path and then some children doc right
00:25:56.279
that we can then render out inside of our block so here we're going to Define another Ruby method call this is going
00:26:01.860
to be sort of either get push like get post put delete and then the the actual
00:26:08.419
arguments to that is going to be some string and then a block and inside the block that's where we Define the
00:26:13.799
contents for like the request the like business Logic for the request that we want to actually run and then inside of
00:26:19.799
our we can define a Sinatra app that uses this Sinatra route and as its children we can define a ruby method
00:26:26.279
call and for now we're just going to print out tests to keep things easy and we can do the same thing with Express so
00:26:32.700
in in Express land I just put everything in one giant function but let's run them both so for
00:26:40.500
okay so now we're printing out some routes for Sinatra some routes for
00:26:46.980
express pretty cool stuff all right another example
00:26:53.520
in this case we want to render out what it looks like to use the SDK so we're going to like print out what it what
00:26:59.520
does it look like to use stripe Ruby to make an API call to stripe so at the top we might have some spec and some methods
00:27:06.000
and then we have this API call which is going to use a
00:27:12.299
couple of other higher order components one is going to be the call E and that's going to like figure out okay which
00:27:18.720
resource are we talking about is it customer or coupon and then based on that resource which which method are we
00:27:24.779
going to call create retrieve list Etc so we have some params that we're taking
00:27:30.900
in and printing out a ruby symbol hash because that is the thing that you would
00:27:36.000
pass in as an argument to like a create call we also have this Kali I'm again like
00:27:41.520
sort of hard coding a bunch of this for brevity but you could use tools to compose stripe colon colon some other
00:27:49.020
namespace class name Etc with the name of the method at the end
00:27:54.419
okay so down at the bottom what we have is API call Ruby we give it a path we give it the HTTP method and then some
00:28:01.799
params just as this like JavaScript object right here and then we can run
00:28:07.080
and render this out so number five so now we get stripe customer create and
00:28:13.980
you can see the email the payment method Etc so those are the live demo it's like the
00:28:20.640
live demo portion and I wanted to like just quickly look at where this is used so when we're in
00:28:28.500
the documentation here um this all of this code that you see that
00:28:34.620
is part of rendering out the curl API call using the stripe CLI using stripe
00:28:41.400
Ruby python PHP go java.net this is all using that same tooling under the hood
00:28:47.220
to build out an API request and what's really cool is this enables documentation writers technical writers
00:28:54.720
to build out code in seven languages plus curl plus stripe CLI without
00:29:00.000
actually knowing how to write most of those languages right and so what we've done is we've taken that react code and
00:29:06.659
built it into this tool it is a a markdock
00:29:13.380
component so that you can just pass in a few arguments to this code gen snippet
00:29:20.820
component markdoc is the open source library that we use to implement our documentation but what's nice about this
00:29:27.120
is that when you go to generate the API calls we can also run validations so we
00:29:32.820
know okay the checkout session endpoint requires that you pass a success URL and a cancel URL so we're not actually going
00:29:39.299
to render the code for that unless it's valid so we can go through and make sure that not only are we able to generate
00:29:45.059
the code in all these different languages it's valid code in all the different languages and we can even include things like metadata so now we
00:29:52.020
can enable documentation and Technical documentation writers but also just like
00:29:57.179
the amount of code that we've deleted from our code base that is just purely for examples was uh amazing
00:30:05.820
um it's actually really fun to find old examples that are not using this Cogen snippet tool yet and just go and just
00:30:11.640
delete hundreds of lines of stuff that's either you know in Erb templates or just is hard coded in these markdoc files
00:30:19.140
um so that's this was a tool that was sort of like just put together in an afternoon using the core foundation of
00:30:26.880
the code gen tooling now there's other there's a few other things here that we do so in the API reference you've
00:30:33.360
probably seen similar API reference manuals where on the right side you see the code but oftentimes the code that's
00:30:39.720
being shown to you is like okay here's the path and we're just going to use some like rest client we're going to use
00:30:45.840
some other like low level HTTP library but now we can actually generate the code Snippets that mirror the sdks so
00:30:52.860
that's pretty powerful we can also generate change logs because we can know the diff between each of them and we can
00:30:59.520
uh so this this sort of like changelog bit is all auto-generated Postman collection is auto-generated and one
00:31:06.480
final thing is this the stripe CLI UI which if you go to any of the stripe documentation and hit tilde this comes
00:31:13.140
up and you can say like stripe customers list and that will like actually hit the
00:31:18.179
API bring back your customers and render them directly in the browser so you can kind of go through and check that out
00:31:26.100
all right thank you so much for your time and attention really appreciate you uh joining and hearing about this I was
00:31:32.399
like again super pumped when I heard about it got to use it for a few different projects and uh yeah happy to be able to share
00:31:38.460
so I'm available here if you want to chat and uh yeah otherwise I'll be up here for questions thanks again
00:31:46.140
foreign