(1462,1947,'Designer, Owner, Manager - 1: Hiring the Right People',NULL,'<p><a href=\"http://www.andyrutledge.com/hiring-the-right-people.php\">Andy Rutledge’s latest article</a> seems like it will come in handy when I eventually start my own business. Some great tips here; especially numbers 6 &amp; 8.</p>',NULL,1913,NULL,'2019-10-09 16:41:19','2019-10-09 16:41:19','8d865415-a70a-4a2c-978c-23d63979d24b',1,NULL,NULL,NULL,NULL),(1463,1948,'User Experience Beyond the Web',NULL,'<p>I had the “pleasure” of having jury duty last week. This was the first time I had ever been called for it before, and I must say that the experience definitely left a lot to be desired. It is definitely clear that all of the time spent on user experience on the web ends up providing a better experience for the end user. But my question now is: <strong>why isn’t that kind of effort put in outside of the web?</strong></p>\n\n<p>There was basically no part of my jury duty experience that was pleasurable. Let me walk you through how my day went.</p>\n\n<h2>Getting Up Early</h2>\n<p>First off, I had to get up super early in order to get there on time. If I am just going to be waiting around most of the day, <strong>why do I have to be there at 8:15am?</strong></p>\n\n<h2>Parking</h2>\n<p>So I pulled into the parking lot that they told me to park in, and started to walk to the court house. But wait, I had no clue where to go. There were <strong>no</strong> signs at all. Luckily I guessed right, or I would have been late.</p>\n\n<h2>Security</h2>\n<p>Since I was going into a court house, I totally expected to have to go through security. I was told that jury duty would probably end up being a lot of waiting around, and I saw that they had wireless internet access there, so I figured I would bring my laptop and get some work done.</p>\n\n<p>First, I had to check my cellphone since it had a camera on it. I’m not really sure what I would want to take pictures with, but whatever, I checked it. I did feel a little lost without my phone though.</p>\n\n<p>Next, I had to go through the metal detectors and put my bag on the x-ray machine. The security officer asked me to take out my laptop and turn it on. I was confused as to why I would need to turn it on, but I hit the button and waited for it to power up. Then, he sees that my laptop has a built-in camera, and tells me that I can’t bring it in.</p>\n\n<p>I looked at him befuddled because I couldn’t imagine sitting with my laptop facing out in the courtroom, taking pictures, and not having someone say something to me. The security officer tells me that I have to take it back to my car. So, I had to walk the quarter of a mile back to my car, put the laptop in there, then walk back and go through security.</p>\n\n<p><strong>Seems a little ridiculous, right?</strong> I must give them credit for actually having wireless internet, but not being able to bring in my laptop really pissed me off.</p>\n\n<h2>The Waiting Room</h2>\n<p>Once I got through security and checked in, I was directed to a big room with a bunch of tables and chairs where we would wait for the next hour or so. Of course, the chairs were jammed in together, and there were not enough seats in the room for everyone.</p>\n\n<p>We watched a 15 minute training video, and then the courthouse employees tried to get us to donate money to the court system. Yeah, after you put me in a bad mood because I couldn’t bring in my laptop, I’m sure I’ll jump at the opportunity to give you money.</p>\n\n<p>What a great start to the morning.</p>\n\n<h2>The Next Waiting Room</h2>\n<p>Finally, my group got called to the courtroom, and we stood around and waited for about two hours until we finally got called into the court room to go through the jury selection process.</p>\n\n<p>So again, more waiting, that’s basically what I did all day.</p>\n\n<h2>Does anyone think about the experience?</h2>\n<p>Here we are in a situation where we are supposed to be impartial and have no biases, and I was in a piss poor mood. Why don’t they make these kind of situations as painless as possible? Why isn’t there someone making sure that the experience of having jury duty is not awful?</p>\n\n<p>Just like we devote time thinking about users’ experiences on the websites we are creating; organizations need to consider what those experiences outside of the web are like.</p>',NULL,1914,NULL,'2019-10-09 16:41:19','2019-10-09 16:41:19','9b0bc508-f991-4b05-9129-c2e22bb2656c',1,NULL,NULL,NULL,NULL),(1464,1949,'Creating a Google Map with ExpressionEngine',NULL,'<p>Since I have a newfound love of ExpressionEngine, I wrote my most recent article for NETTUTS about <a href=\"http://net.tutsplus.com/tutorials/other/creating-a-google-map-with-expressionengine/\">creating a Google Map</a> with it.</p>',NULL,1915,NULL,'2019-10-09 16:41:19','2019-10-09 16:41:19','a4ab39aa-54b4-4ac4-a160-a120451e8ec2',1,NULL,NULL,NULL,NULL),(1465,1950,'10 Cost Effective Web Development Techniques',NULL,'<p>Excellent, excellent, excellent <a href=\"http://allinthehead.com/retro/340/10-cost-effective-web-development-techniques\">presentation from Drew McLellan</a>. Wish I could have seen it in person.</p>',NULL,1916,NULL,'2019-10-09 16:41:19','2019-10-09 16:41:19','155d5505-b37f-4d99-9d5a-5800ce4b912c',1,NULL,NULL,NULL,NULL),(1466,1951,'Of Brands and Commodities',NULL,'<p><a href=\"http://www.andyrutledge.com/of-brands-and-commodities.php\">Genius</a>: “Turning down money to make money; sounds like a dodgy strategy, but it’s more powerful than you might think. And it’s required if you want to build a brand.”</p>',NULL,1917,NULL,'2019-10-09 16:41:19','2019-10-09 16:41:19','b4d734e4-5cf8-4af0-bb8c-33c2929b96c6',1,NULL,NULL,NULL,NULL),(1467,1952,'Remember, You are the Expert',NULL,'<p>I’ve been realizing lately that there is a big problem in the web design/development field: we aren’t thought of as experts. Ok maybe that’s not completely true, but I’ve seen a lot of clients “guiding” the process. But actually, maybe this is our own fault, so how can we fix it?</p>\n\n<h2>Be the Expert</h2>\n<p>We have to remember that we are the web experts in this relationship. We need to show confidence when talking with clients. Talk authoritatively about the details of the project and show them that we know what we are talking about. Just like we wouldn’t go tell an architect how to design a house, our clients need to trust us to build their website.</p>\n\n<h2>Stick to Your Guns</h2>\n<p>So let’s say a client suggests something that you know would work better if you did it a different way; don’t just say yes to the client, make your suggestion and build a case for it. Reference other examples. Site statistics. Fight for the best solution. Remember, <strong>you</strong> are the expert.</p>\n\n<h2>Read, Browse, and Read Some More</h2>\n<p>The web is full of great articles, bad examples of web sites, good examples of web sites, and much more. So by just spending time browsing the web, you can amass a huge amount of knowledge about what works and what doesn’t. This will provide you with loads of ammunition to use when clients need your guidance.</p>\n\n<h2>It’s Hard</h2>\n<p>I struggle with it all the time. It’s hard to say no to a client when they are the ones paying you. But the best thing to do is to make your suggestions, back it up with statistics &amp; examples, and hope that the client trusts your judgment.</p>\n\n<p>Remember, <strong>you</strong> are the expert.</p>',NULL,1918,NULL,'2019-10-09 16:41:19','2019-10-09 16:41:19','5c62cc1d-a86b-4b7d-bea6-469e5efc1e32',1,NULL,NULL,NULL,NULL),(1468,1953,'Dog and Pony Show Design',NULL,'<p>Andy Rutledge continues to blow my mind with his <a href=\"http://www.andyrutledge.com/dog-and-pony-show-design.php\">fantastic articles</a>. “Multiple design options are what you visit in your design process on your way toward a solution. What you present to your client must be the most effective result of your exhaustive efforts. Nothing less.”</p>',NULL,1919,NULL,'2019-10-09 16:41:19','2019-10-09 16:41:19','1336d253-26ac-4336-8d54-9ebfa9c498dc',1,NULL,NULL,NULL,NULL),(1469,1954,'jQuery Inline Form Labels',NULL,'<p>I’ve been seeing the trend of applying inline labels on form elements more and more these days. So I definitely needed to come up with a solid solution that would help me easily apply this effect.</p>\n\n<p><a href=\"//assets.trevor-davis.com/play/jquery-inline-form-labels/\"><img src=\"//assets.trevor-davis.com/uploads/images/content/2009/06/jquery-inline-labels.png\" alt=\"jQuery Inline Form Labels\" width=\"280\" height=\"169\" class=\"leftSide\" /></a>Maybe I need to explain a little better what I am referring to. Instead of using a label that is next to or above the input element, the label is actually within the input. Then, when the input is focused, the label goes away and you can enter your value into it. Finally, when the input is no longer focused, if there is no value entered, the inline label is then added back in.</p>\n\n<p><a href=\"//assets.trevor-davis.com/play/jquery-inline-form-labels/\" class=\"more-link\">See Demo</a></p>\n\n<h2>My Solution</h2>\n<p>The title attribute.</p>\n\n<p>It’s so simple, but perfect. A great benefit of using the title attribute, is that when you hover over the input, you get a little tooltip displaying the inline label. So all I need to do is add a title attribute with the text that we want to have show up as the inline label. Then, we just use a little jQuery to make it all happen.</p>\n\n<h3>The jQuery</h3>\n\n<p>First, we want to select each input that has a title attribute, once the document is loaded:</p>\n\n<div class=\"codeblock\"><code>\n$(document).ready(function() {<br /> $(\'input[title]\').each(function() {<br /> &amp;hellip;<br /> });<br />}); \n\n</code></div>\n\n<p>Next, if the value of the input element is empty, we want to take the title attribute and add it as the value of the input.</p>\n\n<pre>$(document).ready(function() {\n $(\'input[title]\').each(function() {\n  <strong>if($(this).val() === \'\') {\n   $(this).val($(this).attr(\'title\')); \n  }</strong>\n });\n});</pre>\n\n<p>After that, we want to setup a function that will fire once the input is focused. When it is focused, if the value is equal to the title attribute, we want to set the value to nothing and add a class of focused:</p>\n\n<pre>$(document).ready(function() {\n $(\'input[title]\').each(function() {\n  if($(this).val() === \'\') {\n   $(this).val($(this).attr(\'title\')); \n  }\n  \n  <strong>$(this).focus(function() {\n   if($(this).val() === $(this).attr(\'title\')) {\n    $(this).val(\'\').addClass(\'focused\'); \n   }\n  });</strong>\n });\n});</pre>\n\n<p>The reason why we add the class of focused is so that we can change the text color, border or anything to make it noticeable that the input is being focused. You can see this effect in the <a href=\"//assets.trevor-davis.com/play/jquery-inline-form-labels/\">demo</a>.\n\n</p><p>Finally, we want to add a function that will fire when the input loses focus. When it does, if the input value is empty, we want to set the value back to the title attribute and remove the class of focused:</p>\n\n<pre>$(document).ready(function() {\n $(\'input[title]\').each(function() {\n  if($(this).val() === \'\') {\n   $(this).val($(this).attr(\'title\')); \n  }\n  \n  $(this).focus(function() {\n   if($(this).val() === $(this).attr(\'title\')) {\n    $(this).val(\'\').addClass(\'focused\'); \n   }\n  });\n  \n  <strong>$(this).blur(function() {\n   if($(this).val() === \'\') {\n    $(this).val($(this).attr(\'title\')).removeClass(\'focused\'); \n   }\n  });</strong>\n });\n});</pre>\n\n<p><a href=\"//assets.trevor-davis.com/play/jquery-inline-form-labels/\" class=\"more-link\">See Demo</a></p>\n\n<p>And that’s it. It’s just a little bit of code, but it can go a long way. So take it and build on it.</p>',NULL,1920,NULL,'2019-10-09 16:41:19','2019-10-09 16:41:19','c992ecc1-1980-4b32-bf92-53b12f589433',1,NULL,NULL,NULL,NULL),(1470,1955,'Walls Come Tumbling Down',NULL,'<p>Andy Clarke has posted the <a href=\"http://forabeautifulweb.com/blog/about/walls_come_tumbling_down_presentation_slides_and_transcript/\">slides and transcript</a> from his presentation at @media2009. It’s a long one, so I scanned it, but it looked like a fantastic presentation.</p>',NULL,1921,NULL,'2019-10-09 16:41:19','2019-10-09 16:41:19','884a4e6c-a804-48c8-9879-02802f542b96',1,NULL,NULL,NULL,NULL),(1471,1956,'Enough with the IE6 Whining',NULL,'<p>Seriously, I can’t go a day without reading about someone complaining about IE6. Yes, we all know it’s support is terrible. Yes, we know that Microsoft sat around and did nothing for 5 years. But look, they have stepped their game up, they have released 2 browser versions in 3 years. Yes, they are not up to par with more standards compliant browsers, but they are a major improvement over IE6.</p>\n\n<p>So I ask you: <strong>what is Microsoft supposed to do</strong>?</p>\n\n<p>It isn’t their fault that users won’t upgrade their browser.</p>\n\n<h2>Suck It Up</h2>\n\n<p>If you call yourself a web developer, you should be able to make things presentable in IE6. If you can’t, then you probably shouldn’t call yourself one. So suck it up and deal with it. <strong>Doesn’t the challenge make our jobs more interesting?</strong></p>\n\n<p>I’m not saying that your site has to look exactly the same in all browsers. <a href=\"http://dowebsitesneedtolookexactlythesameineverybrowser.com/\">We already know the answer to that question</a>. Just make it presentable. Make sure a user can access all content on the site. Remember, it’s <strong>still</strong> all about the content.</p>\n\n<h3>Better Yet</h3>\n<p>Take a look at the traffic to the site and determine to what degree you even need to support it. If IE6 visitors only compromise a very small percentage, maybe consider using <a href=\"http://forabeautifulweb.com/blog/about/universal_internet_explorer_6_css/\">Andy Clarke’s Universal Internet Explorer 6 CSS</a>. That will put the content front and center in IE6, and you won’t even have to worry about it.</p>\n\n<p>Just please, stop complaining.</p>\n\n<p><strong>&lt;/rant&gt;</strong></p>',NULL,1922,NULL,'2019-10-09 16:41:19','2019-10-09 16:41:19','87c5e34c-08eb-4041-9547-f388abd10ee3',1,NULL,NULL,NULL,NULL),(1472,1957,'Misunderstanding markup',NULL,'<p>Everyone is freaking out about the XHTML 2 Working Group disbanding at the end of the year. Relax people! Jeremy Keith <a href=\"http://adactio.com/journal/1595/\">helps to explain why nobody should worry</a>.</p>',NULL,1923,NULL,'2019-10-09 16:41:19','2019-10-09 16:41:19','618ab407-0851-46eb-9bd6-683cb1bcc782',1,NULL,NULL,NULL,NULL),(1473,1958,'Packt Book Giveaway: jQuery, WordPress, &amp; Open Source CMS',NULL,'<p>I am pleased to announced that I have 3 <a href=\"http://www.packtpub.com/\">Packt</a> books to giveaway: <a href=\"http://www.packtpub.com/learning-jquery-1.3/book/mid/130709nwu5nv\">Learning jQuery 1.3</a>, <a href=\"http://www.packtpub.com/wordpress-2-7-complete-2nd-edition/book/mid/130709sh1anm\">WordPress 2.7 Complete</a>, &amp; <a href=\"http://www.packtpub.com/choosing-an-open-source-cms-beginners-guide/book/mid/1307090ncy0g\">Choosing an Open Source CMS</a>. Entering to win one of these books is very simple, and you can enter in two different ways.</p>\n\n<p><img src=\"//assets.trevor-davis.com/uploads/images/content/2009/07/packt-books.png\" alt=\"\" class=\"pullLeft\" width=\"520\" height=\"265\" /></p>\n\n<p>But first, let me provide a little more detail about the books.</p>\n\n<h2>Learning jQuery 1.3</h2>\n<p><a href=\"http://www.packtpub.com/learning-jquery-1.3/book/mid/130709nwu5nv\"><img src=\"//assets.trevor-davis.com/uploads/images/content/2009/07/packt-jquery.jpg\" alt=\"Learning jQuery 1.3\" width=\"90\" height=\"110\" class=\"leftSide frame pullLeft\" /></a>To build interesting, interactive sites, developers are turning to JavaScript libraries such as jQuery to automate common tasks and simplify complicated ones. Because many web developers have more experience with HTML and CSS than with JavaScript, the library\'s design lends itself to a quick start for designers with little programming experience. Experienced programmers will also be aided by its conceptual consistency.</p>\n<p>Revised and updated for version 1.3 of jQuery, this book teaches you the basics of jQuery for adding interactions and animations to your pages. Even if previous attempts at writing JavaScript have left you baffled, this book will guide you past the pitfalls associated with AJAX, events, effects, and advanced JavaScript language features.</p>\n<p><a href=\"http://www.packtpub.com/learning-jquery-1.3/book/mid/130709nwu5nv\" class=\"more-link\">Full Book Detail</a></p>\n\n\n<h2>WordPress 2.7 Complete</h2>\n<p><a href=\"http://www.packtpub.com/wordpress-2-7-complete-2nd-edition/book/mid/130709sh1anm\"><img src=\"//assets.trevor-davis.com/uploads/images/content/2009/07/packt-wordpress.jpg\" alt=\"WordPress 2.7 Complete\" width=\"90\" height=\"110\" class=\"leftSide frame pullLeft\" /></a>Using WordPress you can easily create dynamic blogs and web sites with great content and many outstanding features. It is an ideal tool for developing blogs and although it is chiefly used for blogging, it can also be used as a complete CMS with very little effort. You can customize the features, incorporate your own design, and even write your own plug-ins with ease. Its versatility and ease of use have attracted a large, enthusiastic, and helpful community of users. While it is easy to get started with WordPress, its full power is not obvious.</p>\n<p>If you want to create a powerful, fully-featured blog or non-blog web site in no time, this book is for you. It will give you a rapid and straightforward introduction to the rich and powerful features of WordPress and get you up and running with a state-of-the-art blog as quickly and painlessly as possible. It will help you learn everything WordPress has to offer, from the ground up, so you can build your complete web site. You will see many of WordPress\'s hidden powers that will help you build a fully functioning web site.</p>\n\n<p><a href=\"http://www.packtpub.com/wordpress-2-7-complete-2nd-edition/book/mid/130709sh1anm\" class=\"more-link\">Full Book Detail</a></p>\n\n<h2>Choosing an Open Source CMS</h2>\n<p><a href=\"http://www.packtpub.com/choosing-an-open-source-cms-beginners-guide/book/mid/1307090ncy0g\"><img src=\"//assets.trevor-davis.com/uploads/images/content/2009/07/packt-cms.jpg\" alt=\"Choosing an Open Source CMS\" width=\"90\" height=\"110\" class=\"leftSide frame pullLeft\" /></a>There are many powerful open source CMSs available to take the pain away from managing a web site. These systems are feature rich, often easy to use, and free. Unfortunately, there are so many choices it\'s tough to be sure you\'re choosing the right one. How can you be sure that you are selecting and working with the right tool?</p>\n\n<p>This book will guide you through choosing the right CMS for your needs. You can be confident in your choice of CMS for the needs of your project. It will also help you make a start using the CMS, and give you a feel for what it\'s like to use it â€“ even before you install it yourself.</p>\n\n<p>Are you bewildered by the many open source CMSs available online? Open source CMSs are the best way to create and manage sophisticated web sites. You can create a site that precisely meets your business goals, and keep the site up to date easily because these systems give you full control over every aspect of your site. Because open source CMSs are free to download, you have a huge amount of choice between the various systems.</p>\n\n<p><a href=\"http://www.packtpub.com/choosing-an-open-source-cms-beginners-guide/book/mid/1307090ncy0g\" class=\"more-link\">Full Book Detail</a></p>\n\n<h2>How to Enter</h2>\n<p>There are two different ways to enter:</p>\n<ol><li>Post a comment on this blog post with the book of your choice: <strong>jQuery</strong>, <strong>WordPress</strong>, or <strong>CMS</strong>. Make sure you provide a valid email address so that I can get in touch with you if you win.</li>\n<li>Tweet about it. Here is what you need to tweet: \n<p><a href=\"http://bit.ly/5J7Gj\">http://bit.ly/5J7Gj</a> Free Packt Book Giveaway from <a href=\"http://twitter.com/davist11\">@davist11</a> I want the <strong>(BOOK NAME HERE)</strong> book.</p>\nThen just replace <strong>BOOK NAME HERE</strong> with the book of your choice: <strong>jQuery</strong>, <strong>WordPress</strong>, or <strong>CMS</strong>.</li>\n</ol><h2>Contest Details</h2>\n<p>You can enter once by submitting a comment on this post and <strong>as many times as you want on Twitter</strong>. The contest will end Friday, July 24th at 6 PM ET. Once over, I will randomly choose the winners and notify them to get their addresses.</p>\n\n<p>That’s it, now get going and enter already. <strong>Big thanks to <a href=\"http://www.packtpub.com\">Packt Publishing</a> for sponsoring the giveaway!</strong></p>',NULL,1924,NULL,'2019-10-09 16:41:19','2019-10-09 16:41:19','62550619-e4a7-4155-9d29-2053585a1fa5',1,NULL,NULL,NULL,NULL),(1474,1959,'Strangers at a cocktail party',NULL,'<p><a href=\"http://www.37signals.com/svn/posts/1808-strangers-at-a-cocktail-party\">I love this way of thinking</a>. A successful environment is one where you are able to tell people when they’re full of crap.</p>',NULL,1925,NULL,'2019-10-09 16:41:19','2019-10-09 16:41:19','1a414ddb-4975-43de-bdcd-ab8bfa8cc8e9',1,NULL,NULL,NULL,NULL),(1475,1960,'Web Design is a Journey',NULL,'<p>I definitely don’t categorize myself as a designer because there is no way I can create such <a href=\"http://carsonified.com/blog/design/web-design-is-a-journey/\">amazing work as this</a>. It’s fantastic to see the <strong>very</strong> different directions that Mike went in before reaching the final design.</p>',NULL,1926,NULL,'2019-10-09 16:41:19','2019-10-09 16:41:19','e6b8a3ab-beb7-4c53-b410-b311fa38b9f6',1,NULL,NULL,NULL,NULL),(1476,1961,'Packt Book Giveaway Winners',NULL,'<p>Thank you everyone for participating in the <a href=\"//trevor-davis.com/blog/news/packt-book-giveaway/\">Packt Book Giveaway</a>. It was interesting to see how many more people were interested in the jQuery book compared to the others. Now, on to the winners…</p>\n\n<ul><li><p>The <strong>Choosing an Open Source CMS</strong> book was won by <a href=\"//trevor-davis.com/blog/news/packt-book-giveaway/#comment-3212\">Eric D. Greene</a> with his comment on the blog article.</p></li>\n<li><p>The <strong>WordPress 2.7 Complete</strong> book was won by <a href=\"http://twitter.com/mudd06/status/2823637564\">Adrian Turner</a> with his Twitter entry.</p></li>\n<li><p>The <strong>Learning jQuery 1.3</strong> book was won by <a href=\"//trevor-davis.com/blog/news/packt-book-giveaway/#comment-3222\">CodeJoust Chattanooga Webdesign Development</a> for their comment on the blog article.</p></li>\n</ul><p>The winners have been contacted, but if their are any problems, I will choose a new winner. Thanks everyone for the entries, and I hope to be able to do this again.</p>',NULL,1927,NULL,'2019-10-09 16:41:20','2019-10-09 16:41:20','6a8be39e-6785-44ad-8e36-1df499467fa3',1,NULL,NULL,NULL,NULL),(1477,1962,'Create a Newsletter with ExpressionEngine &amp; FieldFrame',NULL,'<p>I guess it is time to come back from my little hiatus to actually write a blog post. I recently moved, so I have been busy with getting settled and working on freelance projects as well. If you <a href=\"http://twitter.com/davist11\">follow me on Twitter</a>, you may have noticed that I have recently become obsessed with ExpressionEngine. I completed a <a href=\"//trevor-davis.com/work/ecfc/\">project</a> at work using it, and I realized that I could have done something much more efficiently.</p>\n\n<p><a href=\"http://ee.trevor-davis.com/newsletter/\" class=\"more-link\">View Demo</a></p>\n<p>I had to create an “online newsletter” that had issues that were made up of multiple articles. I ended up creating two separate weblogs: one for each issue, and one for individual articles. In the issues weblog, there was a <a href=\"http://brandon-kelly.com/playa\">Playa</a> custom field which could be used to pick the individual articles to be published in that issue. But, another one of Brandon Kelly’s fabulous extensions, <a href=\"http://brandon-kelly.com/fieldframe\">FieldFrame</a>, seems to be a much better choice for creating this functionality.</p>\n<p>So, download, install, &amp; enable the <a href=\"http://brandon-kelly.com/fieldframe\">FieldFrame Extension</a>, and let’s be on our way.</p>\n<h2>Creating the Custom Field Group</h2>\n<p>First, let’s create a field group named <strong>Newsletter</strong>. Now, we just need to create one custom field with the field name of <strong>newsletter_articles</strong>. Select <strong>FF Matrix</strong> as the field type.</p>\n\n<p>We want to have two cells in the FF Matrix: <strong>articles_title</strong> &amp; <strong>articles_body</strong>. The cell types should be text and textarea, respectively. Then, adjust the sizes as you see fit.</p>\n\n<p><img src=\"//assets.trevor-davis.com/uploads/images/content/2009/08/newsletter-ff.png\" alt=\"FF Matrix Configuration\" width=\"570\" height=\"282\" class=\"frame pullLeft\" /></p>\n\n<h2>Creating the Weblog</h2>\n<p>Now that we have the custom field group setup, we need to create a new weblog called <strong>newsletter</strong> and make sure to assign our <strong>Newsletter field group</strong> to it. Now that the newsletter weblog is created, we can start adding newsletters.</p>\n\n<p><img src=\"//assets.trevor-davis.com/uploads/images/content/2009/08/newletter-entry.png\" alt=\"Newsletter Entry Form\" width=\"570\" height=\"304\" class=\"frame pullLeft\" /></p>\n\n<p>First, fill in the main title field, and then add in one or more articles. Now, let’s get onto coding the output template.</p>\n\n<h2>Creating the Template</h2>\n<p>Let’s start by creating a new template group called <strong>newsletter</strong>. We have two different pages that we want to create: the page listing all of the newsletter entries, and the individual newsletter entry displaying all of the articles. But, we can do this with only one template.</p>\n\n<p>So, open up the index template in the newsletter template group, and we will start by setting up the structure of the template:</p>\n\n<div class=\"codeblock\"><code>\n{assign_variable:weblog=\"newsletter\"}<br />{embed=\"newsletter/.header\" title=\"{if segment_2}<br /> {!--Display individual newsletter entry title here--}<br />{if:else}<br /> Newsletters<br />{/if}<br />\"}<br /><br />{if segment_2}<br /> {!--Display full individual newsletter entry with 1 or more articles--}<br />{if:else}<br /> {!--Display list of newsletters entered--}<br />{/if}<br /><br />{embed=\"newsletter/.footer\"} \n\n</code></div>\n\n<p>We start by creating a variable to store the name of our weblog. Then, I created a simple header and footer to store some of the HTML that frames the page. I am passing in the title value in an embed variable to the header and displaying that in the browser title.</p>\n\n<p>If the segment_2 value is not null, we know that we are on an individual newsletter page, so we will display that title. If the segment_2 value is null, then we are on the main newsletter listing page, so we just display Newsletters.</p>\n\n<p>We are using the same conditional again for the content on the page. We either show the individual newsletter entry with the articles, or we show the list of newsletter entered. So let’s build out the code a little more. First, let’s finish displaying the title:</p>\n\n<div class=\"codeblock\"><code>\n{embed=\"newsletter/.header\" title=\"{if segment_2}<br /> {exp:weblog:entries weblog=\"{weblog}\" limit=\"1\" disable=\"categories|category_fields|custom_fields|member_data|pagination|trackbacks\"}<br />  {title} : {entry_date format=\"%F %j, %Y\"}<br /> {/exp:weblog:entries}<br />{if:else}<br /> Newsletters<br />{/if}<br />\"} \n\n</code></div>\n<p>Pretty simple stuff here, just displaying the title and entry date of the newsletter entry. Next, let’s tackle displaying the single newsletter entry view:</p>\n\n<div class=\"codeblock\"><code>\n{if segment_2}<br /> {exp:weblog:entries weblog=\"{weblog}\" limit=\"1\" disable=\"categories|category_fields|custom_fields|member_data|pagination|trackbacks\"}<br />  &lt;h1&gt;{title}: {entry_date format=\"%F %j, %Y\"}&lt;/h1&gt;<br /><br />  {newsletter_articles}<br />   &lt;div class=\"entry\"&gt;<br />    &lt;h2&gt;{articles_title}&lt;/h2&gt;<br />    {articles_body}<br />   &lt;/div&gt;<br />  {/newsletter_articles}<br /> {/exp:weblog:entries}<br /> &lt;p&gt;&lt;a href=\"{path=\"newsletter\"}\"&gt;&amp;laquo; Back to Newsletters&lt;/a&gt;&lt;/p&gt; \n\n</code></div>\n\n<p>The beginning should look pretty normal: just using the standard exp:weblog:entries tag to pull in the individual entry. We first display the title and entry date. Then, the next part is where we are taking advantage of the <a href=\"http://brandon-kelly.com/fieldframe/docs/ff-matrix\">FieldFrame Matrix</a>. We are basically just looping through all of the <strong>newsletter_articles</strong> and displaying them in divs.</p>\n\n<p>Finally, let’s finish up by displaying the list of newsletter entries:</p>\n<div class=\"codeblock\"><code>\n{if:else}<br /> {exp:weblog:entries weblog=\"{weblog}\" disable=\"categories|category_fields|custom_fields|member_data|pagination|trackbacks\"}<br />  {if count == 1}<br />   &lt;ul&gt;<br />  {/if}<br /><br />   &lt;li&gt;&lt;a href=\"{url_title_path=\"newsletter\"}\"&gt;{title}: {entry_date format=\"%F %j, %Y\"}&lt;/a&gt;&lt;/li&gt;<br />  {if count == total_results}<br />   &lt;/ul&gt;<br />  {/if}<br /> {/exp:weblog:entries}<br />{/if} \n\n</code></div>\n\n<p>Simple stuff again: just looping through all newsletter entries and displaying them in a list. The two conditional statements are so you don’t end up with any empty unordered lists when there are no entries.</p>\n\n<p><a href=\"http://ee.trevor-davis.com/newsletter/\" class=\"more-link\">View Demo</a></p>\n\n<p>I wish I would have realized this would have been a more efficient way to build a newsletter in EE for the project; but, this is why always learning is so important.</p>',NULL,1929,NULL,'2019-10-09 16:41:20','2019-10-09 16:41:20','eb6c2e8d-4178-4940-b6b6-bff6a2bf986c',1,NULL,NULL,NULL,NULL),(1478,1963,'Simple jQuery Text Resizer',NULL,'<p>I have done JavaScript text resizers a couple of different ways before, but I think I found my favorite way on a recent project. In previous projects, I have messed around with determining the current font size and adjusting it appropriately. But, in my opinion, simplifying things has made it a much better implementation.</p>\n\n\n<p>If you want to skip right to the <a href=\"//assets.trevor-davis.com/play/jquery-text-resizer/\">demo</a>, feel free.</p>\n\n<p><a href=\"//assets.trevor-davis.com/play/jquery-text-resizer/\" class=\"more-link\">View Demo</a></p>\n\n<h2>Disclaimer</h2>\n<p>Let me first say that I have started to size text in pixels and <a href=\"http://danielmall.com/archives/2007/04/20/soft_serve.php\">soft serving</a> EMs to IE6. There are tons of different font sizing techniques you can use, but this is what is working for me. So use whatever technique you please, and adjust as needed.</p>\n\n<p>Another thing: <strong>I hate text resizers</strong>. In my opinion, there is no reason to duplicate browser functionality. I feel the same about back and print links, but sometimes the functionality is requested, so I have to build it.</p>\n\n<h2>Concept</h2>\n<p>The idea is very simple: you click on the text size you want, and a class is added to the body to indicate which size the user has selected. Then, we take advantage of that body class when we are writing our CSS to size the different elements appropriately.</p>\n\n<h2>Code</h2>\n<p>Let’s first start as we always should, by creating the markup:</p>\n\n<div class=\"codeblock\"><code>\n&lt;ul class=\"resizer\"&gt;<br /> &lt;li class=\"small\"&gt;&lt;a href=\"#\"&gt;A&lt;/a&gt;&lt;/li&gt;<br /> &lt;li class=\"medium\"&gt;&lt;a href=\"#\"&gt;A&lt;/a&gt;&lt;/li&gt;<br /> &lt;li class=\"large\"&gt;&lt;a href=\"#\"&gt;A&lt;/a&gt;&lt;/li&gt;<br />&lt;/ul&gt; \n\n</code></div>\n\n<h3>jQuery</h3>\n<p>The markup was simple enough, so let’s get started on the jQuery. First, we want to execute our code when the document is loaded, and then add an event when one of the resizer links are clicked:</p>\n\n<div class=\"codeblock\"><code>\n$(document).ready(function() {<br /> $(\'.resizer a\').click(function() {<br /><br /> });<br />}); \n\n</code></div>\n\n<p>Next, we want to get the class of the parent of the link that has been clicked, remove any of the resizer classes from the body, and add the new one:</p>\n\n<div class=\"codeblock\"><code>\n$(document).ready(function() {<br /> $(\'.resizer a\').click(function() {<br />  var textSize = $(this).parent().attr(\'class\');<br />  $(\'body\').removeClass(\'small medium large\').addClass(textSize);<br /> });<br />}); \n\n</code></div>\n\n<p>We also don’t want to regular action of the link to be followed, so we need to <strong>return false</strong>:</p>\n\n<div class=\"codeblock\"><code>\n$(document).ready(function() {<br /> $(\'.resizer a\').click(function() {<br />  var textSize = $(this).parent().attr(\'class\');<br />  $(\'body\').removeClass(\'small medium large\').addClass(textSize);<br />  return false;<br /> });<br />}); \n\n</code></div>\n\n<p>I also think it is important to remember what text size a user has selected while browsing the site, so we will take advantage of the <a href=\"http://plugins.jquery.com/project/cookie\">jQuery Cookie plugin</a> to help us with that. We will set a cookie that denotes which size the user has selected:</p>\n\n<div class=\"codeblock\"><code>\n$(document).ready(function() {<br /> $(\'.resizer a\').click(function() {<br />  var textSize = $(this).parent().attr(\'class\');<br />  $(\'body\').removeClass(\'small medium large\').addClass(textSize);<br />  $.cookie(\'TEXT_SIZE\',textSize, { path: \'/\', expires: 10000 });<br />  return false;<br /> });<br />}); \n\n</code></div>\n\n<p>Finally, we just need to add a check to the beginning of the script, so that if that cookie is set, we add that size as a class to the body:</p>\n\n<div class=\"codeblock\"><code>\n$(document).ready(function() {<br /> if($.cookie(\'TEXT_SIZE\')) {<br />  $(\'body\').addClass($.cookie(\'TEXT_SIZE\')); <br /> }<br /> $(\'.resizer a\').click(function() {<br />  var textSize = $(this).parent().attr(\'class\');<br />  $(\'body\').removeClass(\'small medium large\').addClass(textSize);<br />  $.cookie(\'TEXT_SIZE\',textSize, { path: \'/\', expires: 10000 });<br />  return false;<br /> });<br />}); \n\n</code></div>\n\n<h3>CSS</h3>\n<p> Now is where we get to the really powerful part of doing the text resizing like this: the CSS. We can start by simply stating our text size when it is in the small/default state:</p>\n\n<div class=\"codeblock\"><code>\nbody { font: 12px/18px Arial, sans-serif; } \n\n</code></div>\n\n<p>Then, we just need to make a simple adjustment for the medium and large sizes:</p>\n\n<div class=\"codeblock\"><code>\n.medium { font-size: 16px; line-height: 22px; }<br />.large { font-size: 20px; line-height: 26px; } \n\n</code></div>\n\n<p>So you can just carry through this idea for the rest of the elements that have been assigned a font size:</p>\n\n<div class=\"codeblock\"><code>\nh1 { font-size: 30px; line-height: 36px; }<br />.medium h1 { font-size: 34px; line-height: 40px; }<br />.large h1 { font-size: 38px; line-height: 44px; }<br />h2 { font-size: 24px; line-height: 30px; }<br />.medium h2 { font-size: 28px; line-height: 34px; }<br />.large h2 { font-size: 32px; line-height: 38px; }<br />h3 { font-size: 18px; line-height: 24px; }<br />.medium h3 { font-size: 22px; line-height: 28px; }<br />.large h3 { font-size: 26px; line-height: 32px; } \n\n</code></div>\n\n<p><a href=\"//assets.trevor-davis.com/play/jquery-text-resizer/\" class=\"more-link\">View Demo</a></p>\n\n<p>The idea is very simple, and it really separates the presentation and behavioral layers. So what do you think? Do you have another technique that you like?</p>',NULL,1930,NULL,'2019-10-09 16:41:20','2019-10-09 16:41:20','32fa2274-d126-486d-a648-e50e16482a63',1,NULL,NULL,NULL,NULL),(1479,1964,'The State of the Web Design Profession',NULL,'<p>Noah Stokes has written a fantastic article on <a href=\"http://esbueno.noahstokes.com/post/190407732/the-state-of-the-web-design-profession\">the State of the Web Design Profession</a>. Well said.</p>',NULL,1931,NULL,'2019-10-09 16:41:20','2019-10-09 16:41:20','b501bc99-215d-4fce-90b3-324ac153305f',1,NULL,NULL,NULL,NULL),(1480,1965,'What Gives?',NULL,'<p>I like <a href=\"http://boxofchocolates.ca/archives/2009/10/01/what-gives/\">this</a>: “We’re working at building the most important communications network in history. What we do today matters”. Good read, things need to change.</p>',NULL,1932,NULL,'2019-10-09 16:41:20','2019-10-09 16:41:20','78e58709-9515-4824-9085-1df1bbe775cd',1,NULL,NULL,NULL,NULL),(1481,1966,'Dear Small Businesses: Some Advice',NULL,'<p>Jonathan Longnecker has posted <a href=\"http://fortysevenmedia.com/blog/archives/dear_small_businesses_some_advice/\">a well written article</a> expressing his love and frustrations of designing websites with small businesses. Some very nice points and advice here.</p>',NULL,1933,NULL,'2019-10-09 16:41:20','2019-10-09 16:41:20','4d7b19b2-536e-4293-8e83-de408bcbe492',1,NULL,NULL,NULL,NULL),(1482,1967,'Spammers, Evildoers, and Opportunists',NULL,'<p>Derek Powazek <a href=\"http://powazek.com/posts/2090\">shares his opinion of SEO</a>. I’m not going to lie; I agree with what he is saying.</p>',NULL,1934,NULL,'2019-10-09 16:41:20','2019-10-09 16:41:20','88b293e8-9ad4-4a02-8664-58fd690d86ed',1,NULL,NULL,NULL,NULL),(1483,1968,'SEO FAQ',NULL,'<p>Derek Powazek <a href=\"http://powazek.com/posts/2101\">clarifies some points</a> from his latest post. Again, great stuff here.</p>',NULL,1935,NULL,'2019-10-09 16:41:20','2019-10-09 16:41:20','93fc160a-48f8-428f-a9db-5d2d9e435bab',1,NULL,NULL,NULL,NULL),(1484,1969,'ExpressionEngine: Embed an Embed within Itself?',NULL,'<p>At work this week, there was discussion on how to accomplish something in ExpressionEngine. We wanted to pull in entries that were in one category, but if there were no entries, then pull in from other categories and display that instead. We were kind of stumped as to how to do that.</p>\n\n<p>I’m not sure if we were missing some easy way to do that, but we couldn’t think of a nice way to accomplish it.</p>\n\n<h2>Let’s Backup</h2>\n<p>I guess it will be helpful to give you some more context. We had created a Channel (our term for Weblog) for <strong>events</strong>. You could categorize the events, and they would publish in different places.</p>\n<p>In this instance, the homepage, we wanted to pull an event from one category, but if there were none, then just display an event from another category.</p>\n\n<h2>The Initial Code</h2>\n\n<p>This code was separated out in an embed so that we could use it in various places on the site:</p>\n\n<div class=\"codeblock\"><code>\n{assign_variable:channel_name=\"{embed:channel}\"}<br />{assign_variable:category_id=\"{embed:category}\"}<br /><br />{exp:weblog:entries weblog=\"{channel_name}\" category=\"{category_id}\" show_future_entries=\"yes\" show_expired=\"no\" limit=\"1\" disable=â€œcategory_fields|custom_fields|member_data|pagination|trackbacksâ€}<br /><br /> &lt;h2&gt;{title}&lt;/h2&gt;<br /> {if events_feature_image}<br />  &lt;p class=\"rightSide\"&gt;&lt;a href=\"{url_title_path=\"{embed:template_path}\"}\"&gt;&lt;img src=\"{events_feature_image}\" alt=\"\" /&gt;&lt;/a&gt;&lt;/p&gt;<br /> {/if}<br /> {if events_summary}<br />  {events_summary}<br /> {/if}<br /><br /> &lt;p&gt;&lt;a href=\"{url_title_path=\"{embed:template_path}\"}\" class=\"more\"&gt;Read more &amp;raquo;&lt;/a&gt;&lt;/p&gt;<br />{/exp:weblog:entries} \n\n</code></div>\n\n<p>The code doesn’t really need to be explained; it’s not the important part of this post. So on the homepage, we had code that looked like this to pull in the event:</p>\n\n<div class=\"codeblock\"><code>\n{embed=\"site/.events\" channel=\"events\" category=\"7\" template_path=\"news-events/events\"} \n\n</code></div>\n\n<p>Now, what we really wanted to be able to do was to modify the <strong>exp:weblog:entries</strong> code to pull from a different category if there were no results. Something like this:</p>\n\n<div class=\"codeblock\"><code>\n{exp:weblog:entries weblog=\"{channel_name}\" category=\"{category_id}\" show_future_entries=\"yes\" show_expired=\"no\" limit=\"1\" disable=â€œcategory_fields|custom_fields|member_data|pagination|trackbacksâ€}<br />&amp;hellip;<br /> {if no_results}<br />  Code  to pull from a different category<br /> {/if}<br />&amp;hellip;<br />{/exp:weblog:entries} \n\n</code></div>\n\n<p>But the problem was, there really was no code that we could put in there that would pull from another category since you can’t nest <strong>exp:weblog:entries</strong> tags. So that’s when I remembered that you could stick an embed file in there that could have the <strong>exp:weblog:entries</strong> tag inside of it.</p>\n\n<p>Then we realized that the code we wanted to write would be exactly like the code in the embed file we were already working with.</p>\n\n<p>So we did a little investigation and found out that <a href=\"http://expressionengine.com/docs/templates/embedding_templates.html\">according to the documentation (see notes section)</a>, you cannot embed an embed within itself.</p>\n\n<p>That makes sense, because you could create an infinite loop. But what if we knew that it would not return an infinite loop?</p>\n\n<h2>Modified Code</h2>\n\n<p>So we determined that what we could do is not pass in the category on the embed statement, and that would pull back any events.</p>\n\n<div class=\"codeblock\"><code>\n{exp:weblog:entries weblog=\"{channel_name}\" category=\"{category_id}\" show_future_entries=\"yes\" show_expired=\"no\" limit=\"1\" disable=â€œcategory_fields|custom_fields|member_data|pagination|trackbacksâ€}<br />&amp;hellip;<br /> {if no_results}<br />  {embed=\"site/.events\" channel=\"events\" template_path=\"news-events/events\"}<br /> {/if}<br />&amp;hellip;<br />{/exp:weblog:entries} \n\n</code></div>\n\n<p>See how there is no category parameter this time? Here is the full modified code:</p>\n\n<div class=\"codeblock\"><code>\n{assign_variable:channel_name=\"{embed:channel}\"}<br />{assign_variable:category_id=\"{embed:category}\"}<br /><br />{exp:weblog:entries weblog=\"{channel_name}\" category=\"{category_id}\" show_future_entries=\"yes\" show_expired=\"no\" limit=\"1\" disable=â€œcategory_fields|custom_fields|member_data|pagination|trackbacksâ€}<br /><br /> &lt;h2&gt;{title}&lt;/h2&gt;<br /> {if events_feature_image}<br />  &lt;p class=\"rightSide\"&gt;&lt;a href=\"{url_title_path=\"{embed:template_path}\"}\"&gt;&lt;img src=\"{events_feature_image}\" alt=\"\" /&gt;&lt;/a&gt;&lt;/p&gt;<br /> {/if}<br /> {if events_summary}<br />  {events_summary}<br /> {/if}<br /><br /> &lt;p&gt;&lt;a href=\"{url_title_path=\"{embed:template_path}\"}\" class=\"more\"&gt;Read more &amp;raquo;&lt;/a&gt;&lt;/p&gt;<br /><br /> &lt;strong&gt;{if no_results}<br />  {embed=\"site/.events\" channel=\"events\" template_path=\"news-events/events\"}<br /> {/if}&lt;/strong&gt;<br />{/exp:weblog:entries} \n\n</code></div>\n\n<p><strong>And that worked!</strong></p>\n\n<h2>Houston, we still have a problem…</h2>\n<p>But, we then realized that the same problem would occur if there were no future events in any categories. So, we still needed to go back and solve that problem by similarly passing the value for the <strong>show_expired</strong> parameter in the embed statement as well. I left that to my colleague, so I didn’t test this code, but this is my guess of how to solve that problem:</p>\n\n<div class=\"codeblock\"><code>\n{assign_variable:channel_name=\"{embed:channel}\"}<br />{assign_variable:category_id=\"{embed:category}\"}<br />&lt;strong&gt;{assign_variable:show_expired=\"{embed:show_expired}\"}&lt;/strong&gt;<br /><br />{exp:weblog:entries weblog=\"{channel_name}\" category=\"{category_id}\" show_future_entries=\"yes\" &lt;strong&gt;show_expired=\"{show_expired}\"&lt;/strong&gt; limit=\"1\" disable=â€œcategory_fields|custom_fields|member_data|pagination|trackbacksâ€}<br /><br /> &lt;h2&gt;{title}&lt;/h2&gt;<br /> {if events_feature_image}<br />  &lt;p class=\"rightSide\"&gt;&lt;a href=\"{url_title_path=\"{embed:template_path}\"}\"&gt;&lt;img src=\"{events_feature_image}\" alt=\"\" /&gt;&lt;/a&gt;&lt;/p&gt;<br /> {/if}<br /> {if events_summary}<br />  {events_summary}<br /> {/if}<br /><br /> &lt;p&gt;&lt;a href=\"{url_title_path=\"{embed:template_path}\"}\" class=\"more\"&gt;Read more &amp;raquo;&lt;/a&gt;&lt;/p&gt;<br /><br /> {if no_results}<br />  {embed=\"site/.events\" channel=\"events\" &lt;strong&gt;show_expired=\"yes\"&lt;/strong&gt; template_path=\"news-events/events\"}<br /> {/if}<br />{/exp:weblog:entries} \n\n</code></div>\n\n<h2>Conclusion</h2>\n<p>Was there some really easy way to do this that we completely blanked on? It seemed a little <em>hacky</em>, but the solution worked.</p>',NULL,1936,NULL,'2019-10-09 16:41:20','2019-10-09 16:41:20','c77e6b76-1fda-4030-b6ac-1e9acf926548',1,NULL,NULL,NULL,NULL),(1485,1970,'Creativity is Not Design (Design Test 2)',NULL,'<p>Andy Rutledge has created a <a href=\"http://www.andyrutledge.com/creativity-is-not-design-test-2.php\">second design test</a> to show that creativity does not necessarily mean you are an effective designer. The <a href=\"http://www.andyrutledge.com/design-test.php\">first test</a> is excellent as well. I need to learn more about design principles…</p>',NULL,1937,NULL,'2019-10-09 16:41:20','2019-10-09 16:41:20','eab249af-aa8e-4c79-aff5-4ef3801bc8f3',1,NULL,NULL,NULL,NULL),(1486,1971,'Reversed Ordered List with jQuery',NULL,'<p>At work this past week, a client requested something that I wasn’t sure how to achieve: a reversed ordered list. So basically, they wanted to have a top 10 list, with the first item being numbered 10 and the last 1.</p>\n\n<p>If you want to <a href=\"//assets.trevor-davis.com/play/reversed-ordered-list-with-jquery/\">skip ahead to the demo</a>, go ahead.</p>\n\n<p><a href=\"//assets.trevor-davis.com/play/reversed-ordered-list-with-jquery/\" class=\"more-link\">View Demo</a></p>\n\n<p>Now sure, I could have just written the numbers in as text, but it’s a list, and it’s ordered! Here is an example of what the client wanted:</p>\n\n<p>10. Lorem ipsum dolor sit amet, consectetur adipiscing elit.<br />\n9. Lorem ipsum dolor sit amet, consectetur adipiscing elit.<br />\n8. Lorem ipsum dolor sit amet, consectetur adipiscing elit.<br />\n…<br />\n1. Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>\n\n<p>After some digging around, I found out that you can add the <strong>value attribute</strong> to each list item to specify the number to display. So basically, I just needed to code my list like this:</p>\n\n<div class=\"codeblock\"><code>\n&lt;ol&gt;<br /> &lt;li value=\"10\"&gt;Lorem ipsum dolor sit amet, consectetur adipiscing elit.&lt;/li&gt;<br /> &lt;li value=\"9\"&gt;Lorem ipsum dolor sit amet, consectetur adipiscing elit.&lt;/li&gt;<br /> &lt;li value=\"8\"&gt;Lorem ipsum dolor sit amet, consectetur adipiscing elit.&lt;/li&gt;<br /> &amp;hellip;<br /> &lt;li value=\"1\"&gt;Lorem ipsum dolor sit amet, consectetur adipiscing elit.&lt;/li&gt;<br />&lt;/ol&gt; \n\n</code></div>\n\n<p>Pretty straightforward, but also pretty ugly. So what happens when the client decides they want to insert another bullet in the middle of the list? Yep, that’s right, they would have to adjust the numbering for the rest of the list.</p>\n\n<p>Pretty crappy, so let’s use the powerfulness of jQuery to make this a little better.</p>\n\n<h2>The Markup</h2>\n<p>So just like before, we just want to create an ordered list, but this time, we will leave off the value attribute. We are also going to add a class to the ordered list that we will use as a hook to add in the jQuery functionality:</p>\n\n<div class=\"codeblock\"><code>\n&lt;ol class=\"reversed\"&gt;<br /> &lt;li&gt;Lorem ipsum dolor sit amet, consectetur adipiscing elit.&lt;/li&gt;<br /> &lt;li&gt;Lorem ipsum dolor sit amet, consectetur adipiscing elit.&lt;/li&gt;<br /> &lt;li&gt;Lorem ipsum dolor sit amet, consectetur adipiscing elit.&lt;/li&gt;<br /> &amp;hellip;<br /> &lt;li&gt;Lorem ipsum dolor sit amet, consectetur adipiscing elit.&lt;/li&gt;<br />&lt;/ol&gt; \n\n</code></div>\n\n<h2>The jQuery</h2>\n<p>Mapping out the code a bit: we want to select each element with a class of reversed, and count the total number of children list items. Then, we want to loop through the children, and update the value attribute to be the value of the total number of children minus a counter variable that we started at zero and increment each time through the loop.</p>\n\n<p>That seems relatively straightforward, so I’ll just show the code that I wrote:</p>\n\n<div class=\"codeblock\"><code>\n$(document).ready(function() {<br /> $(\'.reversed\').each(function() {<br />  var $children = $(this).children(\'li\');<br />  var totalChildren = $children.length;<br />  var start = 0;<br />  $children.each(function() {<br />   $(this).val(totalChildren - start);<br />   start++;<br />  });<br /> });<br />}); \n\n</code></div>\n\n<p><a href=\"//assets.trevor-davis.com/play/reversed-ordered-list-with-jquery/\" class=\"more-link\">View Demo</a></p>\n\n<p>It looks like with HTML 5, we get a <a href=\"http://blog.whatwg.org/reverse-ordered-lists\">reversed attribute</a> that accomplishes the same thing, but until it’s fully supported, this quick &amp; easy solution seems to work.</p>\n\n<h2>On a Personal Note</h2>\n<p>I have been severely neglecting my blog, but for good reason. I have been teaching some intro to web development courses at <a href=\"http://www.cdiabu.com/\">CDIABU</a> in Georgetown. Also, I will be starting a new job on December 1st. I will be joining the amazing team at <a href=\"http://www.viget.com/\">Viget Labs</a> as their new front-end developer.</p>',NULL,1938,NULL,'2019-10-09 16:41:20','2019-10-09 16:41:20','10e18064-7426-441c-b878-f6b2913284bb',1,NULL,NULL,NULL,NULL),(1487,1972,'Freeform + FieldFrame = ExpressionEngine Form Builder',NULL,'<p>A form builder is a regular request for some clients when they are looking for a content management system. There aren’t that many CMS that have this kind of functionality built-in, and even if they do, the implementation is usually less than desirable.</p>\n<p>If you follow along with what I’ve been up to, you can probably tell that I have been on a big <a href=\"http://expressionengine.com/\">ExpressionEngine</a> kick. I’ve been using it on a ton of projects recently, and I love it for its flexibility. Although it does lack a true form builder, I figured out a simple way to build one.</p>\n\n<p>If you are impatient and just want to get to the <a href=\"http://ee.trevor-davis.com/forms/contact-form/\">demo</a>, go ahead. Although the form will look like nothing special, as I have just added some simple styling. The real magic of the form builder happens in the Control Panel.</p>\n\n<h2>We Need Add-ons</h2>\n<p>This form builder would not be possible without the use of some awesome add-ons:</p>\n\n<ul><li><a href=\"http://devot-ee.com/add-ons/extensions/fieldframe/\"><strong>FieldFrame</strong></a><p>This one is a no-brainer. I can’t even imagine building a site without it.</p></li>\n <li><a href=\"http://devot-ee.com/add-ons/modules/freeform/\"><strong>Freeform</strong></a><p>If you need a form in EE, this is the way to do it.</p></li>\n <li><a href=\"http://devot-ee.com/add-ons/extensions/freeform-data-select/\"><strong>Freeform Data Select</strong></a><p>A new fieldtype which pulls in templates and fields from the Freeform module.</p></li>\n</ul><h2>Creating a Field Group</h2>\n<p>I built a custom Field Group called Forms, which consisted of four fields:</p>\n\n<ul><li>Template</li>\n <li>Notification Email Addresses</li>\n <li>Return Page</li>\n <li>Fields</li>\n</ul><p>The first three are pretty simple, so I will just give a quick run through on the specifications for those fields and give a more detail review of the <strong>Fields</strong> field:</p>\n\n<h3>Template</h3>\n<p>This is where you select the Freeform template that will be used for the email. This field is not completely necessary, as just using the default template should be good enough, but I figured since it was an option, to throw it in.</p>\n<ul><li><strong>Field Name</strong>: form_template</li>\n <li><strong>Field Type</strong>: Freeform Data Select</li>\n <li><strong>Populate drop-down with</strong>: Freeform Templates</li>\n</ul><h3>Notification Email Addresses</h3>\n<p>This is where you will enter the email address(es) that you want to email when the form is submitted. Since Freeform wants multiple email addresses separated by the | character, I added some help text describing that as well.</p>\n<ul><li><strong>Field Name</strong>: form_notify</li>\n <li><strong>Field Type</strong>: Text Input</li>\n <li><strong>Default Text Formatting for This Field</strong>: None</li>\n <li><strong>Hide Formatting Menu</strong></li>\n</ul><h3>Return Page</h3>\n<p>This is where you enter the URL to the thank you page. Once a user successfully submits the form, they will be redirected here.</p>\n<ul><li><strong>Field Name</strong>: form_return</li>\n <li><strong>Field Type</strong>: Text Input</li>\n <li><strong>Default Text Formatting for This Field</strong>: None</li>\n <li><strong>Hide Formatting Menu</strong></li>\n</ul><h3>Fields</h3>\n<p>This is where the magic happens. This field is a FF Matrix field type that consists of five other fields. Each row of the FF Matrix represents one field (or field group) in the form. I’ll give a brief description of each field of the FF Matrix and show you a screenshot so you can get a better picture:</p>\n\n<ul><li><strong>Field Name</strong>: form_field</li>\n <li><strong>Field Type</strong>: FF Matrix</li>\n</ul><h4>Label</h4>\n<p>This is where you will enter the label for the form field:</p>\n<ul><li><strong>Col Name</strong>: label</li>\n <li><strong>Cell Type</strong>: Text Input</li>\n</ul><h4>Field</h4>\n<p>This field pulls in all of the fields that have been entered into the Freeform module. So you are presented with a dropdown of all of the fields, and you just select the appropriate one:</p>\n\n<ul><li><strong>Col Name</strong>: field</li>\n <li><strong>Cell Type</strong>: Freeform Data Select</li>\n <li><strong>Populate drop-down with</strong>: Freeform fields</li>\n</ul><h4>Field Type</h4>\n<p>This is where you select the type of form field you want to use. I put in a few different options, but this could be expanded upon too:</p>\n\n<ul><li><strong>Col Name</strong>: type</li>\n <li><strong>Cell Type</strong>: FF Select</li>\n <li><strong>Select Options</strong>: Text Input<br />\n  Textarea<br />\n  Select<br />\n  Multi-select<br />\n  Checkbox<br />\n  Checkbox Group<br />\n  Radio Group\n </li>\n</ul><h4>Is this field required?</h4>\n<p>With most forms, there are some fields that are required and some that are not. If you want the field to be required, you just check the checkbox and the Freeform module will make sure it is filled in:</p>\n\n<ul><li><strong>Col Name</strong>: required</li>\n <li><strong>Cell Type</strong>: FF Checkbox</li>\n <li><strong>Checkbox Label</strong>: Is this field required?</li>\n</ul><h4>Options</h4>\n<p>Finally, this field is used when you select a field type that has multiple options. For example, if you select a “Select” field type, you need to provide the options to populate it. So you enter the options separated by the | character:</p>\n\n<ul><li><strong>Col Name</strong>: options</li>\n <li><strong>Cell Type</strong>: Text Input</li>\n</ul><p><a href=\"//assets.trevor-davis.com/uploads/images/content/2009/11/ff-matrix.png\" title=\"FieldFrame Matrix Configuration\"><img src=\"//assets.trevor-davis.com/uploads/images/content/2009/11/ff-matrix_thumb.png\" alt=\"FieldFrame Matrix Configuration\" width=\"570\" height=\"203\" class=\"pullLeft frame\" /></a></p>\n\n<p>So that is all you need for the Field Group, now go ahead and create a Forms Channel (or Weblog) and make sure to assign the Forms Field Group to it.</p>\n\n<p>Now, when you go to publish a Forms entry, you should see something like this:</p>\n\n<p><a href=\"//assets.trevor-davis.com/uploads/images/content/2009/11/form-entry.png\" title=\"New Forms Entry\"><img src=\"//assets.trevor-davis.com/uploads/images/content/2009/11/form-entry_thumb.png\" alt=\"New Forms Entry\" width=\"570\" height=\"258\" class=\"pullLeft frame\" /></a></p>\n\n<p>I made a <a href=\"http://ee.trevor-davis.com/forms/contact-form/\">demo form</a> showing off the various types of form fields. Here is what that entry looks like in the Control Panel:</p>\n\n<p><a href=\"//assets.trevor-davis.com/uploads/images/content/2009/11/demo-entry.png\" title=\"Demo Form Entry in Control Panel\"><img src=\"//assets.trevor-davis.com/uploads/images/content/2009/11/demo-entry_thumb.png\" alt=\"Demo Form Entry in Control Panel\" width=\"570\" height=\"400\" class=\"pullLeft frame\" /></a></p>\n\n<h2>Template</h2>\n<p>Now that we have our Channel and Field Group all setup, we need to deal with the template. You could really setup your template/template group in various ways, so I’m not going to get into those details. One detail that you need to know is that <strong>I enabled PHP for my template</strong>.</p>\n\n<p>First, we just need to start with a simple <strong>exp:weblog:entries</strong> tag:</p>\n\n<div class=\"codeblock\"><code>\n{exp:weblog:entries weblog=\"forms\" limit=\"1\" disable=\"categories|category_fields|member_data|pagination|trackbacks\"}<br />…<br />{/exp:weblog:entries} \n\n</code></div>\n\n<p>Next, we want to start the Freeform form tag:</p>\n\n<div class=\"codeblock\"><code>\n{exp:weblog:entries weblog=\"forms\" limit=\"1\" disable=\"categories|category_fields|member_data|pagination|trackbacks\"}<br /> {exp:freeform:form form_name=\"{url_title}\" form_id=\"{url_title}\" template=\"{form_template}\" notify=\"{form_notify}\" return=\"{form_return}\"}<br /> …<br /> {/exp:freeform:form}<br />{/exp:weblog:entries} \n\n</code></div>\n\n<p>Since we are inside of the exp:weblog:entries tag, we have access to everything that is being returned from that entry. If you have any questions about the various parameters, <a href=\"http://www.solspace.com/docs/detail/freeform_form/#parameters\">refer to the Freeform Documentation</a>.</p>\n\n<p>So far, the values that we are passing into the parameters are pretty straightforward, just custom fields from our entry. But, passing in the <a href=\"http://www.solspace.com/docs/detail/freeform_form/#required\">required</a> parameter is a little more challenging, since we have to loop through all of the rows in our FF Matrix.</p>\n\n<p>If we <a href=\"http://brandon-kelly.com/fieldframe/docs/ff-matrix\">refer to the FF Matrix documentation</a>, we can see how to loop through the rows in the matrix. I only want to return rows that have the required checkbox checked, and I want to separate the names of the fields with the | character. Then, I use the backspace parameter to remove the last one:</p>\n\n<div class=\"codeblock\"><code>\n{exp:freeform:form form_name=\"{url_title}\" form_id=\"{url_title}\" template=\"{form_template}\" notify=\"{form_notify}\" return=\"{form_return}\" &lt;strong&gt;required=\"{form_field search:required=\'y\' backspace=\'1\'}{field}|{/form_field}\"&lt;/strong&gt;}<br />…<br />{/exp:freeform:form} \n\n</code></div>\n\n<p>Next, we want to add a title, ordered list that will contain the form fields, and the submit button:</p>\n\n<div class=\"codeblock\"><code>\n{exp:freeform:form form_name=\"{url_title}\" form_id=\"{url_title}\" template=\"{form_template}\" notify=\"{form_notify}\" return=\"{form_return}\" required=\"{form_field search:required=\'y\' backspace=\'1\'}{field}|{/form_field}\"}<br /> &lt;h1&gt;{title}&lt;/h1&gt;<br /> &lt;ol class=\"forms\"&gt;<br />  …<br />  &lt;li class=\"buttons\"&gt;&lt;input type=\"submit\" name=\"submit\" value=\"submit\" /&gt;&lt;/li&gt;<br /> &lt;/ol&gt;<br />{/exp:freeform:form} \n\n</code></div>\n\n<p>Now here is where the code gets interesting. Just like we did with the required parameter, we want to loop through each row in the FF Matrix and display a list item for each one:</p>\n\n<div class=\"codeblock\"><code>\n{form_field}<br /> &lt;li&gt;<br /> …<br /> &lt;/li&gt;<br />{/form_field} \n\n</code></div>\n\n<p>First, let’s display the label, if there is one, and denote if the field is required or not:</p>\n\n<div class=\"codeblock\"><code>\n{if \"{label}\"}<br /> &lt;label for=\"{field}\"&gt;{if \"{required}\" == \"y\"}&lt;em class=\"required\"&gt;*&lt;/em&gt;{/if}{label}&lt;/label&gt;<br />{/if} \n\n</code></div>\n\n<p>The rest of the code is a big conditional statement which depends upon the Field Types that you specified in the FF Matrix. Let’s first take a look at the <strong>Text Input</strong>, <strong>Textarea</strong>, and <strong>Checkbox</strong> types since they are pretty straightforward:</p>\n\n<div class=\"codeblock\"><code>\n{if \"{type}\" == \"Text Input\"}<br /> &lt;input type=\"text\" name=\"{field}\" id=\"{field}\" /&gt;<br />{if:elseif \"{type}\" == \"Textarea\"}<br /> &lt;textarea name=\"{field}\" id=\"{field}\"&gt;&lt;/textarea&gt;<br />{if:elseif \"{type}\" == \"Checkbox\"}<br /> &lt;input type=\"checkbox\" class=\"checkbox\" name=\"{field}\" id=\"{field}\" /&gt;<br />…<br />{/if} \n\n</code></div>\n\n<p>So we are just checking the type column in the FF Matrix, and then displaying the rest of the data from the row in the appropriate form field.</p>\n\n<p>Next, let’s walk through what happens if you select the <strong>Select</strong> or <strong>Multi-select</strong> types:</p>\n\n<div class=\"codeblock\"><code>\n{if:elseif \"{type}\" == \"Select\" || \"{type}\" == \"Multi-select\" &amp;&amp; \"{options}\"}<br /> &lt;select name=\"{field}{if \"{type}\" == \"Multi-select\"}[]{/if}\" id=\"{field}\"{if \"{type}\" == \"Multi-select\"} multiple=\"multiple\" size=\"4\"{/if}&gt;<br />  &lt;?php $items = explode(\"|\", \'{options}\'); ?&gt;<br />  &lt;?php foreach ($items as $item) { ?&gt;<br />   &lt;option value=\"&lt;?php echo $item; ?&gt;\"&gt;&lt;?php echo $item; ?&gt;&lt;/option&gt;<br />  &lt;?php } ?&gt;<br /> &lt;/select&gt;<br />…<br />{/if} \n\n</code></div>\n\n<p>So first, we are displaying the <strong>select element</strong>, and if it is a <strong>Multi-select</strong>, we are adding <strong>[]</strong> to the name attribute, and adding the <strong>multiple</strong> and <strong>size</strong> attributes.</p>\n\n<p>Next, we want to take the string of <strong>options</strong> that are separated by the | character, and create an array out of the string using the <a href=\"http://php.net/manual/en/function.explode.php\">explode function</a>.</p>\n\n<p>Then, we loop through the array, and display the options for each one.</p>\n\n<p>Finally, we do virtually the same thing for the <strong>Radio Group</strong> and <strong>Checkbox Group</strong> field types:</p>\n\n<div class=\"codeblock\"><code>\n{if:elseif \"{type}\" == \"Radio Group\" &amp;&amp; \"{options}\"}<br /> &lt;ul class=\"group\"&gt;<br />  &lt;?php $items = explode(\"|\", \'{options}\'); $count = 1; ?&gt;<br />  &lt;?php foreach ($items as $item) { ?&gt;<br />   &lt;li&gt;&lt;input type=\"radio\" class=\"radio\" name=\"{field}\" id=\"{field}&lt;?php echo $count; ?&gt;\" value=\"&lt;?php echo $item; ?&gt;\" /&gt;<br />   &lt;label for=\"{field}&lt;?php echo $count; ?&gt;\"&gt;&lt;?php echo $item; ?&gt;&lt;/label&gt;&lt;/li&gt;<br />   &lt;?php $count++; ?&gt;<br />  &lt;?php } ?&gt;<br /> &lt;/ul&gt;<br />{if:elseif \"{type}\" == \"Checkbox Group\" &amp;&amp; \"{options}\"}<br /> &lt;ul class=\"group\"&gt;<br />  &lt;?php $items = explode(\"|\", \'{options}\'); $count = 1; ?&gt;<br />  &lt;?php foreach ($items as $item) { ?&gt;<br />   &lt;li&gt;&lt;input type=\"checkbox\" class=\"checkbox\" name=\"{field}[]\" id=\"{field}&lt;?php echo $count; ?&gt;\" value=\"&lt;?php echo $item; ?&gt;\" /&gt;<br />   &lt;label for=\"{field}&lt;?php echo $count; ?&gt;\"&gt;&lt;?php echo $item; ?&gt;&lt;/label&gt;&lt;/li&gt;<br />   &lt;?php $count++; ?&gt;<br />  &lt;?php } ?&gt;<br /> &lt;/ul&gt;<br />{/if} \n\n</code></div>\n\n<p>So that’s it really. Here is the full template:</p>\n\n<div class=\"codeblock\"><code>\n{exp:weblog:entries weblog=\"forms\" limit=\"1\" disable=\"categories|category_fields|member_data|pagination|trackbacks\"}<br /><br /> {exp:freeform:form form_name=\"{url_title}\" form_id=\"{url_title}\" template=\"{form_template}\" notify=\"{form_notify}\" return=\"{form_return}\" required=\"{form_field search:required=\'y\' backspace=\'1\'}{field}|{/form_field}\"}<br /><br />  &lt;h1&gt;{title}&lt;/h1&gt;<br />  &lt;ol class=\"forms\"&gt;<br />   {form_field}<br />    &lt;li&gt;<br />     {if \"{label}\"}<br />      &lt;label for=\"{field}\"&gt;{if \"{required}\" == \"y\"}&lt;em class=\"required\"&gt;*&lt;/em&gt;{/if}{label}&lt;/label&gt;<br />     {/if}<br />     {if \"{type}\" == \"Text Input\"}<br />      &lt;input type=\"text\" name=\"{field}\" id=\"{field}\" /&gt;<br />     {if:elseif \"{type}\" == \"Textarea\"}<br />      &lt;textarea name=\"{field}\" id=\"{field}\"&gt;&lt;/textarea&gt;<br />     {if:elseif \"{type}\" == \"Checkbox\"}<br />      &lt;input type=\"checkbox\" class=\"checkbox\" name=\"{field}\" id=\"{field}\" /&gt;<br />     {if:elseif \"{type}\" == \"Select\" || \"{type}\" == \"Multi-select\" &amp;&amp; \"{options}\"}<br />      &lt;select name=\"{field}{if \"{type}\" == \"Multi-select\"}[]{/if}\" id=\"{field}\"{if \"{type}\" == \"Multi-select\"} multiple=\"multiple\" size=\"4\"{/if}&gt;<br />       &lt;?php $items = explode(\"|\", \'{options}\'); ?&gt;<br />       &lt;?php foreach ($items as $item) { ?&gt;<br />        &lt;option value=\"&lt;?php echo $item; ?&gt;\"&gt;&lt;?php echo $item; ?&gt;&lt;/option&gt;<br />       &lt;?php } ?&gt;<br />      &lt;/select&gt;<br />     {if:elseif \"{type}\" == \"Radio Group\" &amp;&amp; \"{options}\"}<br />      &lt;ul class=\"group\"&gt;<br />       &lt;?php $items = explode(\"|\", \'{options}\'); $count = 1; ?&gt;<br />       &lt;?php foreach ($items as $item) { ?&gt;<br />        &lt;li&gt;&lt;input type=\"radio\" class=\"radio\" name=\"{field}\" id=\"{field}&lt;?php echo $count; ?&gt;\" value=\"&lt;?php echo $item; ?&gt;\" /&gt;<br />        &lt;label for=\"{field}&lt;?php echo $count; ?&gt;\"&gt;&lt;?php echo $item; ?&gt;&lt;/label&gt;&lt;/li&gt;<br />        &lt;?php $count++; ?&gt;<br />       &lt;?php } ?&gt;<br />      &lt;/ul&gt;<br />     {if:elseif \"{type}\" == \"Checkbox Group\" &amp;&amp; \"{options}\"}<br />      &lt;ul class=\"group\"&gt;<br />       &lt;?php $items = explode(\"|\", \'{options}\'); $count = 1; ?&gt;<br />       &lt;?php foreach ($items as $item) { ?&gt;<br />        &lt;li&gt;&lt;input type=\"checkbox\" class=\"checkbox\" name=\"{field}[]\" id=\"{field}&lt;?php echo $count; ?&gt;\" value=\"&lt;?php echo $item; ?&gt;\" /&gt;<br />        &lt;label for=\"{field}&lt;?php echo $count; ?&gt;\"&gt;&lt;?php echo $item; ?&gt;&lt;/label&gt;&lt;/li&gt;<br />        &lt;?php $count++; ?&gt;<br />       &lt;?php } ?&gt;<br />      &lt;/ul&gt;<br />     {/if}<br />    &lt;/li&gt;<br />   {/form_field}<br />   &lt;li class=\"buttons\"&gt;&lt;input type=\"submit\" name=\"submit\" value=\"submit\" /&gt;&lt;/li&gt;<br />  &lt;/ol&gt;<br /> {/exp:freeform:form}  <br />{/exp:weblog:entries} \n\n</code></div>\n\n<h2>Conclusion</h2>\n<p>This is not meant to be an all-inclusive form builder, as you can see there are <a href=\"http://www.solspace.com/docs/detail/freeform_form/#parameters\">many other parameters for the Freeform module</a>. But, this was meant to show a creative use of ExpressionEngine and EE add-ons to add functionality that is not directly built into the CMS.</p>\n\n<p>So go forth and create.</p>',NULL,1939,NULL,'2019-10-09 16:41:20','2019-10-09 16:41:20','2982fe88-e90a-4fb4-8688-f6ec2c6f1393',1,NULL,NULL,NULL,NULL),(1488,1973,'Smashing Magazine Killed The Community (Or Maybe It Was Me)',NULL,'<p>It is getting pretty tiresome <a href=\"http://www.drawar.com/articles/smashing-magazine-killed-the-community-or-maybe-it-was-me/\">reading blogs that just have lists</a> as blog posts. Every once in a while they may be ok, but try putting some thought into your posts.</p>',NULL,1940,NULL,'2019-10-09 16:41:20','2019-10-09 16:41:20','88d2855b-905a-4ab3-8a09-c34b7915ca09',1,NULL,NULL,NULL,NULL),(1489,1974,'Simplest jQuery Slideshow',NULL,'<p>I totally agree with <a href=\"http://snook.ca/archives/javascript/simplest-jquery-slideshow\">this thinking</a>. Everyone loves jQuery plugins, but they can sometimes be extremely bloated for things that can be coded relatively simply.</p>',NULL,1941,NULL,'2019-10-09 16:41:20','2019-10-09 16:41:20','2895a810-1866-4f60-bf3e-07290d10e05f',1,NULL,NULL,NULL,NULL),(1490,1975,'Don’t fear the fold — people do scroll',NULL,'<p>I’m definitely in the camp of people who don’t believe in the fold in web design, and <a href=\"http://www.456bereastreet.com/archive/200912/dont_fear_the_fold_people_do_scroll/\">this user testing</a> does provide evidence to support that was of thinking. Designs should still be structured so that more important information is higher on the page though.</p>',NULL,1942,NULL,'2019-10-09 16:41:21','2019-10-09 16:41:21','33c2863e-3d3d-4183-b284-b951fb717710',1,NULL,NULL,NULL,NULL),(1491,1976,'Do what works best for you, not them',NULL,'<p>Cameron Moll <a href=\"http://cameronmoll.com/archives/2010/01/do_what_works_best_for_you/\">reminds us</a> that if something works for you, but isn’t recommended by others, who cares. Do what works best for you.</p>',NULL,1945,NULL,'2019-10-09 16:41:21','2019-10-09 16:41:21','825658f6-eae8-4804-b526-f9860fc9d668',1,NULL,NULL,NULL,NULL),(1492,1977,'The importance of teaching your clients and being the boss',NULL,'<p><strong>Hallelujah</strong>: “We may check the site in a dozen browser and operating configurations but the visitors don’t, and never will, we can not forget that…”</p>',NULL,1946,NULL,'2019-10-09 16:41:21','2019-10-09 16:41:21','efd81aef-4598-4b3a-a6b2-78489d03e6b5',1,NULL,NULL,NULL,NULL),(1493,1978,'On Flash',NULL,'<p>Ever since the iPad was announced and we were informed that flash wasn’t supported, everyone and their mother has been writing articles about flash. I actually thoroughly enjoyed <a href=\"http://jeffcroft.com/blog/2010/feb/01/flash/\">Jeff Croft’s take</a>.</p>',NULL,1947,NULL,'2019-10-09 16:41:21','2019-10-09 16:41:21','f6b32298-ca5b-4083-833f-8a938845091b',1,NULL,NULL,NULL,NULL),(1494,1979,'A Better jQuery In-Field Label Plugin',NULL,'<p>I’ve just written another article for my company blog about using <a href=\"http://www.viget.com/inspire/a-better-jquery-in-field-label-plugin/\">jQuery in-field labels</a>.</p>','http://www.viget.com/inspire/a-better-jquery-in-field-label-plugin/',0,NULL,'2019-10-09 16:41:21','2019-10-09 16:41:21','f9acb1fa-db91-45b7-b7c9-7811d0eaf8bb',1,NULL,NULL,NULL,NULL),(1495,1980,'jQuery Presentation Plugin: Say NO to Keynote!',NULL,'<p>I’m done with Keynote and Powerpoint. I created a <a href=\"http://www.viget.com/inspire/jquery-presentation-plugin/\">jQuery Presentation Plugin</a> to use when giving presentations.</p>','http://www.viget.com/inspire/jquery-presentation-plugin/',0,NULL,'2019-10-09 16:41:21','2019-10-09 16:41:21','2def4e0e-a6ae-4c57-bc07-5bff86eaa070',1,NULL,NULL,NULL,NULL),(1496,1981,'YouTube Chromeless Video Player – jQuery Plugin',NULL,'<p>In my latest blog post on the Viget Inspire blog, I discussed a <a href=\"http://www.viget.com/inspire/youtube-chromeless-video-jquery-plugin/\">YouTube Chromeless Video jQuery Plugin</a> that I wrote while building the <a href=\"http://www.puma.com/running\">PUMA Running site</a>.</p>','http://www.viget.com/inspire/youtube-chromeless-video-jquery-plugin/',0,NULL,'2019-10-09 16:41:21','2019-10-09 16:41:21','fe68343e-7c48-4ed9-bc92-3c8e794ac77b',1,NULL,NULL,NULL,NULL),(1497,1982,'Transition',NULL,'<p>It’s been a long time since I’ve posted anything here, but I’m hoping to change that soon. I’ve been busy with <a href=\"http://www.viget.com/\">a new job</a>, <a href=\"http://www.cdiabu.com/\">teaching</a>, and I even found time to get married too.</p>\n<p>I’ve been working on building a newly designed site with ExpressionEngine, and I am finally getting to the last stages. The hardest part now is porting all of my posts and comments over. So while I am transitioning, I am going to be turning off comments for this site so that I can pull everything over and not worry about missing anything. If you need to, you can <a href=\"/contact/\">contact me through my site</a>.</p>',NULL,1951,NULL,'2019-10-09 16:41:21','2019-10-09 16:41:21','b81eda9d-0b05-4d0c-a0ec-0aeff16173d2',1,NULL,NULL,NULL,NULL),(1498,1983,'My Long Journey from WordPress to ExpressionEngine',NULL,'<p>About the time I started my new job at <a href=\"http://www.viget.com/\">Viget Labs</a> in December 2009, I decided that it was time to start working on a redesigned website. This redesign was a chance for me to play around with some of the new CSS3 properties, @font-face, &amp; jQuery.</p>\n\n<p>My first three designs have also been very white, so I wanted to try something a little different.</p>\n<img src=\"//assets.trevor-davis.com/uploads/images/content/v1.jpg\" alt=\"Version 1\" class=\"centered\" width=\"630\" height=\"320\" /><img src=\"//assets.trevor-davis.com/uploads/images/content/v2.jpg\" alt=\"Version 2\" class=\"centered\" width=\"630\" height=\"320\" /><img src=\"//assets.trevor-davis.com/uploads/images/content/v3.jpg\" alt=\"Version 3\" class=\"centered\" width=\"630\" height=\"320\" /><p>I wanted to go with a dark background, and I wanted to be able to change the feel of the site very easily. So by changing the background color in the stylesheet, I can completely change how the site feels. Check it out with <a href=\"#ad1010\" class=\"color-change\">red</a>, <a href=\"#10ad53\" class=\"color-change\">green</a>, or <a href=\"#7d1baa\" class=\"color-change\">purple</a>. All that is done by just simply changing the background color on the body.</p>\n\n<p>Another big step in this redesign is finally transitioning to ExpressionEngine. My first experience with content management systems began with WordPress, and I had a good run with it, but I felt like it was time to transition to a “real” CMS. Let me just say that going transferring posts form WordPress to ExpressionEngine was a huge pain in the butt.</p>\n\n<p>ExpressionEngine can import a Movable Type format, but WordPress cannot export into that format. There are various scripts on the web that can convert WordPress to Movable Type, but all of them are outdated. So I decided to approach it by installing Movable Type on my server, importing the WordPress file, and then exporting the Movable Type file. Unfortunately, that process doesn’t work that smoothly, and Movable Type kept failing to import the WordPress file. After much searching, I finally found an <a href=\"http://www.flashgamer.com/2010/04/converting_from_wordpress_to_e.html\">AIR application</a> that can convert from WordPress to Movable Type format.</p>\n\n<p>So after some cleanup of the posts, I was finally ready to launch. I haven’t looked at the site in IE yet, and I’m sure there will be some broken URLs, but I will get to that eventually.</p>\n\n<p>I’m also hoping to get back to posting articles more regularly here, so stay tuned.</p>\n\n<h2>Some Other Notes</h2>\n<ul><li>Headings are using Aller &amp; being displayed with @font-face.</li>\n<li>Thanks go out to my friend <a href=\"http://twitter.com/neagle\">Nate Eagle</a> for helping to write my about page.</li>\n<li>Thanks also go out to <a href=\"http://twitter.com/erikreagan\">Erik Reagan</a> for helping me with some last minute htaccess rules</li>\n</ul>',NULL,1952,NULL,'2019-10-09 16:41:21','2019-10-09 16:41:21','9108b45d-65d0-40d0-927e-a4f461bb7f81',1,NULL,NULL,NULL,NULL),(1499,1984,'jQuery Simple Validation Plugin',NULL,'<p>I find that I end up consistently adding form validation to sites, and for some reason, I never made a plugin out of it. I feel like every jQuery validation plugin that I look at is way too bloated for what I really need, so I finally whipped up a simple validation plugin that comes in at about 1.5kb.</p>\n<p>I tried to keep it really simple with this plugin: just check to see if a field that has been marked as required is not empty and check to see if an email address is valid.</p>\n<p>If you want to skip ahead, <a href=\"//assets.trevor-davis.com/play/jQuery-Simple-Validate/\">Check out the demo</a> and <a href=\"http://github.com/davist11/jQuery-Simple-Validate\">download the plugin from GitHub</a>.</p>\n\n<h2>Start with the Markup</h2>\n<p>To get started, I would always start with a simple form marked up in an ordered list:</p>\n\n<pre><code>&lt;form action=\"thanks.htm\" method=\"post\"&gt;\n	&lt;ol class=\"forms\"&gt;\n		&lt;li&gt;\n			&lt;label for=\"name\"&gt;&lt;em class=\"required\"&gt;*&lt;/em&gt; Name&lt;/label&gt;\n			&lt;input type=\"text\" name=\"name\" id=\"name\" /&gt;\n		&lt;/li&gt;\n		&lt;li&gt;\n			&lt;label for=\"email\"&gt;&lt;em class=\"required\"&gt;*&lt;/em&gt; Email&lt;/label&gt;\n			&lt;input type=\"text\" name=\"email\" id=\"email\" /&gt;\n		&lt;/li&gt;\n		&lt;li&gt;\n			&lt;label for=\"website\"&gt;Website&lt;/label&gt;\n			&lt;input type=\"text\" name=\"website\" id=\"website\" /&gt;\n		&lt;/li&gt;\n		&lt;li&gt;\n			&lt;label for=\"comment\"&gt;&lt;em class=\"required\"&gt;*&lt;/em&gt; Comment&lt;/label&gt;\n			&lt;textarea name=\"comment\" id=\"comment\"&gt;&lt;/textarea&gt;\n		&lt;/li&gt;\n		&lt;li class=\"buttons\"&gt;&lt;button type=\"submit\"&gt;Submit&lt;/button&gt;&lt;/li&gt;\n	&lt;/ol&gt;\n&lt;/form&gt;</code></pre>\n\n<p>Then, I need some way to denote which fields should be validated. The HTML5 required attribute, just isn’t supported well enough to use, so all that is needed is to add the class of <strong>required</strong> to each field that needs to be validated.</p>\n\n<pre><code>&lt;form action=\"thanks.htm\" method=\"post\"&gt;\n	&lt;ol class=\"forms\"&gt;\n		&lt;li&gt;\n			&lt;label for=\"name\"&gt;&lt;em class=\"required\"&gt;*&lt;/em&gt; Name&lt;/label&gt;\n			&lt;input type=\"text\" name=\"name\" id=\"name\" <strong>class=\"required\"</strong> /&gt;\n		&lt;/li&gt;\n		&lt;li&gt;\n			&lt;label for=\"email\"&gt;&lt;em class=\"required\"&gt;*&lt;/em&gt; Email&lt;/label&gt;\n			&lt;input type=\"text\" name=\"email\" id=\"email\" <strong>class=\"required\"</strong> /&gt;\n		&lt;/li&gt;\n		&lt;li&gt;\n			&lt;label for=\"website\"&gt;Website&lt;/label&gt;\n			&lt;input type=\"text\" name=\"website\" id=\"website\" /&gt;\n		&lt;/li&gt;\n		&lt;li&gt;\n			&lt;label for=\"comment\"&gt;&lt;em class=\"required\"&gt;*&lt;/em&gt; Comment&lt;/label&gt;\n			&lt;textarea name=\"comment\" id=\"comment\" <strong>class=\"required\"</strong>&gt;&lt;/textarea&gt;\n		&lt;/li&gt;\n		&lt;li class=\"buttons\"&gt;&lt;button type=\"submit\"&gt;Submit&lt;/button&gt;&lt;/li&gt;\n	&lt;/ol&gt;\n&lt;/form&gt;</code></pre>\n\n<p>Since I have an email field, I also need to add the class of <strong>email</strong> to the email field:</p>\n\n<pre><code>&lt;form action=\"thanks.htm\" method=\"post\"&gt;\n	&lt;ol class=\"forms\"&gt;\n		&lt;li&gt;\n			&lt;label for=\"name\"&gt;&lt;em class=\"required\"&gt;*&lt;/em&gt; Name&lt;/label&gt;\n			&lt;input type=\"text\" name=\"name\" id=\"name\" class=\"required\" /&gt;\n		&lt;/li&gt;\n		&lt;li&gt;\n			&lt;label for=\"email\"&gt;&lt;em class=\"required\"&gt;*&lt;/em&gt; Email&lt;/label&gt;\n			&lt;input type=\"text\" name=\"email\" id=\"email\" class=\"required <strong>email</strong>\" /&gt;\n		&lt;/li&gt;\n		&lt;li&gt;\n			&lt;label for=\"website\"&gt;Website&lt;/label&gt;\n			&lt;input type=\"text\" name=\"website\" id=\"website\" /&gt;\n		&lt;/li&gt;\n		&lt;li&gt;\n			&lt;label for=\"comment\"&gt;&lt;em class=\"required\"&gt;*&lt;/em&gt; Comment&lt;/label&gt;\n			&lt;textarea name=\"comment\" id=\"comment\" class=\"required\"&gt;&lt;/textarea&gt;\n		&lt;/li&gt;\n		&lt;li class=\"buttons\"&gt;&lt;button type=\"submit\"&gt;Submit&lt;/button&gt;&lt;/li&gt;\n	&lt;/ol&gt;\n&lt;/form&gt;</code></pre>\n\n<p>I also want to tell my plugin which forms to validate, so I’ll also add a class to the form itself:</p>\n\n<pre><code>&lt;form action=\"thanks.htm\" method=\"post\" <strong>class=\"required-form\"</strong>&gt;\n	&lt;ol class=\"forms\"&gt;\n		&lt;li&gt;\n			&lt;label for=\"name\"&gt;&lt;em class=\"required\"&gt;*&lt;/em&gt; Name&lt;/label&gt;\n			&lt;input type=\"text\" name=\"name\" id=\"name\" class=\"required\" /&gt;\n		&lt;/li&gt;\n		&lt;li&gt;\n			&lt;label for=\"email\"&gt;&lt;em class=\"required\"&gt;*&lt;/em&gt; Email&lt;/label&gt;\n			&lt;input type=\"text\" name=\"email\" id=\"email\" class=\"required email\" /&gt;\n		&lt;/li&gt;\n		&lt;li&gt;\n			&lt;label for=\"website\"&gt;Website&lt;/label&gt;\n			&lt;input type=\"text\" name=\"website\" id=\"website\" /&gt;\n		&lt;/li&gt;\n		&lt;li&gt;\n			&lt;label for=\"comment\"&gt;&lt;em class=\"required\"&gt;*&lt;/em&gt; Comment&lt;/label&gt;\n			&lt;textarea name=\"comment\" id=\"comment\" class=\"required\"&gt;&lt;/textarea&gt;\n		&lt;/li&gt;\n		&lt;li class=\"buttons\"&gt;&lt;button type=\"submit\"&gt;Submit&lt;/button&gt;&lt;/li&gt;\n	&lt;/ol&gt;\n&lt;/form&gt;</code></pre>\n\n<h2>It’s JavaScript Time</h2>\n<p>Get started by including <a href=\"http://jquery.com/\">jQuery</a> and <a href=\"http://github.com/davist11/jQuery-Simple-Validate\">my Simple Validate plugin</a>. Then, include them on the page:</p>\n\n<pre><code>&lt;script type=\"text/javascript\" src=\"scripts/jquery.js\"&gt;&lt;/script&gt;\n&lt;script type=\"text/javascript\" src=\"scripts/jquery.simpleValidate.min.js\"&gt;&lt;/script&gt;</code></pre>\n\n<p>Now, I just need to call my plugin on any form that has required fields:</p>\n<pre><code>$(document).ready(function() {\n	$(\'form.required-form\').simpleValidate();\n});</code></pre>\n\n<p>Just like that, the form validation will work, but I want to customize a few of the options. First, I want to change the error element to use an &lt;em&gt; tag instead of a &lt;strong&gt; tag:</p>\n\n<pre><code>$(document).ready(function() {\n	$(\'form.required-form\').simpleValidate(<strong>{\n		errorElement: \'em\'\n	}</strong>);\n});</code></pre>\n\n<p>Then, maybe I decide that I want to submit the form via AJAX. There is no need to add that kind of functionality into the plugin, AJAX is so easy with jQuery. So I just need to tell the plugin that I’m going to submit the form with AJAX, and then pass in my callback function which will fire once the form is submitted with no errors:</p>\n\n<pre><code>$(document).ready(function() {\n	$(\'form.required-form\').simpleValidate({\n		errorElement: \'em\',\n		<strong>ajaxRequest: true,\n		completeCallback: function($el) {\n			var formData = $el.serialize();\n			//Do AJAX request with formData variable\n		}</strong>\n	});\n});</code></pre>\n\n<h3>Options</h3>\n<p>Here are all of the available options for the plugin:</p>\n<ul><li><h4>errorClass: \'error\'</h4> Class for the error message text</li>\n	<li><h4>errorText: \'{label} is a required field.\'</h4> Structure for the error message text, {label} will be replaced with the associated label text</li>\n	<li><h4>emailErrorText: \'Please enter a valid {label}\'</h4> Structure for the email error message text, {label} will be replaced with the associated label text</li>\n	<li><h4>errorElement: \'strong\'</h4> Element to use for the error message text</li>\n	<li><h4>removeLabelChar: \'*\'</h4> If there is an extra character in the label to denote a required field, strip it out</li>\n	<li><h4>inputErrorClass: \'\'</h4> Class to add to an input when it is marked as having an error</li>\n	<li><h4>completeCallback: \'\'</h4> Function to call once the form is error-free</li>\n	<li><h4>ajaxRequest: false</h4> If you don\'t want to use the default form action and want to submit it via AJAX \n</li></ul><p><a href=\"//assets.trevor-davis.com/play/jQuery-Simple-Validate/\">Check out the demo</a> and <a href=\"http://github.com/davist11/jQuery-Simple-Validate\">download the plugin from GitHub</a>. Let me know if you run into any bugs or have any feature requests.</p>',NULL,1954,NULL,'2019-10-09 16:41:21','2019-10-09 16:41:21','9301a5ae-41cb-4c36-bd54-6019943c18e1',1,NULL,NULL,NULL,NULL),(1500,1985,'jQuery Show Password Plugin',NULL,'<p>In a recent project at work, I had to add in functionality so that a user could see what they had typed in a password field when they click a link. One would think that it is as easy as using JavaScript to change the type attribute, but that of course doesn’t work in IE. Virtually all of the jQuery plugins that I found used a checkbox instead of a link to toggle between the two states. So, I set out to write my own.</p>\n\n<p>If you just want to get to the code, you can <a href=\"http://github.com/davist11/jQuery-Show-Password\">download the plugin from GitHub</a> or <a href=\"//assets.trevor-davis.com/play/jquery-show-password/\">check out the demo</a>.</p>\n\n<p>This plugin works by adding a text field that takes the value of what is typed into the password field. Then, when the link is clicked the password field is hidden and the text field is shown.</p>\n\n<h2>The Markup</h2>\n<p>In the demo, we’ll just start with a simple form:</p>\n\n<pre><code>&lt;form action=\"#\"&gt;\n	&lt;ol class=\"forms\"&gt;\n		&lt;li&gt;\n			&lt;label for=\"username\"&gt;Username&lt;/label&gt;\n			&lt;input type=\"text\" id=\"username\" /&gt;\n		&lt;/li&gt;\n		&lt;li&gt;\n			&lt;label for=\"password\"&gt;Password&lt;/label&gt;\n			&lt;input type=\"password\" id=\"password\" class=\"password\" /&gt;\n		&lt;/li&gt;\n		&lt;li class=\"buttons\"&gt;\n			&lt;button type=\"submit\"&gt;Submit&lt;/button&gt;\n		&lt;/li&gt;\n	&lt;/ol&gt;\n&lt;/form&gt;</code></pre>\n\n<h2>Add a Little Style</h2>\n<p>In the design that I was working on, the link to show the password actually sat on top of the password input field, so we just need to add a little bit of CSS to make that happen:</p>\n\n<pre><code>.forms li {\n	position: relative;\n}\n.show-password-link {\n	display: block;\n	position: absolute;\n	z-index: 11;\n}\n.password-showing {\n	position: absolute;\n	z-index: 10;\n}</code></pre>\n\n<p>By default, the link to show the password has the class of <em>show-password-link</em>, but that can be changed in the plugin options. Also, the <em>password-showing</em> class is added to the text field that is used to show the password, but again, that can be changed via the plugin options.</p>\n\n<h2>And Now, JavaScript Takes Over</h2>\n<p>To get started, you will need to include <a href=\"http://jquery.com/\">jQuery</a> and <a href=\"http://github.com/davist11/jQuery-Show-Password\">my plugin</a>:\n\n</p><pre><code>&lt;script type=\"text/javascript\" src=\"scripts/jquery.js\"&gt;&lt;/script&gt;\n&lt;script type=\"text/javascript\" src=\"scripts/jquery.showPassword.min.js\"&gt;&lt;/script&gt;</code></pre>\n\n<p>Then, you can instantiate it like this:</p>\n\n<pre><code>$(document).ready(function() {\n	$(\':password\').showPassword();\n});</code></pre>\n\n<h3>Options</h3>\n\n<ul><li>\n    <h4>linkClass: \'show-password-link\'</h4>\n    Class for the toggle link\n  </li>\n  <li>\n    <h4>linkText: \'Show\'</h4>\n    Text for the toggle link\n  </li>\n  <li>\n    <h4>showPasswordLinkText: \'Hide\'</h4>\n    Text for the toggle link when password is not masked\n  </li>\n  <li>\n    <h4>showPasswordInputClass: \'password-showing\'</h4>\n    Class for the text input that will show the password\n  </li>\n  <li>\n    <h4>linkRightOffset: 0</h4>\n    Offset for the link from the right of parent\n  </li>\n  <li>\n    <h4>linkTopOffset: 0</h4>\n    Offset for the link from the top of parent\n  </li>\n</ul><p>So there you have it. <a href=\"//assets.trevor-davis.com/play/jquery-show-password/\">Check out the demo</a> and <a href=\"http://github.com/davist11/jQuery-Show-Password\">download the plugin from GitHub</a>.</p>',NULL,1957,NULL,'2019-10-09 16:41:21','2019-10-09 16:41:21','4bf7d6c1-803f-4672-ade6-2c7c3256ea78',1,NULL,NULL,NULL,NULL),(1501,1986,'jQuery Image Scroller Plugin',NULL,'<p>While working on the individual product page for PUMA, I had to use jQuery to create a scrollable interface for really tall products. It’s kind of hard to describe, but <a href=\"http://www.viget.com/inspire/jquery-image-scroller-plugin/\">have a look at the plugin for a better description</a>.</p>','http://www.viget.com/inspire/jquery-image-scroller-plugin/',0,NULL,'2019-10-09 16:41:21','2019-10-09 16:41:21','97e880d2-96cd-4998-845d-da9c2ca18468',1,NULL,NULL,NULL,NULL),(1502,1987,'A Couple of EE 2.x Addons',NULL,'<p>It’s no secret that I’m a big <a href=\"http://expressionengine.com/\">ExpressionEngine</a> fan. I’m really excited to get started using EE 2.x on projects, but the one thing holding me back is add-ons. I’ve never written an add-on, but I use tons of add-ons that others have written.  With that being said, I ended up porting over a couple of add-ons to work with EE 2.x:</p>\n\n<ul><li>\n    <h2>Scroll to Comment</h2>\n    First, I modified Matthew Pennell’s <a href=\"http://devot-ee.com/add-ons/scroll-to-comment/\">Scroll to Comment Extension</a>. When a user submits a comment, they are scrolled down to the newly added comment. You can find the <a href=\"http://github.com/davist11/EE-Scroll-To-Comment\">EE 2.x compatible version on GitHub</a>.\n  </li>\n  <li>\n    <h2>EE Default CP Tabs</h2>\n    We loved using <a href=\"http://devot-ee.com/add-ons/lg-add-cp-tabs/\">LG Add CP Tabs</a> in order to add a tab for <a href=\"http://buildwithstructure.com/\">Structure</a> for all users. As we were getting our EE 2.x template site setup, we noticed that this extension wasn’t converted yet. I made a slight modification so that you only get one textbox to add tabs instead of multiple boxes broken out by member group. You can find <a href=\"http://github.com/davist11/EE-Default-CP-Tabs\">my EE 2.x compatible version on GitHub</a>.\n  </li>\n</ul><p>My hope is to eventually get this site converted over to EE 2.x, and I think the only add-on holding me back is the <a href=\"http://devot-ee.com/add-ons/eeflickr/\">eeFlickr Module</a>.</p>',NULL,1956,NULL,'2019-10-09 16:41:21','2019-10-09 16:41:21','6293a5a1-44a1-415a-9813-0bf5d9c6ad11',1,NULL,NULL,NULL,NULL),(1503,1988,'Find Your Own Starting Point',NULL,'<p><a href=\"http://html5boilerplate.com/\">Everyone</a> and <a href=\"http://html5reset.org/\">their mother</a> has been releasing their HTML5 “boilerplates” for others to use. There is no chance that I would just take such a set of files and start building a site. You’ve got to find a good starting place for yourself, not someone else’s.</p>\n\n<p>I have been starting from a similar point for everything that I build now, and I just finally put it out on <a href=\"http://github.com/davist11/Starter-Template\">GitHub</a>. I’m not doing this because I want someone to use this template to start a site; I’m doing this so that I can have somewhere to always access this set of files.</p>\n\n<p>With that being said, I would urge everyone to have their own starting point. You know your own coding patterns best, so just figure out the best place for yourself to start from. Sure, you can learn from everyone else’s, but it is much more beneficial to have your own. Mine is super basic, so feel free to start from mine and modify it to suit your needs.</p>\n\n<p><a href=\"http://github.com/davist11/Starter-Template\">See my starting point on GitHub</a> and feel free to fork away and modify.</p>\n\n\n',NULL,1960,NULL,'2019-10-09 16:41:21','2019-10-09 16:41:21','930a549d-1c72-4cc9-8527-d610eb196adf',1,NULL,NULL,NULL,NULL),(1504,1989,'How I Got the Most Out of An Event Apart',NULL,'<p>I had the pleasure of attending <a href=\"http://aneventapart.com/2010/dc/\">An Event Apart</a> last week when they finally made it to DC. This was the third time I had atended An Event Apart conference, but I feel like I absorbed the most from this one.</p>\n\n<h2>Leave the Laptop at Home</h2>\n<p>The last two times I attended, I brought my laptop and took notes during the presentations. Sure I learned some things, but I think other things slipped by me as I was typing. This time, I brought a pencil &amp; notebook, and an iPad that was so graciously given to me as a <a href=\"http://www.viget.com/\">Viget</a> 10th anniversary gift.</p>\n<p>Now, I realize that not everyone has the luxury of choosing between a laptop and an iPad, but I really only used the iPad for checking email and Twitter during breaks, so I definitely could have gone without that. I really enjoyed just sitting, absorbing, and sporadically jotting down notes when I thought it was necessary. You’ve got the slides available to download, so don’t feel like you have to write down everything that is being presented to you.</p>\n\n<h2>Focus on the Speakers</h2>\n<p>I know <a href=\"http://afeedapart.com/\">A Feed Apart</a> is really cool, but do you really want to spend your time on Twitter while speakers are presenting? Try checking A Feed Apart during the breaks to catch up on what everyone thought about the speaker. Leave your phone alone and stop checking your email. You paid good money for the conference, so pay attention.</p>\n\n<h2>Stay Sober</h2>\n<p>I didn’t even make it to the opening night party this year because Thursdays are my basketball night, but I heard about numerous people who got drunk at the party. Really people? Aren’t we all adults now? Didn’t we pay good money for this conference? If you want to go re-live your college days, don’t waste $1000 to do it. So go to the party and mingle, but please don’t get sloppy drunk; we really don’t want to hear about it the next day of the conference.</p>\n\n<h2>Just Enjoy Yourself</h2>\n<p>You are surrounded by people just like you for two days; it’s fantastic. We even had lunch the first day with <a href=\"http://twitter.com/jasonsantamaria\">Jason Santa Maria</a> and <a href=\"http://twitter.com/adactio\">Jeremy Keith</a>, how badass is that?</p>\n\n<p>Much thanks goes to <a href=\"http://twitter.com/zeldman\">Zeldman</a> &amp; <a href=\"http://twitter.com/meyerweb\">Eric Meyer</a> for organizing such a fantastic conference, and I look forward to going back again <a href=\"http://aneventapart.com/news/2010/09/02/announcing-our-2011-schedule/\">next year</a>.</p>',NULL,1961,NULL,'2019-10-09 16:41:21','2019-10-09 16:41:21','639745f8-3b6c-453c-9fde-eb48815f1d09',1,NULL,NULL,NULL,NULL),(1505,1990,'jQuery One Page Navigation Plugin',NULL,'<p>When appropriate, I am a fan of the one-page sites. I really like the ones that add smooth scrolling and highlight the navigation depending upon which part of the page you have scrolled to. Here are a few examples: <a href=\"http://www.brizk.com/\">Brizk Design</a> and <a href=\"http://crushlovely.com/\">Crush + Lovely</a>. I finally have a freelance project where a one-page site makes sense, so I needed to write the JavaScript to make the navigation work how I wanted.</p>\n\n<p>I wanted the page to scroll smoothly when the navigation was clicked, so I used the <a href=\"http://flesler.blogspot.com/2007/10/jqueryscrollto.html\">jQuery ScrollTo plugin</a>. I also wanted the page to automatically highlight the correct navigation section depending upon which section was scrolled to, and that was where I added my custom code.</p>\n\n<p>If you want to skip ahead, you can <a href=\"//assets.trevor-davis.com/play/jquery-one-page-nav/\">check out the demo</a> and <a href=\"http://github.com/davist11/jQuery-One-Page-Nav\">download the plugin from GitHub</a>.</p>\n\n<h2>The Markup</h2>\n<p>I started with an unordered list for the navigation and a bunch of sections:</p>\n<pre><code>&lt;ul id=\"nav\"&gt;\n  &lt;li class=\"current\"&gt;&lt;a href=\"#section-1\"&gt;Section 1&lt;/a&gt;&lt;/li&gt;\n  &lt;li&gt;&lt;a href=\"#section-2\"&gt;Section 2&lt;/a&gt;&lt;/li&gt;\n  &lt;li\"&gt;&lt;a href=\"#section-3\"&gt;Section 3&lt;/a&gt;&lt;/li&gt;\n&lt;/ul&gt;\n\n&lt;div id=\"section-1\"&gt;\n  &lt;strong&gt;Section 1&lt;/strong&gt;\n  &lt;p&gt;Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor\n  incididunt ut labore et dolore magna aliqua.&lt;/p&gt;\n&lt;/div&gt;\n&lt;div id=\"section-2\"&gt;\n  &lt;strong&gt;Section 2&lt;/strong&gt;\n  &lt;p&gt;Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor \n  incididunt ut labore et dolore magna aliqua.&lt;/p&gt;\n&lt;/div&gt;\n&lt;div id=\"section-3\"&gt;\n  &lt;strong&gt;Section 3&lt;/strong&gt;\n  &lt;p&gt;Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor \n  incididunt ut labore et dolore magna aliqua.&lt;/p&gt;\n&lt;/div&gt;</code></pre>\n\n<h2>The JavaScript</h2>\n<p>Then, I added jQuery, the ScrollTo plugin, and my plugin to the page:</p>\n<pre><code>&lt;script src=\"jquery.js\"&gt;&lt;/script&gt;\n&lt;script src=\"jquery.scrollTo.js\"&gt;&lt;/script&gt;\n&lt;script src=\"jquery.nav.min.js\"&gt;&lt;/script&gt;</code></pre>\n\n<p>Finally, I just need to call my plugin on the navigation:</p>\n<pre><code>$(document).ready(function() {\n  $(\'#nav\').onePageNav();\n});</code></pre>\n\n<h3>Options</h3>\n<p>There are a few options for this plugin:</p>\n<ul><li>\n<h4>currentClass: \'current\'</h4>\nClass to add to the list item when the navigation item is selected\n</li>\n<li>\n<h4>changeHash: false</h4>\nIf you want the hash to change when the user clicks on the navigation, change this to <strong>true</strong>\n</li>\n<li>\n<h4>scrollSpeed: 750</h4>\nSpeed to scroll the page when the navigation is clicked\n</li>\n</ul><p>And that’s it. <a href=\"//assets.trevor-davis.com/play/jquery-one-page-nav/\">Check out the demo</a> and <a href=\"http://github.com/davist11/jQuery-One-Page-Nav\">download the plugin from GitHub</a>.</p>',NULL,1962,NULL,'2019-10-09 16:41:21','2019-10-09 16:41:21','e11217c2-602e-44e0-ab5f-c3fc3e46d988',1,NULL,NULL,NULL,NULL),(1506,1991,'Simple jQuery Refactoring',NULL,'<p>I’ve learned so much about jQuery while working at Viget. I wrote a <a href=\"http://www.viget.com/inspire/simple-jquery-refactoring/\">blog post</a> about how you can improve your jQuery through some simple refactoring.</p>','http://www.viget.com/inspire/simple-jquery-refactoring/',0,NULL,'2019-10-09 16:41:21','2019-10-09 16:41:21','cd7d51f5-822e-4514-b9ac-05fb0417eaa5',1,NULL,NULL,NULL,NULL),(1507,1992,'Custom File Inputs with a Bit of jQuery',NULL,'<p>I needed to create a custom file input when building <a href=\"http://www.puma.com/cleverlittlebag\">Clever Little Bag</a>, so I’ve <a href=\"http://www.viget.com/inspire/custom-file-inputs-with-a-bit-of-jquery/\">written a tutorial on the Inspire blog</a> discussing that process.</p>',NULL,1968,NULL,'2019-10-09 16:41:22','2019-10-09 16:41:22','c63b19ad-d141-4195-b735-d22a6d622d78',1,NULL,NULL,NULL,NULL),(1508,1993,'Hon-ee Pot Captcha for ExpressionEngine',NULL,'<p>I have a confession to make: <em>I hate captcha</em>. But on the other hand, spam is one of the most frustrating issues ever. So with that being said, I am a big fan of <a href=\"http://haacked.com/archive/2007/09/11/honeypot-captcha.aspx\">Honeypot Captcha</a>.</p>\n\n<p>I couldn’t find any ExpressionEngine addons that added honeypot captcha functionality for both the comment form and the <a href=\"http://www.solspace.com/software/detail/freeform/\">Freeform</a> module, so I decided to go ahead and create one.</p>\n\n<h2>Basic Functionality</h2>\n<p>This extension validates the EE comment form and Freeform forms to make sure a field that is hidden with CSS is left empty.</p>\n\n<h2>Getting Started</h2>\n<ul><li><a href=\"https://github.com/davist11/Hon-ee-Pot-Captcha\">Download Hon-ee Pot Captcha</a></li>\n  <li>Unzip the folder and copy the <em>honeepot</em> folder into your /system/expressionengine/third_party/ directory.</li>\n  <li>Go to Add-ons → Extensions and “Enable extension”.</li>\n  <li>You can customize the field name for the honey pot field and the message a user receives if the field is filled in by going to the extension settings.</li>\n</ul><h3>Setup</h3>\n<p>In the Freeform module, go to Fields → Create a New Field. Now create a field with the field name matching the field name in the Hon-ee Pot Captcha settings. The default is <em>honeepot</em>.</p>\n\n<p>Now in your form, add the honey pot field:</p>\n\n<pre>&lt;li class=\"screen-reader\"&gt;\n  &lt;label for=\"honeepot\"&gt;Don\'t put anything here&lt;/label&gt;\n  &lt;input type=\"text\" name=\"honeepot\" id=\"honeepot\" /&gt;\n&lt;/li&gt;</pre>\n\n<p>In my CSS, I have a class to move things off of the page:</p>\n<pre>.screen-reader {\n  display: block !important;\n  left: -9999px !important;\n  position: absolute !important;\n  top: -9999px !important;\n}</pre>\n\n<p>You can add the same form field to your comment forms as well.</p>\n\n<h2>That is all</h2>\n<p>Hopefully this addition will help to combat some of the spam contact form submissions and comments (even though they get caught by <a href=\"http://loweblog.com/software/low-nospam/\">Low NoSpam</a>). You can <a href=\"https://github.com/davist11/Hon-ee-Pot-Captcha\">download the Hon-ee Pot Captcha extension on Github</a>. Let me know if you run into any issues.</p>',NULL,1971,NULL,'2019-10-09 16:41:22','2019-10-09 16:41:22','4045ea2d-ba52-4375-84c4-20a83a5c7118',1,NULL,NULL,NULL,NULL),(1509,1994,'URL Design',NULL,'<p>Great article about <a href=\"http://warpspire.com/posts/url-design/\">designing URLs</a>. It really is an art and is so easy to do so wrong.</p>',NULL,1972,NULL,'2019-10-09 16:41:22','2019-10-09 16:41:22','b7c6fe3f-bba6-45a3-9dd9-9ce7c8e8c50f',1,NULL,NULL,NULL,NULL),(1510,1995,'ExpressionEngine Config Variables Plugin',NULL,'<p>As I was in the process of moving this site into Git and having a local version, I have been trying to move as many paths as possible into the config.php. One of them included the cache path for <a href=\"http://devot-ee.com/add-ons/image-sizer/\">image sizer</a>. Since the local and production paths are different, I wanted some way for them to be dynamic. In my config.php file, I am using <em>$_SERVER[\'DOCUMENT_ROOT\']</em> to set the base_path. I could have enabled PHP in the template and then use the <em>$_SERVER[\'DOCUMENT_ROOT\']</em>, but that seemed like a silly reason to enable PHP.</p>\n\n<p>So I made a plugin that gives you access to everything in the $config array without having to use PHP.</p>\n\n<h2>Usage</h2>\n\n<pre><code>{exp:config:vars value=\"base_path\"}</code></pre>\n\n<p>To see all possible values, just pass in “all”:</p>\n\n<pre><code>{exp:config:vars value=\"all\"}</code></pre>\n\n<h2>Download</h2>\n\n<p>You can download from <a href=\"https://github.com/davist11/Config-Variables-Plugin\">GitHub</a> or <a href=\"http://devot-ee.com/add-ons/config-variables/\">Devot-ee</a>. As always, let me know if you run into any issues.</p>',NULL,1986,NULL,'2019-10-09 16:41:22','2019-10-09 16:41:22','5a368d82-fe49-46ee-92e8-52d444e33712',1,NULL,NULL,NULL,NULL),(1511,1996,'So You Want to Use .htaccess files with MAMP?',NULL,'<p>Well, this was easy in the older version of MAMP that I had. You would just drop them in place, and they worked. I was having a problem with something, so I thought maybe there was an updated version of MAMP that would solve the problem. Sure enough, there was. So I installed it and went along my way. Then, I went back to the local version of my site, and it was completely busted.</p>\n\n<p>I finally tracked it down to .htaccess files being ignored. So I opened up my <em>http.conf</em> file and went down to line 378, and sure enough this is what I saw:</p>\n\n<pre><code>&lt;Directory /&gt;\n    Options Indexes FollowSymLinks\n    AllowOverride None\n&lt;/Directory&gt;</code></pre>\n\n<p>In the older version of MAMP that I had, the default for this value was <em>All</em>. In order to get .htaccess files working in the new version, I just had to change <em>None</em> to <em>All</em>, restart the server, and everything worked normally. Just thought I would share in case anyone else runs into this problem.</p>',NULL,1989,NULL,'2019-10-09 16:41:22','2019-10-09 16:41:22','a5451282-bf13-45b1-9461-d1fca03fd26d',1,NULL,NULL,NULL,NULL),(1512,1997,'My New Best Friend: CSS Generated Content',NULL,'<p>I’ve started to use generated content more and more these days. <a href=\"http://www.viget.com/inspire/css-generated-content/\">Here are a couple of examples</a> from a recent project.</p>','http://www.viget.com/inspire/css-generated-content/',0,NULL,'2019-10-09 16:41:22','2019-10-09 16:41:22','346cf1f6-592c-4bd6-bcbe-a708a2272918',1,NULL,NULL,NULL,NULL),(1513,1998,'A Couple of Presentations',NULL,'<p>I’ve given a couple of presentations recently, so I thought I would share them.</p>\n\n<h2><a href=\"http://www.slideshare.net/davist11/mee-ee-sitting-in-a-tree\">Mee &amp; EE: Sitting In A Tree</a></h2>\n<p>An internal presentation given to all of <a href=\"http://www.viget.com\">Viget</a> to give an overview of EE and why I love it.</p>\n\n\n\n<h2><a href=\"http://www.slideshare.net/davist11/add-some-awesomesauce\">Add Some Awesome-Sauce</a></h2>\n<p>A presentation given to Clarksburg High School students with a supporting <a href=\"http://hp.trevor-davis.com\">demo site</a> to introduce them to some HTML5 and CSS3 features.</p>\n\n',NULL,1992,NULL,'2019-10-09 16:41:22','2019-10-09 16:41:22','3d5fbba5-e5f4-41b6-988b-836c14fbf372',1,NULL,NULL,NULL,NULL),(1514,1999,'Styling HTML5 Elements: An Irresponsible Choice…Right Now',NULL,'<p>I figured it was time to post about a controversial topic that had come up recently. <a href=\"http://www.viget.com/inspire/html5-elements-irresponsible-choice-right-now/\">I just don’t see the value in using most HTML5 elements right now</a>.</p>','http://www.viget.com/inspire/html5-elements-irresponsible-choice-right-now/',0,NULL,'2019-10-09 16:41:22','2019-10-09 16:41:22','cd720f1f-2902-4ec0-bfd2-0019a7c45e2b',1,NULL,NULL,NULL,NULL),(1515,2000,'Is Ajax ExpressionEngine Plugin',NULL,'<p>For a recent project, I needed to detect whether a request was an AJAX request or not. <a href=\"http://devot-ee.com/add-ons/mx-ajax-detect\">MX Ajax Detect</a> already existed, but I didn’t like that you needed the extra set of tags.</p>\n\n<h2>Usage</h2>\n<pre><code>{if {exp:is_ajax} == \"true\"}\n	OH YEAAAH\n{if:else}\n	OH NOOO\n{/if}</code></pre>\n\n<h2>Download</h2>\n<p>You can find the plugin on <a href=\"http://devot-ee.com/add-ons/is-ajax\">Devot:ee</a> and <a href=\"https://github.com/davist11/is-ajax\">GitHub</a>.</p>',NULL,1999,NULL,'2019-10-09 16:41:22','2019-10-09 16:41:22','4e817f8e-507b-44a8-90b6-16cb63baf0d7',1,NULL,NULL,NULL,NULL),(1516,2001,'Notes From Our Default ExpressionEngine Build',NULL,'<p>I put together some <a href=\"http://www.viget.com/inspire/our-default-expressionengine-build/\">notes about Viget’s default ExpressionEngine build</a> in the hopes that you can find some tips and tricks in all of my nonsense.</p>','http://www.viget.com/inspire/our-default-expressionengine-build/',0,NULL,'2019-10-09 16:41:22','2019-10-09 16:41:22','d32d2fa7-01e5-4217-bfc5-ccef42a7644e',1,NULL,NULL,NULL,NULL),(1517,2002,'Background-clip, Text-shadow, & Gradients; Oh My!',NULL,'<p>I have been able to play around with <a href=\"http://www.viget.com/inspire/background-clip-text-shadow-gradients/\">background-clip, text-shadow, and gradients</a> on a few recent projects, and I wrote up some tricks that I have come across.</p>','http://www.viget.com/inspire/background-clip-text-shadow-gradients/',0,NULL,'2019-10-09 16:41:22','2019-10-09 16:41:22','0237ae19-d274-445c-9e14-83793bf2a072',1,NULL,NULL,NULL,NULL),(1518,2003,'A Long Time Coming',NULL,'<p>It’s funny how quickly you come to hate your own site. <a href=\"//trevor-davis.com/blog/from-wordpress-to-expressionengine\">Almost exactly 2 years ago</a>, I launched a redesigned version of my site. <strong>After maybe a year, I hated it.</strong> But who has time to redo their own site? Apparently it took me 6 months to find the time to finish mine.</p>\n\n<p>Even within those 6 months, I found things that I had started on the site that I hated. My goals were to simplify things a bit, make it responsive, and play around with Sass and Compass. I also wanted to take some of the focus off of my blog, since I really don’t write too much on it anymore (I write almost all of my articles on the <a href=\"http://viget.com\">Viget Blogs</a> these days).</p>\n\n<p>Since I’m giving 2 presentations in the next few weeks (<a href=\"http://refreshdc-july2012.eventbrite.com/\">Refresh DC</a> &amp; <a href=\"http://dceers.org/\">DCEERS</a>), I wanted to get my new site up. So I may have rushed a few things, but I’m pretty happy with it. Let me know if you run into any errors.</p>',NULL,2016,NULL,'2019-10-09 16:41:22','2019-10-09 16:41:22','29a16f79-69b6-417a-8702-f762471ed155',1,NULL,NULL,NULL,NULL),(1519,2004,'Sass & Compass:  Never Write  Regular CSS Again',NULL,'<p>I gave a presentation last week at <a href=\"http://refresh-dc.org/\">Refresh DC</a> about <a href=\"http://sass-lang.com/\">Sass</a> &amp; <a href=\"http://compass-style.org/\">Compass</a>. After being introduced to Sass &amp; Compass about six months ago, I can’t imagine writing regular CSS ever again. I was a little hesitant at first, but now I can’t live without it. I posted my <a href=\"https://speakerdeck.com/u/trevor_davis/p/sass-and-compass-never-write-regular-css-again\">slides online</a>, and <a href=\"https://github.com/davist11/refresh-dc-compass-sass-presentation\">here is the git repo</a> with all of the code samples.</p>',NULL,2017,NULL,'2019-10-09 16:41:22','2019-10-09 16:41:22','2fe59e29-d83d-4dea-81de-e840f5e4ed4c',1,NULL,NULL,NULL,NULL),(1520,2005,'“Advanced”  Templating with ExpressionEngine',NULL,'<p>I was luckily enough to be asked to speak at the <a href=\"http://dceers.org/\">DCEERs Day conference</a> yesterday. I was asked to speak about best templating practices, which ended up being a talk about how I use <a href=\"http://devot-ee.com/add-ons/stash\">Stash</a> and how I build custom plugins to streamline templating. It was a great day filled with discussion about ExpressionEngine, and it made me look forward to EECI even more!</p>\n\n',NULL,2018,NULL,'2019-10-09 16:41:22','2019-10-09 16:41:22','9338ee71-87d0-4423-9ace-5215e46815d9',1,NULL,NULL,NULL,NULL),(1521,2006,'jQuery Stick ‘em: Make Content Sticky on Scroll, to a Point',NULL,'<p>I created a plugin, <a href=\"http://viget.com/inspire/jquery-stick-em\">jQuery Stick ‘em</a>, to allow items to be “sticky” but only within a container.</p>','http://viget.com/inspire/jquery-stick-em',0,NULL,'2019-10-09 16:41:23','2019-10-09 16:41:23','693972a3-c260-4704-8192-20bea21d82bd',1,NULL,NULL,NULL,NULL),(1522,2007,'Dumbwaiter Chrome Extension',NULL,'<p>I recently got around to trying out <a href=\"http://statamic.com/\">Statamic</a> to create a little <a href=\"http://recipes.trevor-davis.com/\">recipe manager</a>. Yes, I know there are tons of apps out there that do this type of stuff, but I wanted to really be able to control everything.</p>\n\n<p>I also wanted to figure out some way that my wife could bookmark recipes for us, and I didn’t expect her to login to my Statamic install and go through that whole process of adding a new entry. I wanted her to be able to click a button when she was on a site displaying a recipe that she wanted to bookmark, and an entry would then be created. That led me to create my first Chrome Extension, <a href=\"https://chrome.google.com/webstore/detail/jeeeliidcblacogbcefhcbljkllhpjdd?hl=en&amp;gl=US\">Dumbwaiter</a>.</p>\n\n<p><img src=\"//assets.trevor-davis.com/uploads/images/content/dumbwaiter-options.png\" alt=\"Dumbwaiter Options\" /></p>\n\n<p>The basic idea is that you provide a URL that will be opened in a popup window when you click the exntension. Then you provide some JavaScript to do something on the current page you are on, and then some more JavaScript to do something with that data. So in my case, I grab the URL of the page where the recipe is coming from, grab the name of the recipe, and then whatever text is highlighted on the page. So, the process to add a recipe is to highlight the actual recipe, then click the Dumbwaiter icon, and all the data will be pre-populated into my Statamic new entry form.</p>\n\n<p>Here is some example code that I am using, but the options are limitless: whatever you can do with jQuery, you can do with Dumbwaiter.</p>\n\n<h3>Retrieve Data Code</h3>\n<pre><code>var title = jQuery(\'meta[property=\"og:title\"]\').attr(\'content\');\nvar source = window.location.href;\nvar img = jQuery(\'meta[property=\"og:image\"]\').attr(\'content\');\nvar content = window.getSelection().toString();\n\nif(!title) {\n	title = jQuery(\'title\').text();\n}\n\nvar data = {\n	title: title,\n	source: source,\n	img: img,\n	content: content\n};</code></pre>\n\n<h3>Insert Data Code</h3>\n<pre><code>function makeSlug(str) { \n	str = str.replace(/^\\s+|\\s+$/g, \'\'); // trim\n	str = str.toLowerCase();\n  \n	// remove accents, swap ñ for n, etc\n	var from = \"àáäâèéëêìíïîòóöôùúüûñç·/_,:;\";\n	var to   = \"aaaaeeeeiiiioooouuuunc------\";\n	for (var i=0, l=from.length ; i &lt; l ; i++) {\n		str = str.replace(new RegExp(from.charAt(i), \'g\'), to.charAt(i));\n	}\n  \n	str = str.replace(/[^a-z0-9 -]/g, \'\') // remove invalid chars\n	.replace(/\\s+/g, \'-\') // collapse whitespace and replace by -\n	.replace(/-+/g, \'-\'); // collapse dashes\n  \n	return str;\n};\n\n$(\'#publish-title\').val(data.title).focus();\nvar slug = makeSlug(data.title);\n$(\'#publish-slug\').val(slug);\n$(\'input[name=\"page[yaml][source]\"]\').val(data.source);\n$(\'textarea.markItUpEditor\').val(data.content);</code></pre>\n\n<p>You can <a href=\"https://chrome.google.com/webstore/detail/jeeeliidcblacogbcefhcbljkllhpjdd?hl=en&amp;gl=US\">download Dumbwaiter here</a>, and let me know if you guys find any creative uses!</p>',NULL,2021,NULL,'2019-10-09 16:41:23','2019-10-09 16:41:23','79a7a879-b6fb-4c27-81c4-8304e28ae74e',1,NULL,NULL,NULL,NULL),(1523,2008,'Who Says the Web is Just for Squares?',NULL,'<p>I had some fun building a crazy diamond responsive grid for a project at work. <a href=\"http://viget.com/inspire/who-says-the-web-is-just-for-squares\">This article</a> explains how I did it.</p>','http://viget.com/inspire/who-says-the-web-is-just-for-squares',0,NULL,'2019-10-09 16:41:23','2019-10-09 16:41:23','4bcc696a-015e-4701-80f9-e2e5fffb34bd',1,NULL,NULL,NULL,NULL),(1524,2009,'JavaScript Execution Patterns for Non-Web Apps',NULL,'<p>I finally got back to blogging and wrote an article about <a href=\"http://viget.com/extend/javascript-execution-patterns-for-non-web-apps\">JavaScript execution patterns</a>, a topic which I recently presented on at the <a href=\"https://speakerdeck.com/trevor_davis/javascript-for-non-web-apps\">DC jQuery Meetup</a>.</p>','http://viget.com/extend/javascript-execution-patterns-for-non-web-apps',0,NULL,'2019-10-09 16:41:23','2019-10-09 16:41:23','1545fad3-8aa0-45d6-859d-dc417ca65464',1,NULL,NULL,NULL,NULL),(1525,2010,'About',NULL,NULL,NULL,0,NULL,'2019-10-09 16:41:23','2019-10-09 16:41:23','92d8f9cf-dc04-4cf7-b825-f9b23bcd93f4',1,NULL,NULL,NULL,NULL),(1526,2016,'About',NULL,NULL,NULL,0,NULL,'2019-10-09 16:41:23','2019-10-09 16:41:23','28434230-5270-4ea6-8296-18635fc33fde',1,NULL,NULL,NULL,NULL),(1527,2022,'Contact','So you want to get in touch?',NULL,NULL,0,NULL,'2019-10-09 16:41:23','2019-10-09 16:41:23','695beb6c-1e33-44e4-a2f6-645a280bcccb',1,NULL,NULL,NULL,NULL),(1529,2029,'Contact','So you want to get in touch?',NULL,NULL,0,NULL,'2019-10-09 16:41:24','2019-10-09 16:41:24','056bbed8-050b-4ceb-9347-454430a7509e',1,NULL,NULL,NULL,NULL),(1532,2042,'Lupus Resource Center',NULL,NULL,NULL,0,NULL,'2019-10-23 16:26:09','2019-10-23 16:26:09','3e50c4e7-f500-4ebf-9b63-6c4fdc5f31b3',1,NULL,NULL,NULL,NULL),(1533,2043,'PBS Kids Development Tracker',NULL,NULL,NULL,0,NULL,'2019-10-23 16:28:33','2019-10-23 16:28:33','b10202a3-f052-421f-a737-b267e614fae7',1,NULL,NULL,NULL,NULL),(1534,2044,'Yes I Foods',NULL,NULL,NULL,0,NULL,'2019-11-05 15:10:59','2019-11-05 15:10:59','bec11a2e-8936-4d05-8081-cdc66b7ea0f1',1,NULL,NULL,NULL,NULL),(1535,2045,'Homepage',NULL,NULL,NULL,0,NULL,'2019-11-10 04:49:48','2019-11-10 04:49:48','061a3336-f6ab-4e9c-936e-6e3921812d6d',1,'I Build Things on the Internet','<p>I’m a <strong>Front-End Development Technical Director</strong> at <a href=\"https://www.viget.com/\">Viget</a>.<br />If you have a project that you think I can help with, <a href=\"{entry:5:url}\">get in touch</a>.</p>',NULL,NULL),(1536,2046,'Homepage',NULL,NULL,NULL,0,NULL,'2020-03-18 20:02:26','2020-03-18 20:02:26','4a43a918-931a-422b-bb28-c9f7b55aec62',1,'I Build Things on the Internet','<p>I’m a <strong>Front-End Development Technical Director</strong> at <a href=\"https://www.viget.com/\">Viget</a>.<br />If you have a project that you think I can help with, <a href=\"{entry:5:url}\">get in touch</a>.</p>',NULL,NULL),(1537,2047,'About',NULL,NULL,NULL,0,NULL,'2020-03-18 20:02:26','2020-03-18 20:02:26','c0ee63c9-ec4a-44b6-8a56-687c769e9fdf',1,NULL,NULL,NULL,NULL),(1538,2053,'Contact','So you want to get in touch?',NULL,NULL,0,NULL,'2020-03-18 20:02:27','2020-03-18 20:02:27','2b4a8fd6-df29-4eb3-b21d-60c7320d4b81',1,NULL,NULL,NULL,NULL),(1540,2055,'Nflpa',NULL,NULL,NULL,0,NULL,'2020-05-29 19:00:45','2022-01-15 13:26:34','e29709d3-3d23-4588-a2ae-5d2bb6db5a0f',1,NULL,NULL,NULL,NULL),(1541,2056,'PHP',NULL,NULL,NULL,0,NULL,'2020-05-29 19:01:06','2020-05-29 19:01:06','4cd00c0a-1281-47c5-8e2c-80a7f365225c',1,NULL,NULL,NULL,NULL),(1542,2057,'NFL Players Association',NULL,NULL,'https://www.nflpa.com/',0,NULL,'2020-05-29 19:01:13','2020-05-29 19:01:51','80dffd0c-0b18-48dd-8cdc-ca3aba21d197',1,NULL,NULL,NULL,NULL),(1543,2058,'NFLPA',NULL,NULL,'https://www.nflpa.com/',0,NULL,'2020-05-29 19:01:13','2020-05-29 19:01:13','af2acbff-6bef-437a-9777-b017f1dd625a',1,NULL,NULL,NULL,NULL),(1544,2059,'NFL Players Association',NULL,NULL,'https://www.nflpa.com/',0,NULL,'2020-05-29 19:01:51','2020-05-29 19:01:51','0900c1a7-073d-4d5b-9823-edf386357ce6',1,NULL,NULL,NULL,NULL),(1545,2060,'Lully Sleep',NULL,NULL,NULL,0,NULL,'2020-07-11 04:19:59','2020-07-11 04:19:59','3879f03c-d710-419c-96b4-375be6f859b9',1,NULL,NULL,NULL,NULL),(1546,2061,'PPS Plus',NULL,NULL,NULL,0,NULL,'2020-07-11 04:20:31','2020-07-11 04:20:31','83fd9581-4e61-413c-82a4-305e893952dc',1,NULL,NULL,NULL,NULL),(1547,2062,'About',NULL,NULL,NULL,0,NULL,'2020-08-10 21:12:18','2020-08-10 21:12:18','539d239a-975d-4f4c-9ea3-6ad84b90964c',1,NULL,NULL,NULL,NULL),(1548,2068,'Homepage',NULL,NULL,NULL,0,NULL,'2020-08-10 21:12:19','2020-08-10 21:12:19','53f7d4d5-55ca-4fe3-8277-060268998fc7',1,'I Build Things on the Internet','<p>I’m a <strong>Front-End Development Technical Director</strong> at <a href=\"https://www.viget.com/\">Viget</a>.<br />If you have a project that you think I can help with, <a href=\"{entry:5:url}\">get in touch</a>.</p>',NULL,NULL),(1549,2069,'Contact','So you want to get in touch?',NULL,NULL,0,NULL,'2020-08-10 21:12:19','2020-08-10 21:12:19','d8ee79ec-16c2-424a-9202-1665030d67af',1,NULL,NULL,NULL,NULL),(1550,2070,'About',NULL,NULL,NULL,0,NULL,'2020-08-10 21:12:19','2020-08-10 21:12:19','c2f5154c-424e-4ff0-b6f0-7297324c393f',1,NULL,NULL,NULL,NULL),(1551,2076,'BDI Furniture',NULL,NULL,'https://www.bdiusa.com/',0,NULL,'2021-01-18 20:36:16','2021-01-18 20:36:16','8aed7efe-7e93-41b7-8fde-a6749fbef88d',1,NULL,NULL,NULL,NULL),(1552,2077,'American Farmland Trust',NULL,NULL,NULL,0,NULL,'2021-01-18 20:36:38','2021-01-18 20:36:38','c685b1e1-f0a6-4915-832e-d1b14925d2b2',1,NULL,NULL,NULL,NULL),(1553,2078,'Lenovo Blog',NULL,NULL,NULL,0,NULL,'2021-01-18 20:36:59','2021-01-18 20:36:59','8c5fde50-6174-4bb0-8d01-92b98a9196cb',1,NULL,NULL,NULL,NULL),(1554,2079,'About',NULL,NULL,NULL,0,NULL,'2021-02-19 17:56:59','2021-02-19 17:56:59','6955ad9d-d7b2-4984-9e93-67fd05d8d652',1,NULL,NULL,NULL,NULL),(1556,2086,'Hrc',NULL,NULL,NULL,0,NULL,'2021-05-03 19:50:50','2022-01-15 13:26:36','29887684-8c76-413d-888a-b834eb6b6eb8',1,NULL,NULL,NULL,NULL),(1557,2087,'Human Rights Campaign',NULL,NULL,'https://www.hrc.org/',0,NULL,'2021-05-03 19:51:10','2021-05-03 19:51:10','912352d7-426b-46e5-9185-db347f531c48',1,NULL,NULL,NULL,NULL),(1558,2088,'Human Rights Campaign',NULL,NULL,'https://www.hrc.org/',0,NULL,'2021-05-03 19:51:10','2021-05-03 19:51:10','1c20a456-0bf1-4d20-9baf-f59ad5310224',1,NULL,NULL,NULL,NULL),(1559,2089,'How We Prevent Leaky Templates in Craft CMS',NULL,'<p>Prevent the flood of leaky templates in Craft CMS with just a little bit of PHP.</p>','https://www.viget.com/articles/how-we-prevent-leaky-templates-in-craft-cms/',0,NULL,'2021-12-01 11:43:19','2023-01-22 15:18:24','f9dd850f-d750-4113-b414-bc41170d9ca9',1,NULL,NULL,NULL,NULL),(1560,2090,'How We Prevent Leaky Templates in Craft CMS',NULL,'<p>Prevent the flood of leaky templates in Craft CMS with just a little bit of PHP.</p>','https://www.viget.com/articles/how-we-prevent-leaky-templates-in-craft-cms/',0,NULL,'2021-12-01 11:43:53','2021-12-01 11:43:53','7958a4e9-9f4b-462a-825c-ea1400aaf635',1,NULL,NULL,NULL,NULL),(1561,2091,'What I Love & Hate About Tailwind CSS',NULL,'<p>As a long time skeptic of Tailwind CSS, I’ve finally given it a try and discovered some things I love and hate.</p>','https://www.viget.com/articles/what-i-love-hate-about-tailwind-css/',0,NULL,'2021-12-01 11:44:02','2023-01-22 15:18:24','5d166e5f-3fd3-4bdf-bf3d-017596ed6ea8',1,NULL,NULL,NULL,NULL),(1562,2092,'What I Love & Hate About Tailwind CSS',NULL,'<p>As a long time skeptic of Tailwind CSS, I’ve finally given it a try and discovered some things I love and hate.</p>','https://www.viget.com/articles/what-i-love-hate-about-tailwind-css/',0,NULL,'2021-12-01 11:44:41','2021-12-01 11:44:41','5878f080-3076-4e41-8702-424be7d658db',1,NULL,NULL,NULL,NULL),(1563,2093,'MW Components',NULL,NULL,'https://www.mwcomponents.com/',0,NULL,'2021-12-01 11:50:36','2021-12-01 11:51:39','57e70eb0-82f0-4e20-9769-85e27dcbaa9d',1,NULL,NULL,NULL,NULL),(1564,2094,'Mwi',NULL,NULL,NULL,0,NULL,'2021-12-01 11:51:12','2022-01-15 13:26:38','386983d8-419a-4ce6-a8d6-fa78b87e6a18',1,NULL,NULL,NULL,NULL),(1565,2095,'MySQL',NULL,NULL,NULL,0,NULL,'2021-12-01 11:51:30','2021-12-01 11:51:30','15351cc4-e07e-475f-8635-40621c7d67a6',1,NULL,NULL,NULL,NULL),(1566,2096,'Twig',NULL,NULL,NULL,0,NULL,'2021-12-01 11:51:33','2021-12-01 11:51:33','380b13ce-3eb1-4a76-921e-df4c7dc2c2c7',1,NULL,NULL,NULL,NULL),(1567,2097,'MW Components',NULL,NULL,'https://www.mwcomponents.com/',0,NULL,'2021-12-01 11:51:39','2021-12-01 11:51:39','74af31a9-e18b-47a7-be15-9ab63f13f9e7',1,NULL,NULL,NULL,NULL),(1569,2099,'CSS Forms',NULL,'<p>Everyone hates forms.</p>\n<p>They are hard to style so that they work with your site design. They are hard to make them accessible. Yeah, yeah we have heard it all. But in reality, they are not that hard to do.</p>\n<p>Since every other web developer/designer has their own method, I thought I would share my two cents.</p>\n<p>When thinking through all of the HTML elements to find something that makes sense for forms, there are many options.</p>\n<ul><li>Unordered List</li>\n<li>Ordered List</li>\n<li>DIVs</li>\n<li>Paragraphs</li>\n<li>Tables (Yes some people still use tables for forms)</li>\n</ul>\n<p>There are probably others. But I like to use a more uncommon element: a Definition List. It is perfect for the job. You have got the definition term, which is essentially like the label. Then you have got the definition description, which is basically the actual form element.</p>\n<p>Let\'s start with some un-styled markup:</p>\n<div class=\"codeblock\"><code>\n&lt;form action=\"#\" method=\"post\" name=\"sendToFriendForm\" id=\"sendToFriendForm\"&gt;\n &lt;dl class=\"forms\"&gt;\n  &lt;dt&gt;&lt;label for=\"name\"&gt;Your Name:&lt;/label&gt;&lt;/dt&gt;\n  &lt;dd&gt;&lt;input name=\"name\" id=\"name\" type=\"text\" /&gt;&lt;/dd&gt;\n\n  &lt;dt&gt;&lt;label for=\"senderEmail\"&gt;Your Email Address: &lt;span class=\"required\"&gt;*&lt;/span&gt;&lt;/label&gt;&lt;/dt&gt;\n  &lt;dd&gt;&lt;input name=\"senderEmail\" id=\"senderEmail\" type=\"text\" /&gt;&lt;/dd&gt;\n\n  &lt;dt&gt;&lt;label for=\"recipientEmail\"&gt;Friend\'s Email Address: &lt;span class=\"required\"&gt;*&lt;/span&gt;&lt;/label&gt;&lt;/dt&gt;\n  &lt;dd&gt;&lt;input name=\"recipientEmail\" id=\"recipientEmail\" type=\"text\" /&gt;&lt;/dd&gt;\n  &lt;dd class=\"help\"&gt;Use commas to separate multiple email addresses.&lt;/dd&gt;\n\n  &lt;dt&gt;&lt;label for=\"sex\"&gt;Sex&lt;/label&gt;&lt;/dt&gt;\n  &lt;dd class=\"radio\"&gt;&lt;input name=\"sex\" id=\"male\" type=\"radio\" /&gt; &lt;label for=\"male\"&gt;Male&lt;/label&gt; &lt;input name=\"sex\" id=\"female\" type=\"radio\" /&gt; &lt;label for=\"female\"&gt;Female&lt;/label&gt;&lt;/dd&gt;\n  &lt;dt&gt;&lt;label for=\"message\"&gt;Message:&lt;/label&gt;&lt;/dt&gt;\n  &lt;dd&gt;&lt;textarea name=\"message\" id=\"message\"&gt;&lt;/textarea&gt;&lt;/dd&gt;\n &lt;/dl&gt;\n &lt;button type=\"submit\"&gt;Submit »&lt;/button&gt;\n&lt;/form&gt; \n\n</code></div>\n<p>I have created the page so you can see <a href=\"//assets.trevor-davis.com/play/cssforms/\">the output</a>. Even un-styled, this form doesn\'t even look bad. But lets add some style:</p>\n<div class=\"codeblock\"><code>\nform {\n  margin: 0;\n  padding: 0;\n }\n\n dl.forms {\n  float: left;\n  width: 100%;\n }\n\n dl.forms dt {\n  margin: 0;\n  padding: 10px 0 0 0;\n  clear: left;\n  float: left;\n  width: 175px;\n }\n\n dl.forms label { font-weight: bold; }\n\n dl.forms dd {\n  margin: 0;\n  padding: 10px 0 0 0;\n }\n\n dl.forms dd.help {\n  clear: left;\n  padding-top: 2px;\n  font-size: 90%;\n  color: #999;\n }\n\n dl.forms input, dl.forms textarea { width: 300px; }\n\n dl.forms dd.radio input { width: auto; }\n\n dl.forms textarea { height: 150px; }\n\n .required {\n  color: #FF0000;\n  font-weight: bold;\n } \n\n</code></div>\n<p>I don\'t think I need to go step by step through that because it is pretty simple styling. I have <a href=\"//assets.trevor-davis.com/play/cssforms/final/\">created the styled page</a> for you to see.</p>\n<p>I personally like forms that have the label and the input element on the same line, but that\'s just me. It is pretty flexible, try resizing the font two times. Still very readable. You could easily do the widths in ems or percentages; I just chose to use pixels since I don\'t have any parent element containing it.</p>\n<p>Should be pretty good in all browsers, especially since we didn\'t do any crazy CSS. I know it looks good in FF, IE6 and IE7. I believe it works fine in Safari and Opera.</p>\n<p>Obviously this isn\'t the be all and end all to styling forms with CSS. But it is something to start with. So, go out and make it better. But be sure to share what you have created.</p>',NULL,1714,NULL,'2022-01-15 13:32:39','2022-01-15 13:32:39','3a7f15ba-6266-4071-9b92-96758e6be5ae',1,NULL,NULL,NULL,NULL),(1571,2106,'Bball smile',NULL,NULL,NULL,0,NULL,'2022-01-15 13:48:45','2022-01-15 13:48:45','1beedbe5-c74d-40b4-883a-b4125e0729fd',1,NULL,NULL,NULL,NULL),(1572,2107,'Bball chill',NULL,NULL,NULL,0,NULL,'2022-01-15 13:49:00','2023-05-12 15:18:14','29c4778b-2cab-405d-88ae-7ffde6a1204a',1,NULL,NULL,NULL,NULL),(1573,2108,'About',NULL,NULL,NULL,0,NULL,'2022-01-15 13:49:05','2022-01-15 13:49:05','361f6f34-b39c-4248-9919-3e8c4cf2b7e1',1,NULL,NULL,NULL,NULL),(1574,2114,'Bball save',NULL,NULL,NULL,0,NULL,'2022-01-15 13:50:43','2023-05-12 15:18:40','83651501-1067-4b97-bfad-f8325279098d',1,NULL,NULL,NULL,NULL),(1576,2121,'About',NULL,NULL,NULL,0,NULL,'2022-01-15 13:52:53','2022-01-15 13:52:53','db57ffea-6552-4213-885a-c75d2929eb53',1,NULL,NULL,NULL,NULL),(1577,2127,'Bball run',NULL,NULL,NULL,0,NULL,'2022-01-15 13:54:08','2022-01-15 13:54:31','59c632c4-f5b5-4670-b50c-9573c17d2fcc',1,NULL,NULL,NULL,NULL),(1579,2134,'About',NULL,NULL,NULL,0,NULL,'2022-01-15 13:54:37','2022-01-15 13:54:37','4f95bee8-6691-4741-ab73-fd6a675e631d',1,NULL,NULL,NULL,NULL),(1580,2140,'Why I’m So Excited About Remix',NULL,'<p>I’ve been building on the web for a long time. There’s a part of me that still has a bit of an old school mentality, and it’s hard for me to get really excited about new technology. Sure React was cool when it came out for its state management, but I didn’t see it as the be-all and end-all for building on the web. I really like <a href=\"https://craftcms.com/\">Craft CMS</a> for building CMS powered sites since I have full control over the HTML being sent to the browser, and it’s really easy to extend for complex functionality, but it can be a bit complex to setup for beginners and with additional complexity can come performance issues.&nbsp;So it’s been a while since I’ve seen something to be <em>really</em> excited about.</p>\r\n<p>Enter <a href=\"https://remix.run/\">Remix</a>.</p>\r\n<p>Remix is an interesting mix of old school techniques along with modern technology. Ryan Florence actually sums it up perfectly as to where Remix fits in.</p>\r\n<blockquote class=\"twitter-tweet\" data-dnt=\"true\" data-theme=\"dark\"><p lang=\"en\" dir=\"ltr\">Forget “full stack”. Remix is center stack.<br><br>It’s an HTTP tunnel between interactivity and business logic. It’s the part of the stack that no tool before it has solved, not completely.<br><br>I think I finally know how to talk about Remix.</p>— Ryan Florence (@ryanflorence) <a href=\"https://twitter.com/ryanflorence/status/1482233495195770883?ref_src=twsrc%5Etfw\">January 15, 2022</a></blockquote>\r\n<script async=\"\" src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\"></script>\r\n<p>I was able to easily switch my site that was fully powered by Craft to utilize Craft only as a GraphQL endpoint and Remix powering the rest. The two big things I needed to figure out were: how to get data from the GraphQL endpoint, and then how to process input from a user (for my contact form). I would definitely recommend reading through the Remix docs and the two tutorials, but if you can understand these two big pictures things, you’ll have enough to get started with Remix and go deeper once you get into it.</p>\r\n<h2>Getting GraphQL Data (aka Loaders)</h2>\r\n<p>Remix provides a <a href=\"https://remix.run/docs/en/v1/api/conventions#loader\">loader hook</a> that runs on the server to hydrate your component. In this simple example, I run a GraphQL request and return JSON with the results of that request in the loader function.</p>\r\n<script src=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550.js?file=loader.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550#file-loader-jsx\">View Gist</a></noscript>\r\n<p>Then in my <code>Index</code> component, I access the data from the loader hook with <a href=\"https://remix.run/docs/en/v1/api/remix#useloaderdata\">useLoaderData()</a>, and my component is now hydrated with that data. In MVC style of thinking, think of the loader hook as the controller processing the page load request, populating with data from the model, and then passing to the view.</p>\r\n<p>The great part about Remix is that this doesn’t have to be specifically a GraphQL request. This data can come from anywhere. The <a href=\"https://remix.run/docs/en/v1/tutorials/jokes\">Jokes tutorial</a> in the Remix docs even thoroughly walks through how you can manage all this data in <a href=\"https://www.prisma.io/\">Prisma</a>.</p>\r\n<h2>Processing User Input (aka Actions)</h2>\r\n<p>Ok great, so we’ve got data onto the page, but now we need to be able to handle user input. Remix also provides an <a href=\"https://remix.run/docs/en/v1/api/conventions#action\">action hook</a> to process an action request (ex: a form submission). In my case, I have a contact form that sends me an email via SendGrid after submission.</p>\r\n<script src=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550.js?file=action.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550#file-action-jsx\">View Gist</a></noscript>\r\n<p>If you don’t include an <code>action</code> attribute on your form, it will automatically submit to the same page. Again, in MVC thinking, the action would again be equivalent to the controller taking the request input and processing it. But honestly, this takes me back 15 years when form actions would point directly to PHP files.</p>\r\n<h2>Bonus: Progressive Enhancement</h2>\r\n<p>Since Remix is running on the server, you can turn off JavaScript and everything still works great. Data still loads, form actions still process; it’s beautiful. This is not running loaders and actions on the client side; it’s running them on the server. This isn’t an accident, the Remix team is carefully considering the UX.</p>\r\n<blockquote class=\"twitter-tweet\" data-dnt=\"true\" data-theme=\"dark\"><p lang=\"en\" dir=\"ltr\">User experience (UX) and developer experience (DX) are both important. UX is more important than DX.<a href=\"https://twitter.com/remix_run?ref_src=twsrc%5Etfw\">@remix_run</a> has taught me: It\'s easier to start with a great UX and work toward a good DX than it is to start with a great DX and work toward a good UX.</p>— Kent C. Dodds &#x1f4bf; (@kentcdodds) <a href=\"https://twitter.com/kentcdodds/status/1482390454389805058?ref_src=twsrc%5Etfw\">January 15, 2022</a></blockquote>\r\n<script async=\"\" src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\"></script>\r\n<h2>Bonus: So Speedy</h2>\r\n<p>Did I mention how fast everything renders? I don’t tend to put too much stock into Lighthouse scores since they seem so random, but Remix crushes Lighthouse without me having to invest any additional effort into improving performance.</p>\r\n<h2>Give it a Shot</h2>\r\n<p>Remix is built on the <a href=\"https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API\">native Fetch API</a>, so it can run anywhere. While Remix is relatively new, it’s certainly production ready, and there is a dedicated team behind it. If you aren’t ready to dive into Remix yet, at least keep your eye on it because this is a game changer.</p>',NULL,0,NULL,'2022-01-15 14:09:11','2023-02-15 21:55:50','14642574-d1fa-4758-8e43-cf9770249788',1,NULL,NULL,23,NULL),(1591,2151,'Homepage',NULL,NULL,NULL,0,NULL,'2022-01-16 00:38:01','2022-01-16 00:38:01','64d9b6ec-ceab-4953-a2a0-c90c66f64f03',1,'I Build Things on the Internet','<p>I’m a <strong>Front-End Development Technical Director</strong> at <a href=\"https://www.viget.com/\">Viget</a>.<br />If you have a project that you think I can help with, <a href=\"/contact\">get in touch</a>.</p>',NULL,NULL),(1625,2189,'Easter Seals UCP North Carolina',NULL,'<p>For my first project while working for Viget Labs, I built the Easter Seals UCP North Carolina website. My role in the project was to build-out the design and implement the site using ExpressionEngine. I also added in some JavaScript functionality on the homepage and on the individual service pages.</p>',NULL,0,NULL,'2022-01-18 03:21:07','2022-01-18 03:21:07','c4e395e0-9cf6-4708-8091-92abd6e9e53f',1,NULL,NULL,NULL,NULL),(1627,2199,'Team Viget',NULL,'<p>Our <a href=\"http://v1.teamviget.com/\">existing Team Viget site</a> was out of date and was mainly focused on bringing new designers to Viget, and we decided that it was time to make it reflect <em>all</em> of Viget. My role in the project was to build it with HTML &amp; CSS, and to code the JavaScript interactions. Then, I implemented into ExpressionEngine so others could easily add stories. This site works best in Webkit browsers because we were able to take advantage of a lot of experimental properties.</p>',NULL,0,'84871420','2022-01-18 03:21:21','2022-01-18 03:21:21','086f87a3-a1e5-40c6-9666-e8f2a80f9234',1,NULL,NULL,NULL,NULL),(1629,2213,'NMS',NULL,'<p>New Media Strategies partnered with us (Viget) to recreate their web presence. They were looking for something new and different. My role on the project was to build the front-end, which included some light canvas work, and to implement the site into ExpressionEngine, which included custom add-on development.</p>',NULL,0,NULL,'2022-01-18 03:21:32','2022-01-18 03:21:32','ac6fd5f4-ce5a-44cf-bd0a-73acdcaa10b0',1,NULL,NULL,NULL,NULL),(1631,2229,'Carr Workplaces',NULL,'<p>We (Viget) had originally built Carr’s site many years ago. We had the opportunity to redesign it and implement a new CMS. My role in the project was to help a little with building some pieces of the front-end, but my main role was to implement the site in ExpressionEngine, which included custom add-on development.</p>',NULL,0,NULL,'2022-01-18 03:21:46','2022-01-18 03:21:46','bd9da539-b6fd-4178-99e3-44ef648b8928',1,NULL,NULL,NULL,NULL),(1633,2242,'Orbcomm',NULL,'<p>Building this site gave me the opportunity to build a site with <a href=\"http://buildwithcraft.com/\">Craft</a>; something I had been itching to use on a project for some time. My role in the project was to build the front-end of the site, configure Craft, and then integrate the two. In building this site, I also created three Craft plugins: <a href=\"https://github.com/davist11/craft-bust\">Bust</a>, <a href=\"https://github.com/davist11/craft-listing-section\">Listing Section</a>, and <a href=\"https://github.com/davist11/craft-reroute\">Reroute</a>.</p>',NULL,0,NULL,'2022-01-18 03:22:01','2022-01-18 03:22:01','6b31ff17-4c03-4158-acf4-58c0ef44c2c5',1,NULL,NULL,NULL,NULL),(1635,2249,'Elgin Racing',NULL,NULL,'http://elginracing.com/',0,NULL,'2022-01-18 03:22:12','2022-01-18 03:22:12','70d53228-a1be-4bd5-8245-f2b30bb9a80b',1,NULL,NULL,NULL,NULL),(1637,2251,'PPS Plus',NULL,NULL,NULL,0,NULL,'2022-01-18 03:22:27','2022-01-18 03:22:27','bff8b7cc-7fae-4f2a-bd7e-705d1ae3a429',1,NULL,NULL,NULL,NULL),(1639,2253,'Yes I Foods',NULL,NULL,NULL,0,NULL,'2022-01-18 03:22:46','2022-01-18 03:22:46','9187fe27-38ab-4b1e-9032-d0c21a293850',1,NULL,NULL,NULL,NULL),(1641,2259,'AIGA Design Continuum Fund',NULL,'<p>The AIGA Design Continuum Fund is a yearly scholarship awarded to a local design student. We took on this project as pro-bono to support the local design community, and my role was to build the front-end of the site and to integrate into ExpressionEngine.</p>',NULL,0,NULL,'2022-01-18 03:23:33','2022-01-18 03:23:33','b36c1af5-6a95-4de8-92db-9bc3adefaa99',1,NULL,NULL,NULL,NULL),(1643,2265,'Lenovo Blog',NULL,NULL,NULL,0,NULL,'2022-01-18 03:23:43','2022-01-18 03:23:43','517f3c6a-8bc1-4b4b-b9bc-27a94aa1975b',1,NULL,NULL,NULL,NULL),(1644,2266,'Setting Up Live Preview with Craft CMS in Headless Mode',NULL,'<p>In my <a href=\"https://www.trevor-davis.com/blog/why-im-so-excited-about-remix\">previous post</a>, I talked about transitioning my site from being powered by <a href=\"https://craftcms.com/\">Craft</a> to being powered by <a href=\"https://remix.run/\">Remix</a> and a GraphQL endpoint coming from Craft. One of the best features of Craft is <a href=\"https://craftcms.com/features/all#live-preview\">Live Preview</a>, and it took a little configuration to get this working on my new Remix powered site.</p>\r\n<h2>Remix Configuration</h2>\r\n<p>These were specific changes that I needed to make on the Remix side, but really it would be the same for any GraphQL request. As Andrew Welch breaks down in <a href=\"https://nystudio107.com/blog/headless-preview-in-craft-cms\">his article</a>, the key is passing the token parameter back that Craft included in the URL.</p>\r\n<p>In the loader function of my blog post route, I call a helper function to setup the GraphQL client, and I pass the request to it:</p>\r\n<script src=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e.js?file=$slug.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e#file-slug-jsx\">View Gist</a></noscript>\r\n<p>And then in my helper function, I take that request, grab the URL params that I want to include, and add those to my GraphQL request endpoint URL:</p>\r\n<script src=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e.js?file=graphql.server.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e#file-graphql-server-jsx\">View Gist</a></noscript>\r\n<p>It wasn’t totally necessary to include the <code>x-craft-preview</code> and <code>x-craft-live-preview</code> parameters, but I figured it couldn’t hurt.</p>\r\n<h2>Craft Configuration</h2>\r\n<p>Now with the Remix configuration in place, I just needed to make two small changes to Craft to get it working correctly. First, I had to update the preview target for my Blog section to point to my Remix site:</p>\r\n<figure><img src=\"{asset:2283:url||//assets.trevor-davis.com/uploads/images/content/blog-section-preview-target.png}\" data-image=\"2283\" alt=\"Setting the preview target in my Blog Section\"></figure>\r\n<p>Then, I had to update the <code>config/general.php</code> to allow iframe requests from my Remix domain:</p>\r\n<script src=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e.js?file=general.php\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e#file-general-php\">View Gist</a></noscript>\r\n\r\n<h2>Voilà, Live Preview</h2>\r\n<p>And just like that, I had live preview working.</p>\r\n<video src=\"//assets.trevor-davis.com/uploads/images/content/live-preview.mp4\" autoplay=\"\" loop=\"\" muted=\"\" controls=\"\" width=\"100%\"></video>',NULL,0,NULL,'2022-01-18 09:49:35','2024-12-17 16:39:36','8e6dceca-ab72-4713-a91d-5ab781c6fdb1',1,NULL,NULL,30,NULL),(1648,2270,'Lansinoh',NULL,'<p>I sure didn’t know it before I started the project, but Lansinoh is one of the leaders in the breastfeeding industry. Since mobile accounted for 47% of visits, building a site to adapt to any device was a must. My role in the project was to build the front-end of the site and integrate with ExpressionEngine, which included ecommerce, user submission forms, and a store finder. This was probably the most complex ExpressionEngine site that I have built to date.</p>',NULL,0,NULL,'2022-01-18 18:17:34','2022-01-18 18:17:34','747afe49-2f79-4a2d-9a17-d27eff4cf357',1,NULL,NULL,NULL,NULL),(1649,2281,'American Farmland Trust',NULL,NULL,NULL,0,NULL,'2022-01-18 18:17:34','2022-01-18 18:17:34','aa494075-c0b8-4d4a-8549-7cc10e181b2d',1,NULL,NULL,NULL,NULL),(1651,2283,'Blog section preview target',NULL,NULL,NULL,0,NULL,'2022-01-22 14:52:21','2022-01-22 14:52:21','4b5a16c4-9d5d-48da-8ab2-e25cb97b4dc2',1,NULL,NULL,NULL,NULL),(1652,2284,'Live preview',NULL,NULL,NULL,0,NULL,'2022-01-22 15:10:52','2022-01-22 15:10:52','16ec3a24-82cb-4fb7-b19d-e993be4c48a1',1,NULL,NULL,NULL,NULL),(1660,2292,'Live preview',NULL,NULL,NULL,0,NULL,'2022-01-22 15:24:44','2022-01-22 15:24:44','b2a26874-c2ba-4389-9766-531e24b38818',1,NULL,NULL,NULL,NULL),(1667,2299,'Live preview',NULL,NULL,NULL,0,NULL,'2022-01-22 15:30:07','2022-01-22 15:30:07','686d2915-7b7d-468f-840a-0d39dd8cb0f1',1,NULL,NULL,NULL,NULL),(1677,2309,'Homepage',NULL,NULL,NULL,0,NULL,'2022-03-04 18:38:38','2022-03-04 18:38:38','3563bbb3-f266-439d-9e68-6982895878f3',1,'I Build Things on the Internet','<p>I’m a <strong>Senior Software Engineer</strong> at <a href=\"https://dutchie.com/\">Dutchie</a>.<br />If you have a project that you think I can help with, <a href=\"/contact\">get in touch</a>.</p>',NULL,NULL),(1685,2317,'Setting Up Live Preview with Craft CMS in Headless Mode',NULL,'<p>In my <a href=\"https://www.trevor-davis.com/blog/why-im-so-excited-about-remix\">previous post</a>, I talked about transitioning my site from being powered by <a href=\"https://craftcms.com/\">Craft</a> to being powered by <a href=\"https://remix.run/\">Remix</a> and a GraphQL endpoint coming from Craft. One of the best features of Craft is <a href=\"https://craftcms.com/features/all#live-preview\">Live Preview</a>, and it took a little configuration to get this working on my new Remix powered site.</p>\r\n<h2>Remix Configuration</h2>\r\n<p>These were specific changes that I needed to make on the Remix side, but really it would be the same for any GraphQL request. As Andrew Welch breaks down in <a href=\"https://nystudio107.com/blog/headless-preview-in-craft-cms\">his article</a>, the key is passing the token parameter back that Craft included in the URL.</p>\r\n<p>In the loader function of my blog post route, I call a helper function to setup the GraphQL client, and I pass the request to it:</p>\r\n<script src=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e.js?file=$slug.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e#file-slug-jsx\">View Gist</a></noscript>\r\n<p>And then in my helper function, I take that request, grab the URL params that I want to include, and add those to my GraphQL request endpoint URL:</p>\r\n<script src=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e.js?file=graphql.server.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e#file-graphql-server-jsx\">View Gist</a></noscript>\r\n<p>It wasn’t totally necessary to include the <code>x-craft-preview</code> and <code>x-craft-live-preview</code> parameters, but I figured it couldn’t hurt.</p>\r\n<h2>Craft Configuration</h2>\r\n<p>Now with the Remix configuration in place, I just needed to make two small changes to Craft to get it working correctly. First, I had to update the preview target for my Blog section to point to my Remix site:</p>\r\n<figure><img src=\"{asset:2283:url||//assets.trevor-davis.com/uploads/images/content/blog-section-preview-target.png}\" data-image=\"2283\" alt=\"Setting the preview target in my Blog Section\"></figure>\r\n<p>Then, I had to update the <code>config/general.php</code> to allow iframe requests from my Remix domain:</p>\r\n<script src=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e.js?file=general.php\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e#file-general-php\">View Gist</a></noscript>\r\n\r\n<h2>Voilà, Live Preview</h2>\r\n<p>And just like that, I had live preview working.</p>\r\n<video src=\"//assets.trevor-davis.com/uploads/images/content/live-preview.mp4\" autoplay=\"\" loop=\"\" muted=\"\" controls=\"\" width=\"100%\"></video>',NULL,0,NULL,'2022-04-20 15:15:45','2022-04-20 15:15:45','79a04638-cd9a-4c54-ae5c-2da63dd58d86',1,NULL,NULL,55,NULL),(1686,2318,'Setting Up Live Preview with Craft CMS in Headless Mode',NULL,'<p>In my <a href=\"https://www.trevor-davis.com/blog/why-im-so-excited-about-remix\">previous post</a>, I talked about transitioning my site from being powered by <a href=\"https://craftcms.com/\">Craft</a> to being powered by <a href=\"https://remix.run/\">Remix</a> and a GraphQL endpoint coming from Craft. One of the best features of Craft is <a href=\"https://craftcms.com/features/all#live-preview\">Live Preview</a>, and it took a little configuration to get this working on my new Remix powered site.</p>\r\n<h2>Remix Configuration</h2>\r\n<p>These were specific changes that I needed to make on the Remix side, but really it would be the same for any GraphQL request. As Andrew Welch breaks down in <a href=\"https://nystudio107.com/blog/headless-preview-in-craft-cms\">his article</a>, the key is passing the token parameter back that Craft included in the URL.</p>\r\n<p>In the loader function of my blog post route, I call a helper function to setup the GraphQL client, and I pass the request to it:</p>\r\n<script src=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e.js?file=$slug.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e#file-slug-jsx\">View Gist</a></noscript>\r\n<p>And then in my helper function, I take that request, grab the URL params that I want to include, and add those to my GraphQL request endpoint URL:</p>\r\n<script src=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e.js?file=graphql.server.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e#file-graphql-server-jsx\">View Gist</a></noscript>\r\n<p>It wasn’t totally necessary to include the <code>x-craft-preview</code> and <code>x-craft-live-preview</code> parameters, but I figured it couldn’t hurt.</p>\r\n<h2>Craft Configuration</h2>\r\n<p>Now with the Remix configuration in place, I just needed to make two small changes to Craft to get it working correctly. First, I had to update the preview target for my Blog section to point to my Remix site:</p>\r\n<figure><img src=\"{asset:2283:url||//assets.trevor-davis.com/uploads/images/content/blog-section-preview-target.png}\" data-image=\"2283\" alt=\"Setting the preview target in my Blog Section\"></figure>\r\n<p>Then, I had to update the <code>config/general.php</code> to allow iframe requests from my Remix domain:</p>\r\n<script src=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e.js?file=general.php\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e#file-general-php\">View Gist</a></noscript>\r\n\r\n<h2>Voilà, Live Preview</h2>\r\n<p>And just like that, I had live preview working.</p>\r\n<video src=\"//assets.trevor-davis.com/uploads/images/content/live-preview.mp4\" autoplay=\"\" loop=\"\" muted=\"\" controls=\"\" width=\"100%\"></video>',NULL,0,NULL,'2022-04-20 15:16:01','2022-04-20 15:16:01','55689df2-fcfc-4a5f-aff9-2adf2af6bf9e',1,NULL,NULL,56,NULL),(1687,2319,'Setting Up Live Preview with Craft CMS in Headless Mode',NULL,'<p>In my <a href=\"https://www.trevor-davis.com/blog/why-im-so-excited-about-remix\">previous post</a>, I talked about transitioning my site from being powered by <a href=\"https://craftcms.com/\">Craft</a> to being powered by <a href=\"https://remix.run/\">Remix</a> and a GraphQL endpoint coming from Craft. One of the best features of Craft is <a href=\"https://craftcms.com/features/all#live-preview\">Live Preview</a>, and it took a little configuration to get this working on my new Remix powered site.</p>\r\n<h2>Remix Configuration</h2>\r\n<p>These were specific changes that I needed to make on the Remix side, but really it would be the same for any GraphQL request. As Andrew Welch breaks down in <a href=\"https://nystudio107.com/blog/headless-preview-in-craft-cms\">his article</a>, the key is passing the token parameter back that Craft included in the URL.</p>\r\n<p>In the loader function of my blog post route, I call a helper function to setup the GraphQL client, and I pass the request to it:</p>\r\n<script src=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e.js?file=$slug.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e#file-slug-jsx\">View Gist</a></noscript>\r\n<p>And then in my helper function, I take that request, grab the URL params that I want to include, and add those to my GraphQL request endpoint URL:</p>\r\n<script src=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e.js?file=graphql.server.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e#file-graphql-server-jsx\">View Gist</a></noscript>\r\n<p>It wasn’t totally necessary to include the <code>x-craft-preview</code> and <code>x-craft-live-preview</code> parameters, but I figured it couldn’t hurt.</p>\r\n<h2>Craft Configuration</h2>\r\n<p>Now with the Remix configuration in place, I just needed to make two small changes to Craft to get it working correctly. First, I had to update the preview target for my Blog section to point to my Remix site:</p>\r\n<figure><img src=\"{asset:2283:url||//assets.trevor-davis.com/uploads/images/content/blog-section-preview-target.png}\" data-image=\"2283\" alt=\"Setting the preview target in my Blog Section\"></figure>\r\n<p>Then, I had to update the <code>config/general.php</code> to allow iframe requests from my Remix domain:</p>\r\n<script src=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e.js?file=general.php\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e#file-general-php\">View Gist</a></noscript>\r\n\r\n<h2>Voilà, Live Preview</h2>\r\n<p>And just like that, I had live preview working.</p>\r\n<video src=\"//assets.trevor-davis.com/uploads/images/content/live-preview.mp4\" autoplay=\"\" loop=\"\" muted=\"\" controls=\"\" width=\"100%\"></video>',NULL,0,NULL,'2022-04-20 15:16:38','2022-04-20 15:16:38','ee1aaebd-cd35-4df8-8e68-eaf11980b810',1,NULL,NULL,57,NULL),(1688,2320,'Setting Up Live Preview with Craft CMS in Headless Mode',NULL,'<p>In my <a href=\"https://www.trevor-davis.com/blog/why-im-so-excited-about-remix\">previous post</a>, I talked about transitioning my site from being powered by <a href=\"https://craftcms.com/\">Craft</a> to being powered by <a href=\"https://remix.run/\">Remix</a> and a GraphQL endpoint coming from Craft. One of the best features of Craft is <a href=\"https://craftcms.com/features/all#live-preview\">Live Preview</a>, and it took a little configuration to get this working on my new Remix powered site.</p>\r\n<h2>Remix Configuration</h2>\r\n<p>These were specific changes that I needed to make on the Remix side, but really it would be the same for any GraphQL request. As Andrew Welch breaks down in <a href=\"https://nystudio107.com/blog/headless-preview-in-craft-cms\">his article</a>, the key is passing the token parameter back that Craft included in the URL.</p>\r\n<p>In the loader function of my blog post route, I call a helper function to setup the GraphQL client, and I pass the request to it:</p>\r\n<script src=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e.js?file=$slug.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e#file-slug-jsx\">View Gist</a></noscript>\r\n<p>And then in my helper function, I take that request, grab the URL params that I want to include, and add those to my GraphQL request endpoint URL:</p>\r\n<script src=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e.js?file=graphql.server.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e#file-graphql-server-jsx\">View Gist</a></noscript>\r\n<p>It wasn’t totally necessary to include the <code>x-craft-preview</code> and <code>x-craft-live-preview</code> parameters, but I figured it couldn’t hurt.</p>\r\n<h2>Craft Configuration</h2>\r\n<p>Now with the Remix configuration in place, I just needed to make two small changes to Craft to get it working correctly. First, I had to update the preview target for my Blog section to point to my Remix site:</p>\r\n<figure><img src=\"{asset:2283:url||//assets.trevor-davis.com/uploads/images/content/blog-section-preview-target.png}\" data-image=\"2283\" alt=\"Setting the preview target in my Blog Section\"></figure>\r\n<p>Then, I had to update the <code>config/general.php</code> to allow iframe requests from my Remix domain:</p>\r\n<script src=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e.js?file=general.php\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e#file-general-php\">View Gist</a></noscript>\r\n\r\n<h2>Voilà, Live Preview</h2>\r\n<p>And just like that, I had live preview working.</p>\r\n<video src=\"//assets.trevor-davis.com/uploads/images/content/live-preview.mp4\" autoplay=\"\" loop=\"\" muted=\"\" controls=\"\" width=\"100%\"></video>',NULL,0,NULL,'2022-04-20 15:16:41','2022-04-20 15:16:41','c8540ebe-156a-4caa-b714-bb8a2f17e36b',1,NULL,NULL,56,NULL),(1689,2321,'Setting Up Live Preview with Craft CMS in Headless Mode',NULL,'<p>In my <a href=\"https://www.trevor-davis.com/blog/why-im-so-excited-about-remix\">previous post</a>, I talked about transitioning my site from being powered by <a href=\"https://craftcms.com/\">Craft</a> to being powered by <a href=\"https://remix.run/\">Remix</a> and a GraphQL endpoint coming from Craft. One of the best features of Craft is <a href=\"https://craftcms.com/features/all#live-preview\">Live Preview</a>, and it took a little configuration to get this working on my new Remix powered site.</p>\r\n<h2>Remix Configuration</h2>\r\n<p>These were specific changes that I needed to make on the Remix side, but really it would be the same for any GraphQL request. As Andrew Welch breaks down in <a href=\"https://nystudio107.com/blog/headless-preview-in-craft-cms\">his article</a>, the key is passing the token parameter back that Craft included in the URL.</p>\r\n<p>In the loader function of my blog post route, I call a helper function to setup the GraphQL client, and I pass the request to it:</p>\r\n<script src=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e.js?file=$slug.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e#file-slug-jsx\">View Gist</a></noscript>\r\n<p>And then in my helper function, I take that request, grab the URL params that I want to include, and add those to my GraphQL request endpoint URL:</p>\r\n<script src=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e.js?file=graphql.server.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e#file-graphql-server-jsx\">View Gist</a></noscript>\r\n<p>It wasn’t totally necessary to include the <code>x-craft-preview</code> and <code>x-craft-live-preview</code> parameters, but I figured it couldn’t hurt.</p>\r\n<h2>Craft Configuration</h2>\r\n<p>Now with the Remix configuration in place, I just needed to make two small changes to Craft to get it working correctly. First, I had to update the preview target for my Blog section to point to my Remix site:</p>\r\n<figure><img src=\"{asset:2283:url||//assets.trevor-davis.com/uploads/images/content/blog-section-preview-target.png}\" data-image=\"2283\" alt=\"Setting the preview target in my Blog Section\"></figure>\r\n<p>Then, I had to update the <code>config/general.php</code> to allow iframe requests from my Remix domain:</p>\r\n<script src=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e.js?file=general.php\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e#file-general-php\">View Gist</a></noscript>\r\n\r\n<h2>Voilà, Live Preview</h2>\r\n<p>And just like that, I had live preview working.</p>\r\n<video src=\"//assets.trevor-davis.com/uploads/images/content/live-preview.mp4\" autoplay=\"\" loop=\"\" muted=\"\" controls=\"\" width=\"100%\"></video>',NULL,0,NULL,'2022-04-20 15:18:07','2022-04-20 15:18:07','50d38d39-142e-4715-ad28-498c6f78b929',1,NULL,NULL,57,NULL),(1690,2322,'Setting Up Live Preview with Craft CMS in Headless Mode',NULL,'<p>In my <a href=\"https://www.trevor-davis.com/blog/why-im-so-excited-about-remix\">previous post</a>, I talked about transitioning my site from being powered by <a href=\"https://craftcms.com/\">Craft</a> to being powered by <a href=\"https://remix.run/\">Remix</a> and a GraphQL endpoint coming from Craft. One of the best features of Craft is <a href=\"https://craftcms.com/features/all#live-preview\">Live Preview</a>, and it took a little configuration to get this working on my new Remix powered site.</p>\r\n<h2>Remix Configuration</h2>\r\n<p>These were specific changes that I needed to make on the Remix side, but really it would be the same for any GraphQL request. As Andrew Welch breaks down in <a href=\"https://nystudio107.com/blog/headless-preview-in-craft-cms\">his article</a>, the key is passing the token parameter back that Craft included in the URL.</p>\r\n<p>In the loader function of my blog post route, I call a helper function to setup the GraphQL client, and I pass the request to it:</p>\r\n<script src=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e.js?file=$slug.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e#file-slug-jsx\">View Gist</a></noscript>\r\n<p>And then in my helper function, I take that request, grab the URL params that I want to include, and add those to my GraphQL request endpoint URL:</p>\r\n<script src=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e.js?file=graphql.server.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e#file-graphql-server-jsx\">View Gist</a></noscript>\r\n<p>It wasn’t totally necessary to include the <code>x-craft-preview</code> and <code>x-craft-live-preview</code> parameters, but I figured it couldn’t hurt.</p>\r\n<h2>Craft Configuration</h2>\r\n<p>Now with the Remix configuration in place, I just needed to make two small changes to Craft to get it working correctly. First, I had to update the preview target for my Blog section to point to my Remix site:</p>\r\n<figure><img src=\"{asset:2283:url||//assets.trevor-davis.com/uploads/images/content/blog-section-preview-target.png}\" data-image=\"2283\" alt=\"Setting the preview target in my Blog Section\"></figure>\r\n<p>Then, I had to update the <code>config/general.php</code> to allow iframe requests from my Remix domain:</p>\r\n<script src=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e.js?file=general.php\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e#file-general-php\">View Gist</a></noscript>\r\n\r\n<h2>Voilà, Live Preview</h2>\r\n<p>And just like that, I had live preview working.</p>\r\n<video src=\"//assets.trevor-davis.com/uploads/images/content/live-preview.mp4\" autoplay=\"\" loop=\"\" muted=\"\" controls=\"\" width=\"100%\"></video>',NULL,0,NULL,'2022-04-20 15:18:51','2022-04-20 15:18:51','6f188f15-c4e2-4896-8f97-3043ed80efa3',1,NULL,NULL,56,NULL),(1691,2323,'Setting Up Live Preview with Craft CMS in Headless Mode',NULL,'<p>In my <a href=\"https://www.trevor-davis.com/blog/why-im-so-excited-about-remix\">previous post</a>, I talked about transitioning my site from being powered by <a href=\"https://craftcms.com/\">Craft</a> to being powered by <a href=\"https://remix.run/\">Remix</a> and a GraphQL endpoint coming from Craft. One of the best features of Craft is <a href=\"https://craftcms.com/features/all#live-preview\">Live Preview</a>, and it took a little configuration to get this working on my new Remix powered site.</p>\r\n<h2>Remix Configuration</h2>\r\n<p>These were specific changes that I needed to make on the Remix side, but really it would be the same for any GraphQL request. As Andrew Welch breaks down in <a href=\"https://nystudio107.com/blog/headless-preview-in-craft-cms\">his article</a>, the key is passing the token parameter back that Craft included in the URL.</p>\r\n<p>In the loader function of my blog post route, I call a helper function to setup the GraphQL client, and I pass the request to it:</p>\r\n<script src=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e.js?file=$slug.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e#file-slug-jsx\">View Gist</a></noscript>\r\n<p>And then in my helper function, I take that request, grab the URL params that I want to include, and add those to my GraphQL request endpoint URL:</p>\r\n<script src=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e.js?file=graphql.server.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e#file-graphql-server-jsx\">View Gist</a></noscript>\r\n<p>It wasn’t totally necessary to include the <code>x-craft-preview</code> and <code>x-craft-live-preview</code> parameters, but I figured it couldn’t hurt.</p>\r\n<h2>Craft Configuration</h2>\r\n<p>Now with the Remix configuration in place, I just needed to make two small changes to Craft to get it working correctly. First, I had to update the preview target for my Blog section to point to my Remix site:</p>\r\n<figure><img src=\"{asset:2283:url||//assets.trevor-davis.com/uploads/images/content/blog-section-preview-target.png}\" data-image=\"2283\" alt=\"Setting the preview target in my Blog Section\"></figure>\r\n<p>Then, I had to update the <code>config/general.php</code> to allow iframe requests from my Remix domain:</p>\r\n<script src=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e.js?file=general.php\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e#file-general-php\">View Gist</a></noscript>\r\n\r\n<h2>Voilà, Live Preview</h2>\r\n<p>And just like that, I had live preview working.</p>\r\n<video src=\"//assets.trevor-davis.com/uploads/images/content/live-preview.mp4\" autoplay=\"\" loop=\"\" muted=\"\" controls=\"\" width=\"100%\"></video>',NULL,0,NULL,'2022-04-20 15:19:22','2022-04-20 15:19:22','5305a439-6f28-4405-bd5f-7c0e16a0cc97',1,NULL,NULL,57,NULL),(1692,2324,'Setting Up Live Preview with Craft CMS in Headless Mode',NULL,'<p>In my <a href=\"https://www.trevor-davis.com/blog/why-im-so-excited-about-remix\">previous post</a>, I talked about transitioning my site from being powered by <a href=\"https://craftcms.com/\">Craft</a> to being powered by <a href=\"https://remix.run/\">Remix</a> and a GraphQL endpoint coming from Craft. One of the best features of Craft is <a href=\"https://craftcms.com/features/all#live-preview\">Live Preview</a>, and it took a little configuration to get this working on my new Remix powered site.</p>\r\n<h2>Remix Configuration</h2>\r\n<p>These were specific changes that I needed to make on the Remix side, but really it would be the same for any GraphQL request. As Andrew Welch breaks down in <a href=\"https://nystudio107.com/blog/headless-preview-in-craft-cms\">his article</a>, the key is passing the token parameter back that Craft included in the URL.</p>\r\n<p>In the loader function of my blog post route, I call a helper function to setup the GraphQL client, and I pass the request to it:</p>\r\n<script src=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e.js?file=$slug.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e#file-slug-jsx\">View Gist</a></noscript>\r\n<p>And then in my helper function, I take that request, grab the URL params that I want to include, and add those to my GraphQL request endpoint URL:</p>\r\n<script src=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e.js?file=graphql.server.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e#file-graphql-server-jsx\">View Gist</a></noscript>\r\n<p>It wasn’t totally necessary to include the <code>x-craft-preview</code> and <code>x-craft-live-preview</code> parameters, but I figured it couldn’t hurt.</p>\r\n<h2>Craft Configuration</h2>\r\n<p>Now with the Remix configuration in place, I just needed to make two small changes to Craft to get it working correctly. First, I had to update the preview target for my Blog section to point to my Remix site:</p>\r\n<figure><img src=\"{asset:2283:url||//assets.trevor-davis.com/uploads/images/content/blog-section-preview-target.png}\" data-image=\"2283\" alt=\"Setting the preview target in my Blog Section\"></figure>\r\n<p>Then, I had to update the <code>config/general.php</code> to allow iframe requests from my Remix domain:</p>\r\n<script src=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e.js?file=general.php\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e#file-general-php\">View Gist</a></noscript>\r\n\r\n<h2>Voilà, Live Preview</h2>\r\n<p>And just like that, I had live preview working.</p>\r\n<video src=\"//assets.trevor-davis.com/uploads/images/content/live-preview.mp4\" autoplay=\"\" loop=\"\" muted=\"\" controls=\"\" width=\"100%\"></video>',NULL,0,NULL,'2022-04-20 15:19:38','2022-04-20 15:19:38','d7bf8c9a-0271-4657-9d7c-5d0ffbf1a3dc',1,NULL,NULL,56,NULL),(1693,2325,'Setting Up Live Preview with Craft CMS in Headless Mode',NULL,'<p>In my <a href=\"https://www.trevor-davis.com/blog/why-im-so-excited-about-remix\">previous post</a>, I talked about transitioning my site from being powered by <a href=\"https://craftcms.com/\">Craft</a> to being powered by <a href=\"https://remix.run/\">Remix</a> and a GraphQL endpoint coming from Craft. One of the best features of Craft is <a href=\"https://craftcms.com/features/all#live-preview\">Live Preview</a>, and it took a little configuration to get this working on my new Remix powered site.</p>\r\n<h2>Remix Configuration</h2>\r\n<p>These were specific changes that I needed to make on the Remix side, but really it would be the same for any GraphQL request. As Andrew Welch breaks down in <a href=\"https://nystudio107.com/blog/headless-preview-in-craft-cms\">his article</a>, the key is passing the token parameter back that Craft included in the URL.</p>\r\n<p>In the loader function of my blog post route, I call a helper function to setup the GraphQL client, and I pass the request to it:</p>\r\n<script src=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e.js?file=$slug.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e#file-slug-jsx\">View Gist</a></noscript>\r\n<p>And then in my helper function, I take that request, grab the URL params that I want to include, and add those to my GraphQL request endpoint URL:</p>\r\n<script src=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e.js?file=graphql.server.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e#file-graphql-server-jsx\">View Gist</a></noscript>\r\n<p>It wasn’t totally necessary to include the <code>x-craft-preview</code> and <code>x-craft-live-preview</code> parameters, but I figured it couldn’t hurt.</p>\r\n<h2>Craft Configuration</h2>\r\n<p>Now with the Remix configuration in place, I just needed to make two small changes to Craft to get it working correctly. First, I had to update the preview target for my Blog section to point to my Remix site:</p>\r\n<figure><img src=\"{asset:2283:url||//assets.trevor-davis.com/uploads/images/content/blog-section-preview-target.png}\" data-image=\"2283\" alt=\"Setting the preview target in my Blog Section\"></figure>\r\n<p>Then, I had to update the <code>config/general.php</code> to allow iframe requests from my Remix domain:</p>\r\n<script src=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e.js?file=general.php\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e#file-general-php\">View Gist</a></noscript>\r\n\r\n<h2>Voilà, Live Preview</h2>\r\n<p>And just like that, I had live preview working.</p>\r\n<video src=\"//assets.trevor-davis.com/uploads/images/content/live-preview.mp4\" autoplay=\"\" loop=\"\" muted=\"\" controls=\"\" width=\"100%\"></video>',NULL,0,NULL,'2022-04-20 15:20:00','2022-04-20 15:20:00','692d0ae1-9081-4968-a71e-1d48eabef870',1,NULL,NULL,57,NULL),(1694,2326,'Setting Up Live Preview with Craft CMS in Headless Mode',NULL,'<p>In my <a href=\"https://www.trevor-davis.com/blog/why-im-so-excited-about-remix\">previous post</a>, I talked about transitioning my site from being powered by <a href=\"https://craftcms.com/\">Craft</a> to being powered by <a href=\"https://remix.run/\">Remix</a> and a GraphQL endpoint coming from Craft. One of the best features of Craft is <a href=\"https://craftcms.com/features/all#live-preview\">Live Preview</a>, and it took a little configuration to get this working on my new Remix powered site.</p>\r\n<h2>Remix Configuration</h2>\r\n<p>These were specific changes that I needed to make on the Remix side, but really it would be the same for any GraphQL request. As Andrew Welch breaks down in <a href=\"https://nystudio107.com/blog/headless-preview-in-craft-cms\">his article</a>, the key is passing the token parameter back that Craft included in the URL.</p>\r\n<p>In the loader function of my blog post route, I call a helper function to setup the GraphQL client, and I pass the request to it:</p>\r\n<script src=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e.js?file=$slug.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e#file-slug-jsx\">View Gist</a></noscript>\r\n<p>And then in my helper function, I take that request, grab the URL params that I want to include, and add those to my GraphQL request endpoint URL:</p>\r\n<script src=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e.js?file=graphql.server.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e#file-graphql-server-jsx\">View Gist</a></noscript>\r\n<p>It wasn’t totally necessary to include the <code>x-craft-preview</code> and <code>x-craft-live-preview</code> parameters, but I figured it couldn’t hurt.</p>\r\n<h2>Craft Configuration</h2>\r\n<p>Now with the Remix configuration in place, I just needed to make two small changes to Craft to get it working correctly. First, I had to update the preview target for my Blog section to point to my Remix site:</p>\r\n<figure><img src=\"{asset:2283:url||//assets.trevor-davis.com/uploads/images/content/blog-section-preview-target.png}\" data-image=\"2283\" alt=\"Setting the preview target in my Blog Section\"></figure>\r\n<p>Then, I had to update the <code>config/general.php</code> to allow iframe requests from my Remix domain:</p>\r\n<script src=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e.js?file=general.php\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e#file-general-php\">View Gist</a></noscript>\r\n\r\n<h2>Voilà, Live Preview</h2>\r\n<p>And just like that, I had live preview working.</p>\r\n<video src=\"//assets.trevor-davis.com/uploads/images/content/live-preview.mp4\" autoplay=\"\" loop=\"\" muted=\"\" controls=\"\" width=\"100%\"></video>',NULL,0,NULL,'2022-04-20 15:20:21','2022-04-20 15:20:21','d1a116b7-f4a3-4fcf-971e-b70c1c6745b2',1,NULL,NULL,56,NULL),(1695,2327,'Setting Up Live Preview with Craft CMS in Headless Mode',NULL,'<p>In my <a href=\"https://www.trevor-davis.com/blog/why-im-so-excited-about-remix\">previous post</a>, I talked about transitioning my site from being powered by <a href=\"https://craftcms.com/\">Craft</a> to being powered by <a href=\"https://remix.run/\">Remix</a> and a GraphQL endpoint coming from Craft. One of the best features of Craft is <a href=\"https://craftcms.com/features/all#live-preview\">Live Preview</a>, and it took a little configuration to get this working on my new Remix powered site.</p>\r\n<h2>Remix Configuration</h2>\r\n<p>These were specific changes that I needed to make on the Remix side, but really it would be the same for any GraphQL request. As Andrew Welch breaks down in <a href=\"https://nystudio107.com/blog/headless-preview-in-craft-cms\">his article</a>, the key is passing the token parameter back that Craft included in the URL.</p>\r\n<p>In the loader function of my blog post route, I call a helper function to setup the GraphQL client, and I pass the request to it:</p>\r\n<script src=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e.js?file=$slug.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e#file-slug-jsx\">View Gist</a></noscript>\r\n<p>And then in my helper function, I take that request, grab the URL params that I want to include, and add those to my GraphQL request endpoint URL:</p>\r\n<script src=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e.js?file=graphql.server.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e#file-graphql-server-jsx\">View Gist</a></noscript>\r\n<p>It wasn’t totally necessary to include the <code>x-craft-preview</code> and <code>x-craft-live-preview</code> parameters, but I figured it couldn’t hurt.</p>\r\n<h2>Craft Configuration</h2>\r\n<p>Now with the Remix configuration in place, I just needed to make two small changes to Craft to get it working correctly. First, I had to update the preview target for my Blog section to point to my Remix site:</p>\r\n<figure><img src=\"{asset:2283:url||//assets.trevor-davis.com/uploads/images/content/blog-section-preview-target.png}\" data-image=\"2283\" alt=\"Setting the preview target in my Blog Section\"></figure>\r\n<p>Then, I had to update the <code>config/general.php</code> to allow iframe requests from my Remix domain:</p>\r\n<script src=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e.js?file=general.php\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e#file-general-php\">View Gist</a></noscript>\r\n\r\n<h2>Voilà, Live Preview</h2>\r\n<p>And just like that, I had live preview working.</p>\r\n<video src=\"//assets.trevor-davis.com/uploads/images/content/live-preview.mp4\" autoplay=\"\" loop=\"\" muted=\"\" controls=\"\" width=\"100%\"></video>',NULL,0,NULL,'2022-04-20 15:21:03','2022-04-20 15:21:03','3e185e88-a0a1-4e33-8cec-3aa2e6110180',1,NULL,NULL,57,NULL),(1696,2328,'Setting Up Live Preview with Craft CMS in Headless Mode',NULL,'<p>In my <a href=\"https://www.trevor-davis.com/blog/why-im-so-excited-about-remix\">previous post</a>, I talked about transitioning my site from being powered by <a href=\"https://craftcms.com/\">Craft</a> to being powered by <a href=\"https://remix.run/\">Remix</a> and a GraphQL endpoint coming from Craft. One of the best features of Craft is <a href=\"https://craftcms.com/features/all#live-preview\">Live Preview</a>, and it took a little configuration to get this working on my new Remix powered site.</p>\r\n<h2>Remix Configuration</h2>\r\n<p>These were specific changes that I needed to make on the Remix side, but really it would be the same for any GraphQL request. As Andrew Welch breaks down in <a href=\"https://nystudio107.com/blog/headless-preview-in-craft-cms\">his article</a>, the key is passing the token parameter back that Craft included in the URL.</p>\r\n<p>In the loader function of my blog post route, I call a helper function to setup the GraphQL client, and I pass the request to it:</p>\r\n<script src=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e.js?file=$slug.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e#file-slug-jsx\">View Gist</a></noscript>\r\n<p>And then in my helper function, I take that request, grab the URL params that I want to include, and add those to my GraphQL request endpoint URL:</p>\r\n<script src=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e.js?file=graphql.server.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e#file-graphql-server-jsx\">View Gist</a></noscript>\r\n<p>It wasn’t totally necessary to include the <code>x-craft-preview</code> and <code>x-craft-live-preview</code> parameters, but I figured it couldn’t hurt.</p>\r\n<h2>Craft Configuration</h2>\r\n<p>Now with the Remix configuration in place, I just needed to make two small changes to Craft to get it working correctly. First, I had to update the preview target for my Blog section to point to my Remix site:</p>\r\n<figure><img src=\"{asset:2283:url||//assets.trevor-davis.com/uploads/images/content/blog-section-preview-target.png}\" data-image=\"2283\" alt=\"Setting the preview target in my Blog Section\"></figure>\r\n<p>Then, I had to update the <code>config/general.php</code> to allow iframe requests from my Remix domain:</p>\r\n<script src=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e.js?file=general.php\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e#file-general-php\">View Gist</a></noscript>\r\n\r\n<h2>Voilà, Live Preview</h2>\r\n<p>And just like that, I had live preview working.</p>\r\n<video src=\"//assets.trevor-davis.com/uploads/images/content/live-preview.mp4\" autoplay=\"\" loop=\"\" muted=\"\" controls=\"\" width=\"100%\"></video>',NULL,0,NULL,'2022-04-20 15:21:08','2022-04-20 15:21:08','226b11e2-5e29-411a-872c-924ecc79c1ca',1,NULL,NULL,56,NULL),(1697,2329,'Setting Up Live Preview with Craft CMS in Headless Mode',NULL,'<p>In my <a href=\"https://www.trevor-davis.com/blog/why-im-so-excited-about-remix\">previous post</a>, I talked about transitioning my site from being powered by <a href=\"https://craftcms.com/\">Craft</a> to being powered by <a href=\"https://remix.run/\">Remix</a> and a GraphQL endpoint coming from Craft. One of the best features of Craft is <a href=\"https://craftcms.com/features/all#live-preview\">Live Preview</a>, and it took a little configuration to get this working on my new Remix powered site.</p>\r\n<h2>Remix Configuration</h2>\r\n<p>These were specific changes that I needed to make on the Remix side, but really it would be the same for any GraphQL request. As Andrew Welch breaks down in <a href=\"https://nystudio107.com/blog/headless-preview-in-craft-cms\">his article</a>, the key is passing the token parameter back that Craft included in the URL.</p>\r\n<p>In the loader function of my blog post route, I call a helper function to setup the GraphQL client, and I pass the request to it:</p>\r\n<script src=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e.js?file=$slug.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e#file-slug-jsx\">View Gist</a></noscript>\r\n<p>And then in my helper function, I take that request, grab the URL params that I want to include, and add those to my GraphQL request endpoint URL:</p>\r\n<script src=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e.js?file=graphql.server.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e#file-graphql-server-jsx\">View Gist</a></noscript>\r\n<p>It wasn’t totally necessary to include the <code>x-craft-preview</code> and <code>x-craft-live-preview</code> parameters, but I figured it couldn’t hurt.</p>\r\n<h2>Craft Configuration</h2>\r\n<p>Now with the Remix configuration in place, I just needed to make two small changes to Craft to get it working correctly. First, I had to update the preview target for my Blog section to point to my Remix site:</p>\r\n<figure><img src=\"{asset:2283:url||//assets.trevor-davis.com/uploads/images/content/blog-section-preview-target.png}\" data-image=\"2283\" alt=\"Setting the preview target in my Blog Section\"></figure>\r\n<p>Then, I had to update the <code>config/general.php</code> to allow iframe requests from my Remix domain:</p>\r\n<script src=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e.js?file=general.php\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e#file-general-php\">View Gist</a></noscript>\r\n\r\n<h2>Voilà, Live Preview</h2>\r\n<p>And just like that, I had live preview working.</p>\r\n<video src=\"//assets.trevor-davis.com/uploads/images/content/live-preview.mp4\" autoplay=\"\" loop=\"\" muted=\"\" controls=\"\" width=\"100%\"></video>',NULL,0,NULL,'2022-04-20 15:22:18','2022-04-20 15:22:18','9d8b2f1b-b23f-4c67-b76c-67a1c30fab37',1,NULL,NULL,57,NULL),(1698,2330,'Setting Up Live Preview with Craft CMS in Headless Mode',NULL,'<p>In my <a href=\"https://www.trevor-davis.com/blog/why-im-so-excited-about-remix\">previous post</a>, I talked about transitioning my site from being powered by <a href=\"https://craftcms.com/\">Craft</a> to being powered by <a href=\"https://remix.run/\">Remix</a> and a GraphQL endpoint coming from Craft. One of the best features of Craft is <a href=\"https://craftcms.com/features/all#live-preview\">Live Preview</a>, and it took a little configuration to get this working on my new Remix powered site.</p>\r\n<h2>Remix Configuration</h2>\r\n<p>These were specific changes that I needed to make on the Remix side, but really it would be the same for any GraphQL request. As Andrew Welch breaks down in <a href=\"https://nystudio107.com/blog/headless-preview-in-craft-cms\">his article</a>, the key is passing the token parameter back that Craft included in the URL.</p>\r\n<p>In the loader function of my blog post route, I call a helper function to setup the GraphQL client, and I pass the request to it:</p>\r\n<script src=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e.js?file=$slug.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e#file-slug-jsx\">View Gist</a></noscript>\r\n<p>And then in my helper function, I take that request, grab the URL params that I want to include, and add those to my GraphQL request endpoint URL:</p>\r\n<script src=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e.js?file=graphql.server.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e#file-graphql-server-jsx\">View Gist</a></noscript>\r\n<p>It wasn’t totally necessary to include the <code>x-craft-preview</code> and <code>x-craft-live-preview</code> parameters, but I figured it couldn’t hurt.</p>\r\n<h2>Craft Configuration</h2>\r\n<p>Now with the Remix configuration in place, I just needed to make two small changes to Craft to get it working correctly. First, I had to update the preview target for my Blog section to point to my Remix site:</p>\r\n<figure><img src=\"{asset:2283:url||//assets.trevor-davis.com/uploads/images/content/blog-section-preview-target.png}\" data-image=\"2283\" alt=\"Setting the preview target in my Blog Section\"></figure>\r\n<p>Then, I had to update the <code>config/general.php</code> to allow iframe requests from my Remix domain:</p>\r\n<script src=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e.js?file=general.php\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e#file-general-php\">View Gist</a></noscript>\r\n\r\n<h2>Voilà, Live Preview</h2>\r\n<p>And just like that, I had live preview working.</p>\r\n<video src=\"//assets.trevor-davis.com/uploads/images/content/live-preview.mp4\" autoplay=\"\" loop=\"\" muted=\"\" controls=\"\" width=\"100%\"></video>',NULL,0,NULL,'2022-04-20 15:22:27','2022-04-20 15:22:27','9bf2e839-1b36-4033-a76f-a5211c0c0099',1,NULL,NULL,56,NULL),(1699,2331,'Setting Up Live Preview with Craft CMS in Headless Mode',NULL,'<p>In my <a href=\"https://www.trevor-davis.com/blog/why-im-so-excited-about-remix\">previous post</a>, I talked about transitioning my site from being powered by <a href=\"https://craftcms.com/\">Craft</a> to being powered by <a href=\"https://remix.run/\">Remix</a> and a GraphQL endpoint coming from Craft. One of the best features of Craft is <a href=\"https://craftcms.com/features/all#live-preview\">Live Preview</a>, and it took a little configuration to get this working on my new Remix powered site.</p>\r\n<h2>Remix Configuration</h2>\r\n<p>These were specific changes that I needed to make on the Remix side, but really it would be the same for any GraphQL request. As Andrew Welch breaks down in <a href=\"https://nystudio107.com/blog/headless-preview-in-craft-cms\">his article</a>, the key is passing the token parameter back that Craft included in the URL.</p>\r\n<p>In the loader function of my blog post route, I call a helper function to setup the GraphQL client, and I pass the request to it:</p>\r\n<script src=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e.js?file=$slug.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e#file-slug-jsx\">View Gist</a></noscript>\r\n<p>And then in my helper function, I take that request, grab the URL params that I want to include, and add those to my GraphQL request endpoint URL:</p>\r\n<script src=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e.js?file=graphql.server.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e#file-graphql-server-jsx\">View Gist</a></noscript>\r\n<p>It wasn’t totally necessary to include the <code>x-craft-preview</code> and <code>x-craft-live-preview</code> parameters, but I figured it couldn’t hurt.</p>\r\n<h2>Craft Configuration</h2>\r\n<p>Now with the Remix configuration in place, I just needed to make two small changes to Craft to get it working correctly. First, I had to update the preview target for my Blog section to point to my Remix site:</p>\r\n<figure><img src=\"{asset:2283:url||//assets.trevor-davis.com/uploads/images/content/blog-section-preview-target.png}\" data-image=\"2283\" alt=\"Setting the preview target in my Blog Section\"></figure>\r\n<p>Then, I had to update the <code>config/general.php</code> to allow iframe requests from my Remix domain:</p>\r\n<script src=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e.js?file=general.php\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e#file-general-php\">View Gist</a></noscript>\r\n\r\n<h2>Voilà, Live Preview</h2>\r\n<p>And just like that, I had live preview working.</p>\r\n<video src=\"//assets.trevor-davis.com/uploads/images/content/live-preview.mp4\" autoplay=\"\" loop=\"\" muted=\"\" controls=\"\" width=\"100%\"></video>',NULL,0,NULL,'2022-04-20 15:22:40','2022-04-20 15:22:40','67e5dc24-56e8-4fec-9b93-33e102f74dd5',1,NULL,NULL,57,NULL),(1700,2332,'Setting Up Live Preview with Craft CMS in Headless Mode',NULL,'<p>In my <a href=\"https://www.trevor-davis.com/blog/why-im-so-excited-about-remix\">previous post</a>, I talked about transitioning my site from being powered by <a href=\"https://craftcms.com/\">Craft</a> to being powered by <a href=\"https://remix.run/\">Remix</a> and a GraphQL endpoint coming from Craft. One of the best features of Craft is <a href=\"https://craftcms.com/features/all#live-preview\">Live Preview</a>, and it took a little configuration to get this working on my new Remix powered site.</p>\r\n<h2>Remix Configuration</h2>\r\n<p>These were specific changes that I needed to make on the Remix side, but really it would be the same for any GraphQL request. As Andrew Welch breaks down in <a href=\"https://nystudio107.com/blog/headless-preview-in-craft-cms\">his article</a>, the key is passing the token parameter back that Craft included in the URL.</p>\r\n<p>In the loader function of my blog post route, I call a helper function to setup the GraphQL client, and I pass the request to it:</p>\r\n<script src=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e.js?file=$slug.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e#file-slug-jsx\">View Gist</a></noscript>\r\n<p>And then in my helper function, I take that request, grab the URL params that I want to include, and add those to my GraphQL request endpoint URL:</p>\r\n<script src=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e.js?file=graphql.server.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e#file-graphql-server-jsx\">View Gist</a></noscript>\r\n<p>It wasn’t totally necessary to include the <code>x-craft-preview</code> and <code>x-craft-live-preview</code> parameters, but I figured it couldn’t hurt.</p>\r\n<h2>Craft Configuration</h2>\r\n<p>Now with the Remix configuration in place, I just needed to make two small changes to Craft to get it working correctly. First, I had to update the preview target for my Blog section to point to my Remix site:</p>\r\n<figure><img src=\"{asset:2283:url||//assets.trevor-davis.com/uploads/images/content/blog-section-preview-target.png}\" data-image=\"2283\" alt=\"Setting the preview target in my Blog Section\"></figure>\r\n<p>Then, I had to update the <code>config/general.php</code> to allow iframe requests from my Remix domain:</p>\r\n<script src=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e.js?file=general.php\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e#file-general-php\">View Gist</a></noscript>\r\n\r\n<h2>Voilà, Live Preview</h2>\r\n<p>And just like that, I had live preview working.</p>\r\n<video src=\"//assets.trevor-davis.com/uploads/images/content/live-preview.mp4\" autoplay=\"\" loop=\"\" muted=\"\" controls=\"\" width=\"100%\"></video>',NULL,0,NULL,'2022-04-20 15:22:46','2022-04-20 15:22:46','15aee0bf-ec8c-40a6-a248-0fdfe8d9cbe3',1,NULL,NULL,58,NULL),(1701,2333,'Setting Up Live Preview with Craft CMS in Headless Mode',NULL,'<p>In my <a href=\"https://www.trevor-davis.com/blog/why-im-so-excited-about-remix\">previous post</a>, I talked about transitioning my site from being powered by <a href=\"https://craftcms.com/\">Craft</a> to being powered by <a href=\"https://remix.run/\">Remix</a> and a GraphQL endpoint coming from Craft. One of the best features of Craft is <a href=\"https://craftcms.com/features/all#live-preview\">Live Preview</a>, and it took a little configuration to get this working on my new Remix powered site.</p>\r\n<h2>Remix Configuration</h2>\r\n<p>These were specific changes that I needed to make on the Remix side, but really it would be the same for any GraphQL request. As Andrew Welch breaks down in <a href=\"https://nystudio107.com/blog/headless-preview-in-craft-cms\">his article</a>, the key is passing the token parameter back that Craft included in the URL.</p>\r\n<p>In the loader function of my blog post route, I call a helper function to setup the GraphQL client, and I pass the request to it:</p>\r\n<script src=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e.js?file=$slug.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e#file-slug-jsx\">View Gist</a></noscript>\r\n<p>And then in my helper function, I take that request, grab the URL params that I want to include, and add those to my GraphQL request endpoint URL:</p>\r\n<script src=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e.js?file=graphql.server.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e#file-graphql-server-jsx\">View Gist</a></noscript>\r\n<p>It wasn’t totally necessary to include the <code>x-craft-preview</code> and <code>x-craft-live-preview</code> parameters, but I figured it couldn’t hurt.</p>\r\n<h2>Craft Configuration</h2>\r\n<p>Now with the Remix configuration in place, I just needed to make two small changes to Craft to get it working correctly. First, I had to update the preview target for my Blog section to point to my Remix site:</p>\r\n<figure><img src=\"{asset:2283:url||//assets.trevor-davis.com/uploads/images/content/blog-section-preview-target.png}\" data-image=\"2283\" alt=\"Setting the preview target in my Blog Section\"></figure>\r\n<p>Then, I had to update the <code>config/general.php</code> to allow iframe requests from my Remix domain:</p>\r\n<script src=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e.js?file=general.php\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e#file-general-php\">View Gist</a></noscript>\r\n\r\n<h2>Voilà, Live Preview</h2>\r\n<p>And just like that, I had live preview working.</p>\r\n<video src=\"//assets.trevor-davis.com/uploads/images/content/live-preview.mp4\" autoplay=\"\" loop=\"\" muted=\"\" controls=\"\" width=\"100%\"></video>',NULL,0,NULL,'2022-04-20 19:08:30','2022-04-20 19:08:30','db07dba2-075e-496c-bb5f-2524cbd49c05',1,NULL,NULL,57,NULL),(1702,2334,'Setting Up Live Preview with Craft CMS in Headless Mode',NULL,'<p>In my <a href=\"https://www.trevor-davis.com/blog/why-im-so-excited-about-remix\">previous post</a>, I talked about transitioning my site from being powered by <a href=\"https://craftcms.com/\">Craft</a> to being powered by <a href=\"https://remix.run/\">Remix</a> and a GraphQL endpoint coming from Craft. One of the best features of Craft is <a href=\"https://craftcms.com/features/all#live-preview\">Live Preview</a>, and it took a little configuration to get this working on my new Remix powered site.</p>\r\n<h2>Remix Configuration</h2>\r\n<p>These were specific changes that I needed to make on the Remix side, but really it would be the same for any GraphQL request. As Andrew Welch breaks down in <a href=\"https://nystudio107.com/blog/headless-preview-in-craft-cms\">his article</a>, the key is passing the token parameter back that Craft included in the URL.</p>\r\n<p>In the loader function of my blog post route, I call a helper function to setup the GraphQL client, and I pass the request to it:</p>\r\n<script src=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e.js?file=$slug.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e#file-slug-jsx\">View Gist</a></noscript>\r\n<p>And then in my helper function, I take that request, grab the URL params that I want to include, and add those to my GraphQL request endpoint URL:</p>\r\n<script src=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e.js?file=graphql.server.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e#file-graphql-server-jsx\">View Gist</a></noscript>\r\n<p>It wasn’t totally necessary to include the <code>x-craft-preview</code> and <code>x-craft-live-preview</code> parameters, but I figured it couldn’t hurt.</p>\r\n<h2>Craft Configuration</h2>\r\n<p>Now with the Remix configuration in place, I just needed to make two small changes to Craft to get it working correctly. First, I had to update the preview target for my Blog section to point to my Remix site:</p>\r\n<figure><img src=\"{asset:2283:url||//assets.trevor-davis.com/uploads/images/content/blog-section-preview-target.png}\" data-image=\"2283\" alt=\"Setting the preview target in my Blog Section\"></figure>\r\n<p>Then, I had to update the <code>config/general.php</code> to allow iframe requests from my Remix domain:</p>\r\n<script src=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e.js?file=general.php\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e#file-general-php\">View Gist</a></noscript>\r\n\r\n<h2>Voilà, Live Preview</h2>\r\n<p>And just like that, I had live preview working.</p>\r\n<video src=\"//assets.trevor-davis.com/uploads/images/content/live-preview.mp4\" autoplay=\"\" loop=\"\" muted=\"\" controls=\"\" width=\"100%\"></video>',NULL,0,NULL,'2022-04-20 19:08:37','2022-04-20 19:08:37','3c39fee4-5d4f-4496-a745-f65bb327ca64',1,NULL,NULL,58,NULL),(1703,2335,'Setting Up Live Preview with Craft CMS in Headless Mode',NULL,'<p>In my <a href=\"https://www.trevor-davis.com/blog/why-im-so-excited-about-remix\">previous post</a>, I talked about transitioning my site from being powered by <a href=\"https://craftcms.com/\">Craft</a> to being powered by <a href=\"https://remix.run/\">Remix</a> and a GraphQL endpoint coming from Craft. One of the best features of Craft is <a href=\"https://craftcms.com/features/all#live-preview\">Live Preview</a>, and it took a little configuration to get this working on my new Remix powered site.</p>\r\n<h2>Remix Configuration</h2>\r\n<p>These were specific changes that I needed to make on the Remix side, but really it would be the same for any GraphQL request. As Andrew Welch breaks down in <a href=\"https://nystudio107.com/blog/headless-preview-in-craft-cms\">his article</a>, the key is passing the token parameter back that Craft included in the URL.</p>\r\n<p>In the loader function of my blog post route, I call a helper function to setup the GraphQL client, and I pass the request to it:</p>\r\n<script src=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e.js?file=$slug.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e#file-slug-jsx\">View Gist</a></noscript>\r\n<p>And then in my helper function, I take that request, grab the URL params that I want to include, and add those to my GraphQL request endpoint URL:</p>\r\n<script src=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e.js?file=graphql.server.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e#file-graphql-server-jsx\">View Gist</a></noscript>\r\n<p>It wasn’t totally necessary to include the <code>x-craft-preview</code> and <code>x-craft-live-preview</code> parameters, but I figured it couldn’t hurt.</p>\r\n<h2>Craft Configuration</h2>\r\n<p>Now with the Remix configuration in place, I just needed to make two small changes to Craft to get it working correctly. First, I had to update the preview target for my Blog section to point to my Remix site:</p>\r\n<figure><img src=\"{asset:2283:url||//assets.trevor-davis.com/uploads/images/content/blog-section-preview-target.png}\" data-image=\"2283\" alt=\"Setting the preview target in my Blog Section\"></figure>\r\n<p>Then, I had to update the <code>config/general.php</code> to allow iframe requests from my Remix domain:</p>\r\n<script src=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e.js?file=general.php\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e#file-general-php\">View Gist</a></noscript>\r\n\r\n<h2>Voilà, Live Preview</h2>\r\n<p>And just like that, I had live preview working.</p>\r\n<video src=\"//assets.trevor-davis.com/uploads/images/content/live-preview.mp4\" autoplay=\"\" loop=\"\" muted=\"\" controls=\"\" width=\"100%\"></video>',NULL,0,NULL,'2022-04-20 19:08:43','2022-04-20 19:08:43','2013c8b8-8475-4e25-8a34-96d046b8c71e',1,NULL,NULL,59,NULL),(1704,2336,'Setting Up Live Preview with Craft CMS in Headless Mode',NULL,'<p>In my <a href=\"https://www.trevor-davis.com/blog/why-im-so-excited-about-remix\">previous post</a>, I talked about transitioning my site from being powered by <a href=\"https://craftcms.com/\">Craft</a> to being powered by <a href=\"https://remix.run/\">Remix</a> and a GraphQL endpoint coming from Craft. One of the best features of Craft is <a href=\"https://craftcms.com/features/all#live-preview\">Live Preview</a>, and it took a little configuration to get this working on my new Remix powered site.</p>\r\n<h2>Remix Configuration</h2>\r\n<p>These were specific changes that I needed to make on the Remix side, but really it would be the same for any GraphQL request. As Andrew Welch breaks down in <a href=\"https://nystudio107.com/blog/headless-preview-in-craft-cms\">his article</a>, the key is passing the token parameter back that Craft included in the URL.</p>\r\n<p>In the loader function of my blog post route, I call a helper function to setup the GraphQL client, and I pass the request to it:</p>\r\n<script src=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e.js?file=$slug.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e#file-slug-jsx\">View Gist</a></noscript>\r\n<p>And then in my helper function, I take that request, grab the URL params that I want to include, and add those to my GraphQL request endpoint URL:</p>\r\n<script src=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e.js?file=graphql.server.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e#file-graphql-server-jsx\">View Gist</a></noscript>\r\n<p>It wasn’t totally necessary to include the <code>x-craft-preview</code> and <code>x-craft-live-preview</code> parameters, but I figured it couldn’t hurt.</p>\r\n<h2>Craft Configuration</h2>\r\n<p>Now with the Remix configuration in place, I just needed to make two small changes to Craft to get it working correctly. First, I had to update the preview target for my Blog section to point to my Remix site:</p>\r\n<figure><img src=\"{asset:2283:url||//assets.trevor-davis.com/uploads/images/content/blog-section-preview-target.png}\" data-image=\"2283\" alt=\"Setting the preview target in my Blog Section\"></figure>\r\n<p>Then, I had to update the <code>config/general.php</code> to allow iframe requests from my Remix domain:</p>\r\n<script src=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e.js?file=general.php\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e#file-general-php\">View Gist</a></noscript>\r\n\r\n<h2>Voilà, Live Preview</h2>\r\n<p>And just like that, I had live preview working.</p>\r\n<video src=\"//assets.trevor-davis.com/uploads/images/content/live-preview.mp4\" autoplay=\"\" loop=\"\" muted=\"\" controls=\"\" width=\"100%\"></video>',NULL,0,NULL,'2022-04-20 19:08:53','2022-04-20 19:08:53','a34d2aa9-13b8-47bd-9215-26064dc92da1',1,NULL,NULL,60,NULL),(1716,2348,'Setting Up Live Preview with Craft CMS in Headless Mode',NULL,'<p>In my <a href=\"https://www.trevor-davis.com/blog/why-im-so-excited-about-remix\">previous post</a>, I talked about transitioning my site from being powered by <a href=\"https://craftcms.com/\">Craft</a> to being powered by <a href=\"https://remix.run/\">Remix</a> and a GraphQL endpoint coming from Craft. One of the best features of Craft is <a href=\"https://craftcms.com/features/all#live-preview\">Live Preview</a>, and it took a little configuration to get this working on my new Remix powered site.</p>\r\n<h2>Remix Configuration</h2>\r\n<p>These were specific changes that I needed to make on the Remix side, but really it would be the same for any GraphQL request. As Andrew Welch breaks down in <a href=\"https://nystudio107.com/blog/headless-preview-in-craft-cms\">his article</a>, the key is passing the token parameter back that Craft included in the URL.</p>\r\n<p>In the loader function of my blog post route, I call a helper function to setup the GraphQL client, and I pass the request to it:</p>\r\n<script src=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e.js?file=$slug.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e#file-slug-jsx\">View Gist</a></noscript>\r\n<p>And then in my helper function, I take that request, grab the URL params that I want to include, and add those to my GraphQL request endpoint URL:</p>\r\n<script src=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e.js?file=graphql.server.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e#file-graphql-server-jsx\">View Gist</a></noscript>\r\n<p>It wasn’t totally necessary to include the <code>x-craft-preview</code> and <code>x-craft-live-preview</code> parameters, but I figured it couldn’t hurt.</p>\r\n<h2>Craft Configuration</h2>\r\n<p>Now with the Remix configuration in place, I just needed to make two small changes to Craft to get it working correctly. First, I had to update the preview target for my Blog section to point to my Remix site:</p>\r\n<figure><img src=\"{asset:2283:url||//assets.trevor-davis.com/uploads/images/content/blog-section-preview-target.png}\" data-image=\"2283\" alt=\"Setting the preview target in my Blog Section\"></figure>\r\n<p>Then, I had to update the <code>config/general.php</code> to allow iframe requests from my Remix domain:</p>\r\n<script src=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e.js?file=general.php\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e#file-general-php\">View Gist</a></noscript>\r\n\r\n<h2>Voilà, Live Preview</h2>\r\n<p>And just like that, I had live preview working.</p>\r\n<video src=\"//assets.trevor-davis.com/uploads/images/content/live-preview.mp4\" autoplay=\"\" loop=\"\" muted=\"\" controls=\"\" width=\"100%\"></video>',NULL,0,NULL,'2022-04-20 20:00:37','2022-04-20 20:00:37','a3c2117e-8993-463f-b0dc-8a74a68e5f56',1,NULL,NULL,23,NULL),(1735,2367,'Why I’m So Excited About Remix',NULL,'<p>I’ve been building on the web for a long time. There’s a part of me that still has a bit of an old school mentality, and it’s hard for me to get really excited about new technology. Sure React was cool when it came out for its state management, but I didn’t see it as the be-all and end-all for building on the web. I really like <a href=\"https://craftcms.com/\">Craft CMS</a> for building CMS powered sites since I have full control over the HTML being sent to the browser, and it’s really easy to extend for complex functionality, but it can be a bit complex to setup for beginners and with additional complexity can come performance issues.&nbsp;So it’s been a while since I’ve seen something to be <em>really</em> excited about.</p>\r\n<p>Enter <a href=\"https://remix.run/\">Remix</a>.</p>\r\n<p>Remix is an interesting mix of old school techniques along with modern technology. Ryan Florence actually sums it up perfectly as to where Remix fits in.</p>\r\n<blockquote class=\"twitter-tweet\" data-dnt=\"true\" data-theme=\"dark\"><p lang=\"en\" dir=\"ltr\">Forget “full stack”. Remix is center stack.<br><br>It’s an HTTP tunnel between interactivity and business logic. It’s the part of the stack that no tool before it has solved, not completely.<br><br>I think I finally know how to talk about Remix.</p>— Ryan Florence (@ryanflorence) <a href=\"https://twitter.com/ryanflorence/status/1482233495195770883?ref_src=twsrc%5Etfw\">January 15, 2022</a></blockquote>\r\n<script async=\"\" src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\"></script>\r\n<p>I was able to easily switch my site that was fully powered by Craft to utilize Craft only as a GraphQL endpoint and Remix powering the rest. The two big things I needed to figure out were: how to get data from the GraphQL endpoint, and then how to process input from a user (for my contact form). I would definitely recommend reading through the Remix docs and the two tutorials, but if you can understand these two big pictures things, you’ll have enough to get started with Remix and go deeper once you get into it.</p>\r\n<h2>Getting GraphQL Data (aka Loaders)</h2>\r\n<p>Remix provides a <a href=\"https://remix.run/docs/en/v1/api/conventions#loader\">loader hook</a> that runs on the server to hydrate your component. In this simple example, I run a GraphQL request and return JSON with the results of that request in the loader function.</p>\r\n<script src=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550.js?file=loader.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550#file-loader-jsx\">View Gist</a></noscript>\r\n<p>Then in my <code>Index</code> component, I access the data from the loader hook with <a href=\"https://remix.run/docs/en/v1/api/remix#useloaderdata\">useLoaderData()</a>, and my component is now hydrated with that data. In MVC style of thinking, think of the loader hook as the controller processing the page load request, populating with data from the model, and then passing to the view.</p>\r\n<p>The great part about Remix is that this doesn’t have to be specifically a GraphQL request. This data can come from anywhere. The <a href=\"https://remix.run/docs/en/v1/tutorials/jokes\">Jokes tutorial</a> in the Remix docs even thoroughly walks through how you can manage all this data in <a href=\"https://www.prisma.io/\">Prisma</a>.</p>\r\n<h2>Processing User Input (aka Actions)</h2>\r\n<p>Ok great, so we’ve got data onto the page, but now we need to be able to handle user input. Remix also provides an <a href=\"https://remix.run/docs/en/v1/api/conventions#action\">action hook</a> to process an action request (ex: a form submission). In my case, I have a contact form that sends me an email via SendGrid after submission.</p>\r\n<script src=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550.js?file=action.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550#file-action-jsx\">View Gist</a></noscript>\r\n<p>If you don’t include an <code>action</code> attribute on your form, it will automatically submit to the same page. Again, in MVC thinking, the action would again be equivalent to the controller taking the request input and processing it. But honestly, this takes me back 15 years when form actions would point directly to PHP files.</p>\r\n<h2>Bonus: Progressive Enhancement</h2>\r\n<p>Since Remix is running on the server, you can turn off JavaScript and everything still works great. Data still loads, form actions still process; it’s beautiful. This is not running loaders and actions on the client side; it’s running them on the server. This isn’t an accident, the Remix team is carefully considering the UX.</p>\r\n<blockquote class=\"twitter-tweet\" data-dnt=\"true\" data-theme=\"dark\"><p lang=\"en\" dir=\"ltr\">User experience (UX) and developer experience (DX) are both important. UX is more important than DX.<a href=\"https://twitter.com/remix_run?ref_src=twsrc%5Etfw\">@remix_run</a> has taught me: It\'s easier to start with a great UX and work toward a good DX than it is to start with a great DX and work toward a good UX.</p>— Kent C. Dodds &#x1f4bf; (@kentcdodds) <a href=\"https://twitter.com/kentcdodds/status/1482390454389805058?ref_src=twsrc%5Etfw\">January 15, 2022</a></blockquote>\r\n<script async=\"\" src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\"></script>\r\n<h2>Bonus: So Speedy</h2>\r\n<p>Did I mention how fast everything renders? I don’t tend to put too much stock into Lighthouse scores since they seem so random, but Remix crushes Lighthouse without me having to invest any additional effort into improving performance.</p>\r\n<h2>Give it a Shot</h2>\r\n<p>Remix is built on the <a href=\"https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API\">native Fetch API</a>, so it can run anywhere. While Remix is relatively new, it’s certainly production ready, and there is a dedicated team behind it. If you aren’t ready to dive into Remix yet, at least keep your eye on it because this is a game changer.</p>',NULL,0,NULL,'2022-04-21 14:17:39','2022-04-21 14:17:39','7298588f-d2e5-4ca4-b658-3d0879785820',1,NULL,NULL,17,NULL),(1736,2368,'Why I’m So Excited About Remix',NULL,'<p>I’ve been building on the web for a long time. There’s a part of me that still has a bit of an old school mentality, and it’s hard for me to get really excited about new technology. Sure React was cool when it came out for its state management, but I didn’t see it as the be-all and end-all for building on the web. I really like <a href=\"https://craftcms.com/\">Craft CMS</a> for building CMS powered sites since I have full control over the HTML being sent to the browser, and it’s really easy to extend for complex functionality, but it can be a bit complex to setup for beginners and with additional complexity can come performance issues.&nbsp;So it’s been a while since I’ve seen something to be <em>really</em> excited about.</p>\r\n<p>Enter <a href=\"https://remix.run/\">Remix</a>.</p>\r\n<p>Remix is an interesting mix of old school techniques along with modern technology. Ryan Florence actually sums it up perfectly as to where Remix fits in.</p>\r\n<blockquote class=\"twitter-tweet\" data-dnt=\"true\" data-theme=\"dark\"><p lang=\"en\" dir=\"ltr\">Forget “full stack”. Remix is center stack.<br><br>It’s an HTTP tunnel between interactivity and business logic. It’s the part of the stack that no tool before it has solved, not completely.<br><br>I think I finally know how to talk about Remix.</p>— Ryan Florence (@ryanflorence) <a href=\"https://twitter.com/ryanflorence/status/1482233495195770883?ref_src=twsrc%5Etfw\">January 15, 2022</a></blockquote>\r\n<script async=\"\" src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\"></script>\r\n<p>I was able to easily switch my site that was fully powered by Craft to utilize Craft only as a GraphQL endpoint and Remix powering the rest. The two big things I needed to figure out were: how to get data from the GraphQL endpoint, and then how to process input from a user (for my contact form). I would definitely recommend reading through the Remix docs and the two tutorials, but if you can understand these two big pictures things, you’ll have enough to get started with Remix and go deeper once you get into it.</p>\r\n<h2>Getting GraphQL Data (aka Loaders)</h2>\r\n<p>Remix provides a <a href=\"https://remix.run/docs/en/v1/api/conventions#loader\">loader hook</a> that runs on the server to hydrate your component. In this simple example, I run a GraphQL request and return JSON with the results of that request in the loader function.</p>\r\n<script src=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550.js?file=loader.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550#file-loader-jsx\">View Gist</a></noscript>\r\n<p>Then in my <code>Index</code> component, I access the data from the loader hook with <a href=\"https://remix.run/docs/en/v1/api/remix#useloaderdata\">useLoaderData()</a>, and my component is now hydrated with that data. In MVC style of thinking, think of the loader hook as the controller processing the page load request, populating with data from the model, and then passing to the view.</p>\r\n<p>The great part about Remix is that this doesn’t have to be specifically a GraphQL request. This data can come from anywhere. The <a href=\"https://remix.run/docs/en/v1/tutorials/jokes\">Jokes tutorial</a> in the Remix docs even thoroughly walks through how you can manage all this data in <a href=\"https://www.prisma.io/\">Prisma</a>.</p>\r\n<h2>Processing User Input (aka Actions)</h2>\r\n<p>Ok great, so we’ve got data onto the page, but now we need to be able to handle user input. Remix also provides an <a href=\"https://remix.run/docs/en/v1/api/conventions#action\">action hook</a> to process an action request (ex: a form submission). In my case, I have a contact form that sends me an email via SendGrid after submission.</p>\r\n<script src=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550.js?file=action.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550#file-action-jsx\">View Gist</a></noscript>\r\n<p>If you don’t include an <code>action</code> attribute on your form, it will automatically submit to the same page. Again, in MVC thinking, the action would again be equivalent to the controller taking the request input and processing it. But honestly, this takes me back 15 years when form actions would point directly to PHP files.</p>\r\n<h2>Bonus: Progressive Enhancement</h2>\r\n<p>Since Remix is running on the server, you can turn off JavaScript and everything still works great. Data still loads, form actions still process; it’s beautiful. This is not running loaders and actions on the client side; it’s running them on the server. This isn’t an accident, the Remix team is carefully considering the UX.</p>\r\n<blockquote class=\"twitter-tweet\" data-dnt=\"true\" data-theme=\"dark\"><p lang=\"en\" dir=\"ltr\">User experience (UX) and developer experience (DX) are both important. UX is more important than DX.<a href=\"https://twitter.com/remix_run?ref_src=twsrc%5Etfw\">@remix_run</a> has taught me: It\'s easier to start with a great UX and work toward a good DX than it is to start with a great DX and work toward a good UX.</p>— Kent C. Dodds &#x1f4bf; (@kentcdodds) <a href=\"https://twitter.com/kentcdodds/status/1482390454389805058?ref_src=twsrc%5Etfw\">January 15, 2022</a></blockquote>\r\n<script async=\"\" src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\"></script>\r\n<h2>Bonus: So Speedy</h2>\r\n<p>Did I mention how fast everything renders? I don’t tend to put too much stock into Lighthouse scores since they seem so random, but Remix crushes Lighthouse without me having to invest any additional effort into improving performance.</p>\r\n<h2>Give it a Shot</h2>\r\n<p>Remix is built on the <a href=\"https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API\">native Fetch API</a>, so it can run anywhere. While Remix is relatively new, it’s certainly production ready, and there is a dedicated team behind it. If you aren’t ready to dive into Remix yet, at least keep your eye on it because this is a game changer.</p>',NULL,0,NULL,'2022-04-21 14:28:58','2022-04-21 14:28:58','cf9fea79-2cd9-4692-aa6b-812956ff2981',1,NULL,NULL,16,NULL),(1737,2369,'Why I’m So Excited About Remix',NULL,'<p>I’ve been building on the web for a long time. There’s a part of me that still has a bit of an old school mentality, and it’s hard for me to get really excited about new technology. Sure React was cool when it came out for its state management, but I didn’t see it as the be-all and end-all for building on the web. I really like <a href=\"https://craftcms.com/\">Craft CMS</a> for building CMS powered sites since I have full control over the HTML being sent to the browser, and it’s really easy to extend for complex functionality, but it can be a bit complex to setup for beginners and with additional complexity can come performance issues.&nbsp;So it’s been a while since I’ve seen something to be <em>really</em> excited about.</p>\r\n<p>Enter <a href=\"https://remix.run/\">Remix</a>.</p>\r\n<p>Remix is an interesting mix of old school techniques along with modern technology. Ryan Florence actually sums it up perfectly as to where Remix fits in.</p>\r\n<blockquote class=\"twitter-tweet\" data-dnt=\"true\" data-theme=\"dark\"><p lang=\"en\" dir=\"ltr\">Forget “full stack”. Remix is center stack.<br><br>It’s an HTTP tunnel between interactivity and business logic. It’s the part of the stack that no tool before it has solved, not completely.<br><br>I think I finally know how to talk about Remix.</p>— Ryan Florence (@ryanflorence) <a href=\"https://twitter.com/ryanflorence/status/1482233495195770883?ref_src=twsrc%5Etfw\">January 15, 2022</a></blockquote>\r\n<script async=\"\" src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\"></script>\r\n<p>I was able to easily switch my site that was fully powered by Craft to utilize Craft only as a GraphQL endpoint and Remix powering the rest. The two big things I needed to figure out were: how to get data from the GraphQL endpoint, and then how to process input from a user (for my contact form). I would definitely recommend reading through the Remix docs and the two tutorials, but if you can understand these two big pictures things, you’ll have enough to get started with Remix and go deeper once you get into it.</p>\r\n<h2>Getting GraphQL Data (aka Loaders)</h2>\r\n<p>Remix provides a <a href=\"https://remix.run/docs/en/v1/api/conventions#loader\">loader hook</a> that runs on the server to hydrate your component. In this simple example, I run a GraphQL request and return JSON with the results of that request in the loader function.</p>\r\n<script src=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550.js?file=loader.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550#file-loader-jsx\">View Gist</a></noscript>\r\n<p>Then in my <code>Index</code> component, I access the data from the loader hook with <a href=\"https://remix.run/docs/en/v1/api/remix#useloaderdata\">useLoaderData()</a>, and my component is now hydrated with that data. In MVC style of thinking, think of the loader hook as the controller processing the page load request, populating with data from the model, and then passing to the view.</p>\r\n<p>The great part about Remix is that this doesn’t have to be specifically a GraphQL request. This data can come from anywhere. The <a href=\"https://remix.run/docs/en/v1/tutorials/jokes\">Jokes tutorial</a> in the Remix docs even thoroughly walks through how you can manage all this data in <a href=\"https://www.prisma.io/\">Prisma</a>.</p>\r\n<h2>Processing User Input (aka Actions)</h2>\r\n<p>Ok great, so we’ve got data onto the page, but now we need to be able to handle user input. Remix also provides an <a href=\"https://remix.run/docs/en/v1/api/conventions#action\">action hook</a> to process an action request (ex: a form submission). In my case, I have a contact form that sends me an email via SendGrid after submission.</p>\r\n<script src=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550.js?file=action.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550#file-action-jsx\">View Gist</a></noscript>\r\n<p>If you don’t include an <code>action</code> attribute on your form, it will automatically submit to the same page. Again, in MVC thinking, the action would again be equivalent to the controller taking the request input and processing it. But honestly, this takes me back 15 years when form actions would point directly to PHP files.</p>\r\n<h2>Bonus: Progressive Enhancement</h2>\r\n<p>Since Remix is running on the server, you can turn off JavaScript and everything still works great. Data still loads, form actions still process; it’s beautiful. This is not running loaders and actions on the client side; it’s running them on the server. This isn’t an accident, the Remix team is carefully considering the UX.</p>\r\n<blockquote class=\"twitter-tweet\" data-dnt=\"true\" data-theme=\"dark\"><p lang=\"en\" dir=\"ltr\">User experience (UX) and developer experience (DX) are both important. UX is more important than DX.<a href=\"https://twitter.com/remix_run?ref_src=twsrc%5Etfw\">@remix_run</a> has taught me: It\'s easier to start with a great UX and work toward a good DX than it is to start with a great DX and work toward a good UX.</p>— Kent C. Dodds &#x1f4bf; (@kentcdodds) <a href=\"https://twitter.com/kentcdodds/status/1482390454389805058?ref_src=twsrc%5Etfw\">January 15, 2022</a></blockquote>\r\n<script async=\"\" src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\"></script>\r\n<h2>Bonus: So Speedy</h2>\r\n<p>Did I mention how fast everything renders? I don’t tend to put too much stock into Lighthouse scores since they seem so random, but Remix crushes Lighthouse without me having to invest any additional effort into improving performance.</p>\r\n<h2>Give it a Shot</h2>\r\n<p>Remix is built on the <a href=\"https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API\">native Fetch API</a>, so it can run anywhere. While Remix is relatively new, it’s certainly production ready, and there is a dedicated team behind it. If you aren’t ready to dive into Remix yet, at least keep your eye on it because this is a game changer.</p>',NULL,0,NULL,'2022-04-21 14:29:00','2022-04-21 14:29:00','f7b31037-b993-4297-94c7-1daec57fdd89',1,NULL,NULL,16,NULL),(1738,2370,'Why I’m So Excited About Remix',NULL,'<p>I’ve been building on the web for a long time. There’s a part of me that still has a bit of an old school mentality, and it’s hard for me to get really excited about new technology. Sure React was cool when it came out for its state management, but I didn’t see it as the be-all and end-all for building on the web. I really like <a href=\"https://craftcms.com/\">Craft CMS</a> for building CMS powered sites since I have full control over the HTML being sent to the browser, and it’s really easy to extend for complex functionality, but it can be a bit complex to setup for beginners and with additional complexity can come performance issues.&nbsp;So it’s been a while since I’ve seen something to be <em>really</em> excited about.</p>\r\n<p>Enter <a href=\"https://remix.run/\">Remix</a>.</p>\r\n<p>Remix is an interesting mix of old school techniques along with modern technology. Ryan Florence actually sums it up perfectly as to where Remix fits in.</p>\r\n<blockquote class=\"twitter-tweet\" data-dnt=\"true\" data-theme=\"dark\"><p lang=\"en\" dir=\"ltr\">Forget “full stack”. Remix is center stack.<br><br>It’s an HTTP tunnel between interactivity and business logic. It’s the part of the stack that no tool before it has solved, not completely.<br><br>I think I finally know how to talk about Remix.</p>— Ryan Florence (@ryanflorence) <a href=\"https://twitter.com/ryanflorence/status/1482233495195770883?ref_src=twsrc%5Etfw\">January 15, 2022</a></blockquote>\r\n<script async=\"\" src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\"></script>\r\n<p>I was able to easily switch my site that was fully powered by Craft to utilize Craft only as a GraphQL endpoint and Remix powering the rest. The two big things I needed to figure out were: how to get data from the GraphQL endpoint, and then how to process input from a user (for my contact form). I would definitely recommend reading through the Remix docs and the two tutorials, but if you can understand these two big pictures things, you’ll have enough to get started with Remix and go deeper once you get into it.</p>\r\n<h2>Getting GraphQL Data (aka Loaders)</h2>\r\n<p>Remix provides a <a href=\"https://remix.run/docs/en/v1/api/conventions#loader\">loader hook</a> that runs on the server to hydrate your component. In this simple example, I run a GraphQL request and return JSON with the results of that request in the loader function.</p>\r\n<script src=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550.js?file=loader.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550#file-loader-jsx\">View Gist</a></noscript>\r\n<p>Then in my <code>Index</code> component, I access the data from the loader hook with <a href=\"https://remix.run/docs/en/v1/api/remix#useloaderdata\">useLoaderData()</a>, and my component is now hydrated with that data. In MVC style of thinking, think of the loader hook as the controller processing the page load request, populating with data from the model, and then passing to the view.</p>\r\n<p>The great part about Remix is that this doesn’t have to be specifically a GraphQL request. This data can come from anywhere. The <a href=\"https://remix.run/docs/en/v1/tutorials/jokes\">Jokes tutorial</a> in the Remix docs even thoroughly walks through how you can manage all this data in <a href=\"https://www.prisma.io/\">Prisma</a>.</p>\r\n<h2>Processing User Input (aka Actions)</h2>\r\n<p>Ok great, so we’ve got data onto the page, but now we need to be able to handle user input. Remix also provides an <a href=\"https://remix.run/docs/en/v1/api/conventions#action\">action hook</a> to process an action request (ex: a form submission). In my case, I have a contact form that sends me an email via SendGrid after submission.</p>\r\n<script src=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550.js?file=action.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550#file-action-jsx\">View Gist</a></noscript>\r\n<p>If you don’t include an <code>action</code> attribute on your form, it will automatically submit to the same page. Again, in MVC thinking, the action would again be equivalent to the controller taking the request input and processing it. But honestly, this takes me back 15 years when form actions would point directly to PHP files.</p>\r\n<h2>Bonus: Progressive Enhancement</h2>\r\n<p>Since Remix is running on the server, you can turn off JavaScript and everything still works great. Data still loads, form actions still process; it’s beautiful. This is not running loaders and actions on the client side; it’s running them on the server. This isn’t an accident, the Remix team is carefully considering the UX.</p>\r\n<blockquote class=\"twitter-tweet\" data-dnt=\"true\" data-theme=\"dark\"><p lang=\"en\" dir=\"ltr\">User experience (UX) and developer experience (DX) are both important. UX is more important than DX.<a href=\"https://twitter.com/remix_run?ref_src=twsrc%5Etfw\">@remix_run</a> has taught me: It\'s easier to start with a great UX and work toward a good DX than it is to start with a great DX and work toward a good UX.</p>— Kent C. Dodds &#x1f4bf; (@kentcdodds) <a href=\"https://twitter.com/kentcdodds/status/1482390454389805058?ref_src=twsrc%5Etfw\">January 15, 2022</a></blockquote>\r\n<script async=\"\" src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\"></script>\r\n<h2>Bonus: So Speedy</h2>\r\n<p>Did I mention how fast everything renders? I don’t tend to put too much stock into Lighthouse scores since they seem so random, but Remix crushes Lighthouse without me having to invest any additional effort into improving performance.</p>\r\n<h2>Give it a Shot</h2>\r\n<p>Remix is built on the <a href=\"https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API\">native Fetch API</a>, so it can run anywhere. While Remix is relatively new, it’s certainly production ready, and there is a dedicated team behind it. If you aren’t ready to dive into Remix yet, at least keep your eye on it because this is a game changer.</p>',NULL,0,NULL,'2022-04-21 14:34:53','2022-04-21 14:34:53','98aa5900-045f-4a62-a084-8551defb420a',1,NULL,NULL,15,NULL),(1739,2371,'Why I’m So Excited About Remix',NULL,'<p>I’ve been building on the web for a long time. There’s a part of me that still has a bit of an old school mentality, and it’s hard for me to get really excited about new technology. Sure React was cool when it came out for its state management, but I didn’t see it as the be-all and end-all for building on the web. I really like <a href=\"https://craftcms.com/\">Craft CMS</a> for building CMS powered sites since I have full control over the HTML being sent to the browser, and it’s really easy to extend for complex functionality, but it can be a bit complex to setup for beginners and with additional complexity can come performance issues.&nbsp;So it’s been a while since I’ve seen something to be <em>really</em> excited about.</p>\r\n<p>Enter <a href=\"https://remix.run/\">Remix</a>.</p>\r\n<p>Remix is an interesting mix of old school techniques along with modern technology. Ryan Florence actually sums it up perfectly as to where Remix fits in.</p>\r\n<blockquote class=\"twitter-tweet\" data-dnt=\"true\" data-theme=\"dark\"><p lang=\"en\" dir=\"ltr\">Forget “full stack”. Remix is center stack.<br><br>It’s an HTTP tunnel between interactivity and business logic. It’s the part of the stack that no tool before it has solved, not completely.<br><br>I think I finally know how to talk about Remix.</p>— Ryan Florence (@ryanflorence) <a href=\"https://twitter.com/ryanflorence/status/1482233495195770883?ref_src=twsrc%5Etfw\">January 15, 2022</a></blockquote>\r\n<script async=\"\" src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\"></script>\r\n<p>I was able to easily switch my site that was fully powered by Craft to utilize Craft only as a GraphQL endpoint and Remix powering the rest. The two big things I needed to figure out were: how to get data from the GraphQL endpoint, and then how to process input from a user (for my contact form). I would definitely recommend reading through the Remix docs and the two tutorials, but if you can understand these two big pictures things, you’ll have enough to get started with Remix and go deeper once you get into it.</p>\r\n<h2>Getting GraphQL Data (aka Loaders)</h2>\r\n<p>Remix provides a <a href=\"https://remix.run/docs/en/v1/api/conventions#loader\">loader hook</a> that runs on the server to hydrate your component. In this simple example, I run a GraphQL request and return JSON with the results of that request in the loader function.</p>\r\n<script src=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550.js?file=loader.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550#file-loader-jsx\">View Gist</a></noscript>\r\n<p>Then in my <code>Index</code> component, I access the data from the loader hook with <a href=\"https://remix.run/docs/en/v1/api/remix#useloaderdata\">useLoaderData()</a>, and my component is now hydrated with that data. In MVC style of thinking, think of the loader hook as the controller processing the page load request, populating with data from the model, and then passing to the view.</p>\r\n<p>The great part about Remix is that this doesn’t have to be specifically a GraphQL request. This data can come from anywhere. The <a href=\"https://remix.run/docs/en/v1/tutorials/jokes\">Jokes tutorial</a> in the Remix docs even thoroughly walks through how you can manage all this data in <a href=\"https://www.prisma.io/\">Prisma</a>.</p>\r\n<h2>Processing User Input (aka Actions)</h2>\r\n<p>Ok great, so we’ve got data onto the page, but now we need to be able to handle user input. Remix also provides an <a href=\"https://remix.run/docs/en/v1/api/conventions#action\">action hook</a> to process an action request (ex: a form submission). In my case, I have a contact form that sends me an email via SendGrid after submission.</p>\r\n<script src=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550.js?file=action.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550#file-action-jsx\">View Gist</a></noscript>\r\n<p>If you don’t include an <code>action</code> attribute on your form, it will automatically submit to the same page. Again, in MVC thinking, the action would again be equivalent to the controller taking the request input and processing it. But honestly, this takes me back 15 years when form actions would point directly to PHP files.</p>\r\n<h2>Bonus: Progressive Enhancement</h2>\r\n<p>Since Remix is running on the server, you can turn off JavaScript and everything still works great. Data still loads, form actions still process; it’s beautiful. This is not running loaders and actions on the client side; it’s running them on the server. This isn’t an accident, the Remix team is carefully considering the UX.</p>\r\n<blockquote class=\"twitter-tweet\" data-dnt=\"true\" data-theme=\"dark\"><p lang=\"en\" dir=\"ltr\">User experience (UX) and developer experience (DX) are both important. UX is more important than DX.<a href=\"https://twitter.com/remix_run?ref_src=twsrc%5Etfw\">@remix_run</a> has taught me: It\'s easier to start with a great UX and work toward a good DX than it is to start with a great DX and work toward a good UX.</p>— Kent C. Dodds &#x1f4bf; (@kentcdodds) <a href=\"https://twitter.com/kentcdodds/status/1482390454389805058?ref_src=twsrc%5Etfw\">January 15, 2022</a></blockquote>\r\n<script async=\"\" src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\"></script>\r\n<h2>Bonus: So Speedy</h2>\r\n<p>Did I mention how fast everything renders? I don’t tend to put too much stock into Lighthouse scores since they seem so random, but Remix crushes Lighthouse without me having to invest any additional effort into improving performance.</p>\r\n<h2>Give it a Shot</h2>\r\n<p>Remix is built on the <a href=\"https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API\">native Fetch API</a>, so it can run anywhere. While Remix is relatively new, it’s certainly production ready, and there is a dedicated team behind it. If you aren’t ready to dive into Remix yet, at least keep your eye on it because this is a game changer.</p>',NULL,0,NULL,'2022-04-21 14:35:05','2022-04-21 14:35:05','2eef7283-e456-46c6-be58-8eaf388462c5',1,NULL,NULL,16,NULL),(1740,2372,'Why I’m So Excited About Remix',NULL,'<p>I’ve been building on the web for a long time. There’s a part of me that still has a bit of an old school mentality, and it’s hard for me to get really excited about new technology. Sure React was cool when it came out for its state management, but I didn’t see it as the be-all and end-all for building on the web. I really like <a href=\"https://craftcms.com/\">Craft CMS</a> for building CMS powered sites since I have full control over the HTML being sent to the browser, and it’s really easy to extend for complex functionality, but it can be a bit complex to setup for beginners and with additional complexity can come performance issues.&nbsp;So it’s been a while since I’ve seen something to be <em>really</em> excited about.</p>\r\n<p>Enter <a href=\"https://remix.run/\">Remix</a>.</p>\r\n<p>Remix is an interesting mix of old school techniques along with modern technology. Ryan Florence actually sums it up perfectly as to where Remix fits in.</p>\r\n<blockquote class=\"twitter-tweet\" data-dnt=\"true\" data-theme=\"dark\"><p lang=\"en\" dir=\"ltr\">Forget “full stack”. Remix is center stack.<br><br>It’s an HTTP tunnel between interactivity and business logic. It’s the part of the stack that no tool before it has solved, not completely.<br><br>I think I finally know how to talk about Remix.</p>— Ryan Florence (@ryanflorence) <a href=\"https://twitter.com/ryanflorence/status/1482233495195770883?ref_src=twsrc%5Etfw\">January 15, 2022</a></blockquote>\r\n<script async=\"\" src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\"></script>\r\n<p>I was able to easily switch my site that was fully powered by Craft to utilize Craft only as a GraphQL endpoint and Remix powering the rest. The two big things I needed to figure out were: how to get data from the GraphQL endpoint, and then how to process input from a user (for my contact form). I would definitely recommend reading through the Remix docs and the two tutorials, but if you can understand these two big pictures things, you’ll have enough to get started with Remix and go deeper once you get into it.</p>\r\n<h2>Getting GraphQL Data (aka Loaders)</h2>\r\n<p>Remix provides a <a href=\"https://remix.run/docs/en/v1/api/conventions#loader\">loader hook</a> that runs on the server to hydrate your component. In this simple example, I run a GraphQL request and return JSON with the results of that request in the loader function.</p>\r\n<script src=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550.js?file=loader.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550#file-loader-jsx\">View Gist</a></noscript>\r\n<p>Then in my <code>Index</code> component, I access the data from the loader hook with <a href=\"https://remix.run/docs/en/v1/api/remix#useloaderdata\">useLoaderData()</a>, and my component is now hydrated with that data. In MVC style of thinking, think of the loader hook as the controller processing the page load request, populating with data from the model, and then passing to the view.</p>\r\n<p>The great part about Remix is that this doesn’t have to be specifically a GraphQL request. This data can come from anywhere. The <a href=\"https://remix.run/docs/en/v1/tutorials/jokes\">Jokes tutorial</a> in the Remix docs even thoroughly walks through how you can manage all this data in <a href=\"https://www.prisma.io/\">Prisma</a>.</p>\r\n<h2>Processing User Input (aka Actions)</h2>\r\n<p>Ok great, so we’ve got data onto the page, but now we need to be able to handle user input. Remix also provides an <a href=\"https://remix.run/docs/en/v1/api/conventions#action\">action hook</a> to process an action request (ex: a form submission). In my case, I have a contact form that sends me an email via SendGrid after submission.</p>\r\n<script src=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550.js?file=action.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550#file-action-jsx\">View Gist</a></noscript>\r\n<p>If you don’t include an <code>action</code> attribute on your form, it will automatically submit to the same page. Again, in MVC thinking, the action would again be equivalent to the controller taking the request input and processing it. But honestly, this takes me back 15 years when form actions would point directly to PHP files.</p>\r\n<h2>Bonus: Progressive Enhancement</h2>\r\n<p>Since Remix is running on the server, you can turn off JavaScript and everything still works great. Data still loads, form actions still process; it’s beautiful. This is not running loaders and actions on the client side; it’s running them on the server. This isn’t an accident, the Remix team is carefully considering the UX.</p>\r\n<blockquote class=\"twitter-tweet\" data-dnt=\"true\" data-theme=\"dark\"><p lang=\"en\" dir=\"ltr\">User experience (UX) and developer experience (DX) are both important. UX is more important than DX.<a href=\"https://twitter.com/remix_run?ref_src=twsrc%5Etfw\">@remix_run</a> has taught me: It\'s easier to start with a great UX and work toward a good DX than it is to start with a great DX and work toward a good UX.</p>— Kent C. Dodds &#x1f4bf; (@kentcdodds) <a href=\"https://twitter.com/kentcdodds/status/1482390454389805058?ref_src=twsrc%5Etfw\">January 15, 2022</a></blockquote>\r\n<script async=\"\" src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\"></script>\r\n<h2>Bonus: So Speedy</h2>\r\n<p>Did I mention how fast everything renders? I don’t tend to put too much stock into Lighthouse scores since they seem so random, but Remix crushes Lighthouse without me having to invest any additional effort into improving performance.</p>\r\n<h2>Give it a Shot</h2>\r\n<p>Remix is built on the <a href=\"https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API\">native Fetch API</a>, so it can run anywhere. While Remix is relatively new, it’s certainly production ready, and there is a dedicated team behind it. If you aren’t ready to dive into Remix yet, at least keep your eye on it because this is a game changer.</p>',NULL,0,NULL,'2022-04-21 14:40:52','2022-04-21 14:40:52','2240a7fd-3e3f-4fb7-a28b-edd9bb3a51b7',1,NULL,NULL,17,NULL),(1741,2373,'Why I’m So Excited About Remix',NULL,'<p>I’ve been building on the web for a long time. There’s a part of me that still has a bit of an old school mentality, and it’s hard for me to get really excited about new technology. Sure React was cool when it came out for its state management, but I didn’t see it as the be-all and end-all for building on the web. I really like <a href=\"https://craftcms.com/\">Craft CMS</a> for building CMS powered sites since I have full control over the HTML being sent to the browser, and it’s really easy to extend for complex functionality, but it can be a bit complex to setup for beginners and with additional complexity can come performance issues.&nbsp;So it’s been a while since I’ve seen something to be <em>really</em> excited about.</p>\r\n<p>Enter <a href=\"https://remix.run/\">Remix</a>.</p>\r\n<p>Remix is an interesting mix of old school techniques along with modern technology. Ryan Florence actually sums it up perfectly as to where Remix fits in.</p>\r\n<blockquote class=\"twitter-tweet\" data-dnt=\"true\" data-theme=\"dark\"><p lang=\"en\" dir=\"ltr\">Forget “full stack”. Remix is center stack.<br><br>It’s an HTTP tunnel between interactivity and business logic. It’s the part of the stack that no tool before it has solved, not completely.<br><br>I think I finally know how to talk about Remix.</p>— Ryan Florence (@ryanflorence) <a href=\"https://twitter.com/ryanflorence/status/1482233495195770883?ref_src=twsrc%5Etfw\">January 15, 2022</a></blockquote>\r\n<script async=\"\" src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\"></script>\r\n<p>I was able to easily switch my site that was fully powered by Craft to utilize Craft only as a GraphQL endpoint and Remix powering the rest. The two big things I needed to figure out were: how to get data from the GraphQL endpoint, and then how to process input from a user (for my contact form). I would definitely recommend reading through the Remix docs and the two tutorials, but if you can understand these two big pictures things, you’ll have enough to get started with Remix and go deeper once you get into it.</p>\r\n<h2>Getting GraphQL Data (aka Loaders)</h2>\r\n<p>Remix provides a <a href=\"https://remix.run/docs/en/v1/api/conventions#loader\">loader hook</a> that runs on the server to hydrate your component. In this simple example, I run a GraphQL request and return JSON with the results of that request in the loader function.</p>\r\n<script src=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550.js?file=loader.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550#file-loader-jsx\">View Gist</a></noscript>\r\n<p>Then in my <code>Index</code> component, I access the data from the loader hook with <a href=\"https://remix.run/docs/en/v1/api/remix#useloaderdata\">useLoaderData()</a>, and my component is now hydrated with that data. In MVC style of thinking, think of the loader hook as the controller processing the page load request, populating with data from the model, and then passing to the view.</p>\r\n<p>The great part about Remix is that this doesn’t have to be specifically a GraphQL request. This data can come from anywhere. The <a href=\"https://remix.run/docs/en/v1/tutorials/jokes\">Jokes tutorial</a> in the Remix docs even thoroughly walks through how you can manage all this data in <a href=\"https://www.prisma.io/\">Prisma</a>.</p>\r\n<h2>Processing User Input (aka Actions)</h2>\r\n<p>Ok great, so we’ve got data onto the page, but now we need to be able to handle user input. Remix also provides an <a href=\"https://remix.run/docs/en/v1/api/conventions#action\">action hook</a> to process an action request (ex: a form submission). In my case, I have a contact form that sends me an email via SendGrid after submission.</p>\r\n<script src=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550.js?file=action.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550#file-action-jsx\">View Gist</a></noscript>\r\n<p>If you don’t include an <code>action</code> attribute on your form, it will automatically submit to the same page. Again, in MVC thinking, the action would again be equivalent to the controller taking the request input and processing it. But honestly, this takes me back 15 years when form actions would point directly to PHP files.</p>\r\n<h2>Bonus: Progressive Enhancement</h2>\r\n<p>Since Remix is running on the server, you can turn off JavaScript and everything still works great. Data still loads, form actions still process; it’s beautiful. This is not running loaders and actions on the client side; it’s running them on the server. This isn’t an accident, the Remix team is carefully considering the UX.</p>\r\n<blockquote class=\"twitter-tweet\" data-dnt=\"true\" data-theme=\"dark\"><p lang=\"en\" dir=\"ltr\">User experience (UX) and developer experience (DX) are both important. UX is more important than DX.<a href=\"https://twitter.com/remix_run?ref_src=twsrc%5Etfw\">@remix_run</a> has taught me: It\'s easier to start with a great UX and work toward a good DX than it is to start with a great DX and work toward a good UX.</p>— Kent C. Dodds &#x1f4bf; (@kentcdodds) <a href=\"https://twitter.com/kentcdodds/status/1482390454389805058?ref_src=twsrc%5Etfw\">January 15, 2022</a></blockquote>\r\n<script async=\"\" src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\"></script>\r\n<h2>Bonus: So Speedy</h2>\r\n<p>Did I mention how fast everything renders? I don’t tend to put too much stock into Lighthouse scores since they seem so random, but Remix crushes Lighthouse without me having to invest any additional effort into improving performance.</p>\r\n<h2>Give it a Shot</h2>\r\n<p>Remix is built on the <a href=\"https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API\">native Fetch API</a>, so it can run anywhere. While Remix is relatively new, it’s certainly production ready, and there is a dedicated team behind it. If you aren’t ready to dive into Remix yet, at least keep your eye on it because this is a game changer.</p>',NULL,0,NULL,'2022-04-21 14:40:58','2022-04-21 14:40:58','b21c8c82-2994-4899-a56d-7da665b9270e',1,NULL,NULL,16,NULL),(1742,2374,'Why I’m So Excited About Remix',NULL,'<p>I’ve been building on the web for a long time. There’s a part of me that still has a bit of an old school mentality, and it’s hard for me to get really excited about new technology. Sure React was cool when it came out for its state management, but I didn’t see it as the be-all and end-all for building on the web. I really like <a href=\"https://craftcms.com/\">Craft CMS</a> for building CMS powered sites since I have full control over the HTML being sent to the browser, and it’s really easy to extend for complex functionality, but it can be a bit complex to setup for beginners and with additional complexity can come performance issues.&nbsp;So it’s been a while since I’ve seen something to be <em>really</em> excited about.</p>\r\n<p>Enter <a href=\"https://remix.run/\">Remix</a>.</p>\r\n<p>Remix is an interesting mix of old school techniques along with modern technology. Ryan Florence actually sums it up perfectly as to where Remix fits in.</p>\r\n<blockquote class=\"twitter-tweet\" data-dnt=\"true\" data-theme=\"dark\"><p lang=\"en\" dir=\"ltr\">Forget “full stack”. Remix is center stack.<br><br>It’s an HTTP tunnel between interactivity and business logic. It’s the part of the stack that no tool before it has solved, not completely.<br><br>I think I finally know how to talk about Remix.</p>— Ryan Florence (@ryanflorence) <a href=\"https://twitter.com/ryanflorence/status/1482233495195770883?ref_src=twsrc%5Etfw\">January 15, 2022</a></blockquote>\r\n<script async=\"\" src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\"></script>\r\n<p>I was able to easily switch my site that was fully powered by Craft to utilize Craft only as a GraphQL endpoint and Remix powering the rest. The two big things I needed to figure out were: how to get data from the GraphQL endpoint, and then how to process input from a user (for my contact form). I would definitely recommend reading through the Remix docs and the two tutorials, but if you can understand these two big pictures things, you’ll have enough to get started with Remix and go deeper once you get into it.</p>\r\n<h2>Getting GraphQL Data (aka Loaders)</h2>\r\n<p>Remix provides a <a href=\"https://remix.run/docs/en/v1/api/conventions#loader\">loader hook</a> that runs on the server to hydrate your component. In this simple example, I run a GraphQL request and return JSON with the results of that request in the loader function.</p>\r\n<script src=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550.js?file=loader.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550#file-loader-jsx\">View Gist</a></noscript>\r\n<p>Then in my <code>Index</code> component, I access the data from the loader hook with <a href=\"https://remix.run/docs/en/v1/api/remix#useloaderdata\">useLoaderData()</a>, and my component is now hydrated with that data. In MVC style of thinking, think of the loader hook as the controller processing the page load request, populating with data from the model, and then passing to the view.</p>\r\n<p>The great part about Remix is that this doesn’t have to be specifically a GraphQL request. This data can come from anywhere. The <a href=\"https://remix.run/docs/en/v1/tutorials/jokes\">Jokes tutorial</a> in the Remix docs even thoroughly walks through how you can manage all this data in <a href=\"https://www.prisma.io/\">Prisma</a>.</p>\r\n<h2>Processing User Input (aka Actions)</h2>\r\n<p>Ok great, so we’ve got data onto the page, but now we need to be able to handle user input. Remix also provides an <a href=\"https://remix.run/docs/en/v1/api/conventions#action\">action hook</a> to process an action request (ex: a form submission). In my case, I have a contact form that sends me an email via SendGrid after submission.</p>\r\n<script src=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550.js?file=action.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550#file-action-jsx\">View Gist</a></noscript>\r\n<p>If you don’t include an <code>action</code> attribute on your form, it will automatically submit to the same page. Again, in MVC thinking, the action would again be equivalent to the controller taking the request input and processing it. But honestly, this takes me back 15 years when form actions would point directly to PHP files.</p>\r\n<h2>Bonus: Progressive Enhancement</h2>\r\n<p>Since Remix is running on the server, you can turn off JavaScript and everything still works great. Data still loads, form actions still process; it’s beautiful. This is not running loaders and actions on the client side; it’s running them on the server. This isn’t an accident, the Remix team is carefully considering the UX.</p>\r\n<blockquote class=\"twitter-tweet\" data-dnt=\"true\" data-theme=\"dark\"><p lang=\"en\" dir=\"ltr\">User experience (UX) and developer experience (DX) are both important. UX is more important than DX.<a href=\"https://twitter.com/remix_run?ref_src=twsrc%5Etfw\">@remix_run</a> has taught me: It\'s easier to start with a great UX and work toward a good DX than it is to start with a great DX and work toward a good UX.</p>— Kent C. Dodds &#x1f4bf; (@kentcdodds) <a href=\"https://twitter.com/kentcdodds/status/1482390454389805058?ref_src=twsrc%5Etfw\">January 15, 2022</a></blockquote>\r\n<script async=\"\" src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\"></script>\r\n<h2>Bonus: So Speedy</h2>\r\n<p>Did I mention how fast everything renders? I don’t tend to put too much stock into Lighthouse scores since they seem so random, but Remix crushes Lighthouse without me having to invest any additional effort into improving performance.</p>\r\n<h2>Give it a Shot</h2>\r\n<p>Remix is built on the <a href=\"https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API\">native Fetch API</a>, so it can run anywhere. While Remix is relatively new, it’s certainly production ready, and there is a dedicated team behind it. If you aren’t ready to dive into Remix yet, at least keep your eye on it because this is a game changer.</p>',NULL,0,NULL,'2022-04-21 14:41:05','2022-04-21 14:41:05','64177670-3e93-462a-9029-174ef5579bb5',1,NULL,NULL,17,NULL),(1743,2375,'Why I’m So Excited About Remix',NULL,'<p>I’ve been building on the web for a long time. There’s a part of me that still has a bit of an old school mentality, and it’s hard for me to get really excited about new technology. Sure React was cool when it came out for its state management, but I didn’t see it as the be-all and end-all for building on the web. I really like <a href=\"https://craftcms.com/\">Craft CMS</a> for building CMS powered sites since I have full control over the HTML being sent to the browser, and it’s really easy to extend for complex functionality, but it can be a bit complex to setup for beginners and with additional complexity can come performance issues.&nbsp;So it’s been a while since I’ve seen something to be <em>really</em> excited about.</p>\r\n<p>Enter <a href=\"https://remix.run/\">Remix</a>.</p>\r\n<p>Remix is an interesting mix of old school techniques along with modern technology. Ryan Florence actually sums it up perfectly as to where Remix fits in.</p>\r\n<blockquote class=\"twitter-tweet\" data-dnt=\"true\" data-theme=\"dark\"><p lang=\"en\" dir=\"ltr\">Forget “full stack”. Remix is center stack.<br><br>It’s an HTTP tunnel between interactivity and business logic. It’s the part of the stack that no tool before it has solved, not completely.<br><br>I think I finally know how to talk about Remix.</p>— Ryan Florence (@ryanflorence) <a href=\"https://twitter.com/ryanflorence/status/1482233495195770883?ref_src=twsrc%5Etfw\">January 15, 2022</a></blockquote>\r\n<script async=\"\" src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\"></script>\r\n<p>I was able to easily switch my site that was fully powered by Craft to utilize Craft only as a GraphQL endpoint and Remix powering the rest. The two big things I needed to figure out were: how to get data from the GraphQL endpoint, and then how to process input from a user (for my contact form). I would definitely recommend reading through the Remix docs and the two tutorials, but if you can understand these two big pictures things, you’ll have enough to get started with Remix and go deeper once you get into it.</p>\r\n<h2>Getting GraphQL Data (aka Loaders)</h2>\r\n<p>Remix provides a <a href=\"https://remix.run/docs/en/v1/api/conventions#loader\">loader hook</a> that runs on the server to hydrate your component. In this simple example, I run a GraphQL request and return JSON with the results of that request in the loader function.</p>\r\n<script src=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550.js?file=loader.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550#file-loader-jsx\">View Gist</a></noscript>\r\n<p>Then in my <code>Index</code> component, I access the data from the loader hook with <a href=\"https://remix.run/docs/en/v1/api/remix#useloaderdata\">useLoaderData()</a>, and my component is now hydrated with that data. In MVC style of thinking, think of the loader hook as the controller processing the page load request, populating with data from the model, and then passing to the view.</p>\r\n<p>The great part about Remix is that this doesn’t have to be specifically a GraphQL request. This data can come from anywhere. The <a href=\"https://remix.run/docs/en/v1/tutorials/jokes\">Jokes tutorial</a> in the Remix docs even thoroughly walks through how you can manage all this data in <a href=\"https://www.prisma.io/\">Prisma</a>.</p>\r\n<h2>Processing User Input (aka Actions)</h2>\r\n<p>Ok great, so we’ve got data onto the page, but now we need to be able to handle user input. Remix also provides an <a href=\"https://remix.run/docs/en/v1/api/conventions#action\">action hook</a> to process an action request (ex: a form submission). In my case, I have a contact form that sends me an email via SendGrid after submission.</p>\r\n<script src=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550.js?file=action.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550#file-action-jsx\">View Gist</a></noscript>\r\n<p>If you don’t include an <code>action</code> attribute on your form, it will automatically submit to the same page. Again, in MVC thinking, the action would again be equivalent to the controller taking the request input and processing it. But honestly, this takes me back 15 years when form actions would point directly to PHP files.</p>\r\n<h2>Bonus: Progressive Enhancement</h2>\r\n<p>Since Remix is running on the server, you can turn off JavaScript and everything still works great. Data still loads, form actions still process; it’s beautiful. This is not running loaders and actions on the client side; it’s running them on the server. This isn’t an accident, the Remix team is carefully considering the UX.</p>\r\n<blockquote class=\"twitter-tweet\" data-dnt=\"true\" data-theme=\"dark\"><p lang=\"en\" dir=\"ltr\">User experience (UX) and developer experience (DX) are both important. UX is more important than DX.<a href=\"https://twitter.com/remix_run?ref_src=twsrc%5Etfw\">@remix_run</a> has taught me: It\'s easier to start with a great UX and work toward a good DX than it is to start with a great DX and work toward a good UX.</p>— Kent C. Dodds &#x1f4bf; (@kentcdodds) <a href=\"https://twitter.com/kentcdodds/status/1482390454389805058?ref_src=twsrc%5Etfw\">January 15, 2022</a></blockquote>\r\n<script async=\"\" src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\"></script>\r\n<h2>Bonus: So Speedy</h2>\r\n<p>Did I mention how fast everything renders? I don’t tend to put too much stock into Lighthouse scores since they seem so random, but Remix crushes Lighthouse without me having to invest any additional effort into improving performance.</p>\r\n<h2>Give it a Shot</h2>\r\n<p>Remix is built on the <a href=\"https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API\">native Fetch API</a>, so it can run anywhere. While Remix is relatively new, it’s certainly production ready, and there is a dedicated team behind it. If you aren’t ready to dive into Remix yet, at least keep your eye on it because this is a game changer.</p>',NULL,0,NULL,'2022-04-21 14:41:15','2022-04-21 14:41:15','8a77a623-957c-4b4c-a76b-07874ba7fec7',1,NULL,NULL,16,NULL),(1744,2376,'Why I’m So Excited About Remix',NULL,'<p>I’ve been building on the web for a long time. There’s a part of me that still has a bit of an old school mentality, and it’s hard for me to get really excited about new technology. Sure React was cool when it came out for its state management, but I didn’t see it as the be-all and end-all for building on the web. I really like <a href=\"https://craftcms.com/\">Craft CMS</a> for building CMS powered sites since I have full control over the HTML being sent to the browser, and it’s really easy to extend for complex functionality, but it can be a bit complex to setup for beginners and with additional complexity can come performance issues.&nbsp;So it’s been a while since I’ve seen something to be <em>really</em> excited about.</p>\r\n<p>Enter <a href=\"https://remix.run/\">Remix</a>.</p>\r\n<p>Remix is an interesting mix of old school techniques along with modern technology. Ryan Florence actually sums it up perfectly as to where Remix fits in.</p>\r\n<blockquote class=\"twitter-tweet\" data-dnt=\"true\" data-theme=\"dark\"><p lang=\"en\" dir=\"ltr\">Forget “full stack”. Remix is center stack.<br><br>It’s an HTTP tunnel between interactivity and business logic. It’s the part of the stack that no tool before it has solved, not completely.<br><br>I think I finally know how to talk about Remix.</p>— Ryan Florence (@ryanflorence) <a href=\"https://twitter.com/ryanflorence/status/1482233495195770883?ref_src=twsrc%5Etfw\">January 15, 2022</a></blockquote>\r\n<script async=\"\" src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\"></script>\r\n<p>I was able to easily switch my site that was fully powered by Craft to utilize Craft only as a GraphQL endpoint and Remix powering the rest. The two big things I needed to figure out were: how to get data from the GraphQL endpoint, and then how to process input from a user (for my contact form). I would definitely recommend reading through the Remix docs and the two tutorials, but if you can understand these two big pictures things, you’ll have enough to get started with Remix and go deeper once you get into it.</p>\r\n<h2>Getting GraphQL Data (aka Loaders)</h2>\r\n<p>Remix provides a <a href=\"https://remix.run/docs/en/v1/api/conventions#loader\">loader hook</a> that runs on the server to hydrate your component. In this simple example, I run a GraphQL request and return JSON with the results of that request in the loader function.</p>\r\n<script src=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550.js?file=loader.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550#file-loader-jsx\">View Gist</a></noscript>\r\n<p>Then in my <code>Index</code> component, I access the data from the loader hook with <a href=\"https://remix.run/docs/en/v1/api/remix#useloaderdata\">useLoaderData()</a>, and my component is now hydrated with that data. In MVC style of thinking, think of the loader hook as the controller processing the page load request, populating with data from the model, and then passing to the view.</p>\r\n<p>The great part about Remix is that this doesn’t have to be specifically a GraphQL request. This data can come from anywhere. The <a href=\"https://remix.run/docs/en/v1/tutorials/jokes\">Jokes tutorial</a> in the Remix docs even thoroughly walks through how you can manage all this data in <a href=\"https://www.prisma.io/\">Prisma</a>.</p>\r\n<h2>Processing User Input (aka Actions)</h2>\r\n<p>Ok great, so we’ve got data onto the page, but now we need to be able to handle user input. Remix also provides an <a href=\"https://remix.run/docs/en/v1/api/conventions#action\">action hook</a> to process an action request (ex: a form submission). In my case, I have a contact form that sends me an email via SendGrid after submission.</p>\r\n<script src=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550.js?file=action.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550#file-action-jsx\">View Gist</a></noscript>\r\n<p>If you don’t include an <code>action</code> attribute on your form, it will automatically submit to the same page. Again, in MVC thinking, the action would again be equivalent to the controller taking the request input and processing it. But honestly, this takes me back 15 years when form actions would point directly to PHP files.</p>\r\n<h2>Bonus: Progressive Enhancement</h2>\r\n<p>Since Remix is running on the server, you can turn off JavaScript and everything still works great. Data still loads, form actions still process; it’s beautiful. This is not running loaders and actions on the client side; it’s running them on the server. This isn’t an accident, the Remix team is carefully considering the UX.</p>\r\n<blockquote class=\"twitter-tweet\" data-dnt=\"true\" data-theme=\"dark\"><p lang=\"en\" dir=\"ltr\">User experience (UX) and developer experience (DX) are both important. UX is more important than DX.<a href=\"https://twitter.com/remix_run?ref_src=twsrc%5Etfw\">@remix_run</a> has taught me: It\'s easier to start with a great UX and work toward a good DX than it is to start with a great DX and work toward a good UX.</p>— Kent C. Dodds &#x1f4bf; (@kentcdodds) <a href=\"https://twitter.com/kentcdodds/status/1482390454389805058?ref_src=twsrc%5Etfw\">January 15, 2022</a></blockquote>\r\n<script async=\"\" src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\"></script>\r\n<h2>Bonus: So Speedy</h2>\r\n<p>Did I mention how fast everything renders? I don’t tend to put too much stock into Lighthouse scores since they seem so random, but Remix crushes Lighthouse without me having to invest any additional effort into improving performance.</p>\r\n<h2>Give it a Shot</h2>\r\n<p>Remix is built on the <a href=\"https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API\">native Fetch API</a>, so it can run anywhere. While Remix is relatively new, it’s certainly production ready, and there is a dedicated team behind it. If you aren’t ready to dive into Remix yet, at least keep your eye on it because this is a game changer.</p>',NULL,0,NULL,'2022-04-21 14:41:28','2022-04-21 14:41:28','17ae3c21-480f-4725-8208-0407f4706446',1,NULL,NULL,15,NULL),(1745,2377,'Why I’m So Excited About Remix',NULL,'<p>I’ve been building on the web for a long time. There’s a part of me that still has a bit of an old school mentality, and it’s hard for me to get really excited about new technology. Sure React was cool when it came out for its state management, but I didn’t see it as the be-all and end-all for building on the web. I really like <a href=\"https://craftcms.com/\">Craft CMS</a> for building CMS powered sites since I have full control over the HTML being sent to the browser, and it’s really easy to extend for complex functionality, but it can be a bit complex to setup for beginners and with additional complexity can come performance issues.&nbsp;So it’s been a while since I’ve seen something to be <em>really</em> excited about.</p>\r\n<p>Enter <a href=\"https://remix.run/\">Remix</a>.</p>\r\n<p>Remix is an interesting mix of old school techniques along with modern technology. Ryan Florence actually sums it up perfectly as to where Remix fits in.</p>\r\n<blockquote class=\"twitter-tweet\" data-dnt=\"true\" data-theme=\"dark\"><p lang=\"en\" dir=\"ltr\">Forget “full stack”. Remix is center stack.<br><br>It’s an HTTP tunnel between interactivity and business logic. It’s the part of the stack that no tool before it has solved, not completely.<br><br>I think I finally know how to talk about Remix.</p>— Ryan Florence (@ryanflorence) <a href=\"https://twitter.com/ryanflorence/status/1482233495195770883?ref_src=twsrc%5Etfw\">January 15, 2022</a></blockquote>\r\n<script async=\"\" src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\"></script>\r\n<p>I was able to easily switch my site that was fully powered by Craft to utilize Craft only as a GraphQL endpoint and Remix powering the rest. The two big things I needed to figure out were: how to get data from the GraphQL endpoint, and then how to process input from a user (for my contact form). I would definitely recommend reading through the Remix docs and the two tutorials, but if you can understand these two big pictures things, you’ll have enough to get started with Remix and go deeper once you get into it.</p>\r\n<h2>Getting GraphQL Data (aka Loaders)</h2>\r\n<p>Remix provides a <a href=\"https://remix.run/docs/en/v1/api/conventions#loader\">loader hook</a> that runs on the server to hydrate your component. In this simple example, I run a GraphQL request and return JSON with the results of that request in the loader function.</p>\r\n<script src=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550.js?file=loader.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550#file-loader-jsx\">View Gist</a></noscript>\r\n<p>Then in my <code>Index</code> component, I access the data from the loader hook with <a href=\"https://remix.run/docs/en/v1/api/remix#useloaderdata\">useLoaderData()</a>, and my component is now hydrated with that data. In MVC style of thinking, think of the loader hook as the controller processing the page load request, populating with data from the model, and then passing to the view.</p>\r\n<p>The great part about Remix is that this doesn’t have to be specifically a GraphQL request. This data can come from anywhere. The <a href=\"https://remix.run/docs/en/v1/tutorials/jokes\">Jokes tutorial</a> in the Remix docs even thoroughly walks through how you can manage all this data in <a href=\"https://www.prisma.io/\">Prisma</a>.</p>\r\n<h2>Processing User Input (aka Actions)</h2>\r\n<p>Ok great, so we’ve got data onto the page, but now we need to be able to handle user input. Remix also provides an <a href=\"https://remix.run/docs/en/v1/api/conventions#action\">action hook</a> to process an action request (ex: a form submission). In my case, I have a contact form that sends me an email via SendGrid after submission.</p>\r\n<script src=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550.js?file=action.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550#file-action-jsx\">View Gist</a></noscript>\r\n<p>If you don’t include an <code>action</code> attribute on your form, it will automatically submit to the same page. Again, in MVC thinking, the action would again be equivalent to the controller taking the request input and processing it. But honestly, this takes me back 15 years when form actions would point directly to PHP files.</p>\r\n<h2>Bonus: Progressive Enhancement</h2>\r\n<p>Since Remix is running on the server, you can turn off JavaScript and everything still works great. Data still loads, form actions still process; it’s beautiful. This is not running loaders and actions on the client side; it’s running them on the server. This isn’t an accident, the Remix team is carefully considering the UX.</p>\r\n<blockquote class=\"twitter-tweet\" data-dnt=\"true\" data-theme=\"dark\"><p lang=\"en\" dir=\"ltr\">User experience (UX) and developer experience (DX) are both important. UX is more important than DX.<a href=\"https://twitter.com/remix_run?ref_src=twsrc%5Etfw\">@remix_run</a> has taught me: It\'s easier to start with a great UX and work toward a good DX than it is to start with a great DX and work toward a good UX.</p>— Kent C. Dodds &#x1f4bf; (@kentcdodds) <a href=\"https://twitter.com/kentcdodds/status/1482390454389805058?ref_src=twsrc%5Etfw\">January 15, 2022</a></blockquote>\r\n<script async=\"\" src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\"></script>\r\n<h2>Bonus: So Speedy</h2>\r\n<p>Did I mention how fast everything renders? I don’t tend to put too much stock into Lighthouse scores since they seem so random, but Remix crushes Lighthouse without me having to invest any additional effort into improving performance.</p>\r\n<h2>Give it a Shot</h2>\r\n<p>Remix is built on the <a href=\"https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API\">native Fetch API</a>, so it can run anywhere. While Remix is relatively new, it’s certainly production ready, and there is a dedicated team behind it. If you aren’t ready to dive into Remix yet, at least keep your eye on it because this is a game changer.</p>',NULL,0,NULL,'2022-04-21 14:41:32','2022-04-21 14:41:32','ad18092e-7bba-4254-a0d7-2f65299453a6',1,NULL,NULL,18,NULL),(1746,2378,'Why I’m So Excited About Remix',NULL,'<p>I’ve been building on the web for a long time. There’s a part of me that still has a bit of an old school mentality, and it’s hard for me to get really excited about new technology. Sure React was cool when it came out for its state management, but I didn’t see it as the be-all and end-all for building on the web. I really like <a href=\"https://craftcms.com/\">Craft CMS</a> for building CMS powered sites since I have full control over the HTML being sent to the browser, and it’s really easy to extend for complex functionality, but it can be a bit complex to setup for beginners and with additional complexity can come performance issues.&nbsp;So it’s been a while since I’ve seen something to be <em>really</em> excited about.</p>\r\n<p>Enter <a href=\"https://remix.run/\">Remix</a>.</p>\r\n<p>Remix is an interesting mix of old school techniques along with modern technology. Ryan Florence actually sums it up perfectly as to where Remix fits in.</p>\r\n<blockquote class=\"twitter-tweet\" data-dnt=\"true\" data-theme=\"dark\"><p lang=\"en\" dir=\"ltr\">Forget “full stack”. Remix is center stack.<br><br>It’s an HTTP tunnel between interactivity and business logic. It’s the part of the stack that no tool before it has solved, not completely.<br><br>I think I finally know how to talk about Remix.</p>— Ryan Florence (@ryanflorence) <a href=\"https://twitter.com/ryanflorence/status/1482233495195770883?ref_src=twsrc%5Etfw\">January 15, 2022</a></blockquote>\r\n<script async=\"\" src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\"></script>\r\n<p>I was able to easily switch my site that was fully powered by Craft to utilize Craft only as a GraphQL endpoint and Remix powering the rest. The two big things I needed to figure out were: how to get data from the GraphQL endpoint, and then how to process input from a user (for my contact form). I would definitely recommend reading through the Remix docs and the two tutorials, but if you can understand these two big pictures things, you’ll have enough to get started with Remix and go deeper once you get into it.</p>\r\n<h2>Getting GraphQL Data (aka Loaders)</h2>\r\n<p>Remix provides a <a href=\"https://remix.run/docs/en/v1/api/conventions#loader\">loader hook</a> that runs on the server to hydrate your component. In this simple example, I run a GraphQL request and return JSON with the results of that request in the loader function.</p>\r\n<script src=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550.js?file=loader.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550#file-loader-jsx\">View Gist</a></noscript>\r\n<p>Then in my <code>Index</code> component, I access the data from the loader hook with <a href=\"https://remix.run/docs/en/v1/api/remix#useloaderdata\">useLoaderData()</a>, and my component is now hydrated with that data. In MVC style of thinking, think of the loader hook as the controller processing the page load request, populating with data from the model, and then passing to the view.</p>\r\n<p>The great part about Remix is that this doesn’t have to be specifically a GraphQL request. This data can come from anywhere. The <a href=\"https://remix.run/docs/en/v1/tutorials/jokes\">Jokes tutorial</a> in the Remix docs even thoroughly walks through how you can manage all this data in <a href=\"https://www.prisma.io/\">Prisma</a>.</p>\r\n<h2>Processing User Input (aka Actions)</h2>\r\n<p>Ok great, so we’ve got data onto the page, but now we need to be able to handle user input. Remix also provides an <a href=\"https://remix.run/docs/en/v1/api/conventions#action\">action hook</a> to process an action request (ex: a form submission). In my case, I have a contact form that sends me an email via SendGrid after submission.</p>\r\n<script src=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550.js?file=action.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550#file-action-jsx\">View Gist</a></noscript>\r\n<p>If you don’t include an <code>action</code> attribute on your form, it will automatically submit to the same page. Again, in MVC thinking, the action would again be equivalent to the controller taking the request input and processing it. But honestly, this takes me back 15 years when form actions would point directly to PHP files.</p>\r\n<h2>Bonus: Progressive Enhancement</h2>\r\n<p>Since Remix is running on the server, you can turn off JavaScript and everything still works great. Data still loads, form actions still process; it’s beautiful. This is not running loaders and actions on the client side; it’s running them on the server. This isn’t an accident, the Remix team is carefully considering the UX.</p>\r\n<blockquote class=\"twitter-tweet\" data-dnt=\"true\" data-theme=\"dark\"><p lang=\"en\" dir=\"ltr\">User experience (UX) and developer experience (DX) are both important. UX is more important than DX.<a href=\"https://twitter.com/remix_run?ref_src=twsrc%5Etfw\">@remix_run</a> has taught me: It\'s easier to start with a great UX and work toward a good DX than it is to start with a great DX and work toward a good UX.</p>— Kent C. Dodds &#x1f4bf; (@kentcdodds) <a href=\"https://twitter.com/kentcdodds/status/1482390454389805058?ref_src=twsrc%5Etfw\">January 15, 2022</a></blockquote>\r\n<script async=\"\" src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\"></script>\r\n<h2>Bonus: So Speedy</h2>\r\n<p>Did I mention how fast everything renders? I don’t tend to put too much stock into Lighthouse scores since they seem so random, but Remix crushes Lighthouse without me having to invest any additional effort into improving performance.</p>\r\n<h2>Give it a Shot</h2>\r\n<p>Remix is built on the <a href=\"https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API\">native Fetch API</a>, so it can run anywhere. While Remix is relatively new, it’s certainly production ready, and there is a dedicated team behind it. If you aren’t ready to dive into Remix yet, at least keep your eye on it because this is a game changer.</p>',NULL,0,NULL,'2022-04-21 14:41:39','2022-04-21 14:41:39','c64c5e8e-2331-45d9-9ad5-2bbf329b7e59',1,NULL,NULL,17,NULL),(1747,2379,'Why I’m So Excited About Remix',NULL,'<p>I’ve been building on the web for a long time. There’s a part of me that still has a bit of an old school mentality, and it’s hard for me to get really excited about new technology. Sure React was cool when it came out for its state management, but I didn’t see it as the be-all and end-all for building on the web. I really like <a href=\"https://craftcms.com/\">Craft CMS</a> for building CMS powered sites since I have full control over the HTML being sent to the browser, and it’s really easy to extend for complex functionality, but it can be a bit complex to setup for beginners and with additional complexity can come performance issues.&nbsp;So it’s been a while since I’ve seen something to be <em>really</em> excited about.</p>\r\n<p>Enter <a href=\"https://remix.run/\">Remix</a>.</p>\r\n<p>Remix is an interesting mix of old school techniques along with modern technology. Ryan Florence actually sums it up perfectly as to where Remix fits in.</p>\r\n<blockquote class=\"twitter-tweet\" data-dnt=\"true\" data-theme=\"dark\"><p lang=\"en\" dir=\"ltr\">Forget “full stack”. Remix is center stack.<br><br>It’s an HTTP tunnel between interactivity and business logic. It’s the part of the stack that no tool before it has solved, not completely.<br><br>I think I finally know how to talk about Remix.</p>— Ryan Florence (@ryanflorence) <a href=\"https://twitter.com/ryanflorence/status/1482233495195770883?ref_src=twsrc%5Etfw\">January 15, 2022</a></blockquote>\r\n<script async=\"\" src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\"></script>\r\n<p>I was able to easily switch my site that was fully powered by Craft to utilize Craft only as a GraphQL endpoint and Remix powering the rest. The two big things I needed to figure out were: how to get data from the GraphQL endpoint, and then how to process input from a user (for my contact form). I would definitely recommend reading through the Remix docs and the two tutorials, but if you can understand these two big pictures things, you’ll have enough to get started with Remix and go deeper once you get into it.</p>\r\n<h2>Getting GraphQL Data (aka Loaders)</h2>\r\n<p>Remix provides a <a href=\"https://remix.run/docs/en/v1/api/conventions#loader\">loader hook</a> that runs on the server to hydrate your component. In this simple example, I run a GraphQL request and return JSON with the results of that request in the loader function.</p>\r\n<script src=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550.js?file=loader.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550#file-loader-jsx\">View Gist</a></noscript>\r\n<p>Then in my <code>Index</code> component, I access the data from the loader hook with <a href=\"https://remix.run/docs/en/v1/api/remix#useloaderdata\">useLoaderData()</a>, and my component is now hydrated with that data. In MVC style of thinking, think of the loader hook as the controller processing the page load request, populating with data from the model, and then passing to the view.</p>\r\n<p>The great part about Remix is that this doesn’t have to be specifically a GraphQL request. This data can come from anywhere. The <a href=\"https://remix.run/docs/en/v1/tutorials/jokes\">Jokes tutorial</a> in the Remix docs even thoroughly walks through how you can manage all this data in <a href=\"https://www.prisma.io/\">Prisma</a>.</p>\r\n<h2>Processing User Input (aka Actions)</h2>\r\n<p>Ok great, so we’ve got data onto the page, but now we need to be able to handle user input. Remix also provides an <a href=\"https://remix.run/docs/en/v1/api/conventions#action\">action hook</a> to process an action request (ex: a form submission). In my case, I have a contact form that sends me an email via SendGrid after submission.</p>\r\n<script src=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550.js?file=action.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550#file-action-jsx\">View Gist</a></noscript>\r\n<p>If you don’t include an <code>action</code> attribute on your form, it will automatically submit to the same page. Again, in MVC thinking, the action would again be equivalent to the controller taking the request input and processing it. But honestly, this takes me back 15 years when form actions would point directly to PHP files.</p>\r\n<h2>Bonus: Progressive Enhancement</h2>\r\n<p>Since Remix is running on the server, you can turn off JavaScript and everything still works great. Data still loads, form actions still process; it’s beautiful. This is not running loaders and actions on the client side; it’s running them on the server. This isn’t an accident, the Remix team is carefully considering the UX.</p>\r\n<blockquote class=\"twitter-tweet\" data-dnt=\"true\" data-theme=\"dark\"><p lang=\"en\" dir=\"ltr\">User experience (UX) and developer experience (DX) are both important. UX is more important than DX.<a href=\"https://twitter.com/remix_run?ref_src=twsrc%5Etfw\">@remix_run</a> has taught me: It\'s easier to start with a great UX and work toward a good DX than it is to start with a great DX and work toward a good UX.</p>— Kent C. Dodds &#x1f4bf; (@kentcdodds) <a href=\"https://twitter.com/kentcdodds/status/1482390454389805058?ref_src=twsrc%5Etfw\">January 15, 2022</a></blockquote>\r\n<script async=\"\" src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\"></script>\r\n<h2>Bonus: So Speedy</h2>\r\n<p>Did I mention how fast everything renders? I don’t tend to put too much stock into Lighthouse scores since they seem so random, but Remix crushes Lighthouse without me having to invest any additional effort into improving performance.</p>\r\n<h2>Give it a Shot</h2>\r\n<p>Remix is built on the <a href=\"https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API\">native Fetch API</a>, so it can run anywhere. While Remix is relatively new, it’s certainly production ready, and there is a dedicated team behind it. If you aren’t ready to dive into Remix yet, at least keep your eye on it because this is a game changer.</p>',NULL,0,NULL,'2022-04-21 14:41:44','2022-04-21 14:41:44','e30287f0-558b-4800-8aef-fe7cc22ac8c5',1,NULL,NULL,16,NULL),(1748,2380,'Why I’m So Excited About Remix',NULL,'<p>I’ve been building on the web for a long time. There’s a part of me that still has a bit of an old school mentality, and it’s hard for me to get really excited about new technology. Sure React was cool when it came out for its state management, but I didn’t see it as the be-all and end-all for building on the web. I really like <a href=\"https://craftcms.com/\">Craft CMS</a> for building CMS powered sites since I have full control over the HTML being sent to the browser, and it’s really easy to extend for complex functionality, but it can be a bit complex to setup for beginners and with additional complexity can come performance issues.&nbsp;So it’s been a while since I’ve seen something to be <em>really</em> excited about.</p>\r\n<p>Enter <a href=\"https://remix.run/\">Remix</a>.</p>\r\n<p>Remix is an interesting mix of old school techniques along with modern technology. Ryan Florence actually sums it up perfectly as to where Remix fits in.</p>\r\n<blockquote class=\"twitter-tweet\" data-dnt=\"true\" data-theme=\"dark\"><p lang=\"en\" dir=\"ltr\">Forget “full stack”. Remix is center stack.<br><br>It’s an HTTP tunnel between interactivity and business logic. It’s the part of the stack that no tool before it has solved, not completely.<br><br>I think I finally know how to talk about Remix.</p>— Ryan Florence (@ryanflorence) <a href=\"https://twitter.com/ryanflorence/status/1482233495195770883?ref_src=twsrc%5Etfw\">January 15, 2022</a></blockquote>\r\n<script async=\"\" src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\"></script>\r\n<p>I was able to easily switch my site that was fully powered by Craft to utilize Craft only as a GraphQL endpoint and Remix powering the rest. The two big things I needed to figure out were: how to get data from the GraphQL endpoint, and then how to process input from a user (for my contact form). I would definitely recommend reading through the Remix docs and the two tutorials, but if you can understand these two big pictures things, you’ll have enough to get started with Remix and go deeper once you get into it.</p>\r\n<h2>Getting GraphQL Data (aka Loaders)</h2>\r\n<p>Remix provides a <a href=\"https://remix.run/docs/en/v1/api/conventions#loader\">loader hook</a> that runs on the server to hydrate your component. In this simple example, I run a GraphQL request and return JSON with the results of that request in the loader function.</p>\r\n<script src=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550.js?file=loader.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550#file-loader-jsx\">View Gist</a></noscript>\r\n<p>Then in my <code>Index</code> component, I access the data from the loader hook with <a href=\"https://remix.run/docs/en/v1/api/remix#useloaderdata\">useLoaderData()</a>, and my component is now hydrated with that data. In MVC style of thinking, think of the loader hook as the controller processing the page load request, populating with data from the model, and then passing to the view.</p>\r\n<p>The great part about Remix is that this doesn’t have to be specifically a GraphQL request. This data can come from anywhere. The <a href=\"https://remix.run/docs/en/v1/tutorials/jokes\">Jokes tutorial</a> in the Remix docs even thoroughly walks through how you can manage all this data in <a href=\"https://www.prisma.io/\">Prisma</a>.</p>\r\n<h2>Processing User Input (aka Actions)</h2>\r\n<p>Ok great, so we’ve got data onto the page, but now we need to be able to handle user input. Remix also provides an <a href=\"https://remix.run/docs/en/v1/api/conventions#action\">action hook</a> to process an action request (ex: a form submission). In my case, I have a contact form that sends me an email via SendGrid after submission.</p>\r\n<script src=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550.js?file=action.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550#file-action-jsx\">View Gist</a></noscript>\r\n<p>If you don’t include an <code>action</code> attribute on your form, it will automatically submit to the same page. Again, in MVC thinking, the action would again be equivalent to the controller taking the request input and processing it. But honestly, this takes me back 15 years when form actions would point directly to PHP files.</p>\r\n<h2>Bonus: Progressive Enhancement</h2>\r\n<p>Since Remix is running on the server, you can turn off JavaScript and everything still works great. Data still loads, form actions still process; it’s beautiful. This is not running loaders and actions on the client side; it’s running them on the server. This isn’t an accident, the Remix team is carefully considering the UX.</p>\r\n<blockquote class=\"twitter-tweet\" data-dnt=\"true\" data-theme=\"dark\"><p lang=\"en\" dir=\"ltr\">User experience (UX) and developer experience (DX) are both important. UX is more important than DX.<a href=\"https://twitter.com/remix_run?ref_src=twsrc%5Etfw\">@remix_run</a> has taught me: It\'s easier to start with a great UX and work toward a good DX than it is to start with a great DX and work toward a good UX.</p>— Kent C. Dodds &#x1f4bf; (@kentcdodds) <a href=\"https://twitter.com/kentcdodds/status/1482390454389805058?ref_src=twsrc%5Etfw\">January 15, 2022</a></blockquote>\r\n<script async=\"\" src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\"></script>\r\n<h2>Bonus: So Speedy</h2>\r\n<p>Did I mention how fast everything renders? I don’t tend to put too much stock into Lighthouse scores since they seem so random, but Remix crushes Lighthouse without me having to invest any additional effort into improving performance.</p>\r\n<h2>Give it a Shot</h2>\r\n<p>Remix is built on the <a href=\"https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API\">native Fetch API</a>, so it can run anywhere. While Remix is relatively new, it’s certainly production ready, and there is a dedicated team behind it. If you aren’t ready to dive into Remix yet, at least keep your eye on it because this is a game changer.</p>',NULL,0,NULL,'2022-04-21 14:41:52','2022-04-21 14:41:52','0012314f-f489-40f4-932d-bbc4e6d85177',1,NULL,NULL,15,NULL),(1749,2381,'Why I’m So Excited About Remix',NULL,'<p>I’ve been building on the web for a long time. There’s a part of me that still has a bit of an old school mentality, and it’s hard for me to get really excited about new technology. Sure React was cool when it came out for its state management, but I didn’t see it as the be-all and end-all for building on the web. I really like <a href=\"https://craftcms.com/\">Craft CMS</a> for building CMS powered sites since I have full control over the HTML being sent to the browser, and it’s really easy to extend for complex functionality, but it can be a bit complex to setup for beginners and with additional complexity can come performance issues.&nbsp;So it’s been a while since I’ve seen something to be <em>really</em> excited about.</p>\r\n<p>Enter <a href=\"https://remix.run/\">Remix</a>.</p>\r\n<p>Remix is an interesting mix of old school techniques along with modern technology. Ryan Florence actually sums it up perfectly as to where Remix fits in.</p>\r\n<blockquote class=\"twitter-tweet\" data-dnt=\"true\" data-theme=\"dark\"><p lang=\"en\" dir=\"ltr\">Forget “full stack”. Remix is center stack.<br><br>It’s an HTTP tunnel between interactivity and business logic. It’s the part of the stack that no tool before it has solved, not completely.<br><br>I think I finally know how to talk about Remix.</p>— Ryan Florence (@ryanflorence) <a href=\"https://twitter.com/ryanflorence/status/1482233495195770883?ref_src=twsrc%5Etfw\">January 15, 2022</a></blockquote>\r\n<script async=\"\" src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\"></script>\r\n<p>I was able to easily switch my site that was fully powered by Craft to utilize Craft only as a GraphQL endpoint and Remix powering the rest. The two big things I needed to figure out were: how to get data from the GraphQL endpoint, and then how to process input from a user (for my contact form). I would definitely recommend reading through the Remix docs and the two tutorials, but if you can understand these two big pictures things, you’ll have enough to get started with Remix and go deeper once you get into it.</p>\r\n<h2>Getting GraphQL Data (aka Loaders)</h2>\r\n<p>Remix provides a <a href=\"https://remix.run/docs/en/v1/api/conventions#loader\">loader hook</a> that runs on the server to hydrate your component. In this simple example, I run a GraphQL request and return JSON with the results of that request in the loader function.</p>\r\n<script src=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550.js?file=loader.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550#file-loader-jsx\">View Gist</a></noscript>\r\n<p>Then in my <code>Index</code> component, I access the data from the loader hook with <a href=\"https://remix.run/docs/en/v1/api/remix#useloaderdata\">useLoaderData()</a>, and my component is now hydrated with that data. In MVC style of thinking, think of the loader hook as the controller processing the page load request, populating with data from the model, and then passing to the view.</p>\r\n<p>The great part about Remix is that this doesn’t have to be specifically a GraphQL request. This data can come from anywhere. The <a href=\"https://remix.run/docs/en/v1/tutorials/jokes\">Jokes tutorial</a> in the Remix docs even thoroughly walks through how you can manage all this data in <a href=\"https://www.prisma.io/\">Prisma</a>.</p>\r\n<h2>Processing User Input (aka Actions)</h2>\r\n<p>Ok great, so we’ve got data onto the page, but now we need to be able to handle user input. Remix also provides an <a href=\"https://remix.run/docs/en/v1/api/conventions#action\">action hook</a> to process an action request (ex: a form submission). In my case, I have a contact form that sends me an email via SendGrid after submission.</p>\r\n<script src=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550.js?file=action.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550#file-action-jsx\">View Gist</a></noscript>\r\n<p>If you don’t include an <code>action</code> attribute on your form, it will automatically submit to the same page. Again, in MVC thinking, the action would again be equivalent to the controller taking the request input and processing it. But honestly, this takes me back 15 years when form actions would point directly to PHP files.</p>\r\n<h2>Bonus: Progressive Enhancement</h2>\r\n<p>Since Remix is running on the server, you can turn off JavaScript and everything still works great. Data still loads, form actions still process; it’s beautiful. This is not running loaders and actions on the client side; it’s running them on the server. This isn’t an accident, the Remix team is carefully considering the UX.</p>\r\n<blockquote class=\"twitter-tweet\" data-dnt=\"true\" data-theme=\"dark\"><p lang=\"en\" dir=\"ltr\">User experience (UX) and developer experience (DX) are both important. UX is more important than DX.<a href=\"https://twitter.com/remix_run?ref_src=twsrc%5Etfw\">@remix_run</a> has taught me: It\'s easier to start with a great UX and work toward a good DX than it is to start with a great DX and work toward a good UX.</p>— Kent C. Dodds &#x1f4bf; (@kentcdodds) <a href=\"https://twitter.com/kentcdodds/status/1482390454389805058?ref_src=twsrc%5Etfw\">January 15, 2022</a></blockquote>\r\n<script async=\"\" src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\"></script>\r\n<h2>Bonus: So Speedy</h2>\r\n<p>Did I mention how fast everything renders? I don’t tend to put too much stock into Lighthouse scores since they seem so random, but Remix crushes Lighthouse without me having to invest any additional effort into improving performance.</p>\r\n<h2>Give it a Shot</h2>\r\n<p>Remix is built on the <a href=\"https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API\">native Fetch API</a>, so it can run anywhere. While Remix is relatively new, it’s certainly production ready, and there is a dedicated team behind it. If you aren’t ready to dive into Remix yet, at least keep your eye on it because this is a game changer.</p>',NULL,0,NULL,'2022-04-21 14:41:55','2022-04-21 14:41:55','91d9d7ec-ef86-42d1-be66-d9998b1200e7',1,NULL,NULL,14,NULL),(1750,2382,'Why I’m So Excited About Remix',NULL,'<p>I’ve been building on the web for a long time. There’s a part of me that still has a bit of an old school mentality, and it’s hard for me to get really excited about new technology. Sure React was cool when it came out for its state management, but I didn’t see it as the be-all and end-all for building on the web. I really like <a href=\"https://craftcms.com/\">Craft CMS</a> for building CMS powered sites since I have full control over the HTML being sent to the browser, and it’s really easy to extend for complex functionality, but it can be a bit complex to setup for beginners and with additional complexity can come performance issues.&nbsp;So it’s been a while since I’ve seen something to be <em>really</em> excited about.</p>\r\n<p>Enter <a href=\"https://remix.run/\">Remix</a>.</p>\r\n<p>Remix is an interesting mix of old school techniques along with modern technology. Ryan Florence actually sums it up perfectly as to where Remix fits in.</p>\r\n<blockquote class=\"twitter-tweet\" data-dnt=\"true\" data-theme=\"dark\"><p lang=\"en\" dir=\"ltr\">Forget “full stack”. Remix is center stack.<br><br>It’s an HTTP tunnel between interactivity and business logic. It’s the part of the stack that no tool before it has solved, not completely.<br><br>I think I finally know how to talk about Remix.</p>— Ryan Florence (@ryanflorence) <a href=\"https://twitter.com/ryanflorence/status/1482233495195770883?ref_src=twsrc%5Etfw\">January 15, 2022</a></blockquote>\r\n<script async=\"\" src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\"></script>\r\n<p>I was able to easily switch my site that was fully powered by Craft to utilize Craft only as a GraphQL endpoint and Remix powering the rest. The two big things I needed to figure out were: how to get data from the GraphQL endpoint, and then how to process input from a user (for my contact form). I would definitely recommend reading through the Remix docs and the two tutorials, but if you can understand these two big pictures things, you’ll have enough to get started with Remix and go deeper once you get into it.</p>\r\n<h2>Getting GraphQL Data (aka Loaders)</h2>\r\n<p>Remix provides a <a href=\"https://remix.run/docs/en/v1/api/conventions#loader\">loader hook</a> that runs on the server to hydrate your component. In this simple example, I run a GraphQL request and return JSON with the results of that request in the loader function.</p>\r\n<script src=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550.js?file=loader.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550#file-loader-jsx\">View Gist</a></noscript>\r\n<p>Then in my <code>Index</code> component, I access the data from the loader hook with <a href=\"https://remix.run/docs/en/v1/api/remix#useloaderdata\">useLoaderData()</a>, and my component is now hydrated with that data. In MVC style of thinking, think of the loader hook as the controller processing the page load request, populating with data from the model, and then passing to the view.</p>\r\n<p>The great part about Remix is that this doesn’t have to be specifically a GraphQL request. This data can come from anywhere. The <a href=\"https://remix.run/docs/en/v1/tutorials/jokes\">Jokes tutorial</a> in the Remix docs even thoroughly walks through how you can manage all this data in <a href=\"https://www.prisma.io/\">Prisma</a>.</p>\r\n<h2>Processing User Input (aka Actions)</h2>\r\n<p>Ok great, so we’ve got data onto the page, but now we need to be able to handle user input. Remix also provides an <a href=\"https://remix.run/docs/en/v1/api/conventions#action\">action hook</a> to process an action request (ex: a form submission). In my case, I have a contact form that sends me an email via SendGrid after submission.</p>\r\n<script src=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550.js?file=action.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550#file-action-jsx\">View Gist</a></noscript>\r\n<p>If you don’t include an <code>action</code> attribute on your form, it will automatically submit to the same page. Again, in MVC thinking, the action would again be equivalent to the controller taking the request input and processing it. But honestly, this takes me back 15 years when form actions would point directly to PHP files.</p>\r\n<h2>Bonus: Progressive Enhancement</h2>\r\n<p>Since Remix is running on the server, you can turn off JavaScript and everything still works great. Data still loads, form actions still process; it’s beautiful. This is not running loaders and actions on the client side; it’s running them on the server. This isn’t an accident, the Remix team is carefully considering the UX.</p>\r\n<blockquote class=\"twitter-tweet\" data-dnt=\"true\" data-theme=\"dark\"><p lang=\"en\" dir=\"ltr\">User experience (UX) and developer experience (DX) are both important. UX is more important than DX.<a href=\"https://twitter.com/remix_run?ref_src=twsrc%5Etfw\">@remix_run</a> has taught me: It\'s easier to start with a great UX and work toward a good DX than it is to start with a great DX and work toward a good UX.</p>— Kent C. Dodds &#x1f4bf; (@kentcdodds) <a href=\"https://twitter.com/kentcdodds/status/1482390454389805058?ref_src=twsrc%5Etfw\">January 15, 2022</a></blockquote>\r\n<script async=\"\" src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\"></script>\r\n<h2>Bonus: So Speedy</h2>\r\n<p>Did I mention how fast everything renders? I don’t tend to put too much stock into Lighthouse scores since they seem so random, but Remix crushes Lighthouse without me having to invest any additional effort into improving performance.</p>\r\n<h2>Give it a Shot</h2>\r\n<p>Remix is built on the <a href=\"https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API\">native Fetch API</a>, so it can run anywhere. While Remix is relatively new, it’s certainly production ready, and there is a dedicated team behind it. If you aren’t ready to dive into Remix yet, at least keep your eye on it because this is a game changer.</p>',NULL,0,NULL,'2022-04-21 14:42:12','2022-04-21 14:42:12','7a623479-1840-4f9c-b830-35eb4208b0c8',1,NULL,NULL,13,NULL),(1751,2383,'Why I’m So Excited About Remix',NULL,'<p>I’ve been building on the web for a long time. There’s a part of me that still has a bit of an old school mentality, and it’s hard for me to get really excited about new technology. Sure React was cool when it came out for its state management, but I didn’t see it as the be-all and end-all for building on the web. I really like <a href=\"https://craftcms.com/\">Craft CMS</a> for building CMS powered sites since I have full control over the HTML being sent to the browser, and it’s really easy to extend for complex functionality, but it can be a bit complex to setup for beginners and with additional complexity can come performance issues.&nbsp;So it’s been a while since I’ve seen something to be <em>really</em> excited about.</p>\r\n<p>Enter <a href=\"https://remix.run/\">Remix</a>.</p>\r\n<p>Remix is an interesting mix of old school techniques along with modern technology. Ryan Florence actually sums it up perfectly as to where Remix fits in.</p>\r\n<blockquote class=\"twitter-tweet\" data-dnt=\"true\" data-theme=\"dark\"><p lang=\"en\" dir=\"ltr\">Forget “full stack”. Remix is center stack.<br><br>It’s an HTTP tunnel between interactivity and business logic. It’s the part of the stack that no tool before it has solved, not completely.<br><br>I think I finally know how to talk about Remix.</p>— Ryan Florence (@ryanflorence) <a href=\"https://twitter.com/ryanflorence/status/1482233495195770883?ref_src=twsrc%5Etfw\">January 15, 2022</a></blockquote>\r\n<script async=\"\" src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\"></script>\r\n<p>I was able to easily switch my site that was fully powered by Craft to utilize Craft only as a GraphQL endpoint and Remix powering the rest. The two big things I needed to figure out were: how to get data from the GraphQL endpoint, and then how to process input from a user (for my contact form). I would definitely recommend reading through the Remix docs and the two tutorials, but if you can understand these two big pictures things, you’ll have enough to get started with Remix and go deeper once you get into it.</p>\r\n<h2>Getting GraphQL Data (aka Loaders)</h2>\r\n<p>Remix provides a <a href=\"https://remix.run/docs/en/v1/api/conventions#loader\">loader hook</a> that runs on the server to hydrate your component. In this simple example, I run a GraphQL request and return JSON with the results of that request in the loader function.</p>\r\n<script src=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550.js?file=loader.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550#file-loader-jsx\">View Gist</a></noscript>\r\n<p>Then in my <code>Index</code> component, I access the data from the loader hook with <a href=\"https://remix.run/docs/en/v1/api/remix#useloaderdata\">useLoaderData()</a>, and my component is now hydrated with that data. In MVC style of thinking, think of the loader hook as the controller processing the page load request, populating with data from the model, and then passing to the view.</p>\r\n<p>The great part about Remix is that this doesn’t have to be specifically a GraphQL request. This data can come from anywhere. The <a href=\"https://remix.run/docs/en/v1/tutorials/jokes\">Jokes tutorial</a> in the Remix docs even thoroughly walks through how you can manage all this data in <a href=\"https://www.prisma.io/\">Prisma</a>.</p>\r\n<h2>Processing User Input (aka Actions)</h2>\r\n<p>Ok great, so we’ve got data onto the page, but now we need to be able to handle user input. Remix also provides an <a href=\"https://remix.run/docs/en/v1/api/conventions#action\">action hook</a> to process an action request (ex: a form submission). In my case, I have a contact form that sends me an email via SendGrid after submission.</p>\r\n<script src=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550.js?file=action.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550#file-action-jsx\">View Gist</a></noscript>\r\n<p>If you don’t include an <code>action</code> attribute on your form, it will automatically submit to the same page. Again, in MVC thinking, the action would again be equivalent to the controller taking the request input and processing it. But honestly, this takes me back 15 years when form actions would point directly to PHP files.</p>\r\n<h2>Bonus: Progressive Enhancement</h2>\r\n<p>Since Remix is running on the server, you can turn off JavaScript and everything still works great. Data still loads, form actions still process; it’s beautiful. This is not running loaders and actions on the client side; it’s running them on the server. This isn’t an accident, the Remix team is carefully considering the UX.</p>\r\n<blockquote class=\"twitter-tweet\" data-dnt=\"true\" data-theme=\"dark\"><p lang=\"en\" dir=\"ltr\">User experience (UX) and developer experience (DX) are both important. UX is more important than DX.<a href=\"https://twitter.com/remix_run?ref_src=twsrc%5Etfw\">@remix_run</a> has taught me: It\'s easier to start with a great UX and work toward a good DX than it is to start with a great DX and work toward a good UX.</p>— Kent C. Dodds &#x1f4bf; (@kentcdodds) <a href=\"https://twitter.com/kentcdodds/status/1482390454389805058?ref_src=twsrc%5Etfw\">January 15, 2022</a></blockquote>\r\n<script async=\"\" src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\"></script>\r\n<h2>Bonus: So Speedy</h2>\r\n<p>Did I mention how fast everything renders? I don’t tend to put too much stock into Lighthouse scores since they seem so random, but Remix crushes Lighthouse without me having to invest any additional effort into improving performance.</p>\r\n<h2>Give it a Shot</h2>\r\n<p>Remix is built on the <a href=\"https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API\">native Fetch API</a>, so it can run anywhere. While Remix is relatively new, it’s certainly production ready, and there is a dedicated team behind it. If you aren’t ready to dive into Remix yet, at least keep your eye on it because this is a game changer.</p>',NULL,0,NULL,'2022-04-21 14:44:55','2022-04-21 14:44:55','d87713f4-b471-47e7-a754-57a32804c7c8',1,NULL,NULL,12,NULL),(1752,2384,'Why I’m So Excited About Remix',NULL,'<p>I’ve been building on the web for a long time. There’s a part of me that still has a bit of an old school mentality, and it’s hard for me to get really excited about new technology. Sure React was cool when it came out for its state management, but I didn’t see it as the be-all and end-all for building on the web. I really like <a href=\"https://craftcms.com/\">Craft CMS</a> for building CMS powered sites since I have full control over the HTML being sent to the browser, and it’s really easy to extend for complex functionality, but it can be a bit complex to setup for beginners and with additional complexity can come performance issues.&nbsp;So it’s been a while since I’ve seen something to be <em>really</em> excited about.</p>\r\n<p>Enter <a href=\"https://remix.run/\">Remix</a>.</p>\r\n<p>Remix is an interesting mix of old school techniques along with modern technology. Ryan Florence actually sums it up perfectly as to where Remix fits in.</p>\r\n<blockquote class=\"twitter-tweet\" data-dnt=\"true\" data-theme=\"dark\"><p lang=\"en\" dir=\"ltr\">Forget “full stack”. Remix is center stack.<br><br>It’s an HTTP tunnel between interactivity and business logic. It’s the part of the stack that no tool before it has solved, not completely.<br><br>I think I finally know how to talk about Remix.</p>— Ryan Florence (@ryanflorence) <a href=\"https://twitter.com/ryanflorence/status/1482233495195770883?ref_src=twsrc%5Etfw\">January 15, 2022</a></blockquote>\r\n<script async=\"\" src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\"></script>\r\n<p>I was able to easily switch my site that was fully powered by Craft to utilize Craft only as a GraphQL endpoint and Remix powering the rest. The two big things I needed to figure out were: how to get data from the GraphQL endpoint, and then how to process input from a user (for my contact form). I would definitely recommend reading through the Remix docs and the two tutorials, but if you can understand these two big pictures things, you’ll have enough to get started with Remix and go deeper once you get into it.</p>\r\n<h2>Getting GraphQL Data (aka Loaders)</h2>\r\n<p>Remix provides a <a href=\"https://remix.run/docs/en/v1/api/conventions#loader\">loader hook</a> that runs on the server to hydrate your component. In this simple example, I run a GraphQL request and return JSON with the results of that request in the loader function.</p>\r\n<script src=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550.js?file=loader.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550#file-loader-jsx\">View Gist</a></noscript>\r\n<p>Then in my <code>Index</code> component, I access the data from the loader hook with <a href=\"https://remix.run/docs/en/v1/api/remix#useloaderdata\">useLoaderData()</a>, and my component is now hydrated with that data. In MVC style of thinking, think of the loader hook as the controller processing the page load request, populating with data from the model, and then passing to the view.</p>\r\n<p>The great part about Remix is that this doesn’t have to be specifically a GraphQL request. This data can come from anywhere. The <a href=\"https://remix.run/docs/en/v1/tutorials/jokes\">Jokes tutorial</a> in the Remix docs even thoroughly walks through how you can manage all this data in <a href=\"https://www.prisma.io/\">Prisma</a>.</p>\r\n<h2>Processing User Input (aka Actions)</h2>\r\n<p>Ok great, so we’ve got data onto the page, but now we need to be able to handle user input. Remix also provides an <a href=\"https://remix.run/docs/en/v1/api/conventions#action\">action hook</a> to process an action request (ex: a form submission). In my case, I have a contact form that sends me an email via SendGrid after submission.</p>\r\n<script src=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550.js?file=action.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550#file-action-jsx\">View Gist</a></noscript>\r\n<p>If you don’t include an <code>action</code> attribute on your form, it will automatically submit to the same page. Again, in MVC thinking, the action would again be equivalent to the controller taking the request input and processing it. But honestly, this takes me back 15 years when form actions would point directly to PHP files.</p>\r\n<h2>Bonus: Progressive Enhancement</h2>\r\n<p>Since Remix is running on the server, you can turn off JavaScript and everything still works great. Data still loads, form actions still process; it’s beautiful. This is not running loaders and actions on the client side; it’s running them on the server. This isn’t an accident, the Remix team is carefully considering the UX.</p>\r\n<blockquote class=\"twitter-tweet\" data-dnt=\"true\" data-theme=\"dark\"><p lang=\"en\" dir=\"ltr\">User experience (UX) and developer experience (DX) are both important. UX is more important than DX.<a href=\"https://twitter.com/remix_run?ref_src=twsrc%5Etfw\">@remix_run</a> has taught me: It\'s easier to start with a great UX and work toward a good DX than it is to start with a great DX and work toward a good UX.</p>— Kent C. Dodds &#x1f4bf; (@kentcdodds) <a href=\"https://twitter.com/kentcdodds/status/1482390454389805058?ref_src=twsrc%5Etfw\">January 15, 2022</a></blockquote>\r\n<script async=\"\" src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\"></script>\r\n<h2>Bonus: So Speedy</h2>\r\n<p>Did I mention how fast everything renders? I don’t tend to put too much stock into Lighthouse scores since they seem so random, but Remix crushes Lighthouse without me having to invest any additional effort into improving performance.</p>\r\n<h2>Give it a Shot</h2>\r\n<p>Remix is built on the <a href=\"https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API\">native Fetch API</a>, so it can run anywhere. While Remix is relatively new, it’s certainly production ready, and there is a dedicated team behind it. If you aren’t ready to dive into Remix yet, at least keep your eye on it because this is a game changer.</p>',NULL,0,NULL,'2022-04-21 14:44:56','2022-04-21 14:44:56','ab3bc6e0-1828-4c77-be63-c82c6d086e75',1,NULL,NULL,14,NULL),(1753,2385,'Why I’m So Excited About Remix',NULL,'<p>I’ve been building on the web for a long time. There’s a part of me that still has a bit of an old school mentality, and it’s hard for me to get really excited about new technology. Sure React was cool when it came out for its state management, but I didn’t see it as the be-all and end-all for building on the web. I really like <a href=\"https://craftcms.com/\">Craft CMS</a> for building CMS powered sites since I have full control over the HTML being sent to the browser, and it’s really easy to extend for complex functionality, but it can be a bit complex to setup for beginners and with additional complexity can come performance issues.&nbsp;So it’s been a while since I’ve seen something to be <em>really</em> excited about.</p>\r\n<p>Enter <a href=\"https://remix.run/\">Remix</a>.</p>\r\n<p>Remix is an interesting mix of old school techniques along with modern technology. Ryan Florence actually sums it up perfectly as to where Remix fits in.</p>\r\n<blockquote class=\"twitter-tweet\" data-dnt=\"true\" data-theme=\"dark\"><p lang=\"en\" dir=\"ltr\">Forget “full stack”. Remix is center stack.<br><br>It’s an HTTP tunnel between interactivity and business logic. It’s the part of the stack that no tool before it has solved, not completely.<br><br>I think I finally know how to talk about Remix.</p>— Ryan Florence (@ryanflorence) <a href=\"https://twitter.com/ryanflorence/status/1482233495195770883?ref_src=twsrc%5Etfw\">January 15, 2022</a></blockquote>\r\n<script async=\"\" src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\"></script>\r\n<p>I was able to easily switch my site that was fully powered by Craft to utilize Craft only as a GraphQL endpoint and Remix powering the rest. The two big things I needed to figure out were: how to get data from the GraphQL endpoint, and then how to process input from a user (for my contact form). I would definitely recommend reading through the Remix docs and the two tutorials, but if you can understand these two big pictures things, you’ll have enough to get started with Remix and go deeper once you get into it.</p>\r\n<h2>Getting GraphQL Data (aka Loaders)</h2>\r\n<p>Remix provides a <a href=\"https://remix.run/docs/en/v1/api/conventions#loader\">loader hook</a> that runs on the server to hydrate your component. In this simple example, I run a GraphQL request and return JSON with the results of that request in the loader function.</p>\r\n<script src=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550.js?file=loader.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550#file-loader-jsx\">View Gist</a></noscript>\r\n<p>Then in my <code>Index</code> component, I access the data from the loader hook with <a href=\"https://remix.run/docs/en/v1/api/remix#useloaderdata\">useLoaderData()</a>, and my component is now hydrated with that data. In MVC style of thinking, think of the loader hook as the controller processing the page load request, populating with data from the model, and then passing to the view.</p>\r\n<p>The great part about Remix is that this doesn’t have to be specifically a GraphQL request. This data can come from anywhere. The <a href=\"https://remix.run/docs/en/v1/tutorials/jokes\">Jokes tutorial</a> in the Remix docs even thoroughly walks through how you can manage all this data in <a href=\"https://www.prisma.io/\">Prisma</a>.</p>\r\n<h2>Processing User Input (aka Actions)</h2>\r\n<p>Ok great, so we’ve got data onto the page, but now we need to be able to handle user input. Remix also provides an <a href=\"https://remix.run/docs/en/v1/api/conventions#action\">action hook</a> to process an action request (ex: a form submission). In my case, I have a contact form that sends me an email via SendGrid after submission.</p>\r\n<script src=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550.js?file=action.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550#file-action-jsx\">View Gist</a></noscript>\r\n<p>If you don’t include an <code>action</code> attribute on your form, it will automatically submit to the same page. Again, in MVC thinking, the action would again be equivalent to the controller taking the request input and processing it. But honestly, this takes me back 15 years when form actions would point directly to PHP files.</p>\r\n<h2>Bonus: Progressive Enhancement</h2>\r\n<p>Since Remix is running on the server, you can turn off JavaScript and everything still works great. Data still loads, form actions still process; it’s beautiful. This is not running loaders and actions on the client side; it’s running them on the server. This isn’t an accident, the Remix team is carefully considering the UX.</p>\r\n<blockquote class=\"twitter-tweet\" data-dnt=\"true\" data-theme=\"dark\"><p lang=\"en\" dir=\"ltr\">User experience (UX) and developer experience (DX) are both important. UX is more important than DX.<a href=\"https://twitter.com/remix_run?ref_src=twsrc%5Etfw\">@remix_run</a> has taught me: It\'s easier to start with a great UX and work toward a good DX than it is to start with a great DX and work toward a good UX.</p>— Kent C. Dodds &#x1f4bf; (@kentcdodds) <a href=\"https://twitter.com/kentcdodds/status/1482390454389805058?ref_src=twsrc%5Etfw\">January 15, 2022</a></blockquote>\r\n<script async=\"\" src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\"></script>\r\n<h2>Bonus: So Speedy</h2>\r\n<p>Did I mention how fast everything renders? I don’t tend to put too much stock into Lighthouse scores since they seem so random, but Remix crushes Lighthouse without me having to invest any additional effort into improving performance.</p>\r\n<h2>Give it a Shot</h2>\r\n<p>Remix is built on the <a href=\"https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API\">native Fetch API</a>, so it can run anywhere. While Remix is relatively new, it’s certainly production ready, and there is a dedicated team behind it. If you aren’t ready to dive into Remix yet, at least keep your eye on it because this is a game changer.</p>',NULL,0,NULL,'2022-04-21 14:44:58','2022-04-21 14:44:58','3dbc1721-bc04-436a-877c-2fb0158d0d4d',1,NULL,NULL,14,NULL),(1754,2386,'Why I’m So Excited About Remix',NULL,'<p>I’ve been building on the web for a long time. There’s a part of me that still has a bit of an old school mentality, and it’s hard for me to get really excited about new technology. Sure React was cool when it came out for its state management, but I didn’t see it as the be-all and end-all for building on the web. I really like <a href=\"https://craftcms.com/\">Craft CMS</a> for building CMS powered sites since I have full control over the HTML being sent to the browser, and it’s really easy to extend for complex functionality, but it can be a bit complex to setup for beginners and with additional complexity can come performance issues.&nbsp;So it’s been a while since I’ve seen something to be <em>really</em> excited about.</p>\r\n<p>Enter <a href=\"https://remix.run/\">Remix</a>.</p>\r\n<p>Remix is an interesting mix of old school techniques along with modern technology. Ryan Florence actually sums it up perfectly as to where Remix fits in.</p>\r\n<blockquote class=\"twitter-tweet\" data-dnt=\"true\" data-theme=\"dark\"><p lang=\"en\" dir=\"ltr\">Forget “full stack”. Remix is center stack.<br><br>It’s an HTTP tunnel between interactivity and business logic. It’s the part of the stack that no tool before it has solved, not completely.<br><br>I think I finally know how to talk about Remix.</p>— Ryan Florence (@ryanflorence) <a href=\"https://twitter.com/ryanflorence/status/1482233495195770883?ref_src=twsrc%5Etfw\">January 15, 2022</a></blockquote>\r\n<script async=\"\" src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\"></script>\r\n<p>I was able to easily switch my site that was fully powered by Craft to utilize Craft only as a GraphQL endpoint and Remix powering the rest. The two big things I needed to figure out were: how to get data from the GraphQL endpoint, and then how to process input from a user (for my contact form). I would definitely recommend reading through the Remix docs and the two tutorials, but if you can understand these two big pictures things, you’ll have enough to get started with Remix and go deeper once you get into it.</p>\r\n<h2>Getting GraphQL Data (aka Loaders)</h2>\r\n<p>Remix provides a <a href=\"https://remix.run/docs/en/v1/api/conventions#loader\">loader hook</a> that runs on the server to hydrate your component. In this simple example, I run a GraphQL request and return JSON with the results of that request in the loader function.</p>\r\n<script src=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550.js?file=loader.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550#file-loader-jsx\">View Gist</a></noscript>\r\n<p>Then in my <code>Index</code> component, I access the data from the loader hook with <a href=\"https://remix.run/docs/en/v1/api/remix#useloaderdata\">useLoaderData()</a>, and my component is now hydrated with that data. In MVC style of thinking, think of the loader hook as the controller processing the page load request, populating with data from the model, and then passing to the view.</p>\r\n<p>The great part about Remix is that this doesn’t have to be specifically a GraphQL request. This data can come from anywhere. The <a href=\"https://remix.run/docs/en/v1/tutorials/jokes\">Jokes tutorial</a> in the Remix docs even thoroughly walks through how you can manage all this data in <a href=\"https://www.prisma.io/\">Prisma</a>.</p>\r\n<h2>Processing User Input (aka Actions)</h2>\r\n<p>Ok great, so we’ve got data onto the page, but now we need to be able to handle user input. Remix also provides an <a href=\"https://remix.run/docs/en/v1/api/conventions#action\">action hook</a> to process an action request (ex: a form submission). In my case, I have a contact form that sends me an email via SendGrid after submission.</p>\r\n<script src=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550.js?file=action.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550#file-action-jsx\">View Gist</a></noscript>\r\n<p>If you don’t include an <code>action</code> attribute on your form, it will automatically submit to the same page. Again, in MVC thinking, the action would again be equivalent to the controller taking the request input and processing it. But honestly, this takes me back 15 years when form actions would point directly to PHP files.</p>\r\n<h2>Bonus: Progressive Enhancement</h2>\r\n<p>Since Remix is running on the server, you can turn off JavaScript and everything still works great. Data still loads, form actions still process; it’s beautiful. This is not running loaders and actions on the client side; it’s running them on the server. This isn’t an accident, the Remix team is carefully considering the UX.</p>\r\n<blockquote class=\"twitter-tweet\" data-dnt=\"true\" data-theme=\"dark\"><p lang=\"en\" dir=\"ltr\">User experience (UX) and developer experience (DX) are both important. UX is more important than DX.<a href=\"https://twitter.com/remix_run?ref_src=twsrc%5Etfw\">@remix_run</a> has taught me: It\'s easier to start with a great UX and work toward a good DX than it is to start with a great DX and work toward a good UX.</p>— Kent C. Dodds &#x1f4bf; (@kentcdodds) <a href=\"https://twitter.com/kentcdodds/status/1482390454389805058?ref_src=twsrc%5Etfw\">January 15, 2022</a></blockquote>\r\n<script async=\"\" src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\"></script>\r\n<h2>Bonus: So Speedy</h2>\r\n<p>Did I mention how fast everything renders? I don’t tend to put too much stock into Lighthouse scores since they seem so random, but Remix crushes Lighthouse without me having to invest any additional effort into improving performance.</p>\r\n<h2>Give it a Shot</h2>\r\n<p>Remix is built on the <a href=\"https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API\">native Fetch API</a>, so it can run anywhere. While Remix is relatively new, it’s certainly production ready, and there is a dedicated team behind it. If you aren’t ready to dive into Remix yet, at least keep your eye on it because this is a game changer.</p>',NULL,0,NULL,'2022-04-21 14:45:09','2022-04-21 14:45:09','b8406e45-6c50-4cab-bd8b-4acc1a2402f9',1,NULL,NULL,14,NULL),(1755,2387,'Why I’m So Excited About Remix',NULL,'<p>I’ve been building on the web for a long time. There’s a part of me that still has a bit of an old school mentality, and it’s hard for me to get really excited about new technology. Sure React was cool when it came out for its state management, but I didn’t see it as the be-all and end-all for building on the web. I really like <a href=\"https://craftcms.com/\">Craft CMS</a> for building CMS powered sites since I have full control over the HTML being sent to the browser, and it’s really easy to extend for complex functionality, but it can be a bit complex to setup for beginners and with additional complexity can come performance issues.&nbsp;So it’s been a while since I’ve seen something to be <em>really</em> excited about.</p>\r\n<p>Enter <a href=\"https://remix.run/\">Remix</a>.</p>\r\n<p>Remix is an interesting mix of old school techniques along with modern technology. Ryan Florence actually sums it up perfectly as to where Remix fits in.</p>\r\n<blockquote class=\"twitter-tweet\" data-dnt=\"true\" data-theme=\"dark\"><p lang=\"en\" dir=\"ltr\">Forget “full stack”. Remix is center stack.<br><br>It’s an HTTP tunnel between interactivity and business logic. It’s the part of the stack that no tool before it has solved, not completely.<br><br>I think I finally know how to talk about Remix.</p>— Ryan Florence (@ryanflorence) <a href=\"https://twitter.com/ryanflorence/status/1482233495195770883?ref_src=twsrc%5Etfw\">January 15, 2022</a></blockquote>\r\n<script async=\"\" src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\"></script>\r\n<p>I was able to easily switch my site that was fully powered by Craft to utilize Craft only as a GraphQL endpoint and Remix powering the rest. The two big things I needed to figure out were: how to get data from the GraphQL endpoint, and then how to process input from a user (for my contact form). I would definitely recommend reading through the Remix docs and the two tutorials, but if you can understand these two big pictures things, you’ll have enough to get started with Remix and go deeper once you get into it.</p>\r\n<h2>Getting GraphQL Data (aka Loaders)</h2>\r\n<p>Remix provides a <a href=\"https://remix.run/docs/en/v1/api/conventions#loader\">loader hook</a> that runs on the server to hydrate your component. In this simple example, I run a GraphQL request and return JSON with the results of that request in the loader function.</p>\r\n<script src=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550.js?file=loader.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550#file-loader-jsx\">View Gist</a></noscript>\r\n<p>Then in my <code>Index</code> component, I access the data from the loader hook with <a href=\"https://remix.run/docs/en/v1/api/remix#useloaderdata\">useLoaderData()</a>, and my component is now hydrated with that data. In MVC style of thinking, think of the loader hook as the controller processing the page load request, populating with data from the model, and then passing to the view.</p>\r\n<p>The great part about Remix is that this doesn’t have to be specifically a GraphQL request. This data can come from anywhere. The <a href=\"https://remix.run/docs/en/v1/tutorials/jokes\">Jokes tutorial</a> in the Remix docs even thoroughly walks through how you can manage all this data in <a href=\"https://www.prisma.io/\">Prisma</a>.</p>\r\n<h2>Processing User Input (aka Actions)</h2>\r\n<p>Ok great, so we’ve got data onto the page, but now we need to be able to handle user input. Remix also provides an <a href=\"https://remix.run/docs/en/v1/api/conventions#action\">action hook</a> to process an action request (ex: a form submission). In my case, I have a contact form that sends me an email via SendGrid after submission.</p>\r\n<script src=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550.js?file=action.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550#file-action-jsx\">View Gist</a></noscript>\r\n<p>If you don’t include an <code>action</code> attribute on your form, it will automatically submit to the same page. Again, in MVC thinking, the action would again be equivalent to the controller taking the request input and processing it. But honestly, this takes me back 15 years when form actions would point directly to PHP files.</p>\r\n<h2>Bonus: Progressive Enhancement</h2>\r\n<p>Since Remix is running on the server, you can turn off JavaScript and everything still works great. Data still loads, form actions still process; it’s beautiful. This is not running loaders and actions on the client side; it’s running them on the server. This isn’t an accident, the Remix team is carefully considering the UX.</p>\r\n<blockquote class=\"twitter-tweet\" data-dnt=\"true\" data-theme=\"dark\"><p lang=\"en\" dir=\"ltr\">User experience (UX) and developer experience (DX) are both important. UX is more important than DX.<a href=\"https://twitter.com/remix_run?ref_src=twsrc%5Etfw\">@remix_run</a> has taught me: It\'s easier to start with a great UX and work toward a good DX than it is to start with a great DX and work toward a good UX.</p>— Kent C. Dodds &#x1f4bf; (@kentcdodds) <a href=\"https://twitter.com/kentcdodds/status/1482390454389805058?ref_src=twsrc%5Etfw\">January 15, 2022</a></blockquote>\r\n<script async=\"\" src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\"></script>\r\n<h2>Bonus: So Speedy</h2>\r\n<p>Did I mention how fast everything renders? I don’t tend to put too much stock into Lighthouse scores since they seem so random, but Remix crushes Lighthouse without me having to invest any additional effort into improving performance.</p>\r\n<h2>Give it a Shot</h2>\r\n<p>Remix is built on the <a href=\"https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API\">native Fetch API</a>, so it can run anywhere. While Remix is relatively new, it’s certainly production ready, and there is a dedicated team behind it. If you aren’t ready to dive into Remix yet, at least keep your eye on it because this is a game changer.</p>',NULL,0,NULL,'2022-04-21 15:10:14','2022-04-21 15:10:14','22595d5c-b537-4b17-84ab-f66d29d4f9c0',1,NULL,NULL,15,NULL),(1756,2388,'Why I’m So Excited About Remix',NULL,'<p>I’ve been building on the web for a long time. There’s a part of me that still has a bit of an old school mentality, and it’s hard for me to get really excited about new technology. Sure React was cool when it came out for its state management, but I didn’t see it as the be-all and end-all for building on the web. I really like <a href=\"https://craftcms.com/\">Craft CMS</a> for building CMS powered sites since I have full control over the HTML being sent to the browser, and it’s really easy to extend for complex functionality, but it can be a bit complex to setup for beginners and with additional complexity can come performance issues.&nbsp;So it’s been a while since I’ve seen something to be <em>really</em> excited about.</p>\r\n<p>Enter <a href=\"https://remix.run/\">Remix</a>.</p>\r\n<p>Remix is an interesting mix of old school techniques along with modern technology. Ryan Florence actually sums it up perfectly as to where Remix fits in.</p>\r\n<blockquote class=\"twitter-tweet\" data-dnt=\"true\" data-theme=\"dark\"><p lang=\"en\" dir=\"ltr\">Forget “full stack”. Remix is center stack.<br><br>It’s an HTTP tunnel between interactivity and business logic. It’s the part of the stack that no tool before it has solved, not completely.<br><br>I think I finally know how to talk about Remix.</p>— Ryan Florence (@ryanflorence) <a href=\"https://twitter.com/ryanflorence/status/1482233495195770883?ref_src=twsrc%5Etfw\">January 15, 2022</a></blockquote>\r\n<script async=\"\" src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\"></script>\r\n<p>I was able to easily switch my site that was fully powered by Craft to utilize Craft only as a GraphQL endpoint and Remix powering the rest. The two big things I needed to figure out were: how to get data from the GraphQL endpoint, and then how to process input from a user (for my contact form). I would definitely recommend reading through the Remix docs and the two tutorials, but if you can understand these two big pictures things, you’ll have enough to get started with Remix and go deeper once you get into it.</p>\r\n<h2>Getting GraphQL Data (aka Loaders)</h2>\r\n<p>Remix provides a <a href=\"https://remix.run/docs/en/v1/api/conventions#loader\">loader hook</a> that runs on the server to hydrate your component. In this simple example, I run a GraphQL request and return JSON with the results of that request in the loader function.</p>\r\n<script src=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550.js?file=loader.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550#file-loader-jsx\">View Gist</a></noscript>\r\n<p>Then in my <code>Index</code> component, I access the data from the loader hook with <a href=\"https://remix.run/docs/en/v1/api/remix#useloaderdata\">useLoaderData()</a>, and my component is now hydrated with that data. In MVC style of thinking, think of the loader hook as the controller processing the page load request, populating with data from the model, and then passing to the view.</p>\r\n<p>The great part about Remix is that this doesn’t have to be specifically a GraphQL request. This data can come from anywhere. The <a href=\"https://remix.run/docs/en/v1/tutorials/jokes\">Jokes tutorial</a> in the Remix docs even thoroughly walks through how you can manage all this data in <a href=\"https://www.prisma.io/\">Prisma</a>.</p>\r\n<h2>Processing User Input (aka Actions)</h2>\r\n<p>Ok great, so we’ve got data onto the page, but now we need to be able to handle user input. Remix also provides an <a href=\"https://remix.run/docs/en/v1/api/conventions#action\">action hook</a> to process an action request (ex: a form submission). In my case, I have a contact form that sends me an email via SendGrid after submission.</p>\r\n<script src=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550.js?file=action.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550#file-action-jsx\">View Gist</a></noscript>\r\n<p>If you don’t include an <code>action</code> attribute on your form, it will automatically submit to the same page. Again, in MVC thinking, the action would again be equivalent to the controller taking the request input and processing it. But honestly, this takes me back 15 years when form actions would point directly to PHP files.</p>\r\n<h2>Bonus: Progressive Enhancement</h2>\r\n<p>Since Remix is running on the server, you can turn off JavaScript and everything still works great. Data still loads, form actions still process; it’s beautiful. This is not running loaders and actions on the client side; it’s running them on the server. This isn’t an accident, the Remix team is carefully considering the UX.</p>\r\n<blockquote class=\"twitter-tweet\" data-dnt=\"true\" data-theme=\"dark\"><p lang=\"en\" dir=\"ltr\">User experience (UX) and developer experience (DX) are both important. UX is more important than DX.<a href=\"https://twitter.com/remix_run?ref_src=twsrc%5Etfw\">@remix_run</a> has taught me: It\'s easier to start with a great UX and work toward a good DX than it is to start with a great DX and work toward a good UX.</p>— Kent C. Dodds &#x1f4bf; (@kentcdodds) <a href=\"https://twitter.com/kentcdodds/status/1482390454389805058?ref_src=twsrc%5Etfw\">January 15, 2022</a></blockquote>\r\n<script async=\"\" src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\"></script>\r\n<h2>Bonus: So Speedy</h2>\r\n<p>Did I mention how fast everything renders? I don’t tend to put too much stock into Lighthouse scores since they seem so random, but Remix crushes Lighthouse without me having to invest any additional effort into improving performance.</p>\r\n<h2>Give it a Shot</h2>\r\n<p>Remix is built on the <a href=\"https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API\">native Fetch API</a>, so it can run anywhere. While Remix is relatively new, it’s certainly production ready, and there is a dedicated team behind it. If you aren’t ready to dive into Remix yet, at least keep your eye on it because this is a game changer.</p>',NULL,0,NULL,'2022-04-21 15:10:29','2022-04-21 15:10:29','51e498a7-9fa7-4345-be5f-530cee913dd0',1,NULL,NULL,16,NULL),(1757,2389,'Why I’m So Excited About Remix',NULL,'<p>I’ve been building on the web for a long time. There’s a part of me that still has a bit of an old school mentality, and it’s hard for me to get really excited about new technology. Sure React was cool when it came out for its state management, but I didn’t see it as the be-all and end-all for building on the web. I really like <a href=\"https://craftcms.com/\">Craft CMS</a> for building CMS powered sites since I have full control over the HTML being sent to the browser, and it’s really easy to extend for complex functionality, but it can be a bit complex to setup for beginners and with additional complexity can come performance issues.&nbsp;So it’s been a while since I’ve seen something to be <em>really</em> excited about.</p>\r\n<p>Enter <a href=\"https://remix.run/\">Remix</a>.</p>\r\n<p>Remix is an interesting mix of old school techniques along with modern technology. Ryan Florence actually sums it up perfectly as to where Remix fits in.</p>\r\n<blockquote class=\"twitter-tweet\" data-dnt=\"true\" data-theme=\"dark\"><p lang=\"en\" dir=\"ltr\">Forget “full stack”. Remix is center stack.<br><br>It’s an HTTP tunnel between interactivity and business logic. It’s the part of the stack that no tool before it has solved, not completely.<br><br>I think I finally know how to talk about Remix.</p>— Ryan Florence (@ryanflorence) <a href=\"https://twitter.com/ryanflorence/status/1482233495195770883?ref_src=twsrc%5Etfw\">January 15, 2022</a></blockquote>\r\n<script async=\"\" src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\"></script>\r\n<p>I was able to easily switch my site that was fully powered by Craft to utilize Craft only as a GraphQL endpoint and Remix powering the rest. The two big things I needed to figure out were: how to get data from the GraphQL endpoint, and then how to process input from a user (for my contact form). I would definitely recommend reading through the Remix docs and the two tutorials, but if you can understand these two big pictures things, you’ll have enough to get started with Remix and go deeper once you get into it.</p>\r\n<h2>Getting GraphQL Data (aka Loaders)</h2>\r\n<p>Remix provides a <a href=\"https://remix.run/docs/en/v1/api/conventions#loader\">loader hook</a> that runs on the server to hydrate your component. In this simple example, I run a GraphQL request and return JSON with the results of that request in the loader function.</p>\r\n<script src=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550.js?file=loader.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550#file-loader-jsx\">View Gist</a></noscript>\r\n<p>Then in my <code>Index</code> component, I access the data from the loader hook with <a href=\"https://remix.run/docs/en/v1/api/remix#useloaderdata\">useLoaderData()</a>, and my component is now hydrated with that data. In MVC style of thinking, think of the loader hook as the controller processing the page load request, populating with data from the model, and then passing to the view.</p>\r\n<p>The great part about Remix is that this doesn’t have to be specifically a GraphQL request. This data can come from anywhere. The <a href=\"https://remix.run/docs/en/v1/tutorials/jokes\">Jokes tutorial</a> in the Remix docs even thoroughly walks through how you can manage all this data in <a href=\"https://www.prisma.io/\">Prisma</a>.</p>\r\n<h2>Processing User Input (aka Actions)</h2>\r\n<p>Ok great, so we’ve got data onto the page, but now we need to be able to handle user input. Remix also provides an <a href=\"https://remix.run/docs/en/v1/api/conventions#action\">action hook</a> to process an action request (ex: a form submission). In my case, I have a contact form that sends me an email via SendGrid after submission.</p>\r\n<script src=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550.js?file=action.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550#file-action-jsx\">View Gist</a></noscript>\r\n<p>If you don’t include an <code>action</code> attribute on your form, it will automatically submit to the same page. Again, in MVC thinking, the action would again be equivalent to the controller taking the request input and processing it. But honestly, this takes me back 15 years when form actions would point directly to PHP files.</p>\r\n<h2>Bonus: Progressive Enhancement</h2>\r\n<p>Since Remix is running on the server, you can turn off JavaScript and everything still works great. Data still loads, form actions still process; it’s beautiful. This is not running loaders and actions on the client side; it’s running them on the server. This isn’t an accident, the Remix team is carefully considering the UX.</p>\r\n<blockquote class=\"twitter-tweet\" data-dnt=\"true\" data-theme=\"dark\"><p lang=\"en\" dir=\"ltr\">User experience (UX) and developer experience (DX) are both important. UX is more important than DX.<a href=\"https://twitter.com/remix_run?ref_src=twsrc%5Etfw\">@remix_run</a> has taught me: It\'s easier to start with a great UX and work toward a good DX than it is to start with a great DX and work toward a good UX.</p>— Kent C. Dodds &#x1f4bf; (@kentcdodds) <a href=\"https://twitter.com/kentcdodds/status/1482390454389805058?ref_src=twsrc%5Etfw\">January 15, 2022</a></blockquote>\r\n<script async=\"\" src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\"></script>\r\n<h2>Bonus: So Speedy</h2>\r\n<p>Did I mention how fast everything renders? I don’t tend to put too much stock into Lighthouse scores since they seem so random, but Remix crushes Lighthouse without me having to invest any additional effort into improving performance.</p>\r\n<h2>Give it a Shot</h2>\r\n<p>Remix is built on the <a href=\"https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API\">native Fetch API</a>, so it can run anywhere. While Remix is relatively new, it’s certainly production ready, and there is a dedicated team behind it. If you aren’t ready to dive into Remix yet, at least keep your eye on it because this is a game changer.</p>',NULL,0,NULL,'2022-04-21 15:10:36','2022-04-21 15:10:36','414fe2b2-f3c2-4bd0-818f-42bec9b541c5',1,NULL,NULL,15,NULL),(1758,2390,'Why I’m So Excited About Remix',NULL,'<p>I’ve been building on the web for a long time. There’s a part of me that still has a bit of an old school mentality, and it’s hard for me to get really excited about new technology. Sure React was cool when it came out for its state management, but I didn’t see it as the be-all and end-all for building on the web. I really like <a href=\"https://craftcms.com/\">Craft CMS</a> for building CMS powered sites since I have full control over the HTML being sent to the browser, and it’s really easy to extend for complex functionality, but it can be a bit complex to setup for beginners and with additional complexity can come performance issues.&nbsp;So it’s been a while since I’ve seen something to be <em>really</em> excited about.</p>\r\n<p>Enter <a href=\"https://remix.run/\">Remix</a>.</p>\r\n<p>Remix is an interesting mix of old school techniques along with modern technology. Ryan Florence actually sums it up perfectly as to where Remix fits in.</p>\r\n<blockquote class=\"twitter-tweet\" data-dnt=\"true\" data-theme=\"dark\"><p lang=\"en\" dir=\"ltr\">Forget “full stack”. Remix is center stack.<br><br>It’s an HTTP tunnel between interactivity and business logic. It’s the part of the stack that no tool before it has solved, not completely.<br><br>I think I finally know how to talk about Remix.</p>— Ryan Florence (@ryanflorence) <a href=\"https://twitter.com/ryanflorence/status/1482233495195770883?ref_src=twsrc%5Etfw\">January 15, 2022</a></blockquote>\r\n<script async=\"\" src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\"></script>\r\n<p>I was able to easily switch my site that was fully powered by Craft to utilize Craft only as a GraphQL endpoint and Remix powering the rest. The two big things I needed to figure out were: how to get data from the GraphQL endpoint, and then how to process input from a user (for my contact form). I would definitely recommend reading through the Remix docs and the two tutorials, but if you can understand these two big pictures things, you’ll have enough to get started with Remix and go deeper once you get into it.</p>\r\n<h2>Getting GraphQL Data (aka Loaders)</h2>\r\n<p>Remix provides a <a href=\"https://remix.run/docs/en/v1/api/conventions#loader\">loader hook</a> that runs on the server to hydrate your component. In this simple example, I run a GraphQL request and return JSON with the results of that request in the loader function.</p>\r\n<script src=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550.js?file=loader.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550#file-loader-jsx\">View Gist</a></noscript>\r\n<p>Then in my <code>Index</code> component, I access the data from the loader hook with <a href=\"https://remix.run/docs/en/v1/api/remix#useloaderdata\">useLoaderData()</a>, and my component is now hydrated with that data. In MVC style of thinking, think of the loader hook as the controller processing the page load request, populating with data from the model, and then passing to the view.</p>\r\n<p>The great part about Remix is that this doesn’t have to be specifically a GraphQL request. This data can come from anywhere. The <a href=\"https://remix.run/docs/en/v1/tutorials/jokes\">Jokes tutorial</a> in the Remix docs even thoroughly walks through how you can manage all this data in <a href=\"https://www.prisma.io/\">Prisma</a>.</p>\r\n<h2>Processing User Input (aka Actions)</h2>\r\n<p>Ok great, so we’ve got data onto the page, but now we need to be able to handle user input. Remix also provides an <a href=\"https://remix.run/docs/en/v1/api/conventions#action\">action hook</a> to process an action request (ex: a form submission). In my case, I have a contact form that sends me an email via SendGrid after submission.</p>\r\n<script src=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550.js?file=action.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550#file-action-jsx\">View Gist</a></noscript>\r\n<p>If you don’t include an <code>action</code> attribute on your form, it will automatically submit to the same page. Again, in MVC thinking, the action would again be equivalent to the controller taking the request input and processing it. But honestly, this takes me back 15 years when form actions would point directly to PHP files.</p>\r\n<h2>Bonus: Progressive Enhancement</h2>\r\n<p>Since Remix is running on the server, you can turn off JavaScript and everything still works great. Data still loads, form actions still process; it’s beautiful. This is not running loaders and actions on the client side; it’s running them on the server. This isn’t an accident, the Remix team is carefully considering the UX.</p>\r\n<blockquote class=\"twitter-tweet\" data-dnt=\"true\" data-theme=\"dark\"><p lang=\"en\" dir=\"ltr\">User experience (UX) and developer experience (DX) are both important. UX is more important than DX.<a href=\"https://twitter.com/remix_run?ref_src=twsrc%5Etfw\">@remix_run</a> has taught me: It\'s easier to start with a great UX and work toward a good DX than it is to start with a great DX and work toward a good UX.</p>— Kent C. Dodds &#x1f4bf; (@kentcdodds) <a href=\"https://twitter.com/kentcdodds/status/1482390454389805058?ref_src=twsrc%5Etfw\">January 15, 2022</a></blockquote>\r\n<script async=\"\" src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\"></script>\r\n<h2>Bonus: So Speedy</h2>\r\n<p>Did I mention how fast everything renders? I don’t tend to put too much stock into Lighthouse scores since they seem so random, but Remix crushes Lighthouse without me having to invest any additional effort into improving performance.</p>\r\n<h2>Give it a Shot</h2>\r\n<p>Remix is built on the <a href=\"https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API\">native Fetch API</a>, so it can run anywhere. While Remix is relatively new, it’s certainly production ready, and there is a dedicated team behind it. If you aren’t ready to dive into Remix yet, at least keep your eye on it because this is a game changer.</p>',NULL,0,NULL,'2022-04-21 15:10:42','2022-04-21 15:10:42','6be52b84-325a-4646-8a7d-45251a06c7ee',1,NULL,NULL,16,NULL),(1759,2391,'Why I’m So Excited About Remix',NULL,'<p>I’ve been building on the web for a long time. There’s a part of me that still has a bit of an old school mentality, and it’s hard for me to get really excited about new technology. Sure React was cool when it came out for its state management, but I didn’t see it as the be-all and end-all for building on the web. I really like <a href=\"https://craftcms.com/\">Craft CMS</a> for building CMS powered sites since I have full control over the HTML being sent to the browser, and it’s really easy to extend for complex functionality, but it can be a bit complex to setup for beginners and with additional complexity can come performance issues.&nbsp;So it’s been a while since I’ve seen something to be <em>really</em> excited about.</p>\r\n<p>Enter <a href=\"https://remix.run/\">Remix</a>.</p>\r\n<p>Remix is an interesting mix of old school techniques along with modern technology. Ryan Florence actually sums it up perfectly as to where Remix fits in.</p>\r\n<blockquote class=\"twitter-tweet\" data-dnt=\"true\" data-theme=\"dark\"><p lang=\"en\" dir=\"ltr\">Forget “full stack”. Remix is center stack.<br><br>It’s an HTTP tunnel between interactivity and business logic. It’s the part of the stack that no tool before it has solved, not completely.<br><br>I think I finally know how to talk about Remix.</p>— Ryan Florence (@ryanflorence) <a href=\"https://twitter.com/ryanflorence/status/1482233495195770883?ref_src=twsrc%5Etfw\">January 15, 2022</a></blockquote>\r\n<script async=\"\" src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\"></script>\r\n<p>I was able to easily switch my site that was fully powered by Craft to utilize Craft only as a GraphQL endpoint and Remix powering the rest. The two big things I needed to figure out were: how to get data from the GraphQL endpoint, and then how to process input from a user (for my contact form). I would definitely recommend reading through the Remix docs and the two tutorials, but if you can understand these two big pictures things, you’ll have enough to get started with Remix and go deeper once you get into it.</p>\r\n<h2>Getting GraphQL Data (aka Loaders)</h2>\r\n<p>Remix provides a <a href=\"https://remix.run/docs/en/v1/api/conventions#loader\">loader hook</a> that runs on the server to hydrate your component. In this simple example, I run a GraphQL request and return JSON with the results of that request in the loader function.</p>\r\n<script src=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550.js?file=loader.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550#file-loader-jsx\">View Gist</a></noscript>\r\n<p>Then in my <code>Index</code> component, I access the data from the loader hook with <a href=\"https://remix.run/docs/en/v1/api/remix#useloaderdata\">useLoaderData()</a>, and my component is now hydrated with that data. In MVC style of thinking, think of the loader hook as the controller processing the page load request, populating with data from the model, and then passing to the view.</p>\r\n<p>The great part about Remix is that this doesn’t have to be specifically a GraphQL request. This data can come from anywhere. The <a href=\"https://remix.run/docs/en/v1/tutorials/jokes\">Jokes tutorial</a> in the Remix docs even thoroughly walks through how you can manage all this data in <a href=\"https://www.prisma.io/\">Prisma</a>.</p>\r\n<h2>Processing User Input (aka Actions)</h2>\r\n<p>Ok great, so we’ve got data onto the page, but now we need to be able to handle user input. Remix also provides an <a href=\"https://remix.run/docs/en/v1/api/conventions#action\">action hook</a> to process an action request (ex: a form submission). In my case, I have a contact form that sends me an email via SendGrid after submission.</p>\r\n<script src=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550.js?file=action.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550#file-action-jsx\">View Gist</a></noscript>\r\n<p>If you don’t include an <code>action</code> attribute on your form, it will automatically submit to the same page. Again, in MVC thinking, the action would again be equivalent to the controller taking the request input and processing it. But honestly, this takes me back 15 years when form actions would point directly to PHP files.</p>\r\n<h2>Bonus: Progressive Enhancement</h2>\r\n<p>Since Remix is running on the server, you can turn off JavaScript and everything still works great. Data still loads, form actions still process; it’s beautiful. This is not running loaders and actions on the client side; it’s running them on the server. This isn’t an accident, the Remix team is carefully considering the UX.</p>\r\n<blockquote class=\"twitter-tweet\" data-dnt=\"true\" data-theme=\"dark\"><p lang=\"en\" dir=\"ltr\">User experience (UX) and developer experience (DX) are both important. UX is more important than DX.<a href=\"https://twitter.com/remix_run?ref_src=twsrc%5Etfw\">@remix_run</a> has taught me: It\'s easier to start with a great UX and work toward a good DX than it is to start with a great DX and work toward a good UX.</p>— Kent C. Dodds &#x1f4bf; (@kentcdodds) <a href=\"https://twitter.com/kentcdodds/status/1482390454389805058?ref_src=twsrc%5Etfw\">January 15, 2022</a></blockquote>\r\n<script async=\"\" src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\"></script>\r\n<h2>Bonus: So Speedy</h2>\r\n<p>Did I mention how fast everything renders? I don’t tend to put too much stock into Lighthouse scores since they seem so random, but Remix crushes Lighthouse without me having to invest any additional effort into improving performance.</p>\r\n<h2>Give it a Shot</h2>\r\n<p>Remix is built on the <a href=\"https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API\">native Fetch API</a>, so it can run anywhere. While Remix is relatively new, it’s certainly production ready, and there is a dedicated team behind it. If you aren’t ready to dive into Remix yet, at least keep your eye on it because this is a game changer.</p>',NULL,0,NULL,'2022-04-21 15:11:49','2022-04-21 15:11:49','7ff98e72-637b-41e7-a207-855c0aae78cb',1,NULL,NULL,17,NULL),(1760,2392,'Why I’m So Excited About Remix',NULL,'<p>I’ve been building on the web for a long time. There’s a part of me that still has a bit of an old school mentality, and it’s hard for me to get really excited about new technology. Sure React was cool when it came out for its state management, but I didn’t see it as the be-all and end-all for building on the web. I really like <a href=\"https://craftcms.com/\">Craft CMS</a> for building CMS powered sites since I have full control over the HTML being sent to the browser, and it’s really easy to extend for complex functionality, but it can be a bit complex to setup for beginners and with additional complexity can come performance issues.&nbsp;So it’s been a while since I’ve seen something to be <em>really</em> excited about.</p>\r\n<p>Enter <a href=\"https://remix.run/\">Remix</a>.</p>\r\n<p>Remix is an interesting mix of old school techniques along with modern technology. Ryan Florence actually sums it up perfectly as to where Remix fits in.</p>\r\n<blockquote class=\"twitter-tweet\" data-dnt=\"true\" data-theme=\"dark\"><p lang=\"en\" dir=\"ltr\">Forget “full stack”. Remix is center stack.<br><br>It’s an HTTP tunnel between interactivity and business logic. It’s the part of the stack that no tool before it has solved, not completely.<br><br>I think I finally know how to talk about Remix.</p>— Ryan Florence (@ryanflorence) <a href=\"https://twitter.com/ryanflorence/status/1482233495195770883?ref_src=twsrc%5Etfw\">January 15, 2022</a></blockquote>\r\n<script async=\"\" src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\"></script>\r\n<p>I was able to easily switch my site that was fully powered by Craft to utilize Craft only as a GraphQL endpoint and Remix powering the rest. The two big things I needed to figure out were: how to get data from the GraphQL endpoint, and then how to process input from a user (for my contact form). I would definitely recommend reading through the Remix docs and the two tutorials, but if you can understand these two big pictures things, you’ll have enough to get started with Remix and go deeper once you get into it.</p>\r\n<h2>Getting GraphQL Data (aka Loaders)</h2>\r\n<p>Remix provides a <a href=\"https://remix.run/docs/en/v1/api/conventions#loader\">loader hook</a> that runs on the server to hydrate your component. In this simple example, I run a GraphQL request and return JSON with the results of that request in the loader function.</p>\r\n<script src=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550.js?file=loader.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550#file-loader-jsx\">View Gist</a></noscript>\r\n<p>Then in my <code>Index</code> component, I access the data from the loader hook with <a href=\"https://remix.run/docs/en/v1/api/remix#useloaderdata\">useLoaderData()</a>, and my component is now hydrated with that data. In MVC style of thinking, think of the loader hook as the controller processing the page load request, populating with data from the model, and then passing to the view.</p>\r\n<p>The great part about Remix is that this doesn’t have to be specifically a GraphQL request. This data can come from anywhere. The <a href=\"https://remix.run/docs/en/v1/tutorials/jokes\">Jokes tutorial</a> in the Remix docs even thoroughly walks through how you can manage all this data in <a href=\"https://www.prisma.io/\">Prisma</a>.</p>\r\n<h2>Processing User Input (aka Actions)</h2>\r\n<p>Ok great, so we’ve got data onto the page, but now we need to be able to handle user input. Remix also provides an <a href=\"https://remix.run/docs/en/v1/api/conventions#action\">action hook</a> to process an action request (ex: a form submission). In my case, I have a contact form that sends me an email via SendGrid after submission.</p>\r\n<script src=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550.js?file=action.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550#file-action-jsx\">View Gist</a></noscript>\r\n<p>If you don’t include an <code>action</code> attribute on your form, it will automatically submit to the same page. Again, in MVC thinking, the action would again be equivalent to the controller taking the request input and processing it. But honestly, this takes me back 15 years when form actions would point directly to PHP files.</p>\r\n<h2>Bonus: Progressive Enhancement</h2>\r\n<p>Since Remix is running on the server, you can turn off JavaScript and everything still works great. Data still loads, form actions still process; it’s beautiful. This is not running loaders and actions on the client side; it’s running them on the server. This isn’t an accident, the Remix team is carefully considering the UX.</p>\r\n<blockquote class=\"twitter-tweet\" data-dnt=\"true\" data-theme=\"dark\"><p lang=\"en\" dir=\"ltr\">User experience (UX) and developer experience (DX) are both important. UX is more important than DX.<a href=\"https://twitter.com/remix_run?ref_src=twsrc%5Etfw\">@remix_run</a> has taught me: It\'s easier to start with a great UX and work toward a good DX than it is to start with a great DX and work toward a good UX.</p>— Kent C. Dodds &#x1f4bf; (@kentcdodds) <a href=\"https://twitter.com/kentcdodds/status/1482390454389805058?ref_src=twsrc%5Etfw\">January 15, 2022</a></blockquote>\r\n<script async=\"\" src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\"></script>\r\n<h2>Bonus: So Speedy</h2>\r\n<p>Did I mention how fast everything renders? I don’t tend to put too much stock into Lighthouse scores since they seem so random, but Remix crushes Lighthouse without me having to invest any additional effort into improving performance.</p>\r\n<h2>Give it a Shot</h2>\r\n<p>Remix is built on the <a href=\"https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API\">native Fetch API</a>, so it can run anywhere. While Remix is relatively new, it’s certainly production ready, and there is a dedicated team behind it. If you aren’t ready to dive into Remix yet, at least keep your eye on it because this is a game changer.</p>',NULL,0,NULL,'2022-04-21 15:11:55','2022-04-21 15:11:55','279b6338-d57f-4534-9b2d-c877f85f318b',1,NULL,NULL,16,NULL),(1761,2393,'Why I’m So Excited About Remix',NULL,'<p>I’ve been building on the web for a long time. There’s a part of me that still has a bit of an old school mentality, and it’s hard for me to get really excited about new technology. Sure React was cool when it came out for its state management, but I didn’t see it as the be-all and end-all for building on the web. I really like <a href=\"https://craftcms.com/\">Craft CMS</a> for building CMS powered sites since I have full control over the HTML being sent to the browser, and it’s really easy to extend for complex functionality, but it can be a bit complex to setup for beginners and with additional complexity can come performance issues.&nbsp;So it’s been a while since I’ve seen something to be <em>really</em> excited about.</p>\r\n<p>Enter <a href=\"https://remix.run/\">Remix</a>.</p>\r\n<p>Remix is an interesting mix of old school techniques along with modern technology. Ryan Florence actually sums it up perfectly as to where Remix fits in.</p>\r\n<blockquote class=\"twitter-tweet\" data-dnt=\"true\" data-theme=\"dark\"><p lang=\"en\" dir=\"ltr\">Forget “full stack”. Remix is center stack.<br><br>It’s an HTTP tunnel between interactivity and business logic. It’s the part of the stack that no tool before it has solved, not completely.<br><br>I think I finally know how to talk about Remix.</p>— Ryan Florence (@ryanflorence) <a href=\"https://twitter.com/ryanflorence/status/1482233495195770883?ref_src=twsrc%5Etfw\">January 15, 2022</a></blockquote>\r\n<script async=\"\" src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\"></script>\r\n<p>I was able to easily switch my site that was fully powered by Craft to utilize Craft only as a GraphQL endpoint and Remix powering the rest. The two big things I needed to figure out were: how to get data from the GraphQL endpoint, and then how to process input from a user (for my contact form). I would definitely recommend reading through the Remix docs and the two tutorials, but if you can understand these two big pictures things, you’ll have enough to get started with Remix and go deeper once you get into it.</p>\r\n<h2>Getting GraphQL Data (aka Loaders)</h2>\r\n<p>Remix provides a <a href=\"https://remix.run/docs/en/v1/api/conventions#loader\">loader hook</a> that runs on the server to hydrate your component. In this simple example, I run a GraphQL request and return JSON with the results of that request in the loader function.</p>\r\n<script src=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550.js?file=loader.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550#file-loader-jsx\">View Gist</a></noscript>\r\n<p>Then in my <code>Index</code> component, I access the data from the loader hook with <a href=\"https://remix.run/docs/en/v1/api/remix#useloaderdata\">useLoaderData()</a>, and my component is now hydrated with that data. In MVC style of thinking, think of the loader hook as the controller processing the page load request, populating with data from the model, and then passing to the view.</p>\r\n<p>The great part about Remix is that this doesn’t have to be specifically a GraphQL request. This data can come from anywhere. The <a href=\"https://remix.run/docs/en/v1/tutorials/jokes\">Jokes tutorial</a> in the Remix docs even thoroughly walks through how you can manage all this data in <a href=\"https://www.prisma.io/\">Prisma</a>.</p>\r\n<h2>Processing User Input (aka Actions)</h2>\r\n<p>Ok great, so we’ve got data onto the page, but now we need to be able to handle user input. Remix also provides an <a href=\"https://remix.run/docs/en/v1/api/conventions#action\">action hook</a> to process an action request (ex: a form submission). In my case, I have a contact form that sends me an email via SendGrid after submission.</p>\r\n<script src=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550.js?file=action.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550#file-action-jsx\">View Gist</a></noscript>\r\n<p>If you don’t include an <code>action</code> attribute on your form, it will automatically submit to the same page. Again, in MVC thinking, the action would again be equivalent to the controller taking the request input and processing it. But honestly, this takes me back 15 years when form actions would point directly to PHP files.</p>\r\n<h2>Bonus: Progressive Enhancement</h2>\r\n<p>Since Remix is running on the server, you can turn off JavaScript and everything still works great. Data still loads, form actions still process; it’s beautiful. This is not running loaders and actions on the client side; it’s running them on the server. This isn’t an accident, the Remix team is carefully considering the UX.</p>\r\n<blockquote class=\"twitter-tweet\" data-dnt=\"true\" data-theme=\"dark\"><p lang=\"en\" dir=\"ltr\">User experience (UX) and developer experience (DX) are both important. UX is more important than DX.<a href=\"https://twitter.com/remix_run?ref_src=twsrc%5Etfw\">@remix_run</a> has taught me: It\'s easier to start with a great UX and work toward a good DX than it is to start with a great DX and work toward a good UX.</p>— Kent C. Dodds &#x1f4bf; (@kentcdodds) <a href=\"https://twitter.com/kentcdodds/status/1482390454389805058?ref_src=twsrc%5Etfw\">January 15, 2022</a></blockquote>\r\n<script async=\"\" src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\"></script>\r\n<h2>Bonus: So Speedy</h2>\r\n<p>Did I mention how fast everything renders? I don’t tend to put too much stock into Lighthouse scores since they seem so random, but Remix crushes Lighthouse without me having to invest any additional effort into improving performance.</p>\r\n<h2>Give it a Shot</h2>\r\n<p>Remix is built on the <a href=\"https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API\">native Fetch API</a>, so it can run anywhere. While Remix is relatively new, it’s certainly production ready, and there is a dedicated team behind it. If you aren’t ready to dive into Remix yet, at least keep your eye on it because this is a game changer.</p>',NULL,0,NULL,'2022-04-21 15:11:59','2022-04-21 15:11:59','586cd849-0fcd-4032-838e-0f5c206bb037',1,NULL,NULL,17,NULL),(1762,2394,'Why I’m So Excited About Remix',NULL,'<p>I’ve been building on the web for a long time. There’s a part of me that still has a bit of an old school mentality, and it’s hard for me to get really excited about new technology. Sure React was cool when it came out for its state management, but I didn’t see it as the be-all and end-all for building on the web. I really like <a href=\"https://craftcms.com/\">Craft CMS</a> for building CMS powered sites since I have full control over the HTML being sent to the browser, and it’s really easy to extend for complex functionality, but it can be a bit complex to setup for beginners and with additional complexity can come performance issues.&nbsp;So it’s been a while since I’ve seen something to be <em>really</em> excited about.</p>\r\n<p>Enter <a href=\"https://remix.run/\">Remix</a>.</p>\r\n<p>Remix is an interesting mix of old school techniques along with modern technology. Ryan Florence actually sums it up perfectly as to where Remix fits in.</p>\r\n<blockquote class=\"twitter-tweet\" data-dnt=\"true\" data-theme=\"dark\"><p lang=\"en\" dir=\"ltr\">Forget “full stack”. Remix is center stack.<br><br>It’s an HTTP tunnel between interactivity and business logic. It’s the part of the stack that no tool before it has solved, not completely.<br><br>I think I finally know how to talk about Remix.</p>— Ryan Florence (@ryanflorence) <a href=\"https://twitter.com/ryanflorence/status/1482233495195770883?ref_src=twsrc%5Etfw\">January 15, 2022</a></blockquote>\r\n<script async=\"\" src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\"></script>\r\n<p>I was able to easily switch my site that was fully powered by Craft to utilize Craft only as a GraphQL endpoint and Remix powering the rest. The two big things I needed to figure out were: how to get data from the GraphQL endpoint, and then how to process input from a user (for my contact form). I would definitely recommend reading through the Remix docs and the two tutorials, but if you can understand these two big pictures things, you’ll have enough to get started with Remix and go deeper once you get into it.</p>\r\n<h2>Getting GraphQL Data (aka Loaders)</h2>\r\n<p>Remix provides a <a href=\"https://remix.run/docs/en/v1/api/conventions#loader\">loader hook</a> that runs on the server to hydrate your component. In this simple example, I run a GraphQL request and return JSON with the results of that request in the loader function.</p>\r\n<script src=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550.js?file=loader.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550#file-loader-jsx\">View Gist</a></noscript>\r\n<p>Then in my <code>Index</code> component, I access the data from the loader hook with <a href=\"https://remix.run/docs/en/v1/api/remix#useloaderdata\">useLoaderData()</a>, and my component is now hydrated with that data. In MVC style of thinking, think of the loader hook as the controller processing the page load request, populating with data from the model, and then passing to the view.</p>\r\n<p>The great part about Remix is that this doesn’t have to be specifically a GraphQL request. This data can come from anywhere. The <a href=\"https://remix.run/docs/en/v1/tutorials/jokes\">Jokes tutorial</a> in the Remix docs even thoroughly walks through how you can manage all this data in <a href=\"https://www.prisma.io/\">Prisma</a>.</p>\r\n<h2>Processing User Input (aka Actions)</h2>\r\n<p>Ok great, so we’ve got data onto the page, but now we need to be able to handle user input. Remix also provides an <a href=\"https://remix.run/docs/en/v1/api/conventions#action\">action hook</a> to process an action request (ex: a form submission). In my case, I have a contact form that sends me an email via SendGrid after submission.</p>\r\n<script src=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550.js?file=action.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550#file-action-jsx\">View Gist</a></noscript>\r\n<p>If you don’t include an <code>action</code> attribute on your form, it will automatically submit to the same page. Again, in MVC thinking, the action would again be equivalent to the controller taking the request input and processing it. But honestly, this takes me back 15 years when form actions would point directly to PHP files.</p>\r\n<h2>Bonus: Progressive Enhancement</h2>\r\n<p>Since Remix is running on the server, you can turn off JavaScript and everything still works great. Data still loads, form actions still process; it’s beautiful. This is not running loaders and actions on the client side; it’s running them on the server. This isn’t an accident, the Remix team is carefully considering the UX.</p>\r\n<blockquote class=\"twitter-tweet\" data-dnt=\"true\" data-theme=\"dark\"><p lang=\"en\" dir=\"ltr\">User experience (UX) and developer experience (DX) are both important. UX is more important than DX.<a href=\"https://twitter.com/remix_run?ref_src=twsrc%5Etfw\">@remix_run</a> has taught me: It\'s easier to start with a great UX and work toward a good DX than it is to start with a great DX and work toward a good UX.</p>— Kent C. Dodds &#x1f4bf; (@kentcdodds) <a href=\"https://twitter.com/kentcdodds/status/1482390454389805058?ref_src=twsrc%5Etfw\">January 15, 2022</a></blockquote>\r\n<script async=\"\" src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\"></script>\r\n<h2>Bonus: So Speedy</h2>\r\n<p>Did I mention how fast everything renders? I don’t tend to put too much stock into Lighthouse scores since they seem so random, but Remix crushes Lighthouse without me having to invest any additional effort into improving performance.</p>\r\n<h2>Give it a Shot</h2>\r\n<p>Remix is built on the <a href=\"https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API\">native Fetch API</a>, so it can run anywhere. While Remix is relatively new, it’s certainly production ready, and there is a dedicated team behind it. If you aren’t ready to dive into Remix yet, at least keep your eye on it because this is a game changer.</p>',NULL,0,NULL,'2022-04-21 15:13:03','2022-04-21 15:13:03','4d7f0a16-6bb6-4619-919f-13e35fd19df7',1,NULL,NULL,18,NULL),(1763,2395,'Why I’m So Excited About Remix',NULL,'<p>I’ve been building on the web for a long time. There’s a part of me that still has a bit of an old school mentality, and it’s hard for me to get really excited about new technology. Sure React was cool when it came out for its state management, but I didn’t see it as the be-all and end-all for building on the web. I really like <a href=\"https://craftcms.com/\">Craft CMS</a> for building CMS powered sites since I have full control over the HTML being sent to the browser, and it’s really easy to extend for complex functionality, but it can be a bit complex to setup for beginners and with additional complexity can come performance issues.&nbsp;So it’s been a while since I’ve seen something to be <em>really</em> excited about.</p>\r\n<p>Enter <a href=\"https://remix.run/\">Remix</a>.</p>\r\n<p>Remix is an interesting mix of old school techniques along with modern technology. Ryan Florence actually sums it up perfectly as to where Remix fits in.</p>\r\n<blockquote class=\"twitter-tweet\" data-dnt=\"true\" data-theme=\"dark\"><p lang=\"en\" dir=\"ltr\">Forget “full stack”. Remix is center stack.<br><br>It’s an HTTP tunnel between interactivity and business logic. It’s the part of the stack that no tool before it has solved, not completely.<br><br>I think I finally know how to talk about Remix.</p>— Ryan Florence (@ryanflorence) <a href=\"https://twitter.com/ryanflorence/status/1482233495195770883?ref_src=twsrc%5Etfw\">January 15, 2022</a></blockquote>\r\n<script async=\"\" src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\"></script>\r\n<p>I was able to easily switch my site that was fully powered by Craft to utilize Craft only as a GraphQL endpoint and Remix powering the rest. The two big things I needed to figure out were: how to get data from the GraphQL endpoint, and then how to process input from a user (for my contact form). I would definitely recommend reading through the Remix docs and the two tutorials, but if you can understand these two big pictures things, you’ll have enough to get started with Remix and go deeper once you get into it.</p>\r\n<h2>Getting GraphQL Data (aka Loaders)</h2>\r\n<p>Remix provides a <a href=\"https://remix.run/docs/en/v1/api/conventions#loader\">loader hook</a> that runs on the server to hydrate your component. In this simple example, I run a GraphQL request and return JSON with the results of that request in the loader function.</p>\r\n<script src=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550.js?file=loader.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550#file-loader-jsx\">View Gist</a></noscript>\r\n<p>Then in my <code>Index</code> component, I access the data from the loader hook with <a href=\"https://remix.run/docs/en/v1/api/remix#useloaderdata\">useLoaderData()</a>, and my component is now hydrated with that data. In MVC style of thinking, think of the loader hook as the controller processing the page load request, populating with data from the model, and then passing to the view.</p>\r\n<p>The great part about Remix is that this doesn’t have to be specifically a GraphQL request. This data can come from anywhere. The <a href=\"https://remix.run/docs/en/v1/tutorials/jokes\">Jokes tutorial</a> in the Remix docs even thoroughly walks through how you can manage all this data in <a href=\"https://www.prisma.io/\">Prisma</a>.</p>\r\n<h2>Processing User Input (aka Actions)</h2>\r\n<p>Ok great, so we’ve got data onto the page, but now we need to be able to handle user input. Remix also provides an <a href=\"https://remix.run/docs/en/v1/api/conventions#action\">action hook</a> to process an action request (ex: a form submission). In my case, I have a contact form that sends me an email via SendGrid after submission.</p>\r\n<script src=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550.js?file=action.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550#file-action-jsx\">View Gist</a></noscript>\r\n<p>If you don’t include an <code>action</code> attribute on your form, it will automatically submit to the same page. Again, in MVC thinking, the action would again be equivalent to the controller taking the request input and processing it. But honestly, this takes me back 15 years when form actions would point directly to PHP files.</p>\r\n<h2>Bonus: Progressive Enhancement</h2>\r\n<p>Since Remix is running on the server, you can turn off JavaScript and everything still works great. Data still loads, form actions still process; it’s beautiful. This is not running loaders and actions on the client side; it’s running them on the server. This isn’t an accident, the Remix team is carefully considering the UX.</p>\r\n<blockquote class=\"twitter-tweet\" data-dnt=\"true\" data-theme=\"dark\"><p lang=\"en\" dir=\"ltr\">User experience (UX) and developer experience (DX) are both important. UX is more important than DX.<a href=\"https://twitter.com/remix_run?ref_src=twsrc%5Etfw\">@remix_run</a> has taught me: It\'s easier to start with a great UX and work toward a good DX than it is to start with a great DX and work toward a good UX.</p>— Kent C. Dodds &#x1f4bf; (@kentcdodds) <a href=\"https://twitter.com/kentcdodds/status/1482390454389805058?ref_src=twsrc%5Etfw\">January 15, 2022</a></blockquote>\r\n<script async=\"\" src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\"></script>\r\n<h2>Bonus: So Speedy</h2>\r\n<p>Did I mention how fast everything renders? I don’t tend to put too much stock into Lighthouse scores since they seem so random, but Remix crushes Lighthouse without me having to invest any additional effort into improving performance.</p>\r\n<h2>Give it a Shot</h2>\r\n<p>Remix is built on the <a href=\"https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API\">native Fetch API</a>, so it can run anywhere. While Remix is relatively new, it’s certainly production ready, and there is a dedicated team behind it. If you aren’t ready to dive into Remix yet, at least keep your eye on it because this is a game changer.</p>',NULL,0,NULL,'2022-04-21 15:13:07','2022-04-21 15:13:07','8007fa1b-1ba7-4bc2-a350-984d75902ee1',1,NULL,NULL,17,NULL),(1764,2396,'Why I’m So Excited About Remix',NULL,'<p>I’ve been building on the web for a long time. There’s a part of me that still has a bit of an old school mentality, and it’s hard for me to get really excited about new technology. Sure React was cool when it came out for its state management, but I didn’t see it as the be-all and end-all for building on the web. I really like <a href=\"https://craftcms.com/\">Craft CMS</a> for building CMS powered sites since I have full control over the HTML being sent to the browser, and it’s really easy to extend for complex functionality, but it can be a bit complex to setup for beginners and with additional complexity can come performance issues.&nbsp;So it’s been a while since I’ve seen something to be <em>really</em> excited about.</p>\r\n<p>Enter <a href=\"https://remix.run/\">Remix</a>.</p>\r\n<p>Remix is an interesting mix of old school techniques along with modern technology. Ryan Florence actually sums it up perfectly as to where Remix fits in.</p>\r\n<blockquote class=\"twitter-tweet\" data-dnt=\"true\" data-theme=\"dark\"><p lang=\"en\" dir=\"ltr\">Forget “full stack”. Remix is center stack.<br><br>It’s an HTTP tunnel between interactivity and business logic. It’s the part of the stack that no tool before it has solved, not completely.<br><br>I think I finally know how to talk about Remix.</p>— Ryan Florence (@ryanflorence) <a href=\"https://twitter.com/ryanflorence/status/1482233495195770883?ref_src=twsrc%5Etfw\">January 15, 2022</a></blockquote>\r\n<script async=\"\" src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\"></script>\r\n<p>I was able to easily switch my site that was fully powered by Craft to utilize Craft only as a GraphQL endpoint and Remix powering the rest. The two big things I needed to figure out were: how to get data from the GraphQL endpoint, and then how to process input from a user (for my contact form). I would definitely recommend reading through the Remix docs and the two tutorials, but if you can understand these two big pictures things, you’ll have enough to get started with Remix and go deeper once you get into it.</p>\r\n<h2>Getting GraphQL Data (aka Loaders)</h2>\r\n<p>Remix provides a <a href=\"https://remix.run/docs/en/v1/api/conventions#loader\">loader hook</a> that runs on the server to hydrate your component. In this simple example, I run a GraphQL request and return JSON with the results of that request in the loader function.</p>\r\n<script src=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550.js?file=loader.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550#file-loader-jsx\">View Gist</a></noscript>\r\n<p>Then in my <code>Index</code> component, I access the data from the loader hook with <a href=\"https://remix.run/docs/en/v1/api/remix#useloaderdata\">useLoaderData()</a>, and my component is now hydrated with that data. In MVC style of thinking, think of the loader hook as the controller processing the page load request, populating with data from the model, and then passing to the view.</p>\r\n<p>The great part about Remix is that this doesn’t have to be specifically a GraphQL request. This data can come from anywhere. The <a href=\"https://remix.run/docs/en/v1/tutorials/jokes\">Jokes tutorial</a> in the Remix docs even thoroughly walks through how you can manage all this data in <a href=\"https://www.prisma.io/\">Prisma</a>.</p>\r\n<h2>Processing User Input (aka Actions)</h2>\r\n<p>Ok great, so we’ve got data onto the page, but now we need to be able to handle user input. Remix also provides an <a href=\"https://remix.run/docs/en/v1/api/conventions#action\">action hook</a> to process an action request (ex: a form submission). In my case, I have a contact form that sends me an email via SendGrid after submission.</p>\r\n<script src=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550.js?file=action.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550#file-action-jsx\">View Gist</a></noscript>\r\n<p>If you don’t include an <code>action</code> attribute on your form, it will automatically submit to the same page. Again, in MVC thinking, the action would again be equivalent to the controller taking the request input and processing it. But honestly, this takes me back 15 years when form actions would point directly to PHP files.</p>\r\n<h2>Bonus: Progressive Enhancement</h2>\r\n<p>Since Remix is running on the server, you can turn off JavaScript and everything still works great. Data still loads, form actions still process; it’s beautiful. This is not running loaders and actions on the client side; it’s running them on the server. This isn’t an accident, the Remix team is carefully considering the UX.</p>\r\n<blockquote class=\"twitter-tweet\" data-dnt=\"true\" data-theme=\"dark\"><p lang=\"en\" dir=\"ltr\">User experience (UX) and developer experience (DX) are both important. UX is more important than DX.<a href=\"https://twitter.com/remix_run?ref_src=twsrc%5Etfw\">@remix_run</a> has taught me: It\'s easier to start with a great UX and work toward a good DX than it is to start with a great DX and work toward a good UX.</p>— Kent C. Dodds &#x1f4bf; (@kentcdodds) <a href=\"https://twitter.com/kentcdodds/status/1482390454389805058?ref_src=twsrc%5Etfw\">January 15, 2022</a></blockquote>\r\n<script async=\"\" src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\"></script>\r\n<h2>Bonus: So Speedy</h2>\r\n<p>Did I mention how fast everything renders? I don’t tend to put too much stock into Lighthouse scores since they seem so random, but Remix crushes Lighthouse without me having to invest any additional effort into improving performance.</p>\r\n<h2>Give it a Shot</h2>\r\n<p>Remix is built on the <a href=\"https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API\">native Fetch API</a>, so it can run anywhere. While Remix is relatively new, it’s certainly production ready, and there is a dedicated team behind it. If you aren’t ready to dive into Remix yet, at least keep your eye on it because this is a game changer.</p>',NULL,0,NULL,'2022-04-21 15:18:21','2022-04-21 15:18:21','fa470201-80f7-45e6-9011-45909b2a1eec',1,NULL,NULL,18,NULL),(1765,2397,'Why I’m So Excited About Remix',NULL,'<p>I’ve been building on the web for a long time. There’s a part of me that still has a bit of an old school mentality, and it’s hard for me to get really excited about new technology. Sure React was cool when it came out for its state management, but I didn’t see it as the be-all and end-all for building on the web. I really like <a href=\"https://craftcms.com/\">Craft CMS</a> for building CMS powered sites since I have full control over the HTML being sent to the browser, and it’s really easy to extend for complex functionality, but it can be a bit complex to setup for beginners and with additional complexity can come performance issues.&nbsp;So it’s been a while since I’ve seen something to be <em>really</em> excited about.</p>\r\n<p>Enter <a href=\"https://remix.run/\">Remix</a>.</p>\r\n<p>Remix is an interesting mix of old school techniques along with modern technology. Ryan Florence actually sums it up perfectly as to where Remix fits in.</p>\r\n<blockquote class=\"twitter-tweet\" data-dnt=\"true\" data-theme=\"dark\"><p lang=\"en\" dir=\"ltr\">Forget “full stack”. Remix is center stack.<br><br>It’s an HTTP tunnel between interactivity and business logic. It’s the part of the stack that no tool before it has solved, not completely.<br><br>I think I finally know how to talk about Remix.</p>— Ryan Florence (@ryanflorence) <a href=\"https://twitter.com/ryanflorence/status/1482233495195770883?ref_src=twsrc%5Etfw\">January 15, 2022</a></blockquote>\r\n<script async=\"\" src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\"></script>\r\n<p>I was able to easily switch my site that was fully powered by Craft to utilize Craft only as a GraphQL endpoint and Remix powering the rest. The two big things I needed to figure out were: how to get data from the GraphQL endpoint, and then how to process input from a user (for my contact form). I would definitely recommend reading through the Remix docs and the two tutorials, but if you can understand these two big pictures things, you’ll have enough to get started with Remix and go deeper once you get into it.</p>\r\n<h2>Getting GraphQL Data (aka Loaders)</h2>\r\n<p>Remix provides a <a href=\"https://remix.run/docs/en/v1/api/conventions#loader\">loader hook</a> that runs on the server to hydrate your component. In this simple example, I run a GraphQL request and return JSON with the results of that request in the loader function.</p>\r\n<script src=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550.js?file=loader.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550#file-loader-jsx\">View Gist</a></noscript>\r\n<p>Then in my <code>Index</code> component, I access the data from the loader hook with <a href=\"https://remix.run/docs/en/v1/api/remix#useloaderdata\">useLoaderData()</a>, and my component is now hydrated with that data. In MVC style of thinking, think of the loader hook as the controller processing the page load request, populating with data from the model, and then passing to the view.</p>\r\n<p>The great part about Remix is that this doesn’t have to be specifically a GraphQL request. This data can come from anywhere. The <a href=\"https://remix.run/docs/en/v1/tutorials/jokes\">Jokes tutorial</a> in the Remix docs even thoroughly walks through how you can manage all this data in <a href=\"https://www.prisma.io/\">Prisma</a>.</p>\r\n<h2>Processing User Input (aka Actions)</h2>\r\n<p>Ok great, so we’ve got data onto the page, but now we need to be able to handle user input. Remix also provides an <a href=\"https://remix.run/docs/en/v1/api/conventions#action\">action hook</a> to process an action request (ex: a form submission). In my case, I have a contact form that sends me an email via SendGrid after submission.</p>\r\n<script src=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550.js?file=action.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550#file-action-jsx\">View Gist</a></noscript>\r\n<p>If you don’t include an <code>action</code> attribute on your form, it will automatically submit to the same page. Again, in MVC thinking, the action would again be equivalent to the controller taking the request input and processing it. But honestly, this takes me back 15 years when form actions would point directly to PHP files.</p>\r\n<h2>Bonus: Progressive Enhancement</h2>\r\n<p>Since Remix is running on the server, you can turn off JavaScript and everything still works great. Data still loads, form actions still process; it’s beautiful. This is not running loaders and actions on the client side; it’s running them on the server. This isn’t an accident, the Remix team is carefully considering the UX.</p>\r\n<blockquote class=\"twitter-tweet\" data-dnt=\"true\" data-theme=\"dark\"><p lang=\"en\" dir=\"ltr\">User experience (UX) and developer experience (DX) are both important. UX is more important than DX.<a href=\"https://twitter.com/remix_run?ref_src=twsrc%5Etfw\">@remix_run</a> has taught me: It\'s easier to start with a great UX and work toward a good DX than it is to start with a great DX and work toward a good UX.</p>— Kent C. Dodds &#x1f4bf; (@kentcdodds) <a href=\"https://twitter.com/kentcdodds/status/1482390454389805058?ref_src=twsrc%5Etfw\">January 15, 2022</a></blockquote>\r\n<script async=\"\" src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\"></script>\r\n<h2>Bonus: So Speedy</h2>\r\n<p>Did I mention how fast everything renders? I don’t tend to put too much stock into Lighthouse scores since they seem so random, but Remix crushes Lighthouse without me having to invest any additional effort into improving performance.</p>\r\n<h2>Give it a Shot</h2>\r\n<p>Remix is built on the <a href=\"https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API\">native Fetch API</a>, so it can run anywhere. While Remix is relatively new, it’s certainly production ready, and there is a dedicated team behind it. If you aren’t ready to dive into Remix yet, at least keep your eye on it because this is a game changer.</p>',NULL,0,NULL,'2022-04-21 15:18:31','2022-04-21 15:18:31','e337b5db-23e0-415b-9b6b-ad54254b3c07',1,NULL,NULL,17,NULL),(1766,2398,'Why I’m So Excited About Remix',NULL,'<p>I’ve been building on the web for a long time. There’s a part of me that still has a bit of an old school mentality, and it’s hard for me to get really excited about new technology. Sure React was cool when it came out for its state management, but I didn’t see it as the be-all and end-all for building on the web. I really like <a href=\"https://craftcms.com/\">Craft CMS</a> for building CMS powered sites since I have full control over the HTML being sent to the browser, and it’s really easy to extend for complex functionality, but it can be a bit complex to setup for beginners and with additional complexity can come performance issues.&nbsp;So it’s been a while since I’ve seen something to be <em>really</em> excited about.</p>\r\n<p>Enter <a href=\"https://remix.run/\">Remix</a>.</p>\r\n<p>Remix is an interesting mix of old school techniques along with modern technology. Ryan Florence actually sums it up perfectly as to where Remix fits in.</p>\r\n<blockquote class=\"twitter-tweet\" data-dnt=\"true\" data-theme=\"dark\"><p lang=\"en\" dir=\"ltr\">Forget “full stack”. Remix is center stack.<br><br>It’s an HTTP tunnel between interactivity and business logic. It’s the part of the stack that no tool before it has solved, not completely.<br><br>I think I finally know how to talk about Remix.</p>— Ryan Florence (@ryanflorence) <a href=\"https://twitter.com/ryanflorence/status/1482233495195770883?ref_src=twsrc%5Etfw\">January 15, 2022</a></blockquote>\r\n<script async=\"\" src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\"></script>\r\n<p>I was able to easily switch my site that was fully powered by Craft to utilize Craft only as a GraphQL endpoint and Remix powering the rest. The two big things I needed to figure out were: how to get data from the GraphQL endpoint, and then how to process input from a user (for my contact form). I would definitely recommend reading through the Remix docs and the two tutorials, but if you can understand these two big pictures things, you’ll have enough to get started with Remix and go deeper once you get into it.</p>\r\n<h2>Getting GraphQL Data (aka Loaders)</h2>\r\n<p>Remix provides a <a href=\"https://remix.run/docs/en/v1/api/conventions#loader\">loader hook</a> that runs on the server to hydrate your component. In this simple example, I run a GraphQL request and return JSON with the results of that request in the loader function.</p>\r\n<script src=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550.js?file=loader.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550#file-loader-jsx\">View Gist</a></noscript>\r\n<p>Then in my <code>Index</code> component, I access the data from the loader hook with <a href=\"https://remix.run/docs/en/v1/api/remix#useloaderdata\">useLoaderData()</a>, and my component is now hydrated with that data. In MVC style of thinking, think of the loader hook as the controller processing the page load request, populating with data from the model, and then passing to the view.</p>\r\n<p>The great part about Remix is that this doesn’t have to be specifically a GraphQL request. This data can come from anywhere. The <a href=\"https://remix.run/docs/en/v1/tutorials/jokes\">Jokes tutorial</a> in the Remix docs even thoroughly walks through how you can manage all this data in <a href=\"https://www.prisma.io/\">Prisma</a>.</p>\r\n<h2>Processing User Input (aka Actions)</h2>\r\n<p>Ok great, so we’ve got data onto the page, but now we need to be able to handle user input. Remix also provides an <a href=\"https://remix.run/docs/en/v1/api/conventions#action\">action hook</a> to process an action request (ex: a form submission). In my case, I have a contact form that sends me an email via SendGrid after submission.</p>\r\n<script src=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550.js?file=action.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550#file-action-jsx\">View Gist</a></noscript>\r\n<p>If you don’t include an <code>action</code> attribute on your form, it will automatically submit to the same page. Again, in MVC thinking, the action would again be equivalent to the controller taking the request input and processing it. But honestly, this takes me back 15 years when form actions would point directly to PHP files.</p>\r\n<h2>Bonus: Progressive Enhancement</h2>\r\n<p>Since Remix is running on the server, you can turn off JavaScript and everything still works great. Data still loads, form actions still process; it’s beautiful. This is not running loaders and actions on the client side; it’s running them on the server. This isn’t an accident, the Remix team is carefully considering the UX.</p>\r\n<blockquote class=\"twitter-tweet\" data-dnt=\"true\" data-theme=\"dark\"><p lang=\"en\" dir=\"ltr\">User experience (UX) and developer experience (DX) are both important. UX is more important than DX.<a href=\"https://twitter.com/remix_run?ref_src=twsrc%5Etfw\">@remix_run</a> has taught me: It\'s easier to start with a great UX and work toward a good DX than it is to start with a great DX and work toward a good UX.</p>— Kent C. Dodds &#x1f4bf; (@kentcdodds) <a href=\"https://twitter.com/kentcdodds/status/1482390454389805058?ref_src=twsrc%5Etfw\">January 15, 2022</a></blockquote>\r\n<script async=\"\" src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\"></script>\r\n<h2>Bonus: So Speedy</h2>\r\n<p>Did I mention how fast everything renders? I don’t tend to put too much stock into Lighthouse scores since they seem so random, but Remix crushes Lighthouse without me having to invest any additional effort into improving performance.</p>\r\n<h2>Give it a Shot</h2>\r\n<p>Remix is built on the <a href=\"https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API\">native Fetch API</a>, so it can run anywhere. While Remix is relatively new, it’s certainly production ready, and there is a dedicated team behind it. If you aren’t ready to dive into Remix yet, at least keep your eye on it because this is a game changer.</p>',NULL,0,NULL,'2022-04-21 15:18:35','2022-04-21 15:18:35','ff27fd45-33f1-4d7d-a3ad-fdf765be8b7a',1,NULL,NULL,18,NULL),(1767,2399,'Why I’m So Excited About Remix',NULL,'<p>I’ve been building on the web for a long time. There’s a part of me that still has a bit of an old school mentality, and it’s hard for me to get really excited about new technology. Sure React was cool when it came out for its state management, but I didn’t see it as the be-all and end-all for building on the web. I really like <a href=\"https://craftcms.com/\">Craft CMS</a> for building CMS powered sites since I have full control over the HTML being sent to the browser, and it’s really easy to extend for complex functionality, but it can be a bit complex to setup for beginners and with additional complexity can come performance issues.&nbsp;So it’s been a while since I’ve seen something to be <em>really</em> excited about.</p>\r\n<p>Enter <a href=\"https://remix.run/\">Remix</a>.</p>\r\n<p>Remix is an interesting mix of old school techniques along with modern technology. Ryan Florence actually sums it up perfectly as to where Remix fits in.</p>\r\n<blockquote class=\"twitter-tweet\" data-dnt=\"true\" data-theme=\"dark\"><p lang=\"en\" dir=\"ltr\">Forget “full stack”. Remix is center stack.<br><br>It’s an HTTP tunnel between interactivity and business logic. It’s the part of the stack that no tool before it has solved, not completely.<br><br>I think I finally know how to talk about Remix.</p>— Ryan Florence (@ryanflorence) <a href=\"https://twitter.com/ryanflorence/status/1482233495195770883?ref_src=twsrc%5Etfw\">January 15, 2022</a></blockquote>\r\n<script async=\"\" src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\"></script>\r\n<p>I was able to easily switch my site that was fully powered by Craft to utilize Craft only as a GraphQL endpoint and Remix powering the rest. The two big things I needed to figure out were: how to get data from the GraphQL endpoint, and then how to process input from a user (for my contact form). I would definitely recommend reading through the Remix docs and the two tutorials, but if you can understand these two big pictures things, you’ll have enough to get started with Remix and go deeper once you get into it.</p>\r\n<h2>Getting GraphQL Data (aka Loaders)</h2>\r\n<p>Remix provides a <a href=\"https://remix.run/docs/en/v1/api/conventions#loader\">loader hook</a> that runs on the server to hydrate your component. In this simple example, I run a GraphQL request and return JSON with the results of that request in the loader function.</p>\r\n<script src=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550.js?file=loader.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550#file-loader-jsx\">View Gist</a></noscript>\r\n<p>Then in my <code>Index</code> component, I access the data from the loader hook with <a href=\"https://remix.run/docs/en/v1/api/remix#useloaderdata\">useLoaderData()</a>, and my component is now hydrated with that data. In MVC style of thinking, think of the loader hook as the controller processing the page load request, populating with data from the model, and then passing to the view.</p>\r\n<p>The great part about Remix is that this doesn’t have to be specifically a GraphQL request. This data can come from anywhere. The <a href=\"https://remix.run/docs/en/v1/tutorials/jokes\">Jokes tutorial</a> in the Remix docs even thoroughly walks through how you can manage all this data in <a href=\"https://www.prisma.io/\">Prisma</a>.</p>\r\n<h2>Processing User Input (aka Actions)</h2>\r\n<p>Ok great, so we’ve got data onto the page, but now we need to be able to handle user input. Remix also provides an <a href=\"https://remix.run/docs/en/v1/api/conventions#action\">action hook</a> to process an action request (ex: a form submission). In my case, I have a contact form that sends me an email via SendGrid after submission.</p>\r\n<script src=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550.js?file=action.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550#file-action-jsx\">View Gist</a></noscript>\r\n<p>If you don’t include an <code>action</code> attribute on your form, it will automatically submit to the same page. Again, in MVC thinking, the action would again be equivalent to the controller taking the request input and processing it. But honestly, this takes me back 15 years when form actions would point directly to PHP files.</p>\r\n<h2>Bonus: Progressive Enhancement</h2>\r\n<p>Since Remix is running on the server, you can turn off JavaScript and everything still works great. Data still loads, form actions still process; it’s beautiful. This is not running loaders and actions on the client side; it’s running them on the server. This isn’t an accident, the Remix team is carefully considering the UX.</p>\r\n<blockquote class=\"twitter-tweet\" data-dnt=\"true\" data-theme=\"dark\"><p lang=\"en\" dir=\"ltr\">User experience (UX) and developer experience (DX) are both important. UX is more important than DX.<a href=\"https://twitter.com/remix_run?ref_src=twsrc%5Etfw\">@remix_run</a> has taught me: It\'s easier to start with a great UX and work toward a good DX than it is to start with a great DX and work toward a good UX.</p>— Kent C. Dodds &#x1f4bf; (@kentcdodds) <a href=\"https://twitter.com/kentcdodds/status/1482390454389805058?ref_src=twsrc%5Etfw\">January 15, 2022</a></blockquote>\r\n<script async=\"\" src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\"></script>\r\n<h2>Bonus: So Speedy</h2>\r\n<p>Did I mention how fast everything renders? I don’t tend to put too much stock into Lighthouse scores since they seem so random, but Remix crushes Lighthouse without me having to invest any additional effort into improving performance.</p>\r\n<h2>Give it a Shot</h2>\r\n<p>Remix is built on the <a href=\"https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API\">native Fetch API</a>, so it can run anywhere. While Remix is relatively new, it’s certainly production ready, and there is a dedicated team behind it. If you aren’t ready to dive into Remix yet, at least keep your eye on it because this is a game changer.</p>',NULL,0,NULL,'2022-04-21 15:18:40','2022-04-21 15:18:40','62d12f97-a38c-4798-b827-f497ddd4ed1f',1,NULL,NULL,17,NULL),(1768,2400,'Why I’m So Excited About Remix',NULL,'<p>I’ve been building on the web for a long time. There’s a part of me that still has a bit of an old school mentality, and it’s hard for me to get really excited about new technology. Sure React was cool when it came out for its state management, but I didn’t see it as the be-all and end-all for building on the web. I really like <a href=\"https://craftcms.com/\">Craft CMS</a> for building CMS powered sites since I have full control over the HTML being sent to the browser, and it’s really easy to extend for complex functionality, but it can be a bit complex to setup for beginners and with additional complexity can come performance issues.&nbsp;So it’s been a while since I’ve seen something to be <em>really</em> excited about.</p>\r\n<p>Enter <a href=\"https://remix.run/\">Remix</a>.</p>\r\n<p>Remix is an interesting mix of old school techniques along with modern technology. Ryan Florence actually sums it up perfectly as to where Remix fits in.</p>\r\n<blockquote class=\"twitter-tweet\" data-dnt=\"true\" data-theme=\"dark\"><p lang=\"en\" dir=\"ltr\">Forget “full stack”. Remix is center stack.<br><br>It’s an HTTP tunnel between interactivity and business logic. It’s the part of the stack that no tool before it has solved, not completely.<br><br>I think I finally know how to talk about Remix.</p>— Ryan Florence (@ryanflorence) <a href=\"https://twitter.com/ryanflorence/status/1482233495195770883?ref_src=twsrc%5Etfw\">January 15, 2022</a></blockquote>\r\n<script async=\"\" src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\"></script>\r\n<p>I was able to easily switch my site that was fully powered by Craft to utilize Craft only as a GraphQL endpoint and Remix powering the rest. The two big things I needed to figure out were: how to get data from the GraphQL endpoint, and then how to process input from a user (for my contact form). I would definitely recommend reading through the Remix docs and the two tutorials, but if you can understand these two big pictures things, you’ll have enough to get started with Remix and go deeper once you get into it.</p>\r\n<h2>Getting GraphQL Data (aka Loaders)</h2>\r\n<p>Remix provides a <a href=\"https://remix.run/docs/en/v1/api/conventions#loader\">loader hook</a> that runs on the server to hydrate your component. In this simple example, I run a GraphQL request and return JSON with the results of that request in the loader function.</p>\r\n<script src=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550.js?file=loader.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550#file-loader-jsx\">View Gist</a></noscript>\r\n<p>Then in my <code>Index</code> component, I access the data from the loader hook with <a href=\"https://remix.run/docs/en/v1/api/remix#useloaderdata\">useLoaderData()</a>, and my component is now hydrated with that data. In MVC style of thinking, think of the loader hook as the controller processing the page load request, populating with data from the model, and then passing to the view.</p>\r\n<p>The great part about Remix is that this doesn’t have to be specifically a GraphQL request. This data can come from anywhere. The <a href=\"https://remix.run/docs/en/v1/tutorials/jokes\">Jokes tutorial</a> in the Remix docs even thoroughly walks through how you can manage all this data in <a href=\"https://www.prisma.io/\">Prisma</a>.</p>\r\n<h2>Processing User Input (aka Actions)</h2>\r\n<p>Ok great, so we’ve got data onto the page, but now we need to be able to handle user input. Remix also provides an <a href=\"https://remix.run/docs/en/v1/api/conventions#action\">action hook</a> to process an action request (ex: a form submission). In my case, I have a contact form that sends me an email via SendGrid after submission.</p>\r\n<script src=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550.js?file=action.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550#file-action-jsx\">View Gist</a></noscript>\r\n<p>If you don’t include an <code>action</code> attribute on your form, it will automatically submit to the same page. Again, in MVC thinking, the action would again be equivalent to the controller taking the request input and processing it. But honestly, this takes me back 15 years when form actions would point directly to PHP files.</p>\r\n<h2>Bonus: Progressive Enhancement</h2>\r\n<p>Since Remix is running on the server, you can turn off JavaScript and everything still works great. Data still loads, form actions still process; it’s beautiful. This is not running loaders and actions on the client side; it’s running them on the server. This isn’t an accident, the Remix team is carefully considering the UX.</p>\r\n<blockquote class=\"twitter-tweet\" data-dnt=\"true\" data-theme=\"dark\"><p lang=\"en\" dir=\"ltr\">User experience (UX) and developer experience (DX) are both important. UX is more important than DX.<a href=\"https://twitter.com/remix_run?ref_src=twsrc%5Etfw\">@remix_run</a> has taught me: It\'s easier to start with a great UX and work toward a good DX than it is to start with a great DX and work toward a good UX.</p>— Kent C. Dodds &#x1f4bf; (@kentcdodds) <a href=\"https://twitter.com/kentcdodds/status/1482390454389805058?ref_src=twsrc%5Etfw\">January 15, 2022</a></blockquote>\r\n<script async=\"\" src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\"></script>\r\n<h2>Bonus: So Speedy</h2>\r\n<p>Did I mention how fast everything renders? I don’t tend to put too much stock into Lighthouse scores since they seem so random, but Remix crushes Lighthouse without me having to invest any additional effort into improving performance.</p>\r\n<h2>Give it a Shot</h2>\r\n<p>Remix is built on the <a href=\"https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API\">native Fetch API</a>, so it can run anywhere. While Remix is relatively new, it’s certainly production ready, and there is a dedicated team behind it. If you aren’t ready to dive into Remix yet, at least keep your eye on it because this is a game changer.</p>',NULL,0,NULL,'2022-04-21 15:20:55','2022-04-21 15:20:55','0f4d73dd-8f98-483f-bab8-9fb896b206dc',1,NULL,NULL,18,NULL),(1769,2401,'Why I’m So Excited About Remix',NULL,'<p>I’ve been building on the web for a long time. There’s a part of me that still has a bit of an old school mentality, and it’s hard for me to get really excited about new technology. Sure React was cool when it came out for its state management, but I didn’t see it as the be-all and end-all for building on the web. I really like <a href=\"https://craftcms.com/\">Craft CMS</a> for building CMS powered sites since I have full control over the HTML being sent to the browser, and it’s really easy to extend for complex functionality, but it can be a bit complex to setup for beginners and with additional complexity can come performance issues.&nbsp;So it’s been a while since I’ve seen something to be <em>really</em> excited about.</p>\r\n<p>Enter <a href=\"https://remix.run/\">Remix</a>.</p>\r\n<p>Remix is an interesting mix of old school techniques along with modern technology. Ryan Florence actually sums it up perfectly as to where Remix fits in.</p>\r\n<blockquote class=\"twitter-tweet\" data-dnt=\"true\" data-theme=\"dark\"><p lang=\"en\" dir=\"ltr\">Forget “full stack”. Remix is center stack.<br><br>It’s an HTTP tunnel between interactivity and business logic. It’s the part of the stack that no tool before it has solved, not completely.<br><br>I think I finally know how to talk about Remix.</p>— Ryan Florence (@ryanflorence) <a href=\"https://twitter.com/ryanflorence/status/1482233495195770883?ref_src=twsrc%5Etfw\">January 15, 2022</a></blockquote>\r\n<script async=\"\" src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\"></script>\r\n<p>I was able to easily switch my site that was fully powered by Craft to utilize Craft only as a GraphQL endpoint and Remix powering the rest. The two big things I needed to figure out were: how to get data from the GraphQL endpoint, and then how to process input from a user (for my contact form). I would definitely recommend reading through the Remix docs and the two tutorials, but if you can understand these two big pictures things, you’ll have enough to get started with Remix and go deeper once you get into it.</p>\r\n<h2>Getting GraphQL Data (aka Loaders)</h2>\r\n<p>Remix provides a <a href=\"https://remix.run/docs/en/v1/api/conventions#loader\">loader hook</a> that runs on the server to hydrate your component. In this simple example, I run a GraphQL request and return JSON with the results of that request in the loader function.</p>\r\n<script src=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550.js?file=loader.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550#file-loader-jsx\">View Gist</a></noscript>\r\n<p>Then in my <code>Index</code> component, I access the data from the loader hook with <a href=\"https://remix.run/docs/en/v1/api/remix#useloaderdata\">useLoaderData()</a>, and my component is now hydrated with that data. In MVC style of thinking, think of the loader hook as the controller processing the page load request, populating with data from the model, and then passing to the view.</p>\r\n<p>The great part about Remix is that this doesn’t have to be specifically a GraphQL request. This data can come from anywhere. The <a href=\"https://remix.run/docs/en/v1/tutorials/jokes\">Jokes tutorial</a> in the Remix docs even thoroughly walks through how you can manage all this data in <a href=\"https://www.prisma.io/\">Prisma</a>.</p>\r\n<h2>Processing User Input (aka Actions)</h2>\r\n<p>Ok great, so we’ve got data onto the page, but now we need to be able to handle user input. Remix also provides an <a href=\"https://remix.run/docs/en/v1/api/conventions#action\">action hook</a> to process an action request (ex: a form submission). In my case, I have a contact form that sends me an email via SendGrid after submission.</p>\r\n<script src=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550.js?file=action.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550#file-action-jsx\">View Gist</a></noscript>\r\n<p>If you don’t include an <code>action</code> attribute on your form, it will automatically submit to the same page. Again, in MVC thinking, the action would again be equivalent to the controller taking the request input and processing it. But honestly, this takes me back 15 years when form actions would point directly to PHP files.</p>\r\n<h2>Bonus: Progressive Enhancement</h2>\r\n<p>Since Remix is running on the server, you can turn off JavaScript and everything still works great. Data still loads, form actions still process; it’s beautiful. This is not running loaders and actions on the client side; it’s running them on the server. This isn’t an accident, the Remix team is carefully considering the UX.</p>\r\n<blockquote class=\"twitter-tweet\" data-dnt=\"true\" data-theme=\"dark\"><p lang=\"en\" dir=\"ltr\">User experience (UX) and developer experience (DX) are both important. UX is more important than DX.<a href=\"https://twitter.com/remix_run?ref_src=twsrc%5Etfw\">@remix_run</a> has taught me: It\'s easier to start with a great UX and work toward a good DX than it is to start with a great DX and work toward a good UX.</p>— Kent C. Dodds &#x1f4bf; (@kentcdodds) <a href=\"https://twitter.com/kentcdodds/status/1482390454389805058?ref_src=twsrc%5Etfw\">January 15, 2022</a></blockquote>\r\n<script async=\"\" src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\"></script>\r\n<h2>Bonus: So Speedy</h2>\r\n<p>Did I mention how fast everything renders? I don’t tend to put too much stock into Lighthouse scores since they seem so random, but Remix crushes Lighthouse without me having to invest any additional effort into improving performance.</p>\r\n<h2>Give it a Shot</h2>\r\n<p>Remix is built on the <a href=\"https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API\">native Fetch API</a>, so it can run anywhere. While Remix is relatively new, it’s certainly production ready, and there is a dedicated team behind it. If you aren’t ready to dive into Remix yet, at least keep your eye on it because this is a game changer.</p>',NULL,0,NULL,'2022-04-21 15:20:58','2022-04-21 15:20:58','a7ab227b-31b3-4341-9a1c-630dea289015',1,NULL,NULL,17,NULL),(1770,2402,'Why I’m So Excited About Remix',NULL,'<p>I’ve been building on the web for a long time. There’s a part of me that still has a bit of an old school mentality, and it’s hard for me to get really excited about new technology. Sure React was cool when it came out for its state management, but I didn’t see it as the be-all and end-all for building on the web. I really like <a href=\"https://craftcms.com/\">Craft CMS</a> for building CMS powered sites since I have full control over the HTML being sent to the browser, and it’s really easy to extend for complex functionality, but it can be a bit complex to setup for beginners and with additional complexity can come performance issues.&nbsp;So it’s been a while since I’ve seen something to be <em>really</em> excited about.</p>\r\n<p>Enter <a href=\"https://remix.run/\">Remix</a>.</p>\r\n<p>Remix is an interesting mix of old school techniques along with modern technology. Ryan Florence actually sums it up perfectly as to where Remix fits in.</p>\r\n<blockquote class=\"twitter-tweet\" data-dnt=\"true\" data-theme=\"dark\"><p lang=\"en\" dir=\"ltr\">Forget “full stack”. Remix is center stack.<br><br>It’s an HTTP tunnel between interactivity and business logic. It’s the part of the stack that no tool before it has solved, not completely.<br><br>I think I finally know how to talk about Remix.</p>— Ryan Florence (@ryanflorence) <a href=\"https://twitter.com/ryanflorence/status/1482233495195770883?ref_src=twsrc%5Etfw\">January 15, 2022</a></blockquote>\r\n<script async=\"\" src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\"></script>\r\n<p>I was able to easily switch my site that was fully powered by Craft to utilize Craft only as a GraphQL endpoint and Remix powering the rest. The two big things I needed to figure out were: how to get data from the GraphQL endpoint, and then how to process input from a user (for my contact form). I would definitely recommend reading through the Remix docs and the two tutorials, but if you can understand these two big pictures things, you’ll have enough to get started with Remix and go deeper once you get into it.</p>\r\n<h2>Getting GraphQL Data (aka Loaders)</h2>\r\n<p>Remix provides a <a href=\"https://remix.run/docs/en/v1/api/conventions#loader\">loader hook</a> that runs on the server to hydrate your component. In this simple example, I run a GraphQL request and return JSON with the results of that request in the loader function.</p>\r\n<script src=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550.js?file=loader.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550#file-loader-jsx\">View Gist</a></noscript>\r\n<p>Then in my <code>Index</code> component, I access the data from the loader hook with <a href=\"https://remix.run/docs/en/v1/api/remix#useloaderdata\">useLoaderData()</a>, and my component is now hydrated with that data. In MVC style of thinking, think of the loader hook as the controller processing the page load request, populating with data from the model, and then passing to the view.</p>\r\n<p>The great part about Remix is that this doesn’t have to be specifically a GraphQL request. This data can come from anywhere. The <a href=\"https://remix.run/docs/en/v1/tutorials/jokes\">Jokes tutorial</a> in the Remix docs even thoroughly walks through how you can manage all this data in <a href=\"https://www.prisma.io/\">Prisma</a>.</p>\r\n<h2>Processing User Input (aka Actions)</h2>\r\n<p>Ok great, so we’ve got data onto the page, but now we need to be able to handle user input. Remix also provides an <a href=\"https://remix.run/docs/en/v1/api/conventions#action\">action hook</a> to process an action request (ex: a form submission). In my case, I have a contact form that sends me an email via SendGrid after submission.</p>\r\n<script src=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550.js?file=action.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550#file-action-jsx\">View Gist</a></noscript>\r\n<p>If you don’t include an <code>action</code> attribute on your form, it will automatically submit to the same page. Again, in MVC thinking, the action would again be equivalent to the controller taking the request input and processing it. But honestly, this takes me back 15 years when form actions would point directly to PHP files.</p>\r\n<h2>Bonus: Progressive Enhancement</h2>\r\n<p>Since Remix is running on the server, you can turn off JavaScript and everything still works great. Data still loads, form actions still process; it’s beautiful. This is not running loaders and actions on the client side; it’s running them on the server. This isn’t an accident, the Remix team is carefully considering the UX.</p>\r\n<blockquote class=\"twitter-tweet\" data-dnt=\"true\" data-theme=\"dark\"><p lang=\"en\" dir=\"ltr\">User experience (UX) and developer experience (DX) are both important. UX is more important than DX.<a href=\"https://twitter.com/remix_run?ref_src=twsrc%5Etfw\">@remix_run</a> has taught me: It\'s easier to start with a great UX and work toward a good DX than it is to start with a great DX and work toward a good UX.</p>— Kent C. Dodds &#x1f4bf; (@kentcdodds) <a href=\"https://twitter.com/kentcdodds/status/1482390454389805058?ref_src=twsrc%5Etfw\">January 15, 2022</a></blockquote>\r\n<script async=\"\" src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\"></script>\r\n<h2>Bonus: So Speedy</h2>\r\n<p>Did I mention how fast everything renders? I don’t tend to put too much stock into Lighthouse scores since they seem so random, but Remix crushes Lighthouse without me having to invest any additional effort into improving performance.</p>\r\n<h2>Give it a Shot</h2>\r\n<p>Remix is built on the <a href=\"https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API\">native Fetch API</a>, so it can run anywhere. While Remix is relatively new, it’s certainly production ready, and there is a dedicated team behind it. If you aren’t ready to dive into Remix yet, at least keep your eye on it because this is a game changer.</p>',NULL,0,NULL,'2022-04-21 15:21:22','2022-04-21 15:21:22','64080909-9fbe-48a1-9bea-3aaac4d9eb0e',1,NULL,NULL,18,NULL),(1771,2403,'Why I’m So Excited About Remix',NULL,'<p>I’ve been building on the web for a long time. There’s a part of me that still has a bit of an old school mentality, and it’s hard for me to get really excited about new technology. Sure React was cool when it came out for its state management, but I didn’t see it as the be-all and end-all for building on the web. I really like <a href=\"https://craftcms.com/\">Craft CMS</a> for building CMS powered sites since I have full control over the HTML being sent to the browser, and it’s really easy to extend for complex functionality, but it can be a bit complex to setup for beginners and with additional complexity can come performance issues.&nbsp;So it’s been a while since I’ve seen something to be <em>really</em> excited about.</p>\r\n<p>Enter <a href=\"https://remix.run/\">Remix</a>.</p>\r\n<p>Remix is an interesting mix of old school techniques along with modern technology. Ryan Florence actually sums it up perfectly as to where Remix fits in.</p>\r\n<blockquote class=\"twitter-tweet\" data-dnt=\"true\" data-theme=\"dark\"><p lang=\"en\" dir=\"ltr\">Forget “full stack”. Remix is center stack.<br><br>It’s an HTTP tunnel between interactivity and business logic. It’s the part of the stack that no tool before it has solved, not completely.<br><br>I think I finally know how to talk about Remix.</p>— Ryan Florence (@ryanflorence) <a href=\"https://twitter.com/ryanflorence/status/1482233495195770883?ref_src=twsrc%5Etfw\">January 15, 2022</a></blockquote>\r\n<script async=\"\" src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\"></script>\r\n<p>I was able to easily switch my site that was fully powered by Craft to utilize Craft only as a GraphQL endpoint and Remix powering the rest. The two big things I needed to figure out were: how to get data from the GraphQL endpoint, and then how to process input from a user (for my contact form). I would definitely recommend reading through the Remix docs and the two tutorials, but if you can understand these two big pictures things, you’ll have enough to get started with Remix and go deeper once you get into it.</p>\r\n<h2>Getting GraphQL Data (aka Loaders)</h2>\r\n<p>Remix provides a <a href=\"https://remix.run/docs/en/v1/api/conventions#loader\">loader hook</a> that runs on the server to hydrate your component. In this simple example, I run a GraphQL request and return JSON with the results of that request in the loader function.</p>\r\n<script src=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550.js?file=loader.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550#file-loader-jsx\">View Gist</a></noscript>\r\n<p>Then in my <code>Index</code> component, I access the data from the loader hook with <a href=\"https://remix.run/docs/en/v1/api/remix#useloaderdata\">useLoaderData()</a>, and my component is now hydrated with that data. In MVC style of thinking, think of the loader hook as the controller processing the page load request, populating with data from the model, and then passing to the view.</p>\r\n<p>The great part about Remix is that this doesn’t have to be specifically a GraphQL request. This data can come from anywhere. The <a href=\"https://remix.run/docs/en/v1/tutorials/jokes\">Jokes tutorial</a> in the Remix docs even thoroughly walks through how you can manage all this data in <a href=\"https://www.prisma.io/\">Prisma</a>.</p>\r\n<h2>Processing User Input (aka Actions)</h2>\r\n<p>Ok great, so we’ve got data onto the page, but now we need to be able to handle user input. Remix also provides an <a href=\"https://remix.run/docs/en/v1/api/conventions#action\">action hook</a> to process an action request (ex: a form submission). In my case, I have a contact form that sends me an email via SendGrid after submission.</p>\r\n<script src=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550.js?file=action.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550#file-action-jsx\">View Gist</a></noscript>\r\n<p>If you don’t include an <code>action</code> attribute on your form, it will automatically submit to the same page. Again, in MVC thinking, the action would again be equivalent to the controller taking the request input and processing it. But honestly, this takes me back 15 years when form actions would point directly to PHP files.</p>\r\n<h2>Bonus: Progressive Enhancement</h2>\r\n<p>Since Remix is running on the server, you can turn off JavaScript and everything still works great. Data still loads, form actions still process; it’s beautiful. This is not running loaders and actions on the client side; it’s running them on the server. This isn’t an accident, the Remix team is carefully considering the UX.</p>\r\n<blockquote class=\"twitter-tweet\" data-dnt=\"true\" data-theme=\"dark\"><p lang=\"en\" dir=\"ltr\">User experience (UX) and developer experience (DX) are both important. UX is more important than DX.<a href=\"https://twitter.com/remix_run?ref_src=twsrc%5Etfw\">@remix_run</a> has taught me: It\'s easier to start with a great UX and work toward a good DX than it is to start with a great DX and work toward a good UX.</p>— Kent C. Dodds &#x1f4bf; (@kentcdodds) <a href=\"https://twitter.com/kentcdodds/status/1482390454389805058?ref_src=twsrc%5Etfw\">January 15, 2022</a></blockquote>\r\n<script async=\"\" src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\"></script>\r\n<h2>Bonus: So Speedy</h2>\r\n<p>Did I mention how fast everything renders? I don’t tend to put too much stock into Lighthouse scores since they seem so random, but Remix crushes Lighthouse without me having to invest any additional effort into improving performance.</p>\r\n<h2>Give it a Shot</h2>\r\n<p>Remix is built on the <a href=\"https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API\">native Fetch API</a>, so it can run anywhere. While Remix is relatively new, it’s certainly production ready, and there is a dedicated team behind it. If you aren’t ready to dive into Remix yet, at least keep your eye on it because this is a game changer.</p>',NULL,0,NULL,'2022-04-21 15:21:32','2022-04-21 15:21:32','65e3e74f-7f5d-4188-a11f-1aaab2e21a28',1,NULL,NULL,17,NULL),(1772,2404,'Setting Up Live Preview with Craft CMS in Headless Mode',NULL,'<p>In my <a href=\"https://www.trevor-davis.com/blog/why-im-so-excited-about-remix\">previous post</a>, I talked about transitioning my site from being powered by <a href=\"https://craftcms.com/\">Craft</a> to being powered by <a href=\"https://remix.run/\">Remix</a> and a GraphQL endpoint coming from Craft. One of the best features of Craft is <a href=\"https://craftcms.com/features/all#live-preview\">Live Preview</a>, and it took a little configuration to get this working on my new Remix powered site.</p>\r\n<h2>Remix Configuration</h2>\r\n<p>These were specific changes that I needed to make on the Remix side, but really it would be the same for any GraphQL request. As Andrew Welch breaks down in <a href=\"https://nystudio107.com/blog/headless-preview-in-craft-cms\">his article</a>, the key is passing the token parameter back that Craft included in the URL.</p>\r\n<p>In the loader function of my blog post route, I call a helper function to setup the GraphQL client, and I pass the request to it:</p>\r\n<script src=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e.js?file=$slug.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e#file-slug-jsx\">View Gist</a></noscript>\r\n<p>And then in my helper function, I take that request, grab the URL params that I want to include, and add those to my GraphQL request endpoint URL:</p>\r\n<script src=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e.js?file=graphql.server.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e#file-graphql-server-jsx\">View Gist</a></noscript>\r\n<p>It wasn’t totally necessary to include the <code>x-craft-preview</code> and <code>x-craft-live-preview</code> parameters, but I figured it couldn’t hurt.</p>\r\n<h2>Craft Configuration</h2>\r\n<p>Now with the Remix configuration in place, I just needed to make two small changes to Craft to get it working correctly. First, I had to update the preview target for my Blog section to point to my Remix site:</p>\r\n<figure><img src=\"{asset:2283:url||//assets.trevor-davis.com/uploads/images/content/blog-section-preview-target.png}\" data-image=\"2283\" alt=\"Setting the preview target in my Blog Section\"></figure>\r\n<p>Then, I had to update the <code>config/general.php</code> to allow iframe requests from my Remix domain:</p>\r\n<script src=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e.js?file=general.php\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e#file-general-php\">View Gist</a></noscript>\r\n\r\n<h2>Voilà, Live Preview</h2>\r\n<p>And just like that, I had live preview working.</p>\r\n<video src=\"//assets.trevor-davis.com/uploads/images/content/live-preview.mp4\" autoplay=\"\" loop=\"\" muted=\"\" controls=\"\" width=\"100%\"></video>',NULL,0,NULL,'2022-04-21 15:27:14','2022-04-21 15:27:14','fdb00af7-b4f1-400b-bf31-d1d95734b289',1,NULL,NULL,24,NULL),(1773,2405,'Setting Up Live Preview with Craft CMS in Headless Mode',NULL,'<p>In my <a href=\"https://www.trevor-davis.com/blog/why-im-so-excited-about-remix\">previous post</a>, I talked about transitioning my site from being powered by <a href=\"https://craftcms.com/\">Craft</a> to being powered by <a href=\"https://remix.run/\">Remix</a> and a GraphQL endpoint coming from Craft. One of the best features of Craft is <a href=\"https://craftcms.com/features/all#live-preview\">Live Preview</a>, and it took a little configuration to get this working on my new Remix powered site.</p>\r\n<h2>Remix Configuration</h2>\r\n<p>These were specific changes that I needed to make on the Remix side, but really it would be the same for any GraphQL request. As Andrew Welch breaks down in <a href=\"https://nystudio107.com/blog/headless-preview-in-craft-cms\">his article</a>, the key is passing the token parameter back that Craft included in the URL.</p>\r\n<p>In the loader function of my blog post route, I call a helper function to setup the GraphQL client, and I pass the request to it:</p>\r\n<script src=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e.js?file=$slug.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e#file-slug-jsx\">View Gist</a></noscript>\r\n<p>And then in my helper function, I take that request, grab the URL params that I want to include, and add those to my GraphQL request endpoint URL:</p>\r\n<script src=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e.js?file=graphql.server.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e#file-graphql-server-jsx\">View Gist</a></noscript>\r\n<p>It wasn’t totally necessary to include the <code>x-craft-preview</code> and <code>x-craft-live-preview</code> parameters, but I figured it couldn’t hurt.</p>\r\n<h2>Craft Configuration</h2>\r\n<p>Now with the Remix configuration in place, I just needed to make two small changes to Craft to get it working correctly. First, I had to update the preview target for my Blog section to point to my Remix site:</p>\r\n<figure><img src=\"{asset:2283:url||//assets.trevor-davis.com/uploads/images/content/blog-section-preview-target.png}\" data-image=\"2283\" alt=\"Setting the preview target in my Blog Section\"></figure>\r\n<p>Then, I had to update the <code>config/general.php</code> to allow iframe requests from my Remix domain:</p>\r\n<script src=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e.js?file=general.php\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e#file-general-php\">View Gist</a></noscript>\r\n\r\n<h2>Voilà, Live Preview</h2>\r\n<p>And just like that, I had live preview working.</p>\r\n<video src=\"//assets.trevor-davis.com/uploads/images/content/live-preview.mp4\" autoplay=\"\" loop=\"\" muted=\"\" controls=\"\" width=\"100%\"></video>',NULL,0,NULL,'2022-04-21 15:27:17','2022-04-21 15:27:17','d1365427-307d-4146-89ef-1d8bac452fb0',1,NULL,NULL,23,NULL),(1774,2406,'Why I’m So Excited About Remix',NULL,'<p>I’ve been building on the web for a long time. There’s a part of me that still has a bit of an old school mentality, and it’s hard for me to get really excited about new technology. Sure React was cool when it came out for its state management, but I didn’t see it as the be-all and end-all for building on the web. I really like <a href=\"https://craftcms.com/\">Craft CMS</a> for building CMS powered sites since I have full control over the HTML being sent to the browser, and it’s really easy to extend for complex functionality, but it can be a bit complex to setup for beginners and with additional complexity can come performance issues.&nbsp;So it’s been a while since I’ve seen something to be <em>really</em> excited about.</p>\r\n<p>Enter <a href=\"https://remix.run/\">Remix</a>.</p>\r\n<p>Remix is an interesting mix of old school techniques along with modern technology. Ryan Florence actually sums it up perfectly as to where Remix fits in.</p>\r\n<blockquote class=\"twitter-tweet\" data-dnt=\"true\" data-theme=\"dark\"><p lang=\"en\" dir=\"ltr\">Forget “full stack”. Remix is center stack.<br><br>It’s an HTTP tunnel between interactivity and business logic. It’s the part of the stack that no tool before it has solved, not completely.<br><br>I think I finally know how to talk about Remix.</p>— Ryan Florence (@ryanflorence) <a href=\"https://twitter.com/ryanflorence/status/1482233495195770883?ref_src=twsrc%5Etfw\">January 15, 2022</a></blockquote>\r\n<script async=\"\" src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\"></script>\r\n<p>I was able to easily switch my site that was fully powered by Craft to utilize Craft only as a GraphQL endpoint and Remix powering the rest. The two big things I needed to figure out were: how to get data from the GraphQL endpoint, and then how to process input from a user (for my contact form). I would definitely recommend reading through the Remix docs and the two tutorials, but if you can understand these two big pictures things, you’ll have enough to get started with Remix and go deeper once you get into it.</p>\r\n<h2>Getting GraphQL Data (aka Loaders)</h2>\r\n<p>Remix provides a <a href=\"https://remix.run/docs/en/v1/api/conventions#loader\">loader hook</a> that runs on the server to hydrate your component. In this simple example, I run a GraphQL request and return JSON with the results of that request in the loader function.</p>\r\n<script src=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550.js?file=loader.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550#file-loader-jsx\">View Gist</a></noscript>\r\n<p>Then in my <code>Index</code> component, I access the data from the loader hook with <a href=\"https://remix.run/docs/en/v1/api/remix#useloaderdata\">useLoaderData()</a>, and my component is now hydrated with that data. In MVC style of thinking, think of the loader hook as the controller processing the page load request, populating with data from the model, and then passing to the view.</p>\r\n<p>The great part about Remix is that this doesn’t have to be specifically a GraphQL request. This data can come from anywhere. The <a href=\"https://remix.run/docs/en/v1/tutorials/jokes\">Jokes tutorial</a> in the Remix docs even thoroughly walks through how you can manage all this data in <a href=\"https://www.prisma.io/\">Prisma</a>.</p>\r\n<h2>Processing User Input (aka Actions)</h2>\r\n<p>Ok great, so we’ve got data onto the page, but now we need to be able to handle user input. Remix also provides an <a href=\"https://remix.run/docs/en/v1/api/conventions#action\">action hook</a> to process an action request (ex: a form submission). In my case, I have a contact form that sends me an email via SendGrid after submission.</p>\r\n<script src=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550.js?file=action.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550#file-action-jsx\">View Gist</a></noscript>\r\n<p>If you don’t include an <code>action</code> attribute on your form, it will automatically submit to the same page. Again, in MVC thinking, the action would again be equivalent to the controller taking the request input and processing it. But honestly, this takes me back 15 years when form actions would point directly to PHP files.</p>\r\n<h2>Bonus: Progressive Enhancement</h2>\r\n<p>Since Remix is running on the server, you can turn off JavaScript and everything still works great. Data still loads, form actions still process; it’s beautiful. This is not running loaders and actions on the client side; it’s running them on the server. This isn’t an accident, the Remix team is carefully considering the UX.</p>\r\n<blockquote class=\"twitter-tweet\" data-dnt=\"true\" data-theme=\"dark\"><p lang=\"en\" dir=\"ltr\">User experience (UX) and developer experience (DX) are both important. UX is more important than DX.<a href=\"https://twitter.com/remix_run?ref_src=twsrc%5Etfw\">@remix_run</a> has taught me: It\'s easier to start with a great UX and work toward a good DX than it is to start with a great DX and work toward a good UX.</p>— Kent C. Dodds &#x1f4bf; (@kentcdodds) <a href=\"https://twitter.com/kentcdodds/status/1482390454389805058?ref_src=twsrc%5Etfw\">January 15, 2022</a></blockquote>\r\n<script async=\"\" src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\"></script>\r\n<h2>Bonus: So Speedy</h2>\r\n<p>Did I mention how fast everything renders? I don’t tend to put too much stock into Lighthouse scores since they seem so random, but Remix crushes Lighthouse without me having to invest any additional effort into improving performance.</p>\r\n<h2>Give it a Shot</h2>\r\n<p>Remix is built on the <a href=\"https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API\">native Fetch API</a>, so it can run anywhere. While Remix is relatively new, it’s certainly production ready, and there is a dedicated team behind it. If you aren’t ready to dive into Remix yet, at least keep your eye on it because this is a game changer.</p>',NULL,0,NULL,'2022-04-21 15:28:13','2022-04-21 15:28:13','d4d9c487-6333-4ad2-a275-05b2d8eed43c',1,NULL,NULL,18,NULL),(1775,2407,'Why I’m So Excited About Remix',NULL,'<p>I’ve been building on the web for a long time. There’s a part of me that still has a bit of an old school mentality, and it’s hard for me to get really excited about new technology. Sure React was cool when it came out for its state management, but I didn’t see it as the be-all and end-all for building on the web. I really like <a href=\"https://craftcms.com/\">Craft CMS</a> for building CMS powered sites since I have full control over the HTML being sent to the browser, and it’s really easy to extend for complex functionality, but it can be a bit complex to setup for beginners and with additional complexity can come performance issues.&nbsp;So it’s been a while since I’ve seen something to be <em>really</em> excited about.</p>\r\n<p>Enter <a href=\"https://remix.run/\">Remix</a>.</p>\r\n<p>Remix is an interesting mix of old school techniques along with modern technology. Ryan Florence actually sums it up perfectly as to where Remix fits in.</p>\r\n<blockquote class=\"twitter-tweet\" data-dnt=\"true\" data-theme=\"dark\"><p lang=\"en\" dir=\"ltr\">Forget “full stack”. Remix is center stack.<br><br>It’s an HTTP tunnel between interactivity and business logic. It’s the part of the stack that no tool before it has solved, not completely.<br><br>I think I finally know how to talk about Remix.</p>— Ryan Florence (@ryanflorence) <a href=\"https://twitter.com/ryanflorence/status/1482233495195770883?ref_src=twsrc%5Etfw\">January 15, 2022</a></blockquote>\r\n<script async=\"\" src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\"></script>\r\n<p>I was able to easily switch my site that was fully powered by Craft to utilize Craft only as a GraphQL endpoint and Remix powering the rest. The two big things I needed to figure out were: how to get data from the GraphQL endpoint, and then how to process input from a user (for my contact form). I would definitely recommend reading through the Remix docs and the two tutorials, but if you can understand these two big pictures things, you’ll have enough to get started with Remix and go deeper once you get into it.</p>\r\n<h2>Getting GraphQL Data (aka Loaders)</h2>\r\n<p>Remix provides a <a href=\"https://remix.run/docs/en/v1/api/conventions#loader\">loader hook</a> that runs on the server to hydrate your component. In this simple example, I run a GraphQL request and return JSON with the results of that request in the loader function.</p>\r\n<script src=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550.js?file=loader.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550#file-loader-jsx\">View Gist</a></noscript>\r\n<p>Then in my <code>Index</code> component, I access the data from the loader hook with <a href=\"https://remix.run/docs/en/v1/api/remix#useloaderdata\">useLoaderData()</a>, and my component is now hydrated with that data. In MVC style of thinking, think of the loader hook as the controller processing the page load request, populating with data from the model, and then passing to the view.</p>\r\n<p>The great part about Remix is that this doesn’t have to be specifically a GraphQL request. This data can come from anywhere. The <a href=\"https://remix.run/docs/en/v1/tutorials/jokes\">Jokes tutorial</a> in the Remix docs even thoroughly walks through how you can manage all this data in <a href=\"https://www.prisma.io/\">Prisma</a>.</p>\r\n<h2>Processing User Input (aka Actions)</h2>\r\n<p>Ok great, so we’ve got data onto the page, but now we need to be able to handle user input. Remix also provides an <a href=\"https://remix.run/docs/en/v1/api/conventions#action\">action hook</a> to process an action request (ex: a form submission). In my case, I have a contact form that sends me an email via SendGrid after submission.</p>\r\n<script src=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550.js?file=action.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550#file-action-jsx\">View Gist</a></noscript>\r\n<p>If you don’t include an <code>action</code> attribute on your form, it will automatically submit to the same page. Again, in MVC thinking, the action would again be equivalent to the controller taking the request input and processing it. But honestly, this takes me back 15 years when form actions would point directly to PHP files.</p>\r\n<h2>Bonus: Progressive Enhancement</h2>\r\n<p>Since Remix is running on the server, you can turn off JavaScript and everything still works great. Data still loads, form actions still process; it’s beautiful. This is not running loaders and actions on the client side; it’s running them on the server. This isn’t an accident, the Remix team is carefully considering the UX.</p>\r\n<blockquote class=\"twitter-tweet\" data-dnt=\"true\" data-theme=\"dark\"><p lang=\"en\" dir=\"ltr\">User experience (UX) and developer experience (DX) are both important. UX is more important than DX.<a href=\"https://twitter.com/remix_run?ref_src=twsrc%5Etfw\">@remix_run</a> has taught me: It\'s easier to start with a great UX and work toward a good DX than it is to start with a great DX and work toward a good UX.</p>— Kent C. Dodds &#x1f4bf; (@kentcdodds) <a href=\"https://twitter.com/kentcdodds/status/1482390454389805058?ref_src=twsrc%5Etfw\">January 15, 2022</a></blockquote>\r\n<script async=\"\" src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\"></script>\r\n<h2>Bonus: So Speedy</h2>\r\n<p>Did I mention how fast everything renders? I don’t tend to put too much stock into Lighthouse scores since they seem so random, but Remix crushes Lighthouse without me having to invest any additional effort into improving performance.</p>\r\n<h2>Give it a Shot</h2>\r\n<p>Remix is built on the <a href=\"https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API\">native Fetch API</a>, so it can run anywhere. While Remix is relatively new, it’s certainly production ready, and there is a dedicated team behind it. If you aren’t ready to dive into Remix yet, at least keep your eye on it because this is a game changer.</p>',NULL,0,NULL,'2022-04-21 15:28:18','2022-04-21 15:28:18','5230ae3a-c5ba-4aa2-af7d-e7465303505e',1,NULL,NULL,17,NULL),(1776,2408,'Why I’m So Excited About Remix',NULL,'<p>I’ve been building on the web for a long time. There’s a part of me that still has a bit of an old school mentality, and it’s hard for me to get really excited about new technology. Sure React was cool when it came out for its state management, but I didn’t see it as the be-all and end-all for building on the web. I really like <a href=\"https://craftcms.com/\">Craft CMS</a> for building CMS powered sites since I have full control over the HTML being sent to the browser, and it’s really easy to extend for complex functionality, but it can be a bit complex to setup for beginners and with additional complexity can come performance issues.&nbsp;So it’s been a while since I’ve seen something to be <em>really</em> excited about.</p>\r\n<p>Enter <a href=\"https://remix.run/\">Remix</a>.</p>\r\n<p>Remix is an interesting mix of old school techniques along with modern technology. Ryan Florence actually sums it up perfectly as to where Remix fits in.</p>\r\n<blockquote class=\"twitter-tweet\" data-dnt=\"true\" data-theme=\"dark\"><p lang=\"en\" dir=\"ltr\">Forget “full stack”. Remix is center stack.<br><br>It’s an HTTP tunnel between interactivity and business logic. It’s the part of the stack that no tool before it has solved, not completely.<br><br>I think I finally know how to talk about Remix.</p>— Ryan Florence (@ryanflorence) <a href=\"https://twitter.com/ryanflorence/status/1482233495195770883?ref_src=twsrc%5Etfw\">January 15, 2022</a></blockquote>\r\n<script async=\"\" src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\"></script>\r\n<p>I was able to easily switch my site that was fully powered by Craft to utilize Craft only as a GraphQL endpoint and Remix powering the rest. The two big things I needed to figure out were: how to get data from the GraphQL endpoint, and then how to process input from a user (for my contact form). I would definitely recommend reading through the Remix docs and the two tutorials, but if you can understand these two big pictures things, you’ll have enough to get started with Remix and go deeper once you get into it.</p>\r\n<h2>Getting GraphQL Data (aka Loaders)</h2>\r\n<p>Remix provides a <a href=\"https://remix.run/docs/en/v1/api/conventions#loader\">loader hook</a> that runs on the server to hydrate your component. In this simple example, I run a GraphQL request and return JSON with the results of that request in the loader function.</p>\r\n<script src=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550.js?file=loader.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550#file-loader-jsx\">View Gist</a></noscript>\r\n<p>Then in my <code>Index</code> component, I access the data from the loader hook with <a href=\"https://remix.run/docs/en/v1/api/remix#useloaderdata\">useLoaderData()</a>, and my component is now hydrated with that data. In MVC style of thinking, think of the loader hook as the controller processing the page load request, populating with data from the model, and then passing to the view.</p>\r\n<p>The great part about Remix is that this doesn’t have to be specifically a GraphQL request. This data can come from anywhere. The <a href=\"https://remix.run/docs/en/v1/tutorials/jokes\">Jokes tutorial</a> in the Remix docs even thoroughly walks through how you can manage all this data in <a href=\"https://www.prisma.io/\">Prisma</a>.</p>\r\n<h2>Processing User Input (aka Actions)</h2>\r\n<p>Ok great, so we’ve got data onto the page, but now we need to be able to handle user input. Remix also provides an <a href=\"https://remix.run/docs/en/v1/api/conventions#action\">action hook</a> to process an action request (ex: a form submission). In my case, I have a contact form that sends me an email via SendGrid after submission.</p>\r\n<script src=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550.js?file=action.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550#file-action-jsx\">View Gist</a></noscript>\r\n<p>If you don’t include an <code>action</code> attribute on your form, it will automatically submit to the same page. Again, in MVC thinking, the action would again be equivalent to the controller taking the request input and processing it. But honestly, this takes me back 15 years when form actions would point directly to PHP files.</p>\r\n<h2>Bonus: Progressive Enhancement</h2>\r\n<p>Since Remix is running on the server, you can turn off JavaScript and everything still works great. Data still loads, form actions still process; it’s beautiful. This is not running loaders and actions on the client side; it’s running them on the server. This isn’t an accident, the Remix team is carefully considering the UX.</p>\r\n<blockquote class=\"twitter-tweet\" data-dnt=\"true\" data-theme=\"dark\"><p lang=\"en\" dir=\"ltr\">User experience (UX) and developer experience (DX) are both important. UX is more important than DX.<a href=\"https://twitter.com/remix_run?ref_src=twsrc%5Etfw\">@remix_run</a> has taught me: It\'s easier to start with a great UX and work toward a good DX than it is to start with a great DX and work toward a good UX.</p>— Kent C. Dodds &#x1f4bf; (@kentcdodds) <a href=\"https://twitter.com/kentcdodds/status/1482390454389805058?ref_src=twsrc%5Etfw\">January 15, 2022</a></blockquote>\r\n<script async=\"\" src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\"></script>\r\n<h2>Bonus: So Speedy</h2>\r\n<p>Did I mention how fast everything renders? I don’t tend to put too much stock into Lighthouse scores since they seem so random, but Remix crushes Lighthouse without me having to invest any additional effort into improving performance.</p>\r\n<h2>Give it a Shot</h2>\r\n<p>Remix is built on the <a href=\"https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API\">native Fetch API</a>, so it can run anywhere. While Remix is relatively new, it’s certainly production ready, and there is a dedicated team behind it. If you aren’t ready to dive into Remix yet, at least keep your eye on it because this is a game changer.</p>',NULL,0,NULL,'2022-04-21 15:28:52','2022-04-21 15:28:52','be3469ca-ba1f-4ab8-ba40-dcd4324a3ec7',1,NULL,NULL,18,NULL),(1777,2409,'Why I’m So Excited About Remix',NULL,'<p>I’ve been building on the web for a long time. There’s a part of me that still has a bit of an old school mentality, and it’s hard for me to get really excited about new technology. Sure React was cool when it came out for its state management, but I didn’t see it as the be-all and end-all for building on the web. I really like <a href=\"https://craftcms.com/\">Craft CMS</a> for building CMS powered sites since I have full control over the HTML being sent to the browser, and it’s really easy to extend for complex functionality, but it can be a bit complex to setup for beginners and with additional complexity can come performance issues.&nbsp;So it’s been a while since I’ve seen something to be <em>really</em> excited about.</p>\r\n<p>Enter <a href=\"https://remix.run/\">Remix</a>.</p>\r\n<p>Remix is an interesting mix of old school techniques along with modern technology. Ryan Florence actually sums it up perfectly as to where Remix fits in.</p>\r\n<blockquote class=\"twitter-tweet\" data-dnt=\"true\" data-theme=\"dark\"><p lang=\"en\" dir=\"ltr\">Forget “full stack”. Remix is center stack.<br><br>It’s an HTTP tunnel between interactivity and business logic. It’s the part of the stack that no tool before it has solved, not completely.<br><br>I think I finally know how to talk about Remix.</p>— Ryan Florence (@ryanflorence) <a href=\"https://twitter.com/ryanflorence/status/1482233495195770883?ref_src=twsrc%5Etfw\">January 15, 2022</a></blockquote>\r\n<script async=\"\" src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\"></script>\r\n<p>I was able to easily switch my site that was fully powered by Craft to utilize Craft only as a GraphQL endpoint and Remix powering the rest. The two big things I needed to figure out were: how to get data from the GraphQL endpoint, and then how to process input from a user (for my contact form). I would definitely recommend reading through the Remix docs and the two tutorials, but if you can understand these two big pictures things, you’ll have enough to get started with Remix and go deeper once you get into it.</p>\r\n<h2>Getting GraphQL Data (aka Loaders)</h2>\r\n<p>Remix provides a <a href=\"https://remix.run/docs/en/v1/api/conventions#loader\">loader hook</a> that runs on the server to hydrate your component. In this simple example, I run a GraphQL request and return JSON with the results of that request in the loader function.</p>\r\n<script src=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550.js?file=loader.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550#file-loader-jsx\">View Gist</a></noscript>\r\n<p>Then in my <code>Index</code> component, I access the data from the loader hook with <a href=\"https://remix.run/docs/en/v1/api/remix#useloaderdata\">useLoaderData()</a>, and my component is now hydrated with that data. In MVC style of thinking, think of the loader hook as the controller processing the page load request, populating with data from the model, and then passing to the view.</p>\r\n<p>The great part about Remix is that this doesn’t have to be specifically a GraphQL request. This data can come from anywhere. The <a href=\"https://remix.run/docs/en/v1/tutorials/jokes\">Jokes tutorial</a> in the Remix docs even thoroughly walks through how you can manage all this data in <a href=\"https://www.prisma.io/\">Prisma</a>.</p>\r\n<h2>Processing User Input (aka Actions)</h2>\r\n<p>Ok great, so we’ve got data onto the page, but now we need to be able to handle user input. Remix also provides an <a href=\"https://remix.run/docs/en/v1/api/conventions#action\">action hook</a> to process an action request (ex: a form submission). In my case, I have a contact form that sends me an email via SendGrid after submission.</p>\r\n<script src=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550.js?file=action.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550#file-action-jsx\">View Gist</a></noscript>\r\n<p>If you don’t include an <code>action</code> attribute on your form, it will automatically submit to the same page. Again, in MVC thinking, the action would again be equivalent to the controller taking the request input and processing it. But honestly, this takes me back 15 years when form actions would point directly to PHP files.</p>\r\n<h2>Bonus: Progressive Enhancement</h2>\r\n<p>Since Remix is running on the server, you can turn off JavaScript and everything still works great. Data still loads, form actions still process; it’s beautiful. This is not running loaders and actions on the client side; it’s running them on the server. This isn’t an accident, the Remix team is carefully considering the UX.</p>\r\n<blockquote class=\"twitter-tweet\" data-dnt=\"true\" data-theme=\"dark\"><p lang=\"en\" dir=\"ltr\">User experience (UX) and developer experience (DX) are both important. UX is more important than DX.<a href=\"https://twitter.com/remix_run?ref_src=twsrc%5Etfw\">@remix_run</a> has taught me: It\'s easier to start with a great UX and work toward a good DX than it is to start with a great DX and work toward a good UX.</p>— Kent C. Dodds &#x1f4bf; (@kentcdodds) <a href=\"https://twitter.com/kentcdodds/status/1482390454389805058?ref_src=twsrc%5Etfw\">January 15, 2022</a></blockquote>\r\n<script async=\"\" src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\"></script>\r\n<h2>Bonus: So Speedy</h2>\r\n<p>Did I mention how fast everything renders? I don’t tend to put too much stock into Lighthouse scores since they seem so random, but Remix crushes Lighthouse without me having to invest any additional effort into improving performance.</p>\r\n<h2>Give it a Shot</h2>\r\n<p>Remix is built on the <a href=\"https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API\">native Fetch API</a>, so it can run anywhere. While Remix is relatively new, it’s certainly production ready, and there is a dedicated team behind it. If you aren’t ready to dive into Remix yet, at least keep your eye on it because this is a game changer.</p>',NULL,0,NULL,'2022-04-21 15:28:54','2022-04-21 15:28:54','f3ce1941-84d7-4251-b3a7-afd57da0e197',1,NULL,NULL,17,NULL),(1778,2410,'Why I’m So Excited About Remix',NULL,'<p>I’ve been building on the web for a long time. There’s a part of me that still has a bit of an old school mentality, and it’s hard for me to get really excited about new technology. Sure React was cool when it came out for its state management, but I didn’t see it as the be-all and end-all for building on the web. I really like <a href=\"https://craftcms.com/\">Craft CMS</a> for building CMS powered sites since I have full control over the HTML being sent to the browser, and it’s really easy to extend for complex functionality, but it can be a bit complex to setup for beginners and with additional complexity can come performance issues.&nbsp;So it’s been a while since I’ve seen something to be <em>really</em> excited about.</p>\r\n<p>Enter <a href=\"https://remix.run/\">Remix</a>.</p>\r\n<p>Remix is an interesting mix of old school techniques along with modern technology. Ryan Florence actually sums it up perfectly as to where Remix fits in.</p>\r\n<blockquote class=\"twitter-tweet\" data-dnt=\"true\" data-theme=\"dark\"><p lang=\"en\" dir=\"ltr\">Forget “full stack”. Remix is center stack.<br><br>It’s an HTTP tunnel between interactivity and business logic. It’s the part of the stack that no tool before it has solved, not completely.<br><br>I think I finally know how to talk about Remix.</p>— Ryan Florence (@ryanflorence) <a href=\"https://twitter.com/ryanflorence/status/1482233495195770883?ref_src=twsrc%5Etfw\">January 15, 2022</a></blockquote>\r\n<script async=\"\" src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\"></script>\r\n<p>I was able to easily switch my site that was fully powered by Craft to utilize Craft only as a GraphQL endpoint and Remix powering the rest. The two big things I needed to figure out were: how to get data from the GraphQL endpoint, and then how to process input from a user (for my contact form). I would definitely recommend reading through the Remix docs and the two tutorials, but if you can understand these two big pictures things, you’ll have enough to get started with Remix and go deeper once you get into it.</p>\r\n<h2>Getting GraphQL Data (aka Loaders)</h2>\r\n<p>Remix provides a <a href=\"https://remix.run/docs/en/v1/api/conventions#loader\">loader hook</a> that runs on the server to hydrate your component. In this simple example, I run a GraphQL request and return JSON with the results of that request in the loader function.</p>\r\n<script src=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550.js?file=loader.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550#file-loader-jsx\">View Gist</a></noscript>\r\n<p>Then in my <code>Index</code> component, I access the data from the loader hook with <a href=\"https://remix.run/docs/en/v1/api/remix#useloaderdata\">useLoaderData()</a>, and my component is now hydrated with that data. In MVC style of thinking, think of the loader hook as the controller processing the page load request, populating with data from the model, and then passing to the view.</p>\r\n<p>The great part about Remix is that this doesn’t have to be specifically a GraphQL request. This data can come from anywhere. The <a href=\"https://remix.run/docs/en/v1/tutorials/jokes\">Jokes tutorial</a> in the Remix docs even thoroughly walks through how you can manage all this data in <a href=\"https://www.prisma.io/\">Prisma</a>.</p>\r\n<h2>Processing User Input (aka Actions)</h2>\r\n<p>Ok great, so we’ve got data onto the page, but now we need to be able to handle user input. Remix also provides an <a href=\"https://remix.run/docs/en/v1/api/conventions#action\">action hook</a> to process an action request (ex: a form submission). In my case, I have a contact form that sends me an email via SendGrid after submission.</p>\r\n<script src=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550.js?file=action.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550#file-action-jsx\">View Gist</a></noscript>\r\n<p>If you don’t include an <code>action</code> attribute on your form, it will automatically submit to the same page. Again, in MVC thinking, the action would again be equivalent to the controller taking the request input and processing it. But honestly, this takes me back 15 years when form actions would point directly to PHP files.</p>\r\n<h2>Bonus: Progressive Enhancement</h2>\r\n<p>Since Remix is running on the server, you can turn off JavaScript and everything still works great. Data still loads, form actions still process; it’s beautiful. This is not running loaders and actions on the client side; it’s running them on the server. This isn’t an accident, the Remix team is carefully considering the UX.</p>\r\n<blockquote class=\"twitter-tweet\" data-dnt=\"true\" data-theme=\"dark\"><p lang=\"en\" dir=\"ltr\">User experience (UX) and developer experience (DX) are both important. UX is more important than DX.<a href=\"https://twitter.com/remix_run?ref_src=twsrc%5Etfw\">@remix_run</a> has taught me: It\'s easier to start with a great UX and work toward a good DX than it is to start with a great DX and work toward a good UX.</p>— Kent C. Dodds &#x1f4bf; (@kentcdodds) <a href=\"https://twitter.com/kentcdodds/status/1482390454389805058?ref_src=twsrc%5Etfw\">January 15, 2022</a></blockquote>\r\n<script async=\"\" src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\"></script>\r\n<h2>Bonus: So Speedy</h2>\r\n<p>Did I mention how fast everything renders? I don’t tend to put too much stock into Lighthouse scores since they seem so random, but Remix crushes Lighthouse without me having to invest any additional effort into improving performance.</p>\r\n<h2>Give it a Shot</h2>\r\n<p>Remix is built on the <a href=\"https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API\">native Fetch API</a>, so it can run anywhere. While Remix is relatively new, it’s certainly production ready, and there is a dedicated team behind it. If you aren’t ready to dive into Remix yet, at least keep your eye on it because this is a game changer.</p>',NULL,0,NULL,'2022-04-21 15:28:57','2022-04-21 15:28:57','fe1a013c-7d26-4c1f-8b37-617ddd1234d5',1,NULL,NULL,18,NULL),(1779,2411,'Why I’m So Excited About Remix',NULL,'<p>I’ve been building on the web for a long time. There’s a part of me that still has a bit of an old school mentality, and it’s hard for me to get really excited about new technology. Sure React was cool when it came out for its state management, but I didn’t see it as the be-all and end-all for building on the web. I really like <a href=\"https://craftcms.com/\">Craft CMS</a> for building CMS powered sites since I have full control over the HTML being sent to the browser, and it’s really easy to extend for complex functionality, but it can be a bit complex to setup for beginners and with additional complexity can come performance issues.&nbsp;So it’s been a while since I’ve seen something to be <em>really</em> excited about.</p>\r\n<p>Enter <a href=\"https://remix.run/\">Remix</a>.</p>\r\n<p>Remix is an interesting mix of old school techniques along with modern technology. Ryan Florence actually sums it up perfectly as to where Remix fits in.</p>\r\n<blockquote class=\"twitter-tweet\" data-dnt=\"true\" data-theme=\"dark\"><p lang=\"en\" dir=\"ltr\">Forget “full stack”. Remix is center stack.<br><br>It’s an HTTP tunnel between interactivity and business logic. It’s the part of the stack that no tool before it has solved, not completely.<br><br>I think I finally know how to talk about Remix.</p>— Ryan Florence (@ryanflorence) <a href=\"https://twitter.com/ryanflorence/status/1482233495195770883?ref_src=twsrc%5Etfw\">January 15, 2022</a></blockquote>\r\n<script async=\"\" src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\"></script>\r\n<p>I was able to easily switch my site that was fully powered by Craft to utilize Craft only as a GraphQL endpoint and Remix powering the rest. The two big things I needed to figure out were: how to get data from the GraphQL endpoint, and then how to process input from a user (for my contact form). I would definitely recommend reading through the Remix docs and the two tutorials, but if you can understand these two big pictures things, you’ll have enough to get started with Remix and go deeper once you get into it.</p>\r\n<h2>Getting GraphQL Data (aka Loaders)</h2>\r\n<p>Remix provides a <a href=\"https://remix.run/docs/en/v1/api/conventions#loader\">loader hook</a> that runs on the server to hydrate your component. In this simple example, I run a GraphQL request and return JSON with the results of that request in the loader function.</p>\r\n<script src=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550.js?file=loader.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550#file-loader-jsx\">View Gist</a></noscript>\r\n<p>Then in my <code>Index</code> component, I access the data from the loader hook with <a href=\"https://remix.run/docs/en/v1/api/remix#useloaderdata\">useLoaderData()</a>, and my component is now hydrated with that data. In MVC style of thinking, think of the loader hook as the controller processing the page load request, populating with data from the model, and then passing to the view.</p>\r\n<p>The great part about Remix is that this doesn’t have to be specifically a GraphQL request. This data can come from anywhere. The <a href=\"https://remix.run/docs/en/v1/tutorials/jokes\">Jokes tutorial</a> in the Remix docs even thoroughly walks through how you can manage all this data in <a href=\"https://www.prisma.io/\">Prisma</a>.</p>\r\n<h2>Processing User Input (aka Actions)</h2>\r\n<p>Ok great, so we’ve got data onto the page, but now we need to be able to handle user input. Remix also provides an <a href=\"https://remix.run/docs/en/v1/api/conventions#action\">action hook</a> to process an action request (ex: a form submission). In my case, I have a contact form that sends me an email via SendGrid after submission.</p>\r\n<script src=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550.js?file=action.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550#file-action-jsx\">View Gist</a></noscript>\r\n<p>If you don’t include an <code>action</code> attribute on your form, it will automatically submit to the same page. Again, in MVC thinking, the action would again be equivalent to the controller taking the request input and processing it. But honestly, this takes me back 15 years when form actions would point directly to PHP files.</p>\r\n<h2>Bonus: Progressive Enhancement</h2>\r\n<p>Since Remix is running on the server, you can turn off JavaScript and everything still works great. Data still loads, form actions still process; it’s beautiful. This is not running loaders and actions on the client side; it’s running them on the server. This isn’t an accident, the Remix team is carefully considering the UX.</p>\r\n<blockquote class=\"twitter-tweet\" data-dnt=\"true\" data-theme=\"dark\"><p lang=\"en\" dir=\"ltr\">User experience (UX) and developer experience (DX) are both important. UX is more important than DX.<a href=\"https://twitter.com/remix_run?ref_src=twsrc%5Etfw\">@remix_run</a> has taught me: It\'s easier to start with a great UX and work toward a good DX than it is to start with a great DX and work toward a good UX.</p>— Kent C. Dodds &#x1f4bf; (@kentcdodds) <a href=\"https://twitter.com/kentcdodds/status/1482390454389805058?ref_src=twsrc%5Etfw\">January 15, 2022</a></blockquote>\r\n<script async=\"\" src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\"></script>\r\n<h2>Bonus: So Speedy</h2>\r\n<p>Did I mention how fast everything renders? I don’t tend to put too much stock into Lighthouse scores since they seem so random, but Remix crushes Lighthouse without me having to invest any additional effort into improving performance.</p>\r\n<h2>Give it a Shot</h2>\r\n<p>Remix is built on the <a href=\"https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API\">native Fetch API</a>, so it can run anywhere. While Remix is relatively new, it’s certainly production ready, and there is a dedicated team behind it. If you aren’t ready to dive into Remix yet, at least keep your eye on it because this is a game changer.</p>',NULL,0,NULL,'2022-04-21 15:42:40','2022-04-21 15:42:40','08713294-a27e-411b-962f-46d64cdd6651',1,NULL,NULL,19,NULL),(1780,2412,'Why I’m So Excited About Remix',NULL,'<p>I’ve been building on the web for a long time. There’s a part of me that still has a bit of an old school mentality, and it’s hard for me to get really excited about new technology. Sure React was cool when it came out for its state management, but I didn’t see it as the be-all and end-all for building on the web. I really like <a href=\"https://craftcms.com/\">Craft CMS</a> for building CMS powered sites since I have full control over the HTML being sent to the browser, and it’s really easy to extend for complex functionality, but it can be a bit complex to setup for beginners and with additional complexity can come performance issues.&nbsp;So it’s been a while since I’ve seen something to be <em>really</em> excited about.</p>\r\n<p>Enter <a href=\"https://remix.run/\">Remix</a>.</p>\r\n<p>Remix is an interesting mix of old school techniques along with modern technology. Ryan Florence actually sums it up perfectly as to where Remix fits in.</p>\r\n<blockquote class=\"twitter-tweet\" data-dnt=\"true\" data-theme=\"dark\"><p lang=\"en\" dir=\"ltr\">Forget “full stack”. Remix is center stack.<br><br>It’s an HTTP tunnel between interactivity and business logic. It’s the part of the stack that no tool before it has solved, not completely.<br><br>I think I finally know how to talk about Remix.</p>— Ryan Florence (@ryanflorence) <a href=\"https://twitter.com/ryanflorence/status/1482233495195770883?ref_src=twsrc%5Etfw\">January 15, 2022</a></blockquote>\r\n<script async=\"\" src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\"></script>\r\n<p>I was able to easily switch my site that was fully powered by Craft to utilize Craft only as a GraphQL endpoint and Remix powering the rest. The two big things I needed to figure out were: how to get data from the GraphQL endpoint, and then how to process input from a user (for my contact form). I would definitely recommend reading through the Remix docs and the two tutorials, but if you can understand these two big pictures things, you’ll have enough to get started with Remix and go deeper once you get into it.</p>\r\n<h2>Getting GraphQL Data (aka Loaders)</h2>\r\n<p>Remix provides a <a href=\"https://remix.run/docs/en/v1/api/conventions#loader\">loader hook</a> that runs on the server to hydrate your component. In this simple example, I run a GraphQL request and return JSON with the results of that request in the loader function.</p>\r\n<script src=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550.js?file=loader.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550#file-loader-jsx\">View Gist</a></noscript>\r\n<p>Then in my <code>Index</code> component, I access the data from the loader hook with <a href=\"https://remix.run/docs/en/v1/api/remix#useloaderdata\">useLoaderData()</a>, and my component is now hydrated with that data. In MVC style of thinking, think of the loader hook as the controller processing the page load request, populating with data from the model, and then passing to the view.</p>\r\n<p>The great part about Remix is that this doesn’t have to be specifically a GraphQL request. This data can come from anywhere. The <a href=\"https://remix.run/docs/en/v1/tutorials/jokes\">Jokes tutorial</a> in the Remix docs even thoroughly walks through how you can manage all this data in <a href=\"https://www.prisma.io/\">Prisma</a>.</p>\r\n<h2>Processing User Input (aka Actions)</h2>\r\n<p>Ok great, so we’ve got data onto the page, but now we need to be able to handle user input. Remix also provides an <a href=\"https://remix.run/docs/en/v1/api/conventions#action\">action hook</a> to process an action request (ex: a form submission). In my case, I have a contact form that sends me an email via SendGrid after submission.</p>\r\n<script src=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550.js?file=action.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550#file-action-jsx\">View Gist</a></noscript>\r\n<p>If you don’t include an <code>action</code> attribute on your form, it will automatically submit to the same page. Again, in MVC thinking, the action would again be equivalent to the controller taking the request input and processing it. But honestly, this takes me back 15 years when form actions would point directly to PHP files.</p>\r\n<h2>Bonus: Progressive Enhancement</h2>\r\n<p>Since Remix is running on the server, you can turn off JavaScript and everything still works great. Data still loads, form actions still process; it’s beautiful. This is not running loaders and actions on the client side; it’s running them on the server. This isn’t an accident, the Remix team is carefully considering the UX.</p>\r\n<blockquote class=\"twitter-tweet\" data-dnt=\"true\" data-theme=\"dark\"><p lang=\"en\" dir=\"ltr\">User experience (UX) and developer experience (DX) are both important. UX is more important than DX.<a href=\"https://twitter.com/remix_run?ref_src=twsrc%5Etfw\">@remix_run</a> has taught me: It\'s easier to start with a great UX and work toward a good DX than it is to start with a great DX and work toward a good UX.</p>— Kent C. Dodds &#x1f4bf; (@kentcdodds) <a href=\"https://twitter.com/kentcdodds/status/1482390454389805058?ref_src=twsrc%5Etfw\">January 15, 2022</a></blockquote>\r\n<script async=\"\" src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\"></script>\r\n<h2>Bonus: So Speedy</h2>\r\n<p>Did I mention how fast everything renders? I don’t tend to put too much stock into Lighthouse scores since they seem so random, but Remix crushes Lighthouse without me having to invest any additional effort into improving performance.</p>\r\n<h2>Give it a Shot</h2>\r\n<p>Remix is built on the <a href=\"https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API\">native Fetch API</a>, so it can run anywhere. While Remix is relatively new, it’s certainly production ready, and there is a dedicated team behind it. If you aren’t ready to dive into Remix yet, at least keep your eye on it because this is a game changer.</p>',NULL,0,NULL,'2022-04-21 15:42:43','2022-04-21 15:42:43','e95aa39d-5c54-4041-99b2-f988fb32062d',1,NULL,NULL,18,NULL),(1781,2413,'Setting Up Live Preview with Craft CMS in Headless Mode',NULL,'<p>In my <a href=\"https://www.trevor-davis.com/blog/why-im-so-excited-about-remix\">previous post</a>, I talked about transitioning my site from being powered by <a href=\"https://craftcms.com/\">Craft</a> to being powered by <a href=\"https://remix.run/\">Remix</a> and a GraphQL endpoint coming from Craft. One of the best features of Craft is <a href=\"https://craftcms.com/features/all#live-preview\">Live Preview</a>, and it took a little configuration to get this working on my new Remix powered site.</p>\r\n<h2>Remix Configuration</h2>\r\n<p>These were specific changes that I needed to make on the Remix side, but really it would be the same for any GraphQL request. As Andrew Welch breaks down in <a href=\"https://nystudio107.com/blog/headless-preview-in-craft-cms\">his article</a>, the key is passing the token parameter back that Craft included in the URL.</p>\r\n<p>In the loader function of my blog post route, I call a helper function to setup the GraphQL client, and I pass the request to it:</p>\r\n<script src=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e.js?file=$slug.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e#file-slug-jsx\">View Gist</a></noscript>\r\n<p>And then in my helper function, I take that request, grab the URL params that I want to include, and add those to my GraphQL request endpoint URL:</p>\r\n<script src=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e.js?file=graphql.server.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e#file-graphql-server-jsx\">View Gist</a></noscript>\r\n<p>It wasn’t totally necessary to include the <code>x-craft-preview</code> and <code>x-craft-live-preview</code> parameters, but I figured it couldn’t hurt.</p>\r\n<h2>Craft Configuration</h2>\r\n<p>Now with the Remix configuration in place, I just needed to make two small changes to Craft to get it working correctly. First, I had to update the preview target for my Blog section to point to my Remix site:</p>\r\n<figure><img src=\"{asset:2283:url||//assets.trevor-davis.com/uploads/images/content/blog-section-preview-target.png}\" data-image=\"2283\" alt=\"Setting the preview target in my Blog Section\"></figure>\r\n<p>Then, I had to update the <code>config/general.php</code> to allow iframe requests from my Remix domain:</p>\r\n<script src=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e.js?file=general.php\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/129038286f04bc5e2941baae32ee509e#file-general-php\">View Gist</a></noscript>\r\n\r\n<h2>Voilà, Live Preview</h2>\r\n<p>And just like that, I had live preview working.</p>\r\n<video src=\"//assets.trevor-davis.com/uploads/images/content/live-preview.mp4\" autoplay=\"\" loop=\"\" muted=\"\" controls=\"\" width=\"100%\"></video>',NULL,0,NULL,'2022-04-21 16:28:07','2022-04-21 16:28:07','a885cbb6-61bf-4904-bd53-b361e8e8c689',1,NULL,NULL,24,NULL),(1782,2414,'Why I’m So Excited About Remix',NULL,'<p>I’ve been building on the web for a long time. There’s a part of me that still has a bit of an old school mentality, and it’s hard for me to get really excited about new technology. Sure React was cool when it came out for its state management, but I didn’t see it as the be-all and end-all for building on the web. I really like <a href=\"https://craftcms.com/\">Craft CMS</a> for building CMS powered sites since I have full control over the HTML being sent to the browser, and it’s really easy to extend for complex functionality, but it can be a bit complex to setup for beginners and with additional complexity can come performance issues.&nbsp;So it’s been a while since I’ve seen something to be <em>really</em> excited about.</p>\r\n<p>Enter <a href=\"https://remix.run/\">Remix</a>.</p>\r\n<p>Remix is an interesting mix of old school techniques along with modern technology. Ryan Florence actually sums it up perfectly as to where Remix fits in.</p>\r\n<blockquote class=\"twitter-tweet\" data-dnt=\"true\" data-theme=\"dark\"><p lang=\"en\" dir=\"ltr\">Forget “full stack”. Remix is center stack.<br><br>It’s an HTTP tunnel between interactivity and business logic. It’s the part of the stack that no tool before it has solved, not completely.<br><br>I think I finally know how to talk about Remix.</p>— Ryan Florence (@ryanflorence) <a href=\"https://twitter.com/ryanflorence/status/1482233495195770883?ref_src=twsrc%5Etfw\">January 15, 2022</a></blockquote>\r\n<script async=\"\" src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\"></script>\r\n<p>I was able to easily switch my site that was fully powered by Craft to utilize Craft only as a GraphQL endpoint and Remix powering the rest. The two big things I needed to figure out were: how to get data from the GraphQL endpoint, and then how to process input from a user (for my contact form). I would definitely recommend reading through the Remix docs and the two tutorials, but if you can understand these two big pictures things, you’ll have enough to get started with Remix and go deeper once you get into it.</p>\r\n<h2>Getting GraphQL Data (aka Loaders)</h2>\r\n<p>Remix provides a <a href=\"https://remix.run/docs/en/v1/api/conventions#loader\">loader hook</a> that runs on the server to hydrate your component. In this simple example, I run a GraphQL request and return JSON with the results of that request in the loader function.</p>\r\n<script src=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550.js?file=loader.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550#file-loader-jsx\">View Gist</a></noscript>\r\n<p>Then in my <code>Index</code> component, I access the data from the loader hook with <a href=\"https://remix.run/docs/en/v1/api/remix#useloaderdata\">useLoaderData()</a>, and my component is now hydrated with that data. In MVC style of thinking, think of the loader hook as the controller processing the page load request, populating with data from the model, and then passing to the view.</p>\r\n<p>The great part about Remix is that this doesn’t have to be specifically a GraphQL request. This data can come from anywhere. The <a href=\"https://remix.run/docs/en/v1/tutorials/jokes\">Jokes tutorial</a> in the Remix docs even thoroughly walks through how you can manage all this data in <a href=\"https://www.prisma.io/\">Prisma</a>.</p>\r\n<h2>Processing User Input (aka Actions)</h2>\r\n<p>Ok great, so we’ve got data onto the page, but now we need to be able to handle user input. Remix also provides an <a href=\"https://remix.run/docs/en/v1/api/conventions#action\">action hook</a> to process an action request (ex: a form submission). In my case, I have a contact form that sends me an email via SendGrid after submission.</p>\r\n<script src=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550.js?file=action.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550#file-action-jsx\">View Gist</a></noscript>\r\n<p>If you don’t include an <code>action</code> attribute on your form, it will automatically submit to the same page. Again, in MVC thinking, the action would again be equivalent to the controller taking the request input and processing it. But honestly, this takes me back 15 years when form actions would point directly to PHP files.</p>\r\n<h2>Bonus: Progressive Enhancement</h2>\r\n<p>Since Remix is running on the server, you can turn off JavaScript and everything still works great. Data still loads, form actions still process; it’s beautiful. This is not running loaders and actions on the client side; it’s running them on the server. This isn’t an accident, the Remix team is carefully considering the UX.</p>\r\n<blockquote class=\"twitter-tweet\" data-dnt=\"true\" data-theme=\"dark\"><p lang=\"en\" dir=\"ltr\">User experience (UX) and developer experience (DX) are both important. UX is more important than DX.<a href=\"https://twitter.com/remix_run?ref_src=twsrc%5Etfw\">@remix_run</a> has taught me: It\'s easier to start with a great UX and work toward a good DX than it is to start with a great DX and work toward a good UX.</p>— Kent C. Dodds &#x1f4bf; (@kentcdodds) <a href=\"https://twitter.com/kentcdodds/status/1482390454389805058?ref_src=twsrc%5Etfw\">January 15, 2022</a></blockquote>\r\n<script async=\"\" src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\"></script>\r\n<h2>Bonus: So Speedy</h2>\r\n<p>Did I mention how fast everything renders? I don’t tend to put too much stock into Lighthouse scores since they seem so random, but Remix crushes Lighthouse without me having to invest any additional effort into improving performance.</p>\r\n<h2>Give it a Shot</h2>\r\n<p>Remix is built on the <a href=\"https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API\">native Fetch API</a>, so it can run anywhere. While Remix is relatively new, it’s certainly production ready, and there is a dedicated team behind it. If you aren’t ready to dive into Remix yet, at least keep your eye on it because this is a game changer.</p>',NULL,0,NULL,'2022-04-21 16:28:54','2022-04-21 16:28:54','d125f48e-2241-4118-9391-45d92561a546',1,NULL,NULL,19,NULL),(1783,2415,'Why I’m So Excited About Remix',NULL,'<p>I’ve been building on the web for a long time. There’s a part of me that still has a bit of an old school mentality, and it’s hard for me to get really excited about new technology. Sure React was cool when it came out for its state management, but I didn’t see it as the be-all and end-all for building on the web. I really like <a href=\"https://craftcms.com/\">Craft CMS</a> for building CMS powered sites since I have full control over the HTML being sent to the browser, and it’s really easy to extend for complex functionality, but it can be a bit complex to setup for beginners and with additional complexity can come performance issues.&nbsp;So it’s been a while since I’ve seen something to be <em>really</em> excited about.</p>\r\n<p>Enter <a href=\"https://remix.run/\">Remix</a>.</p>\r\n<p>Remix is an interesting mix of old school techniques along with modern technology. Ryan Florence actually sums it up perfectly as to where Remix fits in.</p>\r\n<blockquote class=\"twitter-tweet\" data-dnt=\"true\" data-theme=\"dark\"><p lang=\"en\" dir=\"ltr\">Forget “full stack”. Remix is center stack.<br><br>It’s an HTTP tunnel between interactivity and business logic. It’s the part of the stack that no tool before it has solved, not completely.<br><br>I think I finally know how to talk about Remix.</p>— Ryan Florence (@ryanflorence) <a href=\"https://twitter.com/ryanflorence/status/1482233495195770883?ref_src=twsrc%5Etfw\">January 15, 2022</a></blockquote>\r\n<script async=\"\" src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\"></script>\r\n<p>I was able to easily switch my site that was fully powered by Craft to utilize Craft only as a GraphQL endpoint and Remix powering the rest. The two big things I needed to figure out were: how to get data from the GraphQL endpoint, and then how to process input from a user (for my contact form). I would definitely recommend reading through the Remix docs and the two tutorials, but if you can understand these two big pictures things, you’ll have enough to get started with Remix and go deeper once you get into it.</p>\r\n<h2>Getting GraphQL Data (aka Loaders)</h2>\r\n<p>Remix provides a <a href=\"https://remix.run/docs/en/v1/api/conventions#loader\">loader hook</a> that runs on the server to hydrate your component. In this simple example, I run a GraphQL request and return JSON with the results of that request in the loader function.</p>\r\n<script src=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550.js?file=loader.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550#file-loader-jsx\">View Gist</a></noscript>\r\n<p>Then in my <code>Index</code> component, I access the data from the loader hook with <a href=\"https://remix.run/docs/en/v1/api/remix#useloaderdata\">useLoaderData()</a>, and my component is now hydrated with that data. In MVC style of thinking, think of the loader hook as the controller processing the page load request, populating with data from the model, and then passing to the view.</p>\r\n<p>The great part about Remix is that this doesn’t have to be specifically a GraphQL request. This data can come from anywhere. The <a href=\"https://remix.run/docs/en/v1/tutorials/jokes\">Jokes tutorial</a> in the Remix docs even thoroughly walks through how you can manage all this data in <a href=\"https://www.prisma.io/\">Prisma</a>.</p>\r\n<h2>Processing User Input (aka Actions)</h2>\r\n<p>Ok great, so we’ve got data onto the page, but now we need to be able to handle user input. Remix also provides an <a href=\"https://remix.run/docs/en/v1/api/conventions#action\">action hook</a> to process an action request (ex: a form submission). In my case, I have a contact form that sends me an email via SendGrid after submission.</p>\r\n<script src=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550.js?file=action.jsx\"></script>\r\n<noscript><a href=\"https://gist.github.com/davist11/87cdd99eb66d01f2a9dbc026324f9550#file-action-jsx\">View Gist</a></noscript>\r\n<p>If you don’t include an <code>action</code> attribute on your form, it will automatically submit to the same page. Again, in MVC thinking, the action would again be equivalent to the controller taking the request input and processing it. But honestly, this takes me back 15 years when form actions would point directly to PHP files.</p>\r\n<h2>Bonus: Progressive Enhancement</h2>\r\n<p>Since Remix is running on the server, you can turn off JavaScript and everything still works great. Data still loads, form actions still process; it’s beautiful. This is not running loaders and actions on the client side; it’s running them on the server. This isn’t an accident, the Remix team is carefully considering the UX.</p>\r\n<blockquote class=\"twitter-tweet\" data-dnt=\"true\" data-theme=\"dark\"><p lang=\"en\" dir=\"ltr\">User experience (UX) and developer experience (DX) are both important. UX is more important than DX.<a href=\"https://twitter.com/remix_run?ref_src=twsrc%5Etfw\">@remix_run</a> has taught me: It\'s easier to start with a great UX and work toward a good DX than it is to start with a great DX and work toward a good UX.</p>— Kent C. Dodds &#x1f4bf; (@kentcdodds) <a href=\"https://twitter.com/kentcdodds/status/1482390454389805058?ref_src=twsrc%5Etfw\">January 15, 2022</a></blockquote>\r\n<script async=\"\" src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\"></script>\r\n<h2>Bonus: So Speedy</h2>\r\n<p>Did I mention how fast everything renders? I don’t tend to put too much stock into Lighthouse scores since they seem so random, but Remix crushes Lighthouse without me having to invest any additional effort into improving performance.</p>\r\n<h2>Give it a Shot</h2>\r\n<p>Remix is built on the <a href=\"https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API\">native Fetch API</a>, so it can run anywhere. While Remix is relatively new, it’s certainly production ready, and there is a dedicated team behind it. If you aren’t ready to dive into Remix yet, at least keep your eye on it because this is a game changer.</p>',NULL,0,NULL,'2022-04-21 16:33:23','2022-04-21 16:33:23','903bdc61-edbd-4510-841f-593ca0b6250c',1,NULL,NULL,20,NULL),(1784,2416,'“Advanced”  Templating with ExpressionEngine',NULL,'<p>I was luckily enough to be asked to speak at the <a href=\"http://dceers.org/\">DCEERs Day conference</a> yesterday. I was asked to speak about best templating practices, which ended up being a talk about how I use <a href=\"http://devot-ee.com/add-ons/stash\">Stash</a> and how I build custom plugins to streamline templating. It was a great day filled with discussion about ExpressionEngine, and it made me look forward to EECI even more!</p>\n\n',NULL,2018,NULL,'2022-04-22 02:34:33','2022-04-22 02:34:33','eafd3edf-6816-45a1-bd98-ac90fb2696bd',1,NULL,NULL,1,NULL),(1785,2417,'Is Ajax ExpressionEngine Plugin',NULL,'<p>For a recent project, I needed to detect whether a request was an AJAX request or not. <a href=\"http://devot-ee.com/add-ons/mx-ajax-detect\">MX Ajax Detect</a> already existed, but I didn’t like that you needed the extra set of tags.</p>\n\n<h2>Usage</h2>\n<pre><code>{if {exp:is_ajax} == \"true\"}\n	OH YEAAAH\n{if:else}\n	OH NOOO\n{/if}</code></pre>\n\n<h2>Download</h2>\n<p>You can find the plugin on <a href=\"http://devot-ee.com/add-ons/is-ajax\">Devot:ee</a> and <a href=\"https://github.com/davist11/is-ajax\">GitHub</a>.</p>',NULL,1999,NULL,'2022-04-22 11:00:15','2022-04-22 11:00:15','c7aa774c-1412-480c-af90-d2d8bf4ff3bb',1,NULL,NULL,1,NULL),(1786,2418,'Hon-ee Pot Captcha for ExpressionEngine',NULL,'<p>I have a confession to make: <em>I hate captcha</em>. But on the other hand, spam is one of the most frustrating issues ever. So with that being said, I am a big fan of <a href=\"http://haacked.com/archive/2007/09/11/honeypot-captcha.aspx\">Honeypot Captcha</a>.</p>\n\n<p>I couldn’t find any ExpressionEngine addons that added honeypot captcha functionality for both the comment form and the <a href=\"http://www.solspace.com/software/detail/freeform/\">Freeform</a> module, so I decided to go ahead and create one.</p>\n\n<h2>Basic Functionality</h2>\n<p>This extension validates the EE comment form and Freeform forms to make sure a field that is hidden with CSS is left empty.</p>\n\n<h2>Getting Started</h2>\n<ul><li><a href=\"https://github.com/davist11/Hon-ee-Pot-Captcha\">Download Hon-ee Pot Captcha</a></li>\n  <li>Unzip the folder and copy the <em>honeepot</em> folder into your /system/expressionengine/third_party/ directory.</li>\n  <li>Go to Add-ons → Extensions and “Enable extension”.</li>\n  <li>You can customize the field name for the honey pot field and the message a user receives if the field is filled in by going to the extension settings.</li>\n</ul><h3>Setup</h3>\n<p>In the Freeform module, go to Fields → Create a New Field. Now create a field with the field name matching the field name in the Hon-ee Pot Captcha settings. The default is <em>honeepot</em>.</p>\n\n<p>Now in your form, add the honey pot field:</p>\n\n<pre>&lt;li class=\"screen-reader\"&gt;\n  &lt;label for=\"honeepot\"&gt;Don\'t put anything here&lt;/label&gt;\n  &lt;input type=\"text\" name=\"honeepot\" id=\"honeepot\" /&gt;\n&lt;/li&gt;</pre>\n\n<p>In my CSS, I have a class to move things off of the page:</p>\n<pre>.screen-reader {\n  display: block !important;\n  left: -9999px !important;\n  position: absolute !important;\n  top: -9999px !important;\n}</pre>\n\n<p>You can add the same form field to your comment forms as well.</p>\n\n<h2>That is all</h2>\n<p>Hopefully this addition will help to combat some of the spam contact form submissions and comments (even though they get caught by <a href=\"http://loweblog.com/software/low-nospam/\">Low NoSpam</a>). You can <a href=\"https://github.com/davist11/Hon-ee-Pot-Captcha\">download the Hon-ee Pot Captcha extension on Github</a>. Let me know if you run into any issues.</p>',NULL,1971,NULL,'2022-04-22 15:16:27','2022-04-22 15:16:27','947bc15d-3330-450b-b71c-60b7541f3cab',1,NULL,NULL,1,NULL),(1787,2419,'Hon-ee Pot Captcha for ExpressionEngine',NULL,'<p>I have a confession to make: <em>I hate captcha</em>. But on the other hand, spam is one of the most frustrating issues ever. So with that being said, I am a big fan of <a href=\"http://haacked.com/archive/2007/09/11/honeypot-captcha.aspx\">Honeypot Captcha</a>.</p>\n\n<p>I couldn’t find any ExpressionEngine addons that added honeypot captcha functionality for both the comment form and the <a href=\"http://www.solspace.com/software/detail/freeform/\">Freeform</a> module, so I decided to go ahead and create one.</p>\n\n<h2>Basic Functionality</h2>\n<p>This extension validates the EE comment form and Freeform forms to make sure a field that is hidden with CSS is left empty.</p>\n\n<h2>Getting Started</h2>\n<ul><li><a href=\"https://github.com/davist11/Hon-ee-Pot-Captcha\">Download Hon-ee Pot Captcha</a></li>\n  <li>Unzip the folder and copy the <em>honeepot</em> folder into your /system/expressionengine/third_party/ directory.</li>\n  <li>Go to Add-ons → Extensions and “Enable extension”.</li>\n  <li>You can customize the field name for the honey pot field and the message a user receives if the field is filled in by going to the extension settings.</li>\n</ul><h3>Setup</h3>\n<p>In the Freeform module, go to Fields → Create a New Field. Now create a field with the field name matching the field name in the Hon-ee Pot Captcha settings. The default is <em>honeepot</em>.</p>\n\n<p>Now in your form, add the honey pot field:</p>\n\n<pre>&lt;li class=\"screen-reader\"&gt;\n  &lt;label for=\"honeepot\"&gt;Don\'t put anything here&lt;/label&gt;\n  &lt;input type=\"text\" name=\"honeepot\" id=\"honeepot\" /&gt;\n&lt;/li&gt;</pre>\n\n<p>In my CSS, I have a class to move things off of the page:</p>\n<pre>.screen-reader {\n  display: block !important;\n  left: -9999px !important;\n  position: absolute !important;\n  top: -9999px !important;\n}</pre>\n\n<p>You can add the same form field to your comment forms as well.</p>\n\n<h2>That is all</h2>\n<p>Hopefully this addition will help to combat some of the spam contact form submissions and comments (even though they get caught by <a href=\"http://loweblog.com/software/low-nospam/\">Low NoSpam</a>). You can <a href=\"https://github.com/davist11/Hon-ee-Pot-Captcha\">download the Hon-ee Pot Captcha extension on Github</a>. Let me know if you run into any issues.</p>',NULL,1971,NULL,'2022-04-22 15:16:36','2022-04-22 15:16:36','b1153ad2-1cd2-47e2-ae3d-3be29b9e7738',1,NULL,NULL,0,NULL),(1788,2420,'Hon-ee Pot Captcha for ExpressionEngine',NULL,'<p>I have a confession to make: <em>I hate captcha</em>. But on the other hand, spam is one of the most frustrating issues ever. So with that being said, I am a big fan of <a href=\"http://haacked.com/archive/2007/09/11/honeypot-captcha.aspx\">Honeypot Captcha</a>.</p>\n\n<p>I couldn’t find any ExpressionEngine addons that added honeypot captcha functionality for both the comment form and the <a href=\"http://www.solspace.com/software/detail/freeform/\">Freeform</a> module, so I decided to go ahead and create one.</p>\n\n<h2>Basic Functionality</h2>\n<p>This extension validates the EE comment form and Freeform forms to make sure a field that is hidden with CSS is left empty.</p>\n\n<h2>Getting Started</h2>\n<ul><li><a href=\"https://github.com/davist11/Hon-ee-Pot-Captcha\">Download Hon-ee Pot Captcha</a></li>\n  <li>Unzip the folder and copy the <em>honeepot</em> folder into your /system/expressionengine/third_party/ directory.</li>\n  <li>Go to Add-ons → Extensions and “Enable extension”.</li>\n  <li>You can customize the field name for the honey pot field and the message a user receives if the field is filled in by going to the extension settings.</li>\n</ul><h3>Setup</h3>\n<p>In the Freeform module, go to Fields → Create a New Field. Now create a field with the field name matching the field name in the Hon-ee Pot Captcha settings. The default is <em>honeepot</em>.</p>\n\n<p>Now in your form, add the honey pot field:</p>\n\n<pre>&lt;li class=\"screen-reader\"&gt;\n  &lt;label for=\"honeepot\"&gt;Don\'t put anything here&lt;/label&gt;\n  &lt;input type=\"text\" name=\"honeepot\" id=\"honeepot\" /&gt;\n&lt;/li&gt;</pre>\n\n<p>In my CSS, I have a class to move things off of the page:</p>\n<pre>.screen-reader {\n  display: block !important;\n  left: -9999px !important;\n  position: absolute !important;\n  top: -9999px !important;\n}</pre>\n\n<p>You can add the same form field to your comment forms as well.</p>\n\n<h2>That is all</h2>\n<p>Hopefully this addition will help to combat some of the spam contact form submissions and comments (even though they get caught by <a href=\"http://loweblog.com/software/low-nospam/\">Low NoSpam</a>). You can <a href=\"https://github.com/davist11/Hon-ee-Pot-Captcha\">download the Hon-ee Pot Captcha extension on Github</a>. Let me know if you run into any issues.</p>',NULL,1971,NULL,'2022-04-22 15:16:44','2022-04-22 15:16:44','9385a51e-5475-4827-92e8-126d3d780d9d',1,NULL,NULL,1,NULL),(1789,2421,'Hon-ee Pot Captcha for ExpressionEngine',NULL,'<p>I have a confession to make: <em>I hate captcha</em>. But on the other hand, spam is one of the most frustrating issues ever. So with that being said, I am a big fan of <a href=\"http://haacked.com/archive/2007/09/11/honeypot-captcha.aspx\">Honeypot Captcha</a>.</p>\n\n<p>I couldn’t find any ExpressionEngine addons that added honeypot captcha functionality for both the comment form and the <a href=\"http://www.solspace.com/software/detail/freeform/\">Freeform</a> module, so I decided to go ahead and create one.</p>\n\n<h2>Basic Functionality</h2>\n<p>This extension validates the EE comment form and Freeform forms to make sure a field that is hidden with CSS is left empty.</p>\n\n<h2>Getting Started</h2>\n<ul><li><a href=\"https://github.com/davist11/Hon-ee-Pot-Captcha\">Download Hon-ee Pot Captcha</a></li>\n  <li>Unzip the folder and copy the <em>honeepot</em> folder into your /system/expressionengine/third_party/ directory.</li>\n  <li>Go to Add-ons → Extensions and “Enable extension”.</li>\n  <li>You can customize the field name for the honey pot field and the message a user receives if the field is filled in by going to the extension settings.</li>\n</ul><h3>Setup</h3>\n<p>In the Freeform module, go to Fields → Create a New Field. Now create a field with the field name matching the field name in the Hon-ee Pot Captcha settings. The default is <em>honeepot</em>.</p>\n\n<p>Now in your form, add the honey pot field:</p>\n\n<pre>&lt;li class=\"screen-reader\"&gt;\n  &lt;label for=\"honeepot\"&gt;Don\'t put anything here&lt;/label&gt;\n  &lt;input type=\"text\" name=\"honeepot\" id=\"honeepot\" /&gt;\n&lt;/li&gt;</pre>\n\n<p>In my CSS, I have a class to move things off of the page:</p>\n<pre>.screen-reader {\n  display: block !important;\n  left: -9999px !important;\n  position: absolute !important;\n  top: -9999px !important;\n}</pre>\n\n<p>You can add the same form field to your comment forms as well.</p>\n\n<h2>That is all</h2>\n<p>Hopefully this addition will help to combat some of the spam contact form submissions and comments (even though they get caught by <a href=\"http://loweblog.com/software/low-nospam/\">Low NoSpam</a>). You can <a href=\"https://github.com/davist11/Hon-ee-Pot-Captcha\">download the Hon-ee Pot Captcha extension on Github</a>. Let me know if you run into any issues.</p>',NULL,1971,NULL,'2022-04-22 15:17:00','2022-04-22 15:17:00','5a761e84-4a6b-49f3-8b4e-21933f9fdd91',1,NULL,NULL,0,NULL),(1790,2422,'Hon-ee Pot Captcha for ExpressionEngine',NULL,'<p>I have a confession to make: <em>I hate captcha</em>. But on the other hand, spam is one of the most frustrating issues ever. So with that being said, I am a big fan of <a href=\"http://haacked.com/archive/2007/09/11/honeypot-captcha.aspx\">Honeypot Captcha</a>.</p>\n\n<p>I couldn’t find any ExpressionEngine addons that added honeypot captcha functionality for both the comment form and the <a href=\"http://www.solspace.com/software/detail/freeform/\">Freeform</a> module, so I decided to go ahead and create one.</p>\n\n<h2>Basic Functionality</h2>\n<p>This extension validates the EE comment form and Freeform forms to make sure a field that is hidden with CSS is left empty.</p>\n\n<h2>Getting Started</h2>\n<ul><li><a href=\"https://github.com/davist11/Hon-ee-Pot-Captcha\">Download Hon-ee Pot Captcha</a></li>\n  <li>Unzip the folder and copy the <em>honeepot</em> folder into your /system/expressionengine/third_party/ directory.</li>\n  <li>Go to Add-ons → Extensions and “Enable extension”.</li>\n  <li>You can customize the field name for the honey pot field and the message a user receives if the field is filled in by going to the extension settings.</li>\n</ul><h3>Setup</h3>\n<p>In the Freeform module, go to Fields → Create a New Field. Now create a field with the field name matching the field name in the Hon-ee Pot Captcha settings. The default is <em>honeepot</em>.</p>\n\n<p>Now in your form, add the honey pot field:</p>\n\n<pre>&lt;li class=\"screen-reader\"&gt;\n  &lt;label for=\"honeepot\"&gt;Don\'t put anything here&lt;/label&gt;\n  &lt;input type=\"text\" name=\"honeepot\" id=\"honeepot\" /&gt;\n&lt;/li&gt;</pre>\n\n<p>In my CSS, I have a class to move things off of the page:</p>\n<pre>.screen-reader {\n  display: block !important;\n  left: -9999px !important;\n  position: absolute !important;\n  top: -9999px !important;\n}</pre>\n\n<p>You can add the same form field to your comment forms as well.</p>\n\n<h2>That is all</h2>\n<p>Hopefully this addition will help to combat some of the spam contact form submissions and comments (even though they get caught by <a href=\"http://loweblog.com/software/low-nospam/\">Low NoSpam</a>). You can <a href=\"https://github.com/davist11/Hon-ee-Pot-Captcha\">download the Hon-ee Pot Captcha extension on Github</a>. Let me know if you run into any issues.</p>',NULL,1971,NULL,'2022-04-22 15:17:08','2022-04-22 15:17:08','4dda136f-b612-4de6-8048-5c220fe28311',1,NULL,NULL,1,NULL),