Simplify Your Views with Laravel Blade Components | Learn Laravel The Right Way
Chapters8
Introduces the concept of composing templates with Blade components that resemble custom HTML tags.
Learn how to build and reuse Laravel Blade components (class-based and anonymous), pass data, merge attributes, and switch from template inheritance to layout components for cleaner UI code.
Summary
Program With Gio walks through turning Blade templates into reusable components in Laravel. He starts by extracting a navigation section into a Nav component created with Artisan, showing how the component class and blade view live under resources/views/components and app/View/Components. Gio demonstrates both class-based components (with a render method) and anonymous components (blade-only) and explains when you might prefer one over the other. He then shows how to render components in layouts using the x-<component> syntax, and how to nest components within subdirectories using dot notation. The video dives into practical details like passing data as attributes, using colon-prefixed attributes for raw PHP data, and the importance of props to avoid bloated HTML attributes. Gio also covers merging attributes and classes, handling Tailwind color utilities with a lookup table to keep purging safe, and how to render slots and named slots for flexible layouts. Finally, he demonstrates replacing template inheritance with layout components, using slots, named slots, and an extendable header pattern, and highlights route- and request-based active-state logic for navigation highlighting. The session culminates with tips on when to reach for class-based components for more complex logic and how to structure components to be reusable across multiple pages.
Key Takeaways
- Artisan can generate a Blade component scaffold with a class-based component (Nav) and a blade template, located under resources/views/components and app/View/Components.
- Anonymous components are blade-only and do not require a corresponding PHP class, useful for simple, reusable templates like a statistic card.
- To pass raw PHP values to a component, prefix attributes with a colon (e.g., :amount) to avoid Blade escaping and type-issues.
- Attributes passed to a component appear in an attributes bag; use the props directive to explicitly declare which keys are props and should be excluded from HTML attributes.
- Use the merge method on the attributes bag to combine passed classes with component defaults, enabling conditional styling without breaking Tailwind CSS utility classes.
- Tailwind purging can strip dynamically generated classes; Gio suggests mapping logical color names to a safe, static color class map to ensure classes aren’t purged.
- Slots and named slots enable flexible layouts: slot provides default content, while x-slot:header or x-slot:title allows injecting content in specific regions of a component.
Who Is This For?
Essential viewing for Laravel developers who want to streamline their front-end templates with Blade components, especially those moving from template inheritance to reusable components and slots.
Notable Quotes
""Blade components look kind of like HTML tags""
—Gio introduces the concept of Blade components and how they resemble HTML tags.
""We could also place our components within subdirectories in which case we would need to use the dot notation""
—Demonstrates rendering components from nested directories.
""Attributes passed to a component are added to something called the components attribute bag""
—Explains how extra HTML attributes are handled and accessible inside a component.
""If you prefix these attributes with colon, Blade treats that attribute as a piece of raw PHP data""
—Shows how to pass non-string data to components.
""Merging non-class attributes behaves differently—you merge them, but non-class attributes get replaced""
—Describes how to combine attributes and how Tailwind classes can be merged.
Questions This Video Answers
- How do I convert a Blade template into a reusable component in Laravel 9?
- What’s the difference between class-based and anonymous Blade components in Laravel?
- How can I pass dynamic data to a Blade component without turning it into an HTML attribute?
- How do I use named slots in Laravel Blade to build flexible layouts?
- What technique helps keep Tailwind CSS classes from being purged when using dynamic class names in components?
Laravel Blade ComponentsAnonymous ComponentsClass-based ComponentsBlade SlotsTailwind CSS with BladeBlade Attribute MittingComponent PropsLayout ComponentsRoute-based Active StatesBlade Rendering
Full Transcript
[Music] another way of writing blade templates is by using components which kind of look like custom HTML tags so let's extract uh this navigation section right here into its own component so I'm going to cut this out from here and before we write the component we need to create one we can use the Artisan command to do that so we'll do vendor bin sale Shell let's clear that out we'll do PHP artisan make component and we'll call this component Nav Now as you can see this command has created two files one is the component nav PHP class within the vew components namespace and another one is the actual uh nav blades template let's open the nav blades template so we'll do nav blades template and we'll paste in the code that we copied or cut from the layout I also want to show you the new directories that have been created so in here under the resources views we see the new directory called components have been created and that's what contains our blade components the other directory is within the app view with the components directory that contains nav that PHP class so this is the class that renders uh this blade component so if we open that up we see that it extends uh a component class and it has one method in addition to the construct method called render which renders our nav component now let's render this nav component within the layout because we removed it from here so we need to add that back as I mentioned before blade components look kind of like HTML tags so we're going to be able to render this by using the name of the component which is nav prefixed by X and dash so we'll do x dash and then the name of the component which will follow the Kebab case convention so in our case that's simply just nav and we'll self close this tag we could also place our components uh within subdirectories in which case we would need to use the dot notation or the dot character to specify uh from which directory to load this specific component so for example if we had this nav within a subdirectory here called maybe navigation and we place this in there then we would need to render this uh using navigation which is the name of the directory dot nav which is the name of the actual component now you might be asking since uh this nav PHP class is simply rendering this component what's the use of this nav uh class do we even need this component class the answer to that is no we don't need this class in fact if we delete this entirely and refresh the page we see that it still works now something to note here in case you get an error about class not found uh you may need to clear the view cache uh for this to work so if you get some kind of error try running Artisan view clear command and then it should render and work as expected now the reason this still works is because the component that we initially created that has the component class is called class-based component it gives you a little bit more control uh over your component so if you need more control or you're doing something more complicated having the class that manages your blade component makes things a b easier because it gives you the control of what's being passed to it maybe add some logic to it and so on components that don't have a class like this one for example since we got rid of the nav class are called Anonymous components they just have the blade templates they don't have the corresponding class so let's actually move this back here since we don't need this nested and let's fix this here as well and we can actually create create Anonymous components using the same Artisan command that we used before we just need to pass the view option to it so let's try it out and maybe create another component looking at the transactions uh blade template I think it would be good if we extracted uh these statistic uh Cards into a component as you can see we have few of these cards right if we open the page and go to the transactions we see that we have four cards technically we could extract this into a component and then reuse the same component to render four of these cards in our case we are simply duplicating these four times and rendering it that way so instead we want to make this somewhat reusable uh and use blade components for that so let's copy this and we're going to create a new Anonymous component so we'll do PHP this stat and we'll pass the view option which means that it's not going to create the class for this component it's just going to create the blade template making it Anonymous component as you can see the stat blades template has been created in fact actually I want to create it within a directory we'll created it within maybe cards directory and nested under it uh and we'll delete the the previous one that was created so let's delete this one and we'll work with this so let's paste uh the HTML that we copied before and let's adjust this to our needs something to note here is that when we created these components we capitalized the first letter of the component name and in addition to the component name we also capitalizing the first letter of the directory but lell automatically converts that into a lower case when creating the blade uh templates however it does not do that for the class that's because the larvo follows the conventions and it will also convert the Pascal case to Kebab case uh when creating blades templates so if we created something like stat card you will see that stat card was converted to Kebab case with a dash but the class component uh remains in in Pascal case all right so this HTML in here on its own is not good enough as you can imagine because it has this amount uh and the colors kind of hardcoded so if we were to use this component four times you would render uh the same text here and the same amount which is not what we want we want to make this uh reusable so why don't we replace these hardcoded texts here uh with some variables so we'll um call this amount and we can call this label now let's render this uh component from our transactions uh blade let me close the other View files here we're going to comment all of these out and instead we'll render our reusable components so we'll do X cards.
stat and we'll do this four times and then we need to pass as attributes so we'll do label total income and this will be amount 50,000 and we'll do the same thing for others all right so let's go to the browser let's refresh the page and sure enough we see that everything is working except the icons because we haven't worked with that yet but the label and the amount seems to be working the one thing that I want to improve on uh is I want to not have this past as formatted instead I want to kind of delegate the formatting uh to the component itself uh so like we may want to pass the raw value from some kind of uh database or some kind of storage where we're not storing it like this and we're just formatting it for display within the component so what we can do is that in here we can add the dollar sign and then maybe add something like number format amount and format it to two decimal points now of course you would probably extract this to some kind of uh helper function that would do your formatting to stay consistent across your application but we're going to keep things simple for the purposes of this demo so let's replace this now to 50,000 and we'll replace this to 45,000 and this to 5,000 and say here and this should still work as expected so if we go in here we refresh we see that it still works the problem with this is that we are still hardcoding these numbers even though our component is accepting variables the blad template here the transactions.
blade is passing hardcoded values in real app we would be getting the amount probably from a variable passed down from controller so why don't we replace these with some variables so we'll do total income total expense net savings and the goal let's pass these variables uh from our route because we're not using the controller here so for the transactions route we will pass these values in here now this of course Works however there is a potential issue here we are passing down these uh variables this way which essentially just evaluates this value and passes down as string and we may not want to do that we may want to get the raw PHP variable data type for example within our component for example if I go in here and we do Di and dump amount and we refresh the page we see that the 50,000 is string however what do you think is going to happen if we pass another data type like an array or an object so let's say that the goal for whatever reason was an array and we pass that into the cards component and we wanted to accept that as an array for whatever reason so if we go in here and change this to an array and let's get rid of this D and dump and then refresh the page we see that we're getting this error that uh argument one pass to HTML special cars must be string but array was given that's because when we are uh passing the value this way what this does is that blades takes this variable and passes it to the HTML special charge because remember uh this essentially translates to the same thing as PHP Echo e value and whatever this is in this case goal is being passed to this helper function and we may not want to do that we want to pass this variable as like a raw uh variable to our component to do that we need to prefix these attributes uh with colon so if we add colon to these and then get rid of these double curly braces from here and here and what this does is that when you prefix an attribute name with colon blade treats that attribute as a piece of raw PHP data rather than a literal string and it accepts the PHP Expressions variables so you can evaluate some PHP expressions in here for example instead of goal we could pass a time stamp and this will still work now of course the time doesn't make sense for a goal but just for the sake of example we see that it works so it is capable of evaluating PHP expression so if we change this back to goal and we pass this as an array uh it is going to still fail but with a different error now it's failing because uh number format is expecting um integer or float but we're giving it an array we can die and dump uh the amount in here uh and let's actually maybe move this on top because otherwise it would die and dump in here and we would never get to the goal so let's go here refresh and you see that it's passing in as an array all right so let's change this back let's remove the die and dump from here and now let's uh maybe fix the icon uh colors before we do that actually what if you wanted to customize the attributes of the div element right here maybe you want to change the background color or position things differently or just simply add some other HTML attributes say we wanted to add the title to this div container uh maybe we wanted to do something like title total reported income which could be like a longer description of what this statistic card is about now if we refresh the page we're getting the same number format oh yeah the goal that we're passing is still an array so let's rever that back let's open the browser refresh and if we hover over this we see that there is no title in fact we can inspect element and we see that there is no title attribute attributes that are passed to the component are added to something called components attribute bag it's like an object basically and can be accessed via the attributes variable so if we go in here we can Di and dump attributes variable let's open the browser refresh the page and as you can see the attributes is an object of component attribute bag and the attributes array contains three elements title label and amount so to add these attributes to our HTML element we can just do something like attributes and this is going to automatically add the attributes to this div element the reason this works is because um the object implements php's Magic two string method which allows it to render it as a string so if we go here and refresh the page and H over we see that the title now works if we inspect the element however we see that uh in addition to the title attribute we're also getting the label attribute and the amount attribute and we may not want uh this to happen we may only want to add the title attribute and the label and amount are kind of like props they are variables that are passed to the component but we don't want that to be part of the HTML attributes so these amount and uh the label variables are your data variables and if you were using class-based components you would Define your data variables in your Constructor as public properties and then larel would automatically exclude those properties from the attribute bag however since we are using the anonymous component component it is not automatically excluding those because we're not defining these data variables anywhere as being data variables uh they're just regular variables and regular attributes as far as the Lal is concerned however we can hint the component that these two are our data variables or our props so that they get excluded from the attributes bag and we can do that by using the props directive so we'll call the props directive at the top here and pass list of variable names that are our props or data variables so we'll do label and amount and now if we refresh the page again we see that only title is added to the attributes and the other amount and the label attributes are no longer considered HTML attributes they are excluded because they are props so basically all other attributes that are not part of the props directive will be added and available within the attribute bag you can even give the attribute a default value in the props by using the key as your variable name and the value as your default value and it will work so for example if the label was not given for whatever reason we could give it some default label and then within our transactions blade template maybe let's say we don't pass uh the label for the goal card component and if we refresh we see that the default label is added because that's the default value that we are setting within the props directive now what if we wanted to overwrite some of the classes uh within here maybe we want to have the gray background instead of the white background here we could pass the class attribute uh within the transactions blade template and set the back ground color using the Tailwind CSS class and see if that will work so let's remove this title from here and instead I'm going to add class BG gray 100 and let's open the browser refresh the page and as you can see it is not being applied we can inspect element on this component and we see that that class is not being applied that's because we within the component we are already defining the class attribute that sets the background to White using the BG white Tailwind CSS utility class to make this work we need to merge the past class attribute values with the class attribute values that are defined within this component we can use the merge method on the attributes variable to do that so we can do something like attributes merge and pass list of attri attributes to merge so we'll do class and set the class to these values and now what's going to happen is that any additional classes passed to this component will get merged to uh these classes so if we go to the browser and refresh the page we see that the class for the gray background was added to the list of classes here but the background is not changing that's because the CSS is conflicting here since we have two background classes defined we have the background white and background gray and it's setting the white as the background now we have couple of options here one is we could make the gray as important uh basically using the CSS important rule to overwrite that so we could go in here and add important uh this way that's how it works in tailwind and if we go back and refresh the page we see that now uh the background was changed to gray but we still have these two classes in here and that may not always be uh what you want because you don't want to rely on the order of classes for uh things to work you may want to only have the white background in certain cases and otherwise take the background from the component that renders this specific component so to do that we could use something called conditional merging with conditional merging you are able to define the condition on when to render a specific class so let's get rid of this from here and here we can use class method and instead of class this way we can pass uh the list of classes this way and uh we can actually separate these as its own classes and not like a one string so we can do background white Shadow and everything else now we're just going to keep this as one but you could separate those out if you wanted to if we go here and refresh we see that all of those are still added and we still have both the white background and the gray background with white taking the Precedence so if we go in here when you have the numeric indexes on the elements that you pass here it will always be added or merged to the resulting class however if you set this to be the key and then the value be the truy value whether it's true or false some kind of conditional then it will only be rendered or added if whatever this evaluates to returns true so if we set this to true and go in here and refresh the page everything is still normal we still have the white background however if we go here and set this to false and refresh the page we see that now we no longer have that BG white in the list of classes here so this can come in handy if you want to do some conditional merging of the classes the the background color may not be the perfect example for this but you get the idea now one thing I want you to note is that the merging non-class attributes has different effect instead of merging values it is going to replace them so let's say we want to bring the title back here so we set this to total in come as our title and then we wanted to set some kind of default Title Here If the title is not passed uh what we can do is again uh we would call the merge method and you can call the merge method after the class uh method and merge title with some default title now if we go to browser and refresh the page we see that this is total income because we're passing the total income for the first uh component but for the other three components we're setting the default title so as you can see here it's replacing the default title with the title that we pass all right so let's now fix up the colors here we want these to be reusable right so we want to change the colors uh appropriately depending on what color we pass from uh the transactions blades template because we want this to be green and the other one we want it to be red and then we want it to be blue and the last one is yellow so why don't we do something like pass color green and then do the same thing here and this will be red blue and yellow and you could call this anything it doesn't have to be color it could be theme or whatever but we're going to call this color for now let me double check our colors so we have the the green the red blue and the yellow so it's background yellow 100 blue 100 green 100 and red 100 that's for the background and then we also have the text this is text yellow 500 blue 500 green 500 and red 500 so these are the two variables that we need to control dynamically using these let's get rid of the title and we can get rid of the class here since we don't need it let's also get rid of these attributes here because we don't need conditional uh classes or we don't need to merge any attributes or classes in this case so I'm simply just going to get rid of this and call class equals and kind of bring it back to the way it was originally then we want to replace this text green 500 and the background 100 with the proper color that we will calculate or map to based on these values now one quick and dirty way to do this is by simply replacing this uh green right here with the variable that we pass so we pass the color so we can replace this as well color and this is going to work so if we go here and refresh the page we're getting error called undefined variable color which kind of makes sense because color that is being passed is not a variable it's an attribute and this color uh is available under attributes so if we did something like attributes color this would work so if we did this way and refresh the page we see that it works now even though this works we may want to use the variable like we're doing for the label in here in that case we can change this back to color and we can make color be the prop uh just like the label and the amount so if we add color in here and we refresh the page we see that it still works now depending on how you're loading and bundling Tailwind this could lead to issues with Tailwind purging process and not work as you would expect Tailwind basically may not include the BG uh green 100 red 100 yellow 100 and so on classes because uh you may not know that we are using those classes since we're building them dynamically like that and Tailwind has uh something called purging process that it essentially purges all the utility classes from the generated or built uh file that are not in use and since Tailwind cannot figure out uh basically what class You're Building here since it's Dynamic it won't be able to include those classes in the generated file therefore this is not ADV devised in a lot of cases unless of course you had some kind of exclusions in your Tailwind configuration and then you could make it work so in general it's probably best to use the full class names and not dynamically built class names this way unless of course like I said you know tailwind and you know how to add exclusions and all that so to solve this problem we could have some kind of map or a simple lookup table that basically Maps the color uh that we passed like green to the proper full Tailwind CSS background color and the text color so we could have some kind of lookup table here so let's do PHP and PHP and we could uh call this color classes then in here we're going to replace this with color classes variable and access the proper uh list of color classes using the color variable as the key so let's do the same thing for the text in here and this should still work as expected let's refresh the page and as you can see everything still works so there are a lot more features of course and I cannot cover all of them I would suggest to go through the documentation and get yourself familiar with the blade overall directives and components if you plan on using blade as your front end you can do things like like I mentioned conditional merging of attributes attribute filtering can Define dynamic components where component name can be specified as a variable you could also use class directive to apply classes conditionally you can Define inline components in your class-based components and so on speaking of class-based components as I mentioned before they are great for when you need more control and have more complex components you can invoke public methods defined in your component classes uh from your templates and you can also conditionally render your components by defining the should render method in your component class and if it returns false the component won't be rendered at all for the most part it will be using the anonymous components so my advice would be don't use class-based components for every single component start with the anonymous component and then reach for the class-based components when you actually need more control control and features you can also sort of think of class-based components as like a controller where you prepare the data for your component and then pass it down to your uh blade template or your blade component you could reach into other services use service container within your class component and so on all right so now let's change our layout to use components instead of template inheritance in here so as you can see we're still using the yield the section and so on so we want to replace these two fully used uh blade components so first thing that we need to do is we need to move our layout under components then we're going to replace this content section with the slot variable so we'll do slot and Slot is like a placeholder that renders the additional content that is passed to this component so so like if we go to our dashboard uh blade template as an example instead of extends here we could simply use the layout component like HTML tag so we would do something like X layout and then anything that goes in between because so far in our transactions we've had components that are kind of self-closing uh HTML tags right so in here we could put something in between and whatever we put put here that content gets passed as the slot variable so we could put something like hello here uh let's get rid of this for now if we open our dashboard we see that it works we may have more than one slots because we may want to render some additional content in different places like in here for example we are yielding the title instead of that we can simply use named slots so we'll just render a variable called title this way if it's passed and if it's not then we'll simply render the default title which is larvo in this case then within our dashboard page we can inject the content for this named slot using X slot so we can do something like x- slot and then specify the name of the slot in this case being title and then pass the value to it so we'll say dashboard and if we go to the browser and refresh the page we see that the larvo got changed to dashboard next we have this header section in here including the header title let's replace this with another uh named slot so we'll do header title and if it's not given then we'll do default title now from our dashboard page we can either again pass it as a named slot content or it will render as the default title so if we open the browser we refresh the page we see that it's rendering default uh or we can pass it as a slot so we can do this and do header title and pass dashboard as well refresh the page and sure enough it works now if it's a simple text that we're rendering here and it's not like a HTML or anything complex we can pass this as an attribute to our layout component so we can get rid of this entirely and we can actually get rid of the title entirely as well and we can do title dashboard and header title using the Kebab case also dashboard and then if we refresh the page we see that it still works as expected and our component looks much cleaner if you have both the named slot and the attribute defined with the same name then the slot content takes precedence so we could do something like X slot header title and set some header Title Here which will basically override what's defined in here so we can do something like new title and then refresh the page here and as you can see it overwrites and as I mentioned we can pass some HTML here so we can do something like span class text um maybe green 500 and close the tag here and refresh the page we see that it works note that any content that is not defined explicitly as a named slot like this x slot in here will be passed to the component Within the slot variable so if we forgot to put this in here and just put span this way this will just be rendered together within the slot variable all right so let's update the other Pages as well let's copy this and let's do the categories page next uh let me close that out let's replace this and we'll call these categories and categories and we can do categories page let's go to the browser visit categories and sure enough it works we have dashboard we have categories now let's do the transactions page so let's copy this open transactions page I'm going to replace this with the layout component and let's change the title to transactions and we'll change this to a transactions page and for the header what we can do is that we can simply pass these two div within here this way and let's get rid of this whole thing let's refresh the page let's go to transactions and sure enough it works but it's adding this content instead of overwriting or setting this properly on top before the actual content that's because with template inheritance we were using the section and using the parent directive to extend the header with this additional content but right now we are essentially putting all of this content within the slot variable which is rendered right here and instead we want to render it in here we can fix this in multiple ways one way is that we can check if the header slot is set and if it is set then we'll render that otherwise we'll render the default header then within our page template within the transactions blade we'll simply render this whole thing within the header slot so we'll do X slot header and close that and anything within that will be passed basically to this header variable and rendered under here so if the header is set we'll render that otherwise we'll render the default header so let's open the browser ER refresh the page and sure enough now it replaced the header so we're getting closed it's still not extending it so that's something that we need to fix next let's maybe extract this into its own header component uh so that we can do something like X header and then pass the header title here otherwise we'll do default uh title let's create that component in here so we'll do header blade.
PHP and we'll replace this with slot because anything that we pass uh within the X header will be passed here as a Content now to make this extendable we could introduce another variable called extend header Boolean variable that we can check if it's true then we'll render the default header here uh and if it it's false we'll just render this so we can do something like if extend header is set to true and by default we'll set it to false if nothing is passed we can render this as well in here and otherwise uh we'll render the header all the time and this is whatever we pass uh if we want to customize header ourselves so now we can pass the extend header and as a a prop to our layout component so we can do extend header and set it to true and remember this is uh a PHP expression so it's going to be passed as true and if we refresh we see that now it's rendering as before we're basically extending the header rendering the parent header and then rendering our custom header so we're doing somewhat similar to what we were doing with the template inheritance now of course there are many different ways of achieving this mine may not be the cleanest but you basically get the idea blade and larvo in general are very flexible all right so one thing that I want to fix before moving on is uh the current page highlighting right now if you go from dashboard to transaction or to category the dashboard page uh or in the navigation is always highlighted uh So within our navigation component we have this hint here that we want to set the background gray 900 with text white for the current page which is what's set for the dashboard page and then default for non-current Pages it should be this so what we're going to do is that we're going to check if the current page matches with the euro in here uh by using the request helper or the request facade and then based on that we'll decide what classes to add so we can get rid of this and we can do request is and check for this and if it is we'll do this otherwise we'll do uh the default so let's paste this in in here and then we'll do the same thing for other Pages as well so let's copy this and as you can imagine uh you could extract this into a h function or helper method or even to a separate component that handles that for you but I just want to show you a working example uh in here and then you can extract it yourself uh so we'll do this here as well so we'll get rid of this and replace it with this and the same thing here we'll get rid of this and replace it with this and this is going to be transactions and this will be categories let's open the browser refresh the page and sure enough now transactions is highlighted we can go to categories and we can go to dashboard as I mentioned we could clean this up by extracting it into its own component or to its own method and of helper function but I'm going to leave that up for you to do as an exercise you could also do this area current on your own you should conditionally set this to page if it's a current page and to false if it's not current page ARA current is used for assistive Technologies like screen readers now as you notice this is Method call here basically checks for the URI what if you wanted to check for the route name we can do that by using the route e method and that essentially uh determines if the incoming request has a matching named route so we can do route is transactions same thing here route is categories and routee is home and we just need to ensure that our routes are named in here so we're going to name this home and we have transactions in here so let's name this categories now if we go to the browser refresh the page we see that it still works the additional benefit of using route names instead of the uis here to do the matching is that you can do something like star and it's going to match uh to any route name that starts with categories so it can match uh with Pages like categories index show edit and so on and it will still highlight uh the categories page in the navigation bar all right so this is it for this episode thank you so much for watching if you enjoy my videos please hit the like button and subscribe to the channel if you haven't already done so until next time happy coding
More from Program With Gio
Get daily recaps from
Program With Gio
AI-powered summaries delivered to your inbox. Save hours every week while staying fully informed.



