Build Realtime Apps with Ruby & Pakyow
This is a modal window.
The media could not be loaded, either because the server or network failed or because the format is not supported.
Formal Metadata
Title |
| |
Title of Series | ||
Part Number | 23 | |
Number of Parts | 89 | |
Author | ||
License | CC Attribution - ShareAlike 3.0 Unported: You are free to use, adapt and copy, distribute and transmit the work or content in adapted or unchanged form for any legal and non-commercial purpose as long as the work is attributed to the author in the manner specified by the author or licensor and the work or content is shared also in adapted form only under the conditions of this | |
Identifiers | 10.5446/31499 (DOI) | |
Publisher | ||
Release Date | ||
Language |
Content Metadata
Subject Area | ||
Genre | ||
Abstract |
|
RailsConf 201623 / 89
1
2
3
5
7
8
11
12
19
22
28
29
30
31
33
45
47
50
52
53
58
62
67
71
74
76
77
78
79
80
81
84
85
86
88
89
00:00
Mobile appTrailSoftware frameworkSoftware maintenanceWeb 2.0Multiplication signCartesian coordinate systemGoodness of fitBitBuildingProgram slicingQuicksortExterior algebraReal-time operating systemDifferent (Kate Ryan album)Projective planeTwitterHeegaard splittingMappingComputer animation
02:09
View (database)Electronic mailing listMathematicsServer (computing)Web browserCartesian coordinate systemSoftware frameworkArtistic renderingClient (computing)SynchronizationWeb pageComputer architectureSoftware developerForestDependent and independent variablesComputer animation
03:24
BlogNumberClient (computing)DatabaseRight angleState of matterFile formatData conversionWeb pageTouchscreenBitMessage passingTotal S.A.Reading (process)Routing
04:51
Line (geometry)Real-time operating systemStatisticsConnectivity (graph theory)Client (computing)State of matterProcess (computing)Focus (optics)BitCodeMathematicsSoftware testingSystem callDependent and independent variablesSocial classView (database)Artistic renderingLie groupWeb browserSource code
06:15
RoutingConnected spaceSystem callDependent and independent variablesWeb pageClient (computing)StatisticsSynchronizationSoftware frameworkWeb browserSocial classProcess (computing)
06:58
CodeCartesian coordinate systemMultiplication signClient (computing)Server (computing)Software developerView (database)State of matterConnected spaceVolumenvisualisierungQuicksortIntegrated development environmentNumberInformation technology consultingTheoryBuildingTransformation (genetics)Context awarenessTouchscreenComputer configurationWritingMobile appMereologyProcess (computing)Real numberPhase transitionMathematicsScripting languageImplementationMedical imagingBitText editorComputer animation
10:41
Projective planeProcess (computing)User interfaceCartesian coordinate systemSoftware developerFigurate numberBuildingRight angleMereologyComputer animation
11:36
Semantics (computer science)PrototypeArithmetic meanCodeExpressionContext awarenessLogicGreatest elementView (database)Software developerSoftware frameworkProjective planeObject (grammar)QuicksortSet (mathematics)Physical systemInheritance (object-oriented programming)Web 2.0Software design patternAttribute grammarEntire functionWeb applicationCartesian coordinate systemPresentation of a groupPoint (geometry)Matching (graph theory)Data typeData structureBlogSingle-precision floating-point formatTransformation (genetics)Multiplication signBuildingIterationTemplate (C++)ActuaryOcean currentRepetitionRaw image formatWordCASE <Informatik>VolumenvisualisierungOperator (mathematics)MereologyHash functionSound effectComputer animation
16:39
Semantics (computer science)Object (grammar)Dependent and independent variablesClient (computing)ResultantState of matterFront and back endsServer (computing)Artistic renderingMathematicsWeb browserView (database)Presentation of a groupPoint (geometry)Social classNegative numberVolumenvisualisierungBitTransformation (genetics)Software design patternMereologyCartesian coordinate systemRight angleTemplate (C++)Ring (mathematics)Library (computing)PrototypeCodeImplementationTwitterDiscrete groupQuicksortGraph coloringSet (mathematics)IterationLogicData structureMomentumPhase transitionMatching (graph theory)Functional (mathematics)Software frameworkGreatest elementDynamical systemNetwork socketWeb 2.0Mobile appSystem callComputer animation
21:42
Connectivity (graph theory)Group actionHybrid computerView (database)Client (computing)Phase transitionDependent and independent variablesBlogQuicksortArtistic renderingReal-time operating systemCodeRight angleInstance (computer science)Software frameworkMedical imagingComputer animation
22:58
Military baseSingle-precision floating-point formatWeb 2.0SurfaceMobile appComplex (psychology)Cartesian coordinate systemSeries (mathematics)Complete metric spaceBlogRight angleSkeleton (computer programming)Statement (computer science)HyperlinkState of matterComputer fileServer (computing)Point (geometry)Context awarenessQuicksortJava appletScripting languageWeb pageClient (computing)Roundness (object)Arithmetic meanEndliche ModelltheorieCodeVolumenvisualisierungDependent and independent variablesComputer animation
25:11
Mobile appFluid staticsDependent and independent variablesGoodness of fitFront and back endsCartesian coordinate systemMathematicsHuman migrationWeb browserCodeWeb pagePattern languageSoftware frameworkComputer configurationView (database)Phase transitionContent delivery networkProcess (computing)Right angleClient (computing)Web 2.0Server (computing)Real-time operating systemBit rateFormal languageSoftware developerProjective planeDemo (music)Computer animation
27:50
Server (computing)Projective planeClient (computing)Online helpCartesian coordinate systemSoftware developerWordMachine visionWebsiteElectronic program guideGodContext awarenessConfidence intervalCore dumpFocus (optics)BuildingProduct (business)Multiplication signWeb browserOpen setMobile appReal-time operating systemSoftware frameworkView (database)Computer animation
30:35
Computer animation
Transcript: English(auto-generated)
00:11
Let's go ahead and get going. So, hello RailsConf. It's been a pretty good conference, hope you all have enjoyed it. So this morning, we're gonna kick off
00:21
the alternative framework track. We're gonna talk a little bit about how to build real-time apps with Ruby and Pacquiao. I'm Brian Powell, I'm one of the creators of Pacquiao. I play an active role in maintaining it today. About 50% of my time goes towards building new features and fixing problems.
00:40
I have the privilege of working alongside about a dozen or so other maintainers. We love this project, but we love the little slice of the Ruby community that we've been able to carve off for ourselves over the last year or two. You can follow me on Twitter, at Brian P., if you'd like.
01:00
So, I'm curious, who here has heard of Pacquiao before RailsConf? Okay, awesome, a few people. For everyone else, Pacquiao is a web framework for Ruby. Pacquiao is an end-to-end framework, so it doesn't work on top of Rails. You would use it instead of Rails in your stack.
01:20
And Pacquiao, we've designed it to be sort of a different take on building application for the web and it's really different than what you might see in something like Rails or even other ecosystems. There's really nothing quite like it. So, this being RailsConf, excuse me,
01:42
I did want to take just a minute to say thank you publicly to DHH. A couple years ago, he was kind enough to offer his, you could call it an endorsement maybe, of some of the concepts behind Pacquiao. Pacquiao?
02:04
This is why we do what we do. Thank you, DHH. So, Pacquiao, it lets you build server-driven applications that automatically stay in sync with a server.
02:20
So, what this means is Pacquiao is a server-side framework, just like Rails. On the initial request, Pacquiao will perform the rendering on the server side, build up a full HTML response, send that down to the browser, and that's presented in the browser just like any other HTML page would.
02:41
Now, where Pacquiao starts to differ from other server-side frameworks is this view in the browser automatically keeps itself in sync with the server. So, what that means is if we're looking at a list of comments in our application and one of you out there adds a new comment to the list,
03:02
we're gonna see it immediately. Anyone that's looking at that list is gonna see that change immediately in our browser, and the framework handles this for us. So, as the developer, we're not having to move any of our application to the client. It retains this traditional server-driven architecture.
03:22
So, let's look at an example of that together. So, this is a blog that we're building. There's kind of a story behind this. So, we wanna build a blog, but we want it to be a little bit more than just a place to throw random thoughts out. We wanna think of this more as a place
03:41
to start a conversation, right? So, we wanna make this engaging for the reader, and we're gonna do that in a couple of ways. You'll see the two counters. There's a blue one and there's a gray one. The blue counter indicates the number of active readers. How many people are currently, right now, reading this page? And the gray one is the total number of readers
04:02
across the history of this blog post. Underneath that is a comment form, and underneath that is where the comments will be listed. Right now, there aren't any in our database, so we see an empty message. Now, this is built. This is already built in Pacquiao. So, let's simulate usage of this between two clients
04:22
and kind of see where things stand. So, you'll notice as I'm refreshing, it shows up in the one client but not the other one. Same thing with comments. In fact, it's not until that second client refreshes their screen that they're gonna see
04:42
that new state. So, let's fix this. Let's make this a little bit more of an engaging UI. So, we're gonna start by opening up our routes. This is gonna look very different than something you might see in Rails, and we're not gonna try to understand everything that's going on here.
05:00
But what we're gonna do, we're gonna focus on our statistics first, the two counters. We're gonna make those start to render in real time, then we're gonna test that out, then we're gonna come back and do our comments. So, there's two steps that we're gonna take here. We're gonna find the bit of code that's responsible for rendering our counters, and we're gonna add a call to subscribe.
05:22
Oh, great, I can see it right here. So, what this is doing is telling Pacquiao that we want to subscribe this rendered view to any future changes in state that might occur that would affect its rendering. So, that's the first step. The second step is we're going to write
05:44
a client-side JavaScript component. This component's gonna be responsible for rendering the state on the client. Just kidding. We're not gonna have to do that. We will not be writing any JavaScript today, I promise you. I didn't lie in my abstract.
06:02
So, in fact, adding the call to subscribe and telling Pacquiao that we want this view to keep up with its state is all that we have to do. So, let's go back to our browser and test this out. So, we're gonna reload the pages. Notice they're out of sync.
06:21
We're gonna reload one client, and all of a sudden the counters start counting together. We can continue doing this. You can even see the blue, and it goes down to one, and then it comes back up to two as the connection is lost and then reestablished with that second client. And we didn't have to write any JavaScript. All we did is told Pacquiao what we wanted it to do,
06:42
and the framework figured out how to make it happen. So, our comments still aren't really working well, so let's fix that next. So, we're gonna go back to our routes. Here's the code responsible for rendering comments. Add a call to subscribe, just like we did with statistics. And we come back to the browser, reload the changes,
07:03
and if everything works properly, we're gonna start to see comments show up. And in fact, we do. So, one client adds a comment. Any other connected client's gonna see it immediately on their screen. We can go the other way, too, if we want. And again, we didn't write any JavaScript to do this. This is all happening in a server-driven environment.
07:25
You might have heard of Node.js. We embrace Node.js, and I kinda like to think that maybe this is what they were going for when they built Node. It was just a misunderstanding, like somebody had a cold and they said Node.js and someone interpreted it as Node.js and went off and built that.
07:41
I don't know, just a theory. And I wanna be clear, I like JavaScript. I like writing JavaScript. What I don't like as a developer is having to write code that's largely unnecessary. And I think a lot of the JavaScript that we write today is completely unnecessary for us to do.
08:01
So, if we're not writing client-side JavaScript, how in the world is this working? And that's a fair question. Thinking through this, you might think, well, we're trans-compiling our view rendering code that's written in Ruby, and we're trans-compiling that into JavaScript, and we're sending that down to the client and executing it.
08:21
No, we're not doing that. I don't think that's a very good idea. At the end of the day, this approach requires you to build an application in a particular way. It doesn't give you full freedom to build a traditional server-side application. So then you might think that, well,
08:40
we're, when the state changes, we're doing a re-render on the server, we're building up the new HTML, and we're sending that down to the clients. And we're just doing a replacement of the DOM, or even part of the DOM. No, we're not doing that either. I think this is probably a better solution than the first, because at least the server
09:00
is always doing what the server knows to do, and that is, in a server-driven world, render HTML and send that down. So at least it has that going for it. What I dislike, and why we avoided this in Pacquiao's implementation, is inevitably, you replace more of the DOM than you need to.
09:21
So we were really interested in performing the fewest number of DOM transformations necessary to render the new state. So how does this even work? It seems like we've kind of exhausted all of our potential options here. Well, we haven't, Pacquiao works in a different way, and I want to explain this,
09:42
but to really offer a good explanation, we need to step back a little bit. We need to build up some context, some context about how Pacquiao started, the initial problems it was built to solve, et cetera. So, welcome to 2011.
10:01
This is when we first started working on getting a real release of Pacquiao out the door. It's been around for a long time. So I think the first release was August of 2011. And at the time, I was working for Metabon, which is a consulting agency that I started back in 2007. We build web-based apps for all sorts of customers.
10:23
We were working in Rails, mostly, at the time in 2011. We're still around today. We still do some Rails development. And for the four years or so that we'd been in business, we had some unique processes. At least, I think they were pretty unique,
10:40
at least at the time. And we called this process View-First Development. Now, our priority with View-First Development was to get something in front of project stakeholders that they could see and touch and use in a browser as early in the project as we could.
11:01
So when we started a project, we would meet with project stakeholders and we'd determine what in the world it is that we're building, we'd figure out the feature set, we'd prioritize that, and we'd start with the top, the highest priority feature. The kinds of applications that we build are mostly, they mostly involve user interfaces. And so that was what we wanted to start with,
11:23
because that is the tangible thing that we can play with together with the project stakeholders and really use that as a way to talk about some of the more abstract conceptual details of the feature. And the way we wanted it to work is we wanted to create a useful prototype building just the view.
11:40
We didn't want to have to build a prototype application, we just wanted to write the HTML views, the thing that was presented in the browser, and start there. So we'd use that, we'd deliver that in a day or two, we'd iterate on that with the project stakeholder, we could throw it out and start over if we wanted to because we hadn't invested much time. So once the prototype was nailed down, we wanted to build the backend on top.
12:02
So this employs sort of this consistent forward movement. We didn't want to throw out previous work and start over, we wanted to build on top of everything that had happened previously. And the third goal of View-First Development and how we wanted to be building our applications
12:21
is we wanted to be able to revert back to the prototype at any point. So we don't build things in a waterfall fashion, we weren't prototyping the entire application up front and then integrating it into the application and then shipping it. We were doing this one feature at a time. And what we found with technologies such as Rails,
12:42
and Rails is the only one that does this, most server-side frameworks do, is we'd build our prototype in HTML, ERB templates that just contained HTML, they didn't have the Ruby sprinkles. When it came time to integrate the feature into our application, we would sprinkle in the Ruby code and that pretty much destroyed our prototype. We couldn't just see the raw HTML
13:03
without our Ruby sprinkles, so we kinda destroyed it. So that meant when we started building the second feature, we could see its prototype, but we couldn't see it in context of the original feature's prototype. And that made it kinda difficult working through that with stakeholders because they didn't understand why they couldn't see the same thing
13:20
that they saw before. So we really wanted to solve that. And that ended up being really difficult. So we did the only logical thing that we could think of to do at the time, and we built our own framework to solve this very specific problem. When we set out to build PakYow,
13:43
we really had this one goal. This is a pattern that I and a few others had noticed in every single web technology that we'd ever used since we started building it. I guess early 2000s is when I started. And that is that the presentation side of web applications combined two things
14:02
that we thought were really separate and should be treated separately, and those are view structure and rendering logic. So if we look at an ERB template, here we're just iterating over a set of posts and we're rendering an article for each post, and we're putting the value of body into the paragraph deck. And there's two things represented here. There's the structure of the view,
14:21
which is the HTML, and there's the logic to render it, and that's the Ruby sprinkles. And this, if you look at this, it has some semantic meaning to it, the ERB template does, right? We can look at this and we can see that our article tag really does represent a blog post or a post object in this case, right?
14:40
Because we're creating one for every post that we have in our dataset. And we can also see that the paragraph tag represents the body because that's the value that we're sticking into the body tag. So this ERB template has some amount of semantic meaning to us, and that's lost when you build it because you end up with just the HTML. So you lose the semantics of it.
15:00
So we set out to try to save this. So what you see at the bottom is a Pacquiao view. It's the same exact thing as the top. You'll notice there's no Ruby code in this, but there are, however, two attributes. There's a data scope and a data prop. Now, in Pacquiao terminology, a data scope represents a data type.
15:20
So here we're saying that this article represents a post in our system. And the paragraph tag which is nested within the post represents an attribute of it. So the paragraph tag represents the body of its parent scope or post. And that's all the view is in Pacquiao. We can stop there.
15:41
Now, the logic to render it looks something like this. This is just an example. This is, there's many different ways that you can do view rendering in Pacquiao, but this is a simple one. And you'll notice that this doesn't really look like we're rendering HTML. There's no DOM transformations that we're needing to express. Instead, what we're doing is expressing
16:01
our rendering logic in context of the semantics represented by the view. So we're not saying find the article tag in the view and render that. We're saying find me the node, whatever it happens to be that represents the post in my presentation, and apply this data set to it.
16:21
Now, apply is not magical. It's actually pretty simple to understand. So let's look at a couple of examples. So if we have a hash, just a single post object that we want to present, and we apply that to our template, what apply is gonna do is two steps. First, it makes the view template match the data structure that we're applying to it.
16:42
So here that's easy. There's no changes required because our template already represents a single post. We're only applying a single post. So all apply has to do is map the body value right into its place in the template. So we're left with a result on the bottom. Looking at a little bit more complex example
17:00
with two posts, now apply has something to do. Our template only represents one post, but we're trying to present two. So it creates a duplicate, and then it can simply just map the values into the view. And that's all view rendering is in Pacquiao. Okay, so let me wrap that part of it up. Right? This allowed us to do exactly what we wanted.
17:21
We could prototype writing the HTML. We could add the backend code. We didn't have to change our views to do so. And at any point, we could just turn the view rendering part off, and we'd be left with our prototype. So we effectively solved our goals. So we built applications this way for a few months, and we quite enjoyed it.
17:41
And I had this idea, this sort of nagging feeling in my brain that I couldn't shake. Now, keep in mind, this was right around 2012-ish, and single-page apps were starting to become more popular, gain more momentum, as were client-side frameworks. And I couldn't shake the feeling
18:00
that maybe we had something to offer to people who wanted something more than just static views presented in a browser but really wanted a dynamic user experience. And I thought Pacquiao might have a unique solution to this. And it stemmed from this one idea. So this is our first rendering example. And you'll notice that our rendered view
18:21
still has the semantics that the template has. We still know what every node represents in this rendered view. Okay, so we can actually use that previous render as a starting point for the next one. So if we add another post to our state, we don't have to start with the original template. We can start with the first render
18:41
and just build on top of that. And we're left with the exact same result. So it was this idea that rendering is additive, and the code to render the initial view, maybe it's enough to also render changes to an existing view. Now, view rendering in Pacquiao happens on the server.
19:02
It's presented in the browser. And that means what's presented in the browser still has those semantics. We know exactly what it is that it represents in our application. So we already have that piece. We already have a template that we can work from. So all we need now is to get the transformations down to the client, and theoretically, with some magic,
19:21
we can make the client update itself. Okay, so let's walk through a full example of this. So we have the client and the server. Client asks the server for the initial view, and the server responds with a full HTML response presented in the browser. Now, subsequent updates. They also originate from the server.
19:41
So the server is telling the client how it can update itself. And this happens with something called UI transformations. And the way that we build these transformations is we execute the exact same rendering code that we used for the initial render, but instead of rendering HTML,
20:01
we just record the transformations that need to occur. So we're not transpiling that code into JavaScript. We're just creating a set of instructions for the rendering that should occur to reflect the new state. Now, that's just data at this point. It's just a large data structure.
20:22
We can actually serialize that. So that's what we do. We serialize it as a JSON object, and we shove it down a web socket to any client that should be concerned with this state change. Now, there is a client-side library that's part of Pacquiao called ring.js,
20:40
and ring is what receives these transformations and does something with them. So ring, it has the template, now it has the transformations, and all it has to do is step through the transformations and make the necessary updates to reflect them in the view. Now, this happens through something called the View Transformation API.
21:02
So because we've separated our view structure and our rendering logic, we're left with this nice seven methods or so of how we express our view rendering in our Ruby code. And we implement that on the back end in a class called presenter. Presenter's the thing responsible for doing the initial HTML rendering.
21:23
But ring.js also has a client-side implementation of the same API. So when it receives the UI transformations, those transformations are expressed in this common API, and ring can just iterate over it, call the right functions on the client-side, and it's gonna make the browser reflect the new state.
21:51
So Pacquiao falls somewhere between a traditional and a client-side framework, right? It's server-driven, it's a server-side framework, just like Rails, we're getting full HTML responses,
22:03
but once rendered, we're really getting this client-side behavior, but again, we don't have to move anything over to the client. Not even Pacquiao has to move anything to the client. All of our code stays Ruby code, and it stays server-side. So thinking about how we might do this in other server-driven frameworks,
22:23
inevitably we adopt some sort of hybrid approach. So let's just use Rails as an example. If we care about building our real-time blog in Rails, we might do the initial rendering on the server, so that we can still send the full HTML response back.
22:41
Then we might use some client-side tool, maybe EmberJS or Backbone, or maybe you could even use Action Cable for some of this. And that component is responsible for making the client-side state changes as it needs to. So we get that dynamic view. But what we've done is we've kind of,
23:01
we have two problems now, right? We have two code bases that are executed in two different contexts, and they're both concerned with the same thing, and that is how to render our state. Some of that's on the server, some of that's on the client. And this just kind of creates this web of complexity. And it leads to more complexities the further down the rabbit hole you go.
23:20
I think this is largely why people started building single-page apps to begin with. It's conceptually simpler to understand, right? We started off when we were building a server-side application, we only dealt with state on the server, now we've got this hybrid thing and we have to manage two code bases that both render state, so let's just move it
23:41
all to the client and do it there. And on the surface that kind of seems maybe a good idea, and maybe for some kinds of applications it is a good idea. But I really think that single-page apps break the web. And this is a pretty bold statement, but I really believe this.
24:00
If you look back at the entire history of the web, it started off as this server-driven thing. It was a series of hyperlinked documents that were provided by some server. And you were guaranteed to receive exactly what you wanted back in the response from your request.
24:20
With the single-page app model though, if I request a blog post, what I'm gonna get back is an empty skeleton of an HTML file with a JavaScript to include. Hopefully I can load the JavaScript, the CDN's not down or something. And if the JavaScript can be fetched and can be executed,
24:41
then it's gonna make another round trip to the server to get the data through our API, and then finally we can do the rendering, right? And this is a complete departure from how we've been building applications for decades. This isn't how the web works. Every successful technology built on the web
25:00
builds on everything else that was there before. And it just feels like a shame to throw out the server-side applications that we've been building for so long. So in Pakyal, we implement real-time as an enhancement.
25:22
So thinking back to our example application, what we first demoed and what we first saw in the browser was just a static view. That's all it was. Just like any other backend-driven application, like a Rails app or a PHP app, it was the static thing that didn't change in front of you, right? And what we did is we went into the backend code
25:42
and we just told the framework that we wanted it to be subscribed to state changes. That's all we did. And the framework added that into our application, but it did so as an enhancement. It's just a layer on top. The application continues to work even if real-time doesn't work, okay?
26:01
So let's say, for example, someone visits our application without JavaScript. Well, no problem. The first response is a full HTML page. It's already rendered, we can present it. Okay, well, that's not very likely, right? No one disables JavaScript anymore. Well, what if your CDN's down and we can't fetch your JavaScript? That happens to us.
26:21
Maybe we're just not good at ops, but I think that's a common problem. Not a problem, right? Same thing, we still have a rendered view that we can present in the browser. And I think this really reflects the spirit of the web. Right, it really is real-time as an enhancement on top of how we've been building applications for decades.
26:48
Lastly here, I love Ruby. And I don't mind JavaScript, but given the two, you know which one I'm gonna pick. I love the language. And that's what drew me to Rails, right?
27:02
In 2005-ish, when I first started hearing about this thing I was like, oh my goodness, look at how we can build applications. This is awesome. I've been stuck in PHP for so long and I've lost my soul, and here's this awesome way of building things. And Rails has a lot to do with that. Rails is a fantastic tool.
27:20
It allows us to build things in a much simpler way than before, with good patterns and processes. But at the heart of Rails is Ruby. And that's what I really wanna build my applications in. I think as developers, we need options. We need options for how we build things. I don't like this migration towards the client
27:42
and even on the server, having to write JavaScript to build our applications. That just seems like a shame. So where's this project going? So this real-time stuff has been out for about six months. It took about two years of work to figure out how we were gonna make this work. But it works.
28:02
There are production applications, some of them we've built, some of them we have not, that use Pakyow UI and Pakyow Realtime to provide these dynamic views to people in the browser. So we feel like we've solved the hard problems now. We've got all that figured out.
28:20
Now we just have to make it a better framework because if you've ever tried to use Pakyow, documentation's not great, the APIs aren't exactly perfect, and those are the things that we wanna fix. We really have this vision for, Pakyow makes it possible for people to build applications in a completely different way
28:41
and to build these server-side applications that feel like modern client-side apps. And we wanna bring that to people, but more than that, we want this to be the easiest way, even easier than a client-side framework. We want someone to be able to pick this up, build these applications, do more, much easier.
29:00
And that's really the focus of 1.0. So hopefully it'll be out later this year. We'll see, we're not really putting a date on it. We'd love your help. As I said, there's a small community around this. We're really passionate about this project. I think you kind of have to be to work on it for five years. I love building apps in this way.
29:22
You can read more about Pakyow. We have a website, Pakyow.org. We've got guides and documentation. You can build a real-time chat app in, I won't say five minutes, but half an hour, I'd say. Fair enough. And we walk you through how to do that and deploy it to Heroku.
29:40
We're on GitHub. Give us a star. Follow along the development. There are open issues at Pakyow slash Pakyow. And on that note, I did wanna mention that we've started doing this thing with our issues. We label some of them as starter issues. So we're really interested in pulling people from the community in, and some of these,
30:01
because Pakyow has such a weird approach to things, people didn't really know where to start. They didn't have the confidence to begin. So we went in and said, okay, yes, this. It's like two hours or less of context building, we promise, and you'll be able to complete this work. So if you wanna find a place to jump in, look for a starter issue,
30:21
you can follow Pakyow at Pakyow. You can follow me. I'd love to talk more about this. This is something that I'd love to talk about. Thank you very much.