 Thank you guys again for showing up, last session of the day, last session of the conference I think. You guys are either really committed or you're lost. I notice a lot of people in the aisle seats. You don't think that's going to make it any easier for you to get out. You make it to the door, I'm asking you an embarrassing question. I'll repeat the sorry joke I brought in up earlier, but there are slides in this deck where we show some code. If you can't see it that well, you might want to move a little closer. Our screen here was donated by the L.A. School of Optometry. Nothing? Really? Those are the jokes folks. So I asked and they said that only the screen is recorded. So when we start, I want it to sound like there's about a thousand people in here. Because I told my mom I was presenting and she's really proud. Thank you six people. That was about a thousand. Yeah, it's in the mail. I'm not going to repeat that. That's going to come in real handy. Maybe we can get a feel for what people's experience with the various parts of the ecosystem are. Like show of hands, people have used panels before. Decent familiarity with that. And those of you who have used Angular, and those of you who have been arrested, this is going to be great. If I'm getting any closer, I'm going to swallow it. Is there no way to share it whenever you're ready? Alright, I guess we'll go ahead and get started. Welcome everybody. Today we're going to be... Welcome everybody. Today we will be talking about a novel presentation framework, which is a system we built for the Weather.com project. My name is Matt Davis. I'm a senior Drupal developer for Media Current. I'm Jason Smith. I'm a senior software architect at the Weather Company. So this is our basic agenda that we'll be going through today. First we'll do a little introduction to the Weather.com project on Drupal. We'll talk a little bit about the problems they wanted us to help solve from their legacy platforms. And then we'll dive a little bit into our solution, the internals of the presentation framework, before opening up for any questions you all may have. But before we get too far in, let's talk a little bit about the what, the how, and the why. So I'm here specifically to talk about the Weather channel's side of things. We're going to talk about the presentation framework in general and its wider use. When we were building the system for Weather channel, we learned quite a few things about managing large development efforts. Their projects are huge. Touch a lot of pieces of the site. There are many legacy platforms. There are many touch points. So we had to figure out how we can talk to all of them in a way that made sense that was easy to manage. They have huge dev teams. We had to find a way to organize those dev teams so that they're not going kind of crazy and doing their own thing. We had to deal with rapidly changing requirements. As you know with the weather, if you don't like it, often you just wait five minutes and you've got new weather. With Weather channel, if you don't like the requirements, just wait five more. We needed to develop for them a flexible and adaptable presentation to meet the requiring flexible and adaptable requirements. So what exactly is wrong with the traditional CMS model and what did we have to solve here? These are some of the problems that we ran into. With the traditional Drupal site, you have very low control over the DOM unless you have very experienced Drupal themers to deal with it. So that leads to, for designers who are not familiar with Drupal's theme layer, barriers to experimentation and innovation. So if you don't have that knowledge, it slows things down because if you are mainly familiar with Angular, you don't want to have to deal with learning all of the Drupal theming system. So a lot of people are talking these days about headless systems and how headless systems can kind of address some of these issues and let the front-end teams accomplish more without having to know so much about Drupal. But does headless really solve these problems? Well, the headless idea has a lot of promise that comes with it. It offers higher scalability because the front-end and the back-end are decoupled, they can be scaled independently. It can offer a richer user experience because front-end developers can focus on what they do best. They can make whatever innovative designs that they can come up with. And that involves their ability to use whatever bleeding edge technology is available at the time. As you know, if you know something about JavaScript frameworks, it's a very lively and rapidly changing ecosystem out there. So in a headless setup, you can use whatever framework you want. That also offers platform flexibility because you have a services layer between the front-end and the back-end. You can have multiple different front-ends adjusting the back-end data in different ways for different devices, which is the create once, publish everywhere idea. But with all the promise of headless, there's a lot of problems with the headless model that we still have to figure out and solve. So one of the issues that we ran into specifically with the Weather Project is that the product owners wanted the ability to create and maintain their own layouts and make new pages with different layouts as rapidly as possible. And with a purely headless system, they would have to rely on their design team to implement these. They couldn't do it themselves. There can also be sometimes front-end performance concerns. If you end up having to make multiple calls to the services layer on a single page, then you're actually multiplying the number of requests that you have to make. Redirects, aliasing, routing, all of that fun stuff that Drupal has baked into it. You lose the ability to reach those things from the front-end if you're in a wholly decoupled system. And other things like localization, internationalization, Drupal does very well. But you don't have access to all of that necessarily in a fully headless system. Same thing with SEO, made of tags. We worked very hard to develop these tools. There's no reason that the front-end should have to reinvent these things. But one of the biggest things is that in a large enterprise level setup like this where we have a lot of moving parts and a large development team, we in a fully headless system would have very little imposed structure, which means different people could be working on using different frameworks unless we impose some more structure on them. Which leads to chaos. General disarray. So the future does look to be some form of headless. I think you guys probably attended the headless session hosted by Josh Koenig and Amitai. It looks like that is a direction we're heading and the tools just aren't there yet to support it. So many of us need to solve that problem today. So we need some sort of compromise. Nothing? Really? I worked hard on that. So in dealing with the lack of tools, we need to replace it with process and structure. We need guardrails. We need some sort of system with an opinionated approach to how you should build the pages. So what we're trying to do is give you the compromise between a fully headless system and a traditional CMS approach. So to kind of give you more insight into why we're making that decision, I'm going to take a little detour. Many of you guys have heard of Asanada, but Asanada is actually a musical form. It's made up of four or five pieces depending upon who's doing it. There's an introduction where you kind of introduce a theme, an exposition where you kind of play with that theme, introduce new variations, a development where you kind of extend it and do some wild new things with it. Recapitulation, bring the theme back, encode a more extemporization. What's the point? Well, Asanada is a form and it's a guide to composers as to the schematic for their works, for interpreters to understand the grammar and meaning of their work, and for listeners to understand the significance of the musical events. Does that sound familiar from a software perspective? So the recognizable structure, that is to say the process and the structure we supply, helps to prevent developers from going crazy, which as we all know, they do. Three of them were arrested in this room. You guys were wondering what I was going to do with that, didn't you? The boundaries of structure mean that when a new developer comes on board, they only have to learn one thing, not 18 different approaches, and ideally they're all taking the same approach when they're building a new module. And yes, you do put some limits on what you're able to accomplish, but one of the nicest things about having a framework that tells you what you can and can't do is when you're asked to do something you can't do, you can say, no, I can't do that. And then you move on. So we can make beautiful, he got too fast, we're making music. See, killed that one. It was really funny in practice. So we're going to talk a little bit more about how we're using Drupal in the enterprise, headless Drupal. There's a little placard on there. That's John Luke Placard. No? I worked hard on that one too. All right. Oh no, it's me. One of the things that we wanted to do is that for specifically a group like the Weather Company, they have product owners that's to say they want to build a today page or a five-day page. They don't want to have to work with a development team in a series of cycles of iterations of trying to get every little piece right and then try out putting a module on the left, put a module on the right. They want to be able to have direct control over that, build out features as quickly as they possibly can. Their existing platform had a lot of trouble, problems with it. It was really hard to develop new templates. You had to go through a development process. You had to go through a release process. There was a QA and regression cycle. It was a mess. It was hard to reuse templates. It was hard to find and then reapply in a different context. URL parity was hard to keep track of because each URL was a completely different approach into the system. So you'd basically have to have a map to find out where the URLs went. So, panels came to the rescue. For their product owners to be able to manage all of this, we knew that we wanted to give them the ability to use panels so that they could use variants to control URL parity across platforms and control how the variants were selected with selection rules and use whatever context was needed on a particular page, device that a page is being viewed by, or location information to fuel those variants. So this allowed for layout control and reuse of content. So here you see a typical forecast page for the Weather.com site with all these separate pieces of content that are distinct and this is a panels page. So on the back end, we have what you're probably familiar with if you've used the panels module, just a regular drag and drop interface where you can plug in these widgets and then configure them and move them where you need and they can be reused across multiple pages. So how does the presentation framework play into that? Well, we want to give their product owners the ability to use these widgets but where do these widgets come from, these content types? That's what the presentation framework does. It gives their front-end and editorial teams access to as much of Drupal's power as possible without making them learn the more complex parts of Drupal. So how does it do that? Well, we don't want to have their front-end team of 40 developers have to be trained in Drupal. They know Java, they know JavaScript, they know HTML. Those are base skills and they're very strong with them and we want them to be able to move as quickly as they can. So what the presentation framework is, is a system that wraps modules which are really just collections of template files, JavaScript and CSS that shows up on the front-end into a mechanism that can be shown in panels. So you remember that interface where we saw the widgets you can drag and drop so you could compose a page layout? Those widgets come from the presentation framework which are just wrappers for the JavaScript and CSS developed by their front-end team. So their front-end team doesn't know any Drupal. Well, they know very little Drupal. So we're going to talk at a high level. We'll give a high-level architectural review. Then we're going to dig into a little bit more detail. That would be the opportunity for project managers, product owners to take a nap. This is the architectural diagram that we're using. You can see it's pretty simple. Well, that was funnier than I thought. We are obviously building in Drupal. We use panels in the C Tools module as a platform for the Angular Mods or NG Panes system. You can see all that does is allow us to wrap the module plugins as content panes within the panel system. So I'll talk a little bit more about what that means. So first up, Angular Mods, NG Panes. Originally it's Angular Mods and Angular Panes because that's the platform they chose to use. While working on the system, we realized it could be easily generalized. However, we'd already made a commitment on the namespace. So NG Panes is what the internal name of it is. We did do a fair amount of time analyzing the code, thinking if there was some way to refactor it so that we could rename it and get the better namespace. And we did, in fact, do it. After a great deal of thought, we abandoned NG Panes and went for next-gen Panes or NG Panes for short, which we think flows better. So there are only two things that are hard in computer science, naming things and cache invalidation. And off by one errors. So let's talk a little bit about the front-end developer experience that we've built here. As you'll see when we go into a little more detail here, we have these individual Angular Mods that are plugin-based. So different front-end developers can create their own Angular Mods which are independent-ish and self-contained so that because of the structure we've imposed here, they can be working on their own pieces without worrying about them breaking other things. So this is an example of what an individual Angular Mod would look like in the file system. It's a directory that we have set up to be listened to using a hook in our main Angular Mod module. Angular Mods get directory. And we listen to these directories and look for these info files. And the info files are just small pieces of JSON that will declare that this is in fact an Angular Mod and it will include any dependencies from JavaScript, CSS, or other template files that they may want to use. So this is a little example of what the beginning of one of these JSON files would look like. As you can see, it's just declaring the basic information, categorizing it, and we can version it and have specific time to live so that it can be cached independently. And it is reflected directly into the panel's user interface as a content type. We talked earlier about the fact that you can have different types of templates. For example, you can have your Angular module do just one thing, spit an HTML blob onto the page, and that's all you ever really need. You might use that for something like a logo or a quote, for example. I mean, it's not a terribly big module, but it's an easy one to write and suddenly you've got the ability to drag and drop it on there. But we have more sophisticated tools such as the ability to interpret tipple flips. The nice thing about that is that it gives you a great deal of power. The downside of that is that it gives you a great deal of power. So we try not to tell anybody about it. Oops. Yeah, and here, as you see, this is another thing that's included in the JSON files, and this is another little bit of Drupal sneaking in there, but you may recognize this if you're familiar with the Drupal's Forms API. This is a JSONified version of that, where their front-end developers can write these little things, and these forms will actually be shown up in the Painting Configuration form. And here's an example of that happening. Yeah, it's the exact same form. This is a very simple example, obviously, but they can get very complex, depending on the needs of that specific Angular mod. And in some cases, we even defined custom field types on the Drupal side that their teams could then use in their configurations. So another place where we leveraged what Drupal was able to provide of reinventing the wheel is there are plenty of situations where we want to add JavaScript from the module itself, things like the JavaScript that supports an Angular module, the controller, the initializer, et cetera. We provide the ability to list the group that you want it to show up in in terms of aggregation, whether it's in the header or footer, the weight. You might recognize this as being very similar to what Drupal add.js does, and there's a reason for that. That's what it is. So what about cases where an individual Angular mod has to use the same JavaScript code, or CSS, as another Angular mod? Well, in that case, when you know that your piece of code is going to be reused, you can declare it as a separate Angular mod, and then other Angular mods can use it as a dependency so that they're still kept separate and we reduce deduplication... reduce duplication, and this works for JavaScript, image libraries, and CSS, and you can see here how that's accomplished in the JSON file, declaring this Angular mod. You just declare what shared resources your module needs. And how does all of this fit into the panel's integration exactly? So here's our architectural diagram for the actual module. So those of you familiar with C-Tools know that you really only need to implement three functions to present the content pane. This module is no different. In the case of reporting one module, we report, well, in the case of Weather Company, 250 modules, but it's all done via a single callback. Let's go ahead. Most of the magic for the module happens in the Angular mods getMetadata function. This is a function that you can call from anywhere, and it is called in very many places. It walks, although the subscribing folders, those that were announced through the which folder do I want hook, parses and validates that info file. It actually does validate against JSON schema. There is a schema validator out there. It's a fantastic tool. It saves us a ton of problems, because, for example, the biggest issue we dealt with in the beginning is malformed JSON. And if that were to happen invisibly, modules would just disappear. So we throw a wobbly, which is a technical term for error. We also, as part of the Angular mods getMetadata function, read that form API magic that we showed you earlier and turn it into something that makes more sense to the content type system. And lastly, we cache that metadata so that this call doesn't have to walk that file system tree over and over again. One of the neat things about it is, for our particular case, every time we do a code deployment, we go ahead and flush that metadata cache so you're guaranteed to get the updated stuff every time. This is the plug-in that the Ctool system calls. As you can see, it's pretty typical, nothing unusual here. In fact, we still have that single content type callback, but instead of returning one, we return 250 modules. In that content type callback, we call that function that we just introduced, the getMetadata, it lists all of the modules for us. Each one of the info files has the option to specify a callback function, if desired. There are situations where the name of the module isn't enough to provide context to the person dragging and dropping it onto the page. Sometimes they want to know, what's the configuration for this module? A use case for that might be, we've created a presentation framework module for an ad, and we want to know, is this ad in this position or in that position? Which one is it subscribing to? We have callbacks and preview callbacks that you can show that information in panels while you're dragging and dropping it. Validates the modules actually exist. If at some point we've got a panel that uses a module, but the code was later removed, we throw wobbly. If the module code changes out from under the structure we expect, we throw a wobbly. If the module tries to validate a property that doesn't actually exist, because we defined a new property, it throws a wobbly. I didn't want to get too repetitive. Yeah, so we also have a config callback, which again, if you're familiar with creating these Ctools content types plugins, you'll be aware of. It does exactly what you see here. It ingests the form API JSONified version and turns it into the actual form that is shown when you're configuring your content type. It also matches and makes sure that your module type is correct and it serializes it all up and it actually becomes a Ctools exportable, so it's cacheable and featureable, featurizable as well. Lastly, we have the render callback. This is where we actually put the module onto the page. You recall that during the config callback we serialized the data into the panel config. One of the nice things about that is that if you featureize a page containing a module and that config is on there, the config goes with the feature that's exporting that page. We can now develop a full page, featureize it, export it, put it on another site, bring it everything and all the magic goes with it. The render callback loads any shared dependent modules, automatically dedupes them for you. Loads any JavaScript or CSS into the attached part of the render array that it spits out. It does this specifically so that you can cache the output because if you were to simply call Drupal addJS the second time the module's called, your JavaScript disappears. I call that to attention because there are a lot of things that can go wrong when you're trying to build a system like this and we've tried to attend to all of them. The last thing it does is that config that we collected as part of that form API thing you built, we drop that into Drupal settings, though you have the option to whitelist what actually shows up there. For example, if you had to add configuration and you had to put some authentication in the module, it would be only used on the server side, not shown on the client side. We have a ton of stuff that the presentation framework actually does and I know that this probably is a bit dry. I was hoping that we can cover a lot more in the QA or more likely get out of here as quickly as possible. One of the benefits of being the last one of the day. The presentation is pluggable and exportable for the reasons I just described, so that's a really handy tool because it allows you to do your builds and devs and deploy them to prod either by doing database or doing feature exports. Caching is built in and we've solved a lot of the hard problems there. Dependency resolution just works. If you have two modules that use the same shared resource, getting them not to load twice in certain circumstances, particularly when caching is involved is really a challenge. For example, let's say you've cached module A with version one of a dependent library and you have module B that uses the same library, but now the version available is two, we throw a wobbly. We're big on wobblies. We're working right now, as we speak, on localization support. The way that will work is you'll drop a PO file with the English translation into the module folder. It'll automatically be ingested, dropped into the locales table, and then it can be either consumed by your TMS vendor. We're working with both Smartling and League of Tech. Hope they're here. Hi, guys. And then it will be automatically translated, the locale table populated, and eventually, though this is not in the short term, we'll put the PO file back in the module file for every translation available. Okay, but what does all that actually look like in use on the site? So this, once again, is what our site looks like, a typical page here. And you'll see each one of those pieces, each section is a separate Angular mod that their front-end team developed without having the Node Drupal's APIs and without having to ask us for much once we had the system in place. And so, just to give you an idea of how this is powerful for us, leveraging the power of Headless, leveraging the power of Drupal, this is what the Weather Channel architecture looks like for, for example, the Today page. Drupal spits out just that page for every user of the site, because that's the only part of the page that's consistent across every user. The forecast data is different for every user, so we don't put it on the base page. That's what's actually cached by Akamai and Varnish, and that's what actually reaches the browser. Any data that we have that changes on a per-user basis is put into a key value store in the cloud. We have a data caching layer, which is backed by both Cassandra, MongoDB, and Scala for some, for some logic layer. So we use Angular on the front-end. Go ahead. To dynamically populate the, the data that's unique to the visitor. So with this system, even though we have something on the order of, you know, 11 billion locations, we only serve one page out of Drupal. So we effectively can cache this stuff forever. We have 99.5% cache offload at Akamai, and an additional 90% cache offload at Varnish. So our Drupal servers are doing nothing. So how did this actually help to improve product velocity? Well, as was mentioned, their front-end development team have made over 250 of these things. So this is actually just a slice of them. They have really run with this system, and we have not had to be that involved in a lot of it. So how does the presentation framework offer all of the promise of headless? Well, we still have the high-scalability of a decoupled system. We still have a rich user experience that we're offering. Bleeding edge technology, well, we're JS for now, but we are actively working on making this framework extendable. And so in the future, we could theoretically change frameworks without having to change the data layer over the Drupal system. And as far as platform flexibility, because we have that services layer in there, the cell phone app can ingest the data in a completely separate way. What about the problems of headless that we talked about? Well, we've answered each one of these well with the presentation framework. As you've seen, because we're using panels in C-Tools content types, we have given their product owners total control over layout. We're using a sophisticated caching system that mitigates many of the performance issues that could arise in a headless system, and we still have access to all of the Drupal goodies in terms of localization, SEO, and aliasing and routes. And the biggest thing, again, is that we've imposed a structure that allows their front-end teams to still have a lot of creativity and to still make very cool things, but within a very specific set of parameters. So, just to kind of conclude again, go ahead. Because I do it better. The presentation framework provides reusable widgets. We provide strict guidelines about how the modules are created, and we tell you exactly how you're supposed to interface with the system. We're not enforcing just that you're using Angular or just that you're using the HTML or tipple-thip in a certain way. We're also imposing by way of what is possible through the module a architectural or enterprise architectural pattern, that is to say decoupled. We're making it hard for them to break that pattern and making it easier for us to cache pages. I'm benefiting from all those things that he just talked about, which I kind of zoned out at. Oh man, I lost my train of thought. Completely derailed. Present, I said something witty. Each of the modules is independent. Each of the developers can work in a silo, and as we know, developers are most effective when they know that they can work as they're not going to impact the work of other people. So the isolation between modules, the shared modules with the version dependencies, the fact that we show strict warnings and we're very careful about tracking them, this means that developers can work quickly and without fear. If they do something they're not supposed to do, they know quickly. Oh, and I didn't put it up here, but the other thing is that as a result of switching from the old platform to our Drupal deployment system, we can do releases a lot more quickly. I mean, the old release schedule was get 25 people in a room, huddle up, and pray for the best. The new release system is so boring, nobody even knows it's happening. They do several releases a day. We're shooting towards getting them on an hourly basis. The primary things holding us back at this point are unit testing, which I think is probably something that a lot of people are having pain with. So what about contributed work that's come out of this project? We've had an opportunity to contribute several little pieces of code back so far. We have the Classy Panel Styles module that is maintained by Derek Draps and Kendall Totten of Media Current, and that is basically a way of getting a higher fidelity version in the panel's user interface that looks more like what you'll actually see on the front-end side. We have the Wizzy Field Sandbox that's made by Bob Keppford of Media Current. This is something we didn't really touch on much, but there's a whole another way that we can use these Angular mods on the site. For example, articles on the weather site may have embedded slide shows or videos inside of them. The Wizzy Field module allows from the Wizzy Wig in the article body field, you can actually add these Angular mods straight from the Wizzy Wig. There's also the panel's theme Override, which is a very small module that I'm maintaining that allows you to override the theme that will be used on a per-variant basis. And the big one that we are still currently working on is making the presentation framework as a whole contributed back to the community. We do not quite have it in a Sandbox state yet. We're trying to make sure that it will be enough to be used without being dependent on AngularJS and having it be open to other frameworks, but we're not quite there yet, but we would love to, if y'all are interested in helping us to show you the code and to maybe do a sprint on that. So that's about it. I'm from Media Current and Media Current is an amazing place to work. It is a distributed company full of very, very intelligent people and we are hiring. And I, again, am Jason Smith. I work at the Weather Company and there is an intelligent person working there. Okay, there are lots of intelligent people working there. I fit right in. It's a great place to work. The culture is great. They've got offices in New York, San Francisco, London, all over the place, and we are actively looking for Drupal developers. So if you're interested in working on bleeding edge technology or contributing back to open source, and what I think is a really meaningful way, we'd be interested in talking to you. And please leave us thumbs up in the session thing. We'll be happy to take any questions. People want to approach the mic up here. A really beautiful piece of work. That's what my mother says. She's like, you know, so many things right. One question. Closer to the mic. I don't know if the mic is... There we go. Practically. Beautiful piece of work. I think everybody can see that. The question is about these angular mods. Can they do anything outside of their box? Do they have information? I mean, I guess they can get it from the browser, but what if somebody wanted, you know, to have an effect in JavaScript where they would go outside the boxes? Yeah, that's a good question. So he asked, you know, can the modules get any information outside of what they get on the front end? And I think more specifically, can they leverage any of the data in Drupal? So one of the things we didn't talk about is that these are content panes so they can consume context. That is to say, panels context, not context module, which is inferior in every way. Again, I'm very opinionated. The context would have to be defined by somebody who does know Drupal, but once you define the context, in our case, we have a location context. Once you create a context for the panels, whenever that context is available, you can specify in the info file in the JSON that you want to use it. And what will happen is it will show up in that configurator that's both in the Drupal settings and in the object that's passed to the Tipple FIP to operate on. So yes, you can leverage data that's in Drupal. Hey guys. Great presentation. The past two core conversations have been talking about similar ideas in somewhat hypothetical terms, one of the largest or the largest websites in the world just doing it. What would you want to see in Drupal 8, either Drupal 8 contrib or maybe 8.1, 8.2 to make this kind of organization easier in Drupal 8? Panels. Yeah, I want panels ready for Drupal 8 as soon as possible too. No, I mean most of the grunt work is the glue between what happens wrapping their modules and panels. So we leverage heavily what panels provides. Panels does 90% of the heavy lifting here. It provides a caching framework for us. It provides a presentation framework for us. It provides a URL mitigation framework for us, a URL parity framework. It allows us to do the variance and the selection rules. It also provides a presentation about how panels can be extended, not so much about what we've done. What we've done is take it to the next step and allow you to decouple a little bit. So, yeah, I mean we need panels. Sure. So would you plan then to build on the layout module that's in contrib right now? It seems like you're building on the content as opposed to you could certainly do the same in Drupal 8 and extend the block concept which I think is combining course blocks concept with the Drupal 7 panel pane content type concept. I could also see an argument for doing this kind of organization at the layout plugin level. Absolutely, and I did look at it. It wasn't quite mature enough to do something right now. But one of the things that for example is a gap on the panel side that maybe we could, you know, while we're early in the process on the Drupal 8 side is that one of our big initiatives at the Weather Company is that we want to build a fully responsive site and building fully responsive at the theme layer is easy. It's easy-ish. But providing a user interface that allows a product owner to lay out a page so that it behaves one way on this browser a different way on a tablet and a different way on a desktop and a consistent experience without significant training is a big challenge. And so, you know, what would really help is bridging the gap in terms of what the behavior is going to be on the front end and the back end. I've seen some really neat moves towards that, you know, the radio boxes at the top that'll choose, you know, the different break points that you can predict. But, you know, you have to go a step further because if, for example, we have an ad that want to appear on the right sidebar in one situation but in the header in a different situation we have to relate those in a way that's hard to see visually. Thanks guys. Anybody else? You guys just want to go home. We do too. It's okay. Yeah. Thank you. Yeah, we're happy to talk to anyone who wants to come up afterwards. Thanks for listening. Thank you guys for choosing us over Drees.