skip to content

AnalogJS is the full-stack meta-framework for Angular

with Brandon Roberts

There’s a whole lot of interesting innovation happening in AnalogJS. Creator Brandon Roberts will teach us why it’s exciting, whether you’re an Angular dev or not.

Topics

Transcript

Captions provided by White Coat Captioning (https://whitecoatcaptioning.com/). Communication Access Realtime Translation (CART) is provided in order to facilitate communication accessibility and may not be a totally verbatim record of the proceedings.

JASON: Hello, everyone. And welcome to another episode of Learn with Jason. Today on the show, we are going to touch on something really exciting. We're going to be looking into how Angular is evolving and more particularly, how a metaframework is coming out on top of it, which was a little controversial, but it's something I'm really excited by. To teach us about it is the creator, Brandon Roberts. How you doing?

BRANDON: I'm good, Jason. You came right off the top with the controversy. So I'm going to jump on into it, go to it. [ Laughter ]

JASON: I mean, it's one of the things that I have really admired about the way you've handled this is that you are both pushing boundaries and also listening to feedback. Which I think is a pretty rare combo. And I'd want to talk a lot about it. Before I do that, let's make sure everybody knows who we're dealing with here. So for folks who aren't familiar, can you give us a background on yourself?

BRANDON: Yeah, I'm Brandon Roberts, I give the usual pitch, you can follow me on Twitter, Brandon T. Roberts, I block people sometimes, but it's all fun most of the time. Unless we get into the controversial topics, but... that's another thing there. I also am one of the maintainers of NGRX, which has been in the Angular community for a while and creative AnalogJS, which we'll get into. But I've been able to do some cool stuff in the community. Build some things with friends. Kind of keep the community thing going. So, also, engineering lead at Open Sauced, work with wonderful people there. Including Brian Douglas and the rest of the squad. So, yeah, we're doing a lot of open source and I'm happy to be here.

JASON: Yeah, I've been super impressed by that team. Seems like y'all are doing so much cool stuff out there. Just saw you launched the lottery factor, which I really enjoy. [ Laughter ] I've always joked about that and to see that kind of get coded as a metric. Honestly, it's a great metric. And I'm not going to tell anybody what that means. You're going to have to go to the website to figure it out. Let's talk a little bit in the kind of at the high level here. So Analog is a metaframework for Angular, is that the right way to characterize it?

BRANDON: That's the usual pitch, yeah. JASON: Cool. It does a lot of things that metaframeworks do. But the most interesting one for me, at least when I first saw you talking about it was that you've introduced the single file component approach.... into angular, which is, you know, my experience of Angular is that it tends to be very... it's safe to write at the cost of verbosity. You end up with a lot of files,which is good, you know what you're getting into and every Angular project looks the same, so skills transferable. But it also means you have a ton of files and you kind of need to use the Angular CLI to generate things. So Analog looks very different. What was your, like, where did the idea come from? What got you down this path?

BRANDON: Yeah, so the we call them the Analog SFCs, they've gone down a journey themselves. But I agree. I agree with what you said. Angular is great if you're like, if you're a backend, like you come with Java or Csharp shop and you're using classes everywhere. You're used to that P syntax for writing everything. And you kind of transition doing some frontend work with Angular, like the progression there feels very natural in those cases. But also, on the other side of that, if we look at Angular traditionally, like compared to like other frameworks, even outside metaframeworks in general. Just like you said, the verbosity of authoring components can be heavy at times. Some people may say it's boilerplate y because of the amount of things we have to, you have to set up there. The SFC kind of went through a few like iterations as far as what that kind of looked like. So I had thrown the idea. I've thrown the idea out there, you know, more than once, but it looked different. It was I was trying to, the first, I think one of the ones I had out there was basically an exercise in compromise. It was the what about this one? And it basically got trashed and everything. Oh, Angular's turning into React now, well, no, not really. They're fundamentally different how they work. But yeah, that was the first iteration. And then, the like the second iteration of it was, I was like, well, OK, let's kind of, you know, tweak things a little bit, see how this could actually work within the Angular mental model. And so, kind of went back to the drawing board and prototyped it out at first. I didn't have all of the pieces like to connect it together. And this was even before, even after Analog launched and everything. We were already building things with Analog, even just with traditional, call it traditional Angular components and things. JASON: Right.

BRANDON: Then we kind of moved along and me and a friend of mine actually were like pairing together on trying to get it working, using the alternative syntax, for single file components. One day it dawned on me how to connect the two things together that worked within Annular's I think worked within the Angular box, I should say. So the syntax is, it looks very looks similar to Vue and Svelte, and template tag and style tag.

Mm hmm.

BRANDON: You get underneath, you get like a modern Angular component. And that was the kind of the motivation behind it was, I wanted to see what Angular's already doing a lot of things to become more modern, I'm sure we'll kind of talk about that more, but I think like the component is one of the last, like, parts of that effort. And they say they're going to, like, iteratively improve the authoring format for Angular components. But that's because they have a lot of... they have a lot of other things to account for when building those components. And like with Analog, we could take a fresher, cleaner approach, I felt like. JA ya right. Yeah, one of the things that I've talked to Mark Tackson about because how many people depend on it and can't manage a big breaking change. Obviously, I mean, the Angular 1, Angular 2 switch, it was big.

BRANDON: Yeah. JASON: I think they never want to recreate that. I definitely understand their desire to be thoughtful and deliberate and to pace things out. But I think that's sort of like, I feel the relationship between the web and JavaScript frameworks in general is that, you know, the web can't break backward compatibility. It can't just add new stuff all the time. But it relies on JavaScript frameworks to try stuff. And make things work that don't work in the browser and, you know, let people discover what the right features are for building in our current era. And I think, you know, especially as some of these more established frameworks start to become, you know, legacy not in the sense they're like no longer useful, but in the sense they power some of the biggest things on the internet and can't break backward compatibility anymore. Then the metaframeworks on top, things like the Next.js's, the Analogs of the world, they can try stuff, break things. And that's OK. That's kind of what they're there for. And the stuff will get pulled back into the framework of a it's been proven out. Yeah, I love the approach of kind of experimenting and building on top of other people's good work. And you know, ill alluded to this earlier, but one of the things I really liked about the way you've done this, every step of the way, you're like, what do y'all think? And you know, a lot of people are like, this is super cool, and the small group is like this is terrible, I hate this, why are you changing things?

BRANDON: Pitch forks. This is the first I'm hearing about people not liking this stuff. [ Laughter ] I'm going to have to go back and check the history or something. [ Laughter ]

JASON: But so, I mean, I've felt like it's been so I don't know, I like the energy that's being brought to this because it's pushing the, you're pushing the envelope, also listening to feedback and iterating. You mentioned how many different tries it took to get to where you are now. I imagine the single file components are not the only thing that sets analog apart. What else is happening inside of Analog that somebody might want to try out?

BRANDON: Yeah, like I said, to me, the metaframework these days is I consider it to have like a core set of features for the most part. Some of them, you know, could be optional. But for me, the other SFCs aside, if you were just to walk into, you know and wonder what analog is about, there's a few main things there. One of them is like file based routing. In Angular, you have your traditional configuration base set up where you configure the routes, the folders, you create all of the components, you do all of that. You kind of wire out... you're responsible for wiring all of that stuff up manually. And in Analog, there's, we have file based routing, which is similar to Next.js, these other meta frameworks that build on the particular ecosystem. But you still got all of the power of the Angular router. You define files and folders using the standard convention there. And you can just build pages and routes on top of that. That's one of them. The other thing is service side rendering static site generation. This is, if you're, you know, traditionally, Angular has been, we only use Angular in Enterprise, so why do we care about SEO? But there are still people that maybe are building you're in an Angular shop. And you want to build some marketing page or landing page or something like that. And I've seen this over and over where they say, well, something like that doesn't necessarily exist in Angular today so we're going to reach for Next or remix or whichever the service side rendering platform of choice is. And they'll use that. So it gives you an option to build these static sites, and static sites and server side rendering there. API routes is another feature there. You can reach for, you can use this in browse folder where you just get an API built in. You have these endpoints you can create and this is where you can, you know, talk to the server, do different things there. And those are like the biggest features as far as what analog brings in terms of like what a metaframework is. And a lot of this is built on top of like Vite and Nitro. Those are the few things I kind of consider like table steaks for meta frameworks these days. JASON: Yeah, I would agree. And I think you brought up a great point on Angular for Enterprise. Where that's true, but even if your company builds their whole dashboard and it's all behind user log in, SPA, it doesn't matter. You know somebody's going to be loading the SPA way. You don't care about SEO, some of the things that a meta framework might provide. The thing that becomes a bummer about that, is from a team standpoint, you still have to your marketing team still has to go out and build landing pages, the webinar pages, the support docs, all of these public facing things. And if you try to build that without the static site gen or the SSR, you kind of you end up, what I've seen happen in practice, is the companies end up with multiple frameworks.

BRANDON: Mm hmm. JASON: We built our app in Angular, but then we reached for, you know, maybe it's 11ty or it's React and now they've got competing design systems and now, they've got like all of these challenges of getting things together. So really exciting thing for shops that would consider themselves Angular shops is bringing in Analog can actually solve all of the nonapp things that you are currently using other tools for and let you share one design system across all of them. It's just Angular components, right? There's a really and I think this is one of the big appeals to React was that you can kind of bend it into any shape you needed it to. And so, companies would say, well, we can use it everywhere, so we're going to standardize on it. And I think that this gives Angular that same flexibility to say, yeah, we can use it everywhere. So we're going to standardize on it.

BRANDON: Yeah, I agree. I've always talked about like Angular and React as far as one is like a framework. Angular's a framework, you can mold it and build it into whatever you want it to be. Whether it be a static site or landing page or a full blown app. And some of those things have evolved in Angular, also, where they're building more of these primitives that allow projects like Analog to build on top of that. It's exciting to see that how, like, Angular kind of has continued to evolve in that way outside of even just a framework itself making these changes over time. But yeah, like you said, there are people devs who work in a particular shop. They prefer a certain stack, and now that there's an option for them, nothing to take away from these other options, but they use what they're familiar with. And that tends to work out better, you know, for maintenance and even like long term support and things like that.

JASON: Absolutely. Yeah. Well, OK, so I could probably talk about this for like days, but I want to try it, so let me flip us over into the paired programming view here. And let me get this little banner up. I'm also going to show the captioning link. So our show is being live captioned, we've got Diane here from White Coat Captioning, thank you so much, Diane. That's made possible by our sponsor, Netlify. Thank you, Netlify, for making the show more accessible. And we're talking to Brandon. I already showed the link, but I'm going to drop this, again. So make sure you go give a follow, do all of the things. And we're talking about AnalogJS. Here it is.

BRANDON: There you go, the SEO juice is working. JASON: All right. So here's Analog, and if I want to give this a try, what should my first step be?

BRANDON: Yeah, the first step, you could go to read the docs. Which I will give a quick plug here for Stack Blitz, you can open it if you want to tinker around, but for the purposes of here, we could go to read the docs and run it locally. JASON: Cool.

BRANDON: Yeah, the intro page gives you an overview of what kind of the some of the features of Analog and we can kind of get in more of the some of the things that Analog unlocks in the broader ecosystem, too. But yeah, if we go to getting started. Yeah, and then, we'll have a create new applications, yeah, you can copy that. JASON: Let me get one of these. I'm going to get over here. There we go. And then, I'm going to come out here, we're going to create a new one. And, there we go. So we'll call this

BRANDON: Yeah, give it a name here. JASON: Analog... going to give it a name like that. All right. So which one should I start with today?

BRANDON: We could start with full stack application. Couple ones there, full stack or blog, if you know that you want to just build a personal blog there, I would just kind of have a little extra templating there out of the box there full stack is kind of the most common one. There are actually people building full stack apps, not just static sites, but full stack apps there. JASON: Very cool.

BRANDON: You have the option to use tailwind, it false by default. But people have that preference there. I know people have preferences. JASON: Yeah. And I don't know tailwind very well, so I will be faster without it, I think.

BRANDON: Yeah. JASON: We're in the project here, and while that's installing

BRANDON: Yeah, takes to install, installs usually dependencies there. Most of this will, I say once we get into the project, most of it'll look familiar because it's intended to be that way as far as things that you normally use with Angular should feel familiar there. And then, the SFC is kind of a step in a different direction. But that's yeah, that's a different thing. So
JASON: Yeah, under the hood, we've got the Angular pieces, here's the Analog stuff.

BRANDON: Content package, which is for the full stack application, the content package is just kind of included there. It's not necessarily being used yet. But we can get into like some of the with some of the routing and things, how you can use that package there. But then, there's the AnalogJS router package under that. This is where it kind of connects the file based routing to the Angular router. But we can we'll walk through some of that, too. And like I say, you've got your typical Angular things here. JASON: Mm hmm.

BRANDON: Angular packages and some of the other ones are for content things, also, like front matter. JASON: Front matter, markdown. Syntax highlighting.

BRANDON: We've got some stuff cooking there. JASON: Cool. Very cool.

BRANDON: Still on the way there. JASON: Excellent. All right. So I'm should I just run the dev?

BRANDON: Yeah, we can walk through some of the files, too, if we want to take a look at those. But yeah, it's typical setup here. We're still using the Angular CLI here. JASON: What did I do here?

BRANDON: Did we use NPM? JASON: I used NPM.

BRANDON: OK
JASON: It doesn't...

BRANDON: Yeah, there. I'm going to not go on a rant here about peer dependencies. But for this, we can run a command NPM install we won't do legacy, you can do NX dev kit. And then sorry. @dev kit and we'll install a couple other ones, too. NX/vite. And then NX/angular and nx by itself. That will cover all the things we're missing there. JASON: OK.

BRANDON: Usually, it would have them as peer dependencies and they're just included in the setup there. So we got that. JASON: Got it.

BRANDON: Got the message there. And able to kind of boot up things there. It should be on 5 173. JASON: There we go. We've got the, you know, the framework landing page. It's got some details, it's got the counter. And now, let's take a peek at some of these files.

BRANDON: Like I said, typical Angular setup here. Some of the files look familiar if you're familiar with Angular, we've got the Angular JSON file there. And then under app folder. Angular JSON, this is mostly a lot of config. Here. Just to set up the Vite, the AnalogJS builder. I will mention that the Angular CLI, like, I'll say classic traditional Angular also uses Vite as a dev server, but we're using it on both sides to build and to serve everything.

So, I like Vite a lot, and I feel like the Angular ecosystem should have more of it. So, which is also a good bit of motivation for this project. Angular JSON is there. And if we go under the app.config.ts file there. We have usual setup here. This is just some configuration for it needs for starting up the application. So like, zone change detection, that's kind of a relatively new thing that was launched in V18, Angular V18. And then, the provide file router is kind of where we want Analog package imports here. Traditionally, you could import provide router from the Angular router, but that will say you're like I'm going to configure these routes myself. I'm going to go create some files, go create some components and kind of wire them up, and I'm going to set the path and I'm going to set the configuration and everything, but the file router itself scans the pages directory in your application and looks for those particular pages. Things that we have set up as pages. And then, we can it'll create URLs out of those. That index page is already wired up and ready to go there. So yeah, if you go into pages. JASON: That's this one here.

BRANDON: Yeah, just that slash route we initially went to there. And most of this is, you know, like I said, pretty standard Angular component. Pretty standard Angular component. One thing that is slightly different here is we're exporting the component as default. For the routes. So just convention who are using those pages. Outside of that, pretty standard Angular component syntax here. JASON: Got it. There's a question I want to ask before we get too deep here because we just installed some NX stuff. How easy is it to Analog into an existing work space?

BRANDON: Great question. I promise these aren't plant questions, but
[ Laughter ] Yeah, it is, you can integrate into an existing NX work space. And we do have, there is a page in the documentation where it can actually generate, if you want to jump back to the docs really quick. Go to integrations. And then, there's an NX one there. We talk about how NX how you can add analog to an existing NX work space and actually generate from scratch in an NX or an AnalogJS within an existing NX workspace. And this works across versions of Angular, too. If you're on we just released version 18 of Angular, but if you're in NX workspace is maybe an older version for some reason, it'll kind of adjust accordingly there. JASON: Very cool. Speaking of Mark, what's up, Mark, how are you doing?

BRANDON: Thanks, Mark, appreciate you, always. JASON: All right. So, I'm confident we can get this set up alone or set it up into an existing NX workspace. We've got our components. We've got the file based routing.

BRANDON: Yeah. The convention here, I would say it's more similar to Remix file convention in Remix where you can have index pages or if you want to do like nested layouts, you can also do those, also. Which you can walk through an example of nested layouts and things. And then, we can go through content routes and things like that. But
JASON: Yeah.

BRANDON: If we want to create another page, let's say an about page, under pages, create a new file called "about.page.ts." JASON: About.page.ts.

BRANDON: And then, we have to do the usual song and dance. They do @component to create a new Angular component. Yep, and bring that in there. And then, it's a decorator, you call that as a function. Yeah, and then you put an object inside of the decorator there. And we're going to add a couple of things here. We're going to say it's stand alone, true. Yep. And then, we'll add a template in there, also, and this will just be the contents of what we want this component to display. JASON: We'll make it nice and simple for now.

BRANDON: And under the component, you can export default class and name it about page component. And then, save that. We should be ready to rock with this one. If you go back to the browser and go to the... yep, about there. And we have an about page. You can quickly, you can see quickly how we can go from just a general like we didn't have to set up any configuration, which I say you can still do with Angular router today because this is built on top of that. But setting up a page component here, we were able to set up this page file, and now, we have a route here. But the good thing is if we had other components in this particular area, like and you wanted you didn't name them .page.ts, they wouldn't be registered as routes. You can kind of colocate the components to this particular area. JASON: Gotcha, gotcha. Question coming in from the chat, is this ready for production?

BRANDON: I'm glad to say it is. We actually launched our 1.0, man, it's been I can't remember what is if you go to our dev.2, we have a blog post, blog post dev 2/AnalogJS. There it is. Launched 1.0 back in March, actually. So we launched 1.0. So we've just continued to iterate on things since then. But yes. We consider it to be stable and ready to use. And people are using, you know how developers are. They were already using it. Before the 1.0 hit and some people just needed that stamp on it. To start using it today. Using it in their kind of like say, enterprise environments or Angular shops. But this definitely been making the rounds already. JASON: Very cool.

BRANDON: Yeah, so, that was just one example of a route that we could create. We can also create dynamic routes, new ones that have parameters in there. If we create a page. Let's say we want to create, let's say what kind of URL do we want to create here? Just to kind of test this out. We can create one with an ID. JASON: Yeah, we'll do one with an ID and we can make it an echo thing. We'll show the current ID on the page.

BRANDON: Yeah, that works. We can say name, or we can do we could do depending on how we want to do it. What do we want to call the path before the ID? JASON: I mean, let's

BRANDON: Want to prefix it with anything? JASON: Yeah, we'll prefix it with we'll call it article and then give it a slug. Is it square brackets?

BRANDON: Yeah, to create dynamic parameters, you can put the slug in square brackets and .page.ts there. JASON: Sweet.

BRANDON: Yeah, we have that slug.page there, and then, we can create another component in here. And we'd do the same thing there. We have the export there, export default. JASON: Article.

BRANDON: Article page component or article component, the component name is just less descriptive, default class, excuse me. JASON: Right.

BRANDON: Before article component. And then, we have our component here and start this one with stand alone
JASON: What am I doing? I know how my keyboard works.

BRANDON: The object inside of there. Yeah. There you go. And then stand alone true. And then, your template in here. And we are using in line templates here. And you can use in line styles and templates, but for those who prefer external templates where you can define those innen a external HTML file, that's supported there, also. But for the sake here, we're keeping things nice and clean. You could say current, and then
JASON: That's where I want to get the slug.

BRANDON: But we'll wrap that in two, I think you call them curly bois. You don't need the dollar sign, though. JASON: Oh, nice.

BRANDON: Two curly bois, and create a thing called slug there. And we'll go into the component class itself and use that there. We'll name this one, yeah, name this one slug. And then say that equals, oh, sorry, before that we'll inject the router, we'll name a property called router, and then, or sorry, let's do route. Not router. Route equals inject, lower case inject from Angular Core. This is Angular's way of doing dependency injection without going through the constructer. In here, we'll do activated route. So capital A Activated route. We can inject that.

JASON: OK.

BRANDON: Next, we'll create the slug property, and then, we'll say this.route. And then, we'll say we'll say, we can do the param map I would say. Param map. JASON: OK.

BRANDON: And we'll do a little bit of RX.js. The pipe operator there. That second one. Yep, and in there, we'll do a map. To just take. We're going to get the
JASON: Wait. Sorry. You'll have to walk me through this.

BRANDON: Yeah. We'll do just a little bit. We won't get down into the weeds. But yeah, if you type the word map and then it should pop up the operator from RX.js, and that'll be a function you can call, and then, we'll say params and then, just return. Params.get. Sorry, arrow function here. JASON: Like this?

BRANDON: Yes. And then, params, you can return that directly params.get and we called it slug, right? In that
JASON: Yeah.

BRANDON: We'll do that. And in the under the, we'll go back to the component metadata part and we'll go into import or create add property called imports. And we'll import the async pipe here. And we could use async Py. And Angular is, of course Angular is moving towards signals and things, but we'll just use this one for now. And someone else will mention in the chat about the with component binding, which you can use, also, but for this one, we'll just stick with async pipe for now. With the slug inside after the slug in the template in there, you just use the single pipe operator, or single pipe. After that, sorry. JASON: Oh, the actual pipe.

BRANDON: Yeah, and then use async after that. JASON: Oh, cool. OK.

BRANDON: That kind of wires up the slug parameter and gets the value from the observable. Once we get more integration with signals and the router, then this will be a lot less verbose there. You have to do article. And then, testing. So then, there you go. Now, chat. JASON: This is great. This is... yeah, this is every bit as straightforward as I would expect it to be. We have the parameters in here. We do the Angular way of getting the parameters, and we're off to the races.

BRANDON: Yeah. So, yeah, and like I said, we didn't have to configure any of this because the like I said, we're scanning Analog is scanning the pages directly for routes and, actually, you define we didn't have to say that, you know, this usually have to do the colon syntax and say this is a slug. JASON: Right.

BRANDON: But with the square brackets, we infer that from the page itself. So another way to a less verbose way to wire up your routing and things. Like I said, you don't lose anything from the Angular router in that case. We're still using the standard Angular mechanisms here. JASON: Yeah, and we can reach in and grab whatever we need out of the Angular router.

BRANDON: Yep. JASON: That's great. Are you still, I remember a while back, I saw you had shipped, I think originally, you were calling it .ng, and I think that was the source of some of the controversy, and you named it to .analog.

BRANDON: Yes. JASON: Are you still shipping those?

BRANDON: Yeah, we can use that in here, also, if we want to dive into that. JASON: Yeah, let's try it. This is what I saw. Where my eyebrows started going up past my hairline, I was like, oh, what's going on here? I should probably air quote hairline.

BRANDON: Yeah this is a big
[ Laughter ] Yeah, I was like, wow. This was a this was the big point of contention there with the .ng. And the honestly, I didn't think it was going to be that big of a thing just because we had said, you know, out front this was experimental, this was an analog thing, and everybody's like why is this coming to Angular? It's like, well, it's not coming to Angular, yet. But maybe it never will. But I think even the idea of it, I think, is a lot the idea of it is valuable to have out in the community. And for us to be able to iterate on it. It's gotten more positive feedback, I think, than the negative. We got the .analog haters out there. The class component tribe I called them. But then, we got some people who support it, too. So it's balanced there. JASON: Yeah, and so, if I want to do this, then, can I just call this magic.analog?

BRANDON: Yes, and we'll have to enable it, first. Like I said, it is an experimental thing. If we go down into the v config. Inside the analog plugin there. And this is under plugins, analog, open the object up there. And then there's a vite option there. Yeah, that'll be an object. And then an object in there and then we have experimental. And then, we'll have support analog format. We'll enable that. And, that is all we need to oh, analog.ts, we'll probably have to restart the dev server here. And then, we'll we can rename this so it has a page there. Missing entity type. JASON: I think, this is because it's an empty file. Probably just yelling because

BRANDON: Yeah, that's true. We haven't put anything in there, yet. So if we want to create, there's like the Analog files themselves, and then, you can create pages out of these, also. So if we want to just go straight to that, you could rename magic.analog to magic.page.analog. And here, we're going to create a component, let's start out simple. We can have a template tag. Just wrap that in. Template tag. Template tag there. And we can put something in there like, hello, Analog or magic. Yeah, let's call it magic. If you save that. You have to restart the I don't know if we need to restart, again, but it may recover after that. Let's go ahead and restart that, again. JASON: There we go. Now, if we go up to.

BRANDON: Magic. JASON: Magic. This is... this is cool as hell.

BRANDON: Yeah, if we just kind of compare and contrast, like, what we had to do before with the other, like the about page this was about as simple as we could get. We had to do a decorator, stand alone true, the template, export default just for maybe some static content, and we go to the magic, which was aptly named, of course. JASON: Yeah.

BRANDON: We drop a template tag in there, and we get a component that does the same thing. JASON: Yeah. This is truly impressive. Saying a framework for another framework, and it's true, but Analog is following in the glorious tradition of Next for React and Vue. This is something that I think, it really allows us to let the frameworks themselves the, you know, the libraries, whatever you want to call them be primitives and then, we make site builders or app builders or whatever builders on top of them by leveraging things like Vite, which is at this point, I think Vite is under the hood on all of them except

BRANDON: Practically everything. Almost everything. JASON: Almost everything. But Vue, Solid, Astro, Analog, they're all running on Vite now. If you're building for the web, unless you're using Next.js, you're using Vite.

BRANDON: Pretty much, I must say. And when we when we kind of talked about this before, at least Analog itself, Vite has enabled a lot of this to happen. Even with the file based routing, we're using Vite primitives under the hood. Like server side rendering, we're kind of connecting those through Vite plugin, there's a Nitro plugin underneath all of this that makes it happen, too. Vite is like a multiplier these days and allows framework authors, meta framework authors to be able to ship more stuff quicker without having to worry about these things. Because they're handling the heavy lifting on that. JASON: Mm hmm. So question about this with the single file components.

BRANDON: Yep. JASON: Excuse me. This format here, under the hood, I assume you've written some kind of transpiler, compiler or something that sort of unwrapping it into this?

BRANDON: Essentially, that's what we're doing. We're hooking into... we're taking the analog, you know, SFC and we're transpiling that into an Angular class and transferring that to the compiler. The compiler, I treat it like a spec, the compiler says need the components to look this way, I need the format to look a certain way. So we're taking that, like the femme plate, if you took, the template is essentially, you know, what you would drop in the inline template, and we create the component decorator and everything, kind of virtually under the hood. And that was the part that kind of like I mentioned, we kind of went back and forth on, and Joshua Maroney, he's been a real champion of this, also. But yes, that was like the bridge I wanted to create was, you could create the same Angular component without a lot less syntax, a lot less verbosity and get the behavior and things. It fits in the direction I think Angular is going as far as being simpler and with signals and everything. More manageable. JASON: It's still in preference. So Linda just asked the question that was going to be my next question, which is, how about if we want to take this a little bit further and we want to have a .analog component that includes something that we did like in our slug route?

BRANDON: Yeah, we can... you can have logic and things in here. So yeah, let's create another, another page here. We can call it magic slug or magic
JASON: Yeah, why don't we do that? We'll do magic slug.page.analog.

BRANDON: Yeah, that works. So here, we'll we can start with the we can start with the template part here. And then we can kind of work our way through that copy that same thing in there. JASON: And do we use the slug async?

BRANDON: Yeah, we can still keep that for now. Like I said, could've done it a different way as far as using the router component bindings or even convert it to a signal. We could've done that, too. JASON: OK.

BRANDON: But yes, you have your template here, and this is how you define a template. If we want to add logic here, we're going to add a script tag. I usually define these kind of like script template in styles, but the order really doesn't matter. So we're going to define a script. And on the script tag, we'll add like lang.ts to the script itself. So after the script, we do lang equals ts. JASON: Let me make this HTML so it stops yelling at me.

BRANDON: Looks a little better. We are working on, we do have VSCode extension that we've kind of gotten off the ground to help with syntax highlighting and things. JASON: Cool.

BRANDON: That would be something that people
JASON: Should I grab that?

BRANDON: Yeah, it'll help with the squiggly lines and things. JASON: Let's do it.

BRANDON: VSCode, still under in progress there, but AnalogJS features, there you go. JASON: I'm going to install that.

BRANDON: Probably get pre release. It's relatively new. So, yeah, there you go. Now, we get the nice syntax highlighting and the .analog icon there with the files, too. JASON: Dope.

BRANDON: In here, let's say we want to add the two same things with the route and the slug, so you can kind of copy those two well, we'll copy the imports from there. So, this is where you would do, oh, sorry, on the left side, we got that block of imports. You can copy those over. JASON: Oh, these?

BRANDON: Yeah. You can pace those in there, and then, the route on lines 12 and 13. We can copi... oh, sorry, on the class side of things. Copy those two. But on this side, we can create those as variables. We can say const route equals and const slug equals, you can take this out. We're working on those locally there. JASON: OK.

BRANDON: You can define them as const and let variables, or kind of use the other things that you're familiar with, like, with Angular, so if you need to inject more things here, you can do that. And those things will be available to the template. So, in order to make the like we have the imports there with the async pipe, we do provide like a bridge to be able to import like that metadata. But you can, yeah, you can nuke that component decorator because we don't need that. JASON: Don't need it.

BRANDON: Yeah, you can use the inject. We will need the async pipe, though. JASON: We will need the async pipe, OK, I'll get rid of the component decorator.

BRANDON: Yeah, and under the slug or under the imports, we'll use the import block there, yeah, we'll use the define metadata function there. This is kind of like a macro defined metadata, it's kind of like a macro, a function with an object inside of it. JASON: Oh, like this?

BRANDON: Yeah. Got it. This is similar to the component decorator, but we only use this as an escape hatch, when you need to mix some traditional metadata to the component. We'll do the imports there. And we'll do the async pipe, drop that in there. Yeah. JASON: OK. And this is globally defined or do I need to import this from something?

BRANDON: Yeah, it's globally defined. We're still working on some of the types and things there. JASON: Cool.

BRANDON: It didn't add any runtime costs to what you're doing there. JASON: Let's see, what do I got here? Magic slug page. And we've got this going here.

BRANDON: Slug, async. Let's go ahead and restart the maybe the dev server needs to restart there. Go ahead. I didn't see any slug, analog... yeah, that part's fine. Now, we're back
JASON: Home page, test, that's redirecting me home.

BRANDON: Error somewhere. Let's go back to the yes, I see there. JASON: Can't match any routes.

BRANDON: OK. JASON: Am I fighting it because I have a magic and then a

BRANDON: No, those two, as long as they're not conflicting those weren't conflicting pages there. JASON: OK.

BRANDON: Close that really quickly. And then, sorry, stop the dev server, and then, we'll let's do, just like a .vite folder in the modules, we'll delete that so it'll refresh the routes and things. Yeah, so if you delete that. Just start up the dev server, again. I think I got everything there. That page is back now. Magic test. JASON: Two components.

BRANDON: Two components there. Define metadata, missing something. JASON: Let's see.

BRANDON: It's not this is the magic page, right? Or is this the slug page we're editing? Which one is this? JASON: This should be let me this is magic.slog.analog.

BRANDON: Yeah, that looks correct. But the... yeah, what I'm seeing is like our template, we should be showing current, and it's showing magic. So
JASON: It's showing magic, which leads me to believe it's like catching

BRANDON: Oh, OK. This may be I see, I think I know what's going on here. Let's look at our file structure here. OK. I see what's happening. JASON: Do I need to make this one index and drop it in magic?

BRANDON: No, what happened is, we created a layout, basically. So if you have magic.page and then a magic folder, then we have a layout here. JASON: Oh...

BRANDON: Yeah, let's go in here and create a script tag in here. And then, we can kind of work through this script tag and import script lang equals ts there. Lang equals ts, and then, we'll import the router outlet from Angular router. And then, we'll do the define metadata, again, here. And in there, we'll do imports, imports and we'll drop the router outlet in there. And then, yeah. And under our template, we can use the router outlet, all lower case with a dash in the middle there. And it could be a self closing tag there. We'll do that one first. If we save that, and then, if we go back to... our magic page, was trying to see if it should render that under there, define metadata. Yeah, so what's happening, what's happening is we have a layout in our magic page, and we want to render its contents below that. So, that's where that's just a development warning there. JASON: Generated the same component ID, is that

BRANDON: No, that shouldn't affect anything there. But if we wanted to move that one, then we could add a selector there to the component. But we shouldn't need to do that. So let's go back to the magic page. Magic page.analog, go back really quick. Imports, router outlet. Let's just not do the self closing tag. Router outlet and a separate one there. Slash router outlet. JASON: There you go.

BRANDON: Self closing tag there. So there you go. Yeah, that was kind of an unintentional... we had an unintentional layout we were creating there. But it did kind of show off two things, that we were able to create the magic page there, and then, the outlet itself, we created a we accidentally created a nested layout. I did talk about that convention before where you have like I said, a page.analog and then, a folder and then, anything under that folder will be kind of a nested layout. So if we had a couple of links between different magic pages, then we could switch between those without like redestroying the whole layout. JASON: Yeah. Right, I could do something like, we'll do a

BRANDON: Yeah, we'll use a router link here. So yeah, sorry, it'll be an A tag. A space, router link. Lowercase r. Just make the r lowercase. JASON: OK. And you go to magic and we'd say, test.

BRANDON: You can take out the Href. JASON: We do test.

BRANDON: A tag. And we'll import the router link directive for that, too. And we can try a different it's another thing that we have. So we'll add it there. Because we can you can take that one out of there. We'll add a separate one, so under the Angular router, the importer line two, we can take that one out, the router link. And then just import on a separate line. And so, we import router link from Angular router. And then, what we'll do here is after this, we'll use import attributes. We'll say with, after the router, we'll do with, and then an object. And then, you can say "analog," and then "String" quotes. We'll do imports in a string after that. And this is something that we've kind of leaned into in analog itself where using the import attributes, we can skip like the define metadata part because we will handle that underneath. And it'll add those, like those directives or add those things that you import in the component itself. JASON: Oh. And would that work

BRANDON: Minimizes
JASON: Router outlet?

BRANDON: Same thing with that one, too. JASON: That's sick.

BRANDON: Magic test. JASON: It didn't like my... provide export router link.

BRANDON: Sorry, it should be angular router instead of AnalogJS router. And you can actually take out the define metadata. JASON: Whoa. Whoa, where am I? Here we are.

BRANDON: Oh, no. JASON: Magic test.

BRANDON: There you go. JASON: And you said I can take this out.

BRANDON: Yeah, you can take out the define metadata part there. JASON: That's cool. Because now, we're getting into, like, it's really starting to feel kind of I don't know, just feels like very cohesive like I'm not doing anything. Oh, my goodness. Look at it go.

BRANDON: You can link between the two components there. And keep the the goal is to, you know, you keep building. We didn't have to go back to configuration and touch a lot of other files there. We kind of managed those things inside of here. The import attributes is something that's specific to Analog. But it's well, it's a JavaScript proposal. I think it's in stage 3. But it is something that we're kind of leaning on to they've used this in other cases, too, like JSON there. We're using that to kind of decrease the amount of things you kind of have to import and define metadata for. Ideally, you could get pretty far without having to use the define metadata. That's like the bridge. It's like the escape hatch. The escape hatch to the component decorator in a sense. JASON: Got it. Question coming in, is it server side render or client side?

BRANDON: It is both, actually. So we are server side rendering, when we started up, server side rendering zone by default. We're server side rendering this page. And then, once you load it in the browser, then the client side hydration takes over. So, Angular hydrates everything in place. You know, where it can. If we turn off JavaScript, we're still going to get a render page here, we can navigate around, because we're still just using anchor tags with the router links. It renders those, just Hrefs on the server. And then, if we turn JavaScript back
JASON: Yeah, now that I've it's logging, again, now that JavaScript is running. But when it was off, disable JavaScript, and then, I start reloading, you don't get any logs. But it still runs.

BRANDON: Yep. JASON: That's slick. We've got like a functioning site built in Angular that doesn't require JavaScript to operate.

BRANDON: Yep. JASON: That's pretty dope.

BRANDON: Yeah, so we got to show off the SFCs there. Like I said, a lot of, again, a lot of positive feedback about them. We've kind of like I said, did a lot of iteration on them. And you can use them just as part of like I say, your normal workflow. We are using some, like I said, it is experimental. So because we are using some experimental Angular APIs and things. If you opt in, we kind of make that explicit by opting in that you can take advantage of that. So
JASON: Yeah, this is dope. This is extremely cool. What else, I mean what else do you want to show? I feel like we've covered a lot very quickly, which is pretty awesome.

BRANDON: Yeah, we can kind of walk through some of the content, the content side of things. JASON: Yeah, before we do that, let's peek at this. I want to see how these server routes work. I see you've got one kind of set up here.

BRANDON: Yeah, so, we talk about API routes, just having those out of the box here. As I mentioned before, we're using Nitro under the hood was a server engine tool kit. And it allows us to hook into the API routes and these are also file based. So creating the files inside the server routes folder, we get routes out of those. If we go back to the browser, you can visit this directly if you go to /API/V1/hello. And we just get the we have an API out of the box there. And this is similar, like I said, similar to what you would get in other meta frameworks, you can put your server side API logic and things. If you want to connect to a database. JASON: And we can import, we can bring in octokit, we can bring in our TRPC, our Firebase and just do app things in here and be able to access that on the, you know, through a frontend API route?

BRANDON: Yep, definitely. JASON: Very cool.

BRANDON: We also have, what we call server side data fetching. So if you wanted to, you know, put some logic, go fetch some data, go fetch something about page, we could load that on the server. We can use the article one for this. So if you go
JASON: Do we want to do it in the page or the single file component?

BRANDON: I think either one will work. We can do it in the page one for this example. JASON: OK.

BRANDON: Under the article, if you go to create a page, create a file under that in that same folder called article or sorry, called slug.page or slug.server.ts, excuse me. JASON: OK. So slug.server.ts.

BRANDON: Yep. And in here, we want to export a load function. Or it's going to be async function called load. And then, from here, we can just return... we can return an object that says load it true. You could do additional server things like connect to a database and fetch some posts or to dos or things like that here. JASON: Mm hmm.

BRANDON: That's one part of it. If we go to the root of the project and add an environment variable, or .env, excuse me. .env. And in here, we're going to define where the... our post is. We're going to name this and it's going to be all uppercase, upper snake case, I guess. So it'll be vite underscore analog underscore base underscore URL. And we'll hit the equals our host. Http/local host 173. JASON: Which I just learned the other day is code for cite. And now that I can see it, it's like site. Come on.

BRANDON: I'm going to date myself here really badly, but this reminds me of the pagers when we used to, like, the pagers spelled words like hello and other things like that. [ Laughter ] No, you've got to turn it upsidedown to see what the actual word is. [ Laughter ]

JASON: Yeah. Exactly that. OK. So we got this. And does that auto start with it does, the .env, so restarts the server.

BRANDON: Now, we can go back into our our slug. Sorry, go into our page slug.page there. And then, we some information in here. So we can import and inject from the AnalogJS router, we can import the inject load function. JASON: Inject load. And then, we're putting it in the imports?

BRANDON: No, we won't need to put it in there. You can put it in the ... in the... you can define the property in the class itself. We can just name it data. And then we can say equals inject load. And we'll use the... we'll add a generic. Before the parentheses, a generic in front of that. Yeah. There you go. And just put type of load in there. Sorry, import, sorry, import the let me take a step back. Yes, there you go. Import that load function there. Type of load. And that gives us type information about what we're
JASON: Now, we've got already

BRANDON: An observable of the data. That data will all be loaded on the server. JASON: OK. And so, in here, I can do something like, let's have this just dump whatever it is. So we'll do pre tag and then, we can

BRANDON: Yeah, do the double. JASON: What's the shortcut if I wanted to do a JSON stringify?

BRANDON: You have to use a JSON pipe, you have to add that to the imports. You could do JSON there and add it to the imports of the right there with the async pipe is. Yep, that JSON pipe. And then, you add that to the imports down there online 15. There you go. JASON: Great. Cool, it's not mad anymore. Great.

BRANDON: That was, for a server side data fetching, that's all we need to do. You've got to close the pretag, maybe the pretag. JASON: It did something weird.

BRANDON: There you go. JASON: There we go. Now, it's not being weird. OK, so when I come out here, that was on our article.

BRANDON: Article, yep. Article/there. We need async, sorry, we need the async pipe in front of the JSON pipe. JASON: Oh.

BRANDON: We can do something different here. Let's go to in front take the async pipe out. We can actually convert this to a signal here. We'll say to signal there. Just wrap that in a two signal function. And then, there, and then, on the second argument, we'll import that from no, if you go up to the top there and import to signal from Angular Core/RX.js interrupt. If you drop a line under that one. This has always bothered me why the deep imports don't always work. Rxjs interrupt?

BRANDON: Dash interrupt. And the E after Angular there. JASON: Sorry, I was trying to class it up, Angular. Angulare. It's French. [ Laughter ] OK. So then this is a signal. And then, do I have to change anything here?

BRANDON: We'll add one more thing after that. As a second argument to, to signal, we'll do an object there, and we'll say requires sync is true. And that means we're immediately going to get a value from this signal. And then data, we can call that as a function. So we don't need the async pipe anymore there, we can say data and JSON like we would do with signals these days. Now we've got it loaded true. And in that load function, we can access, you know, parameters. You can actually access that ID that we added as a slug. Access that, actually, in the server side data loading. And then, you can do things like load something with that ID or if you wanted to do something there. JASON: You know, I actually have, why don't we try this? Because I have an API, and we have episodes. And so, we can grab like in fact, what is today's episode called? If I grab the slug for it, then I can get this here. And that should give us... my server. There we go. So this is the details for today's episode, right? So we can grab something like this, and then, head back into the code, and we'll be able to fetch this and this can be the slug. Inside the load function there, there's an object you can use to get the slug. It's params.

BRANDON: Inside of there is object, should be params key in there. JASON: OK.

BRANDON: There's, also, a type for that that we can import called page server load. That would help out with the imports there. So after the object, at the end of that, you can do a colon and then page server load from AnalogJS router, and params, that'll give you that. And it might be in I believe it'll be a square bracket under that. Params and slug in quotes. Yeah. Correct there, but I believe it is that will give you the slug that was passed to that particular route, and then, you can see the data that comes from
JASON: And we can just return that and theoretically speaking, what will end up happening, then, is if I have one of the episode slugs, and we go in here, should be able to drop this, and we get the details. Now, we've got server side loading of data based on the slug in the URL, and so, now we can start doing things, like, I assume the content loader and build my site on analog.

BRANDON: Yeah, you could do all of your connect, you could bring in your environment variables and all of your server side stuff you want to do there. And that's also less code you're shipping to the browser. If you have like server logic in there, too. If you wanted to use Angular http client and make requests that way, you could do that, also. So that part is available, too. You're bringing the knowledge of Angular that you know into this space and being able to just build on top of that. And then, we provide some extra things on top of that to kind of smooth things out. JASON: Nice. And then, we've got what I assume is some loving trolling, which is how long do we leave it as .analog before we go back to .ng?

BRANDON: You know what, I am too scarred to go back there. [ Laughter ] But, no, the we're going to stay with stay with that analog extension. I did, you know, as just to be spicy about it, I did think of a maybe we could just make it configureable, we call it .analog, you call it .ng, let's be friends, but we'll leave it as .analog for now. JASON: Got it. So, we've got about ten minutes left of demo time.

BRANDON: Yep. JASON: Is there anything else we haven't looked at yet that you want to make sure we dig into?

BRANDON: Yeah, we could show the we showed the blog as an option, but we can show what content loading looks like in really quickly in Analog. If we go into the and I mentioned this before with the AnalogJS/content package. If we go into the app config file there. And so, we have our router and things like that. And here, we can render mark down as pages. JASON: Oh, cool.

BRANDON: We'll hook this up and maybe throw one more Easter egg in here. But, so, if we go under provide client hydration and use an add provide content under that, provide content, this will be from add analog JS content. If we want to import it from there. @analogjs/content. JASON: OK.

BRANDON: Sorry. Got import on
JASON: Got to spell things right. There we go.

BRANDON: Also, we'll use the with markdown renderer there, so with markdown. Or pass it as an argument, it doesn't have to be an object there. So with markdown renderer and call that as a function. And that actually allows us to do things like render markdown pages and things like that. If we want to create a page under here called hello.md, and then, you want to throw some markdown in here. And we can load that into there. The content package wires up being able to load the markdown as routes there. So then, if you want to put a couple of pages up there that don't necessarily require a component, we can drop that in there, and now, we have a nice markdown component there. Which is something that people are, you know, familiar with, like I said, you're building marketing sites, static sites, or just want to drop some additional links in there, just additional things in there, you can do that with straight up markdown. JASON: Can I chaos agent for a second?

BRANDON: You sure can. JASON: Here's my theory.

BRANDON: Let's see it. JASON: Here's what I'm hoping will happen. If I go to slash magic slash neat, we should get our markdown, but it's going to get dropped into the slot. Is that going to work? Let's find out.

BRANDON: Go for it. JASON: Look at it go!

BRANDON: There you go. JASON: Yo, this is what makes this stuff so magic. Now, you have you can do a basic layout for your site, right? And then you just drop markdown files in for the pages that are only text. And when you've got things like privacy policies, codes of conduct, about pages, you know, stuff like that where all you're really needing is a place to put the content and there's nothing, you know, there's no dynamic thing, there's no custom components, this is huge because it saves so much time and it makes it possible for your team to edit this site without having to know a single bit about coding. They can edit a markdown file. That's huge.

BRANDON: Would you like to throw more magic at this? JASON: Yes, I would absolutely love to throw more magic at this. Let's see if we can wake up more of Linda's cats.

BRANDON: Let's go to the app, then. We'll create, we'll call another file. Create .page .analog file here. Well, let's create, yeah, page.analog file, yep. Under there, we'll just call it more magic or something. .page .analog, there you go. Let's create a template. But in this case, let's get wild. Let's put lang md in our template here.

JASON: OK.

BRANDON: Drop some markdown in there. Yep. So we talked about being able to author Angular components without, you know, author Angular components effortlessly. Script.ts. We don't need to drop anything in there. JASON: We don't need anything?

BRANDON: Yeah, we don't need to drop the script tag, but we can do lang.md, and if we visit that more magic page there, we should if everything works well, we can author the part about this is this is an Angular component, if we wanted to drop some Angular syntax in there, some indirective Angular syntax along with the Angular or just the HTML template or anything, we can do that, too. That's another thing that we've been kind of working on in the background. We do have one we're well, we call it the .agx file format. Or not file format, it's the agx extension. But it's similar to, like, markdown or MDX, I call it MDX but for Angular. But that's another way that we can author Angular component, interactive Angular components with still and still have if you want to build documentation or interactive and inclusive interactive components in there, you could actually drop those Angular components in the template mixed with the markdown and everything kind of gels together. JASON: That is extremely cool. I mean, yeah, this is, like, everything that I would expect it to do, right? Everything we've thrown at it, it works. Yeah, somebody mentioned there's an Astro integration, I think I saw that in the docs.

BRANDON: Yeah, we do have a few integrations with Astro, where you can actually use Angular components within an Astro application, like you would React or Solid or other UI frameworks, you can add those there. They have more integration with testing tools like V test and upcoming, hopefully, support with playright, soon, that'll be on the way soon. You'll be able to use Angular, and all of this is kind of driven by the Vite integration. The Vite plugin in analog can be used within any Angular app, but unlocks so many other things there. JASON: Yeah.

BRANDON: That you'll be able to use. JASON: This is really cool stuff. Like, huge kudos to you and the rest of the team for putting together something that, like, I don't know, I just feel like there's so much energy coming into the Angular community right now through, you know, through the Angular Core team themselves and bringing in some of the more modern JavaScript features and the modernization efforts they're making, through what you're doing with Analog and the I don't know, feels like something special's happening right now. There's energy in Angular that I feel like I haven't seen it for a long time, and so, I'm so excited to see, you know, how far you've come in such a short time. I can't wait to see where you go next.

BRANDON: Yeah. Shout out to the Angular team. They've enabled a lot of this to happen, too. A while ago, you couldn't do any of this. Just because Angular was kind of restricted in that way. But shout out to the team for, you know, supporting the community and supporting projects like Analog and other things we've built over the years. Things have definitely moved along. JASON: And there's some good stuff in here if you want to check it out. We've had Brandon on here talking about Angular, but we've got Jessica and Mark from the Angular team more recently talking about, like, some of those modernization efforts and what's been going on. There's also a bunch of stuff about it at Google.io this year if you want to find those videos somewhere. But yeah, if you've ever been interested in Angular, if you're working on a big team and you need to pass like all the Enterprise compliance things about bringing tools into your work, Angular is extremely worth your while. It is a good, good set of tools and there's a good ecosystem and good people around it. Brandon, if people want to go further here, where else should they like what should they do next?

BRANDON: Yeah, I would say definitely check out the docs @analogjs.org. Dropped the link in the chat there. Definitely check out the docs, visit the GitHub repo, all of those things can be linked from the docs there. And if you're interested in, you know, sponsoring the project, we've got a few people, the Core team, if we go to the contributors in the docs there, definitely want to give them a shout out to the team. Robin, Marco, and Josh have helped and Luis, don't want to forget Luis and Andreas. Those are the ways you can support the project. Give us a star on GitHub, you know, sponsor, if I would say if you can get your if your company's using Analog and you want to continue to see this thing move forward, definitely give us a sponsor or something there. JASON: I saw

BRANDON: We're going to keep building the thing, we're excited about it. JASON: All right. I'm going to put up the link on sponsoring here. Oh, it's literally right here. So there we go. There we go. I want to drop that link directly so everybody can go check this out. And with that, Brandon, thank you so much for spending some time with us today. Y'all, make sure that you, you know, go follow Brandon, check out Analog, make sure you give this thing a try. It's very legit. And while you're checking things on the site, make sure you go and look at the schedule, which is not up to date. There are more episodes coming. This isn't the last one.

BRANDON: Oh, no. I'm glad to be the last guest on the
[ Laughter ] Just kidding. JASON: We've got good stuff coming up. Coming into summer, I've got a lot of travel. So dates will be a little bit intermittent, but really fun stuff coming, so make sure you get on the newsletter, join the Discord to make sure you don't miss an episode, they're just going to keep coming. Y'all, thanks for hanging out, Brandon, thanks for being here. We will catch you all next time.

BRANDON: See ya, friends.