<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Simon Hamp</title>
    <description>The latest articles on DEV Community by Simon Hamp (@simonhamp).</description>
    <link>https://dev.to/simonhamp</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F284111%2F341c0bf7-1d7d-4f87-b136-beaed25d66bb.jpg</url>
      <title>DEV Community: Simon Hamp</title>
      <link>https://dev.to/simonhamp</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/simonhamp"/>
    <language>en</language>
    <item>
      <title>Why You (Probably) Shouldn't Start With an SPA</title>
      <dc:creator>Simon Hamp</dc:creator>
      <pubDate>Thu, 01 Feb 2024 00:00:00 +0000</pubDate>
      <link>https://dev.to/simonhamp/why-you-probably-shouldnt-start-with-an-spa-5f51</link>
      <guid>https://dev.to/simonhamp/why-you-probably-shouldnt-start-with-an-spa-5f51</guid>
      <description>&lt;ul&gt;
&lt;li&gt;Some history, some context&lt;/li&gt;
&lt;li&gt;When does an SPA make sense?&lt;/li&gt;
&lt;li&gt;
So, why are SPAs bad again?

&lt;ul&gt;
&lt;li&gt;Your front-end and back-end get decoupled!&lt;/li&gt;
&lt;li&gt;It may hurt customisability&lt;/li&gt;
&lt;li&gt;Performance will suffer&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;So what's the alternative?&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;I came across &lt;a href="https://www.gregnavis.com/articles/the-architecture-no-one-needs.html" rel="noopener noreferrer"&gt;this interesting article&lt;/a&gt; by &lt;a href="https://twitter.com/gregnavis" rel="noopener noreferrer"&gt;@gregnavis&lt;/a&gt; the other day. I guess it's from a few years ago now, judging by some of the other posts on his blog. But it still holds up. It's maybe even &lt;em&gt;more&lt;/em&gt; relevant now.&lt;/p&gt;

&lt;p&gt;The article is entitled &lt;em&gt;The Architecture No One Needs&lt;/em&gt; and it makes a simple and clear case, arguing that SPA's are more expensive than a standard multi-page app (which may or may not be a monolith).&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I'm going to use SPA throughout this post to mean the whole umbrella of ways you might be building a front-end application that is not server-side rendered.&lt;/p&gt;

&lt;p&gt;I think this is in line with Greg's intent too.&lt;/p&gt;

&lt;p&gt;I don't want to split hairs over whether a particular framework &lt;em&gt;can&lt;/em&gt; be used to build front-end apps that aren't strictly SPAs.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Since I read it, I haven't stopped thinking about this article.&lt;/p&gt;

&lt;p&gt;I found myself agreeing with all of Greg's stated points and it made me realise I actually have a strong opinion about this topic.&lt;/p&gt;

&lt;p&gt;I believe Greg is right, and as time rolls on I think I'm becoming more bullish in my stance on SPAs too.&lt;/p&gt;

&lt;h2&gt;
  
  
  ¶Some history, some context
&lt;/h2&gt;

&lt;p&gt;My foray into the dirty, hubbub streets of front-end frameworks came about because of Laravel Nova and Statamic. They both use Vue, so I learned Vue.&lt;/p&gt;

&lt;p&gt;Of course, I looked around. But React made me wretch. Angular almost made me want to buy a &lt;em&gt;katana&lt;/em&gt; just to perform &lt;em&gt;seppuku&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;I hear things about all of these and more thanks to Twitter. I can say some of it is good, but most of it continues to push me away.&lt;/p&gt;

&lt;p&gt;I stuck with Vue. I actually like Vue a lot, even if v3 has caused a bit of headache—it's actually better for it in my opinion and yes I do like the composition API.&lt;/p&gt;

&lt;p&gt;Overall though, I'm definitely heading more towards preferring &lt;em&gt;not&lt;/em&gt; to have to build my front-end using node/deno/bun or whatever tool becomes popular today.&lt;/p&gt;

&lt;p&gt;That said, you just &lt;em&gt;try&lt;/em&gt; and pry Tailwind from my frigid, rigid fingers!&lt;/p&gt;

&lt;p&gt;I'm quite firmly in the &lt;a href="https://livewire.laravel.com" rel="noopener noreferrer"&gt;Livewire&lt;/a&gt; camp now. In another life, I may even like HTMX?&lt;/p&gt;

&lt;p&gt;I've built a few SPAs, but I can probably count them on one hand. But not only will I probably not build another one, I think you shouldn't either. I'm strongly encouraging my clients not to.&lt;/p&gt;

&lt;p&gt;I do think SPAs have a place, but it is &lt;strong&gt;almost certainly not in your project&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Yes, I know this argument has been made before and probably far more eloquently than I'm going to, but you know I just felt like I needed to get this out of my head in my own way.&lt;/p&gt;

&lt;h2&gt;
  
  
  ¶When does an SPA make sense?
&lt;/h2&gt;

&lt;p&gt;Let's get this out of the way first before I dunk on SPAs some more.&lt;/p&gt;

&lt;p&gt;They &lt;em&gt;do&lt;/em&gt; have a place:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;I believe that the main advantage of an SPA is/was/has always been the decoupling of the front-end from the back-end.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;As time goes on and engineers specialise in areas that interest them the most, roles become more well-defined. This is why we have 'front-end' and 'back-end' and 'full stack' engineers.&lt;/p&gt;

&lt;p&gt;Although there is principally a lot of overlap (this is all programming at the end of the day and many concepts are similar), the domain—the environment that the engineer is most familiar with—is what determines their preference.&lt;/p&gt;

&lt;p&gt;Some engineers will prefer back-end because they don't want to think about or deal with a certain class of bugs or issues that arise from the rapidly-evolving world of front-end development.&lt;/p&gt;

&lt;p&gt;They may be uncomfortable using 3 or 4 different languages at the same time to get their work done, or they groan as soon as there's another major version of some framework which is going to require a load of refactoring that doesn't add immediate value to your product.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Consider: every user of your app could be using a different version of a particular browser, which uses one kind of rendering engine, and a specific level of conformity to various web standards e.g. ECMAScript (the official standard that underpins what most of us think of as JavaScript) or CSS. &lt;strong&gt;Keeping on top of these variations and differences across desktop and mobile is enough to make anyone's head spin.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And other engineers will prefer the front-end for its stateful nature, or because they're more comfortable with JavaScript/TypeScript, they grok CSS, and they love the intersection of code and design.&lt;/p&gt;

&lt;p&gt;Or maybe they just dislike dealing with databases, concurrency, queues, messaging and APIs a lot more than they dislike wild browser evolution.&lt;/p&gt;

&lt;p&gt;In any case, whatever size your team is, there will be these preferences. For example, I consider myself a full-stack developer, but honestly I like to avoid front-end work as much as possible, so will generally take the easy route there.&lt;/p&gt;

&lt;p&gt;Developing an SPA could allow you/your business to split the work of front-end and back-end into separate teams, which &lt;em&gt;may&lt;/em&gt; help each team focus so they can do what they do best and be the happiest they can be.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Which is the most important metric that will make an appreciable difference to your bottom-line long term.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Being intentional about this will see you hit Conway's Law head-on and potentially tackle that beast in the best way, as long as you build up the necessary lines of communication.&lt;/p&gt;

&lt;p&gt;It also allows you to scale the two parts of the system separately—both in terms of team scaling and resource scaling—which, if you ever need that flexibility, could end up saving you from a certain group of headaches.&lt;/p&gt;

&lt;p&gt;And I'm gonna be honest, building distributed systems like this is a cool problem to solve and will be a point of growth for many of your engineers.&lt;/p&gt;

&lt;h2&gt;
  
  
  ¶So, why are SPAs bad again?
&lt;/h2&gt;

&lt;p&gt;Yeh, so far this all sounds great, right? Well, just letting ol' Conway right into your living room isn't exactly the best idea.&lt;/p&gt;

&lt;p&gt;Aside of all the points that Greg makes in his article (if you haven't read it yet, go read it), I want to present three &lt;em&gt;extra&lt;/em&gt; reasons why I think an SPA is a bad idea.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¶Your front-end and back-end get decoupled!
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Your back-end and front-end are &lt;em&gt;always&lt;/em&gt; coupled.&lt;/strong&gt; So trying to split them in anything but the most extreme circumstances is an exercise in futility.&lt;/p&gt;

&lt;p&gt;I think this is probably the worst part of this whole story.&lt;/p&gt;

&lt;p&gt;If your back-end team want to move in one direction, they've got to align with the front-end team. If timings and priorities don't work out, it's going to force someone to either put a hold on some work that really needs sorting out or do some grunt work just to patch over a hole that's about to appear.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;This is communication overhead.&lt;/strong&gt; It adds risk. It adds complexity. It adds meetings into engineers' calendars. It adds friction, and stress, and distraction.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;It flies in the face of that number one principle: let your teams focus and be happy.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This literally costs you money one way or another, cost that you could avoid.&lt;/p&gt;

&lt;p&gt;Deployments get unavoidably riskier in ways that are &lt;a href="https://github.com/asatarin/testing-distributed-systems" rel="noopener noreferrer"&gt;super difficult to test&lt;/a&gt; because testing distributed systems is really hard.&lt;/p&gt;

&lt;p&gt;Again, this might all be fine, &lt;em&gt;in the most extreme cases&lt;/em&gt;, where you &lt;em&gt;need&lt;/em&gt; the decoupling. Then this extra expense, and complexity, and churn-causing evil, is just a &lt;em&gt;necessary&lt;/em&gt; evil that you have to learn to swallow and live with.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;But I've got &lt;code&gt;x&lt;/code&gt; engineers, &lt;code&gt;y1&lt;/code&gt; are front-end, &lt;code&gt;y2&lt;/code&gt; are back-end. What do I do?&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I would strongly recommend that one of your engineering groups need to roll up their sleeves and get on learning the other group's code, tooling and responsibilities.&lt;/p&gt;

&lt;p&gt;This will have multiple benefits: career progression and learning opportunities, &lt;a href="https://en.wikipedia.org/wiki/Bus_factor" rel="noopener noreferrer"&gt;increased bus factor&lt;/a&gt;, fewer meetings and more collaboration.&lt;/p&gt;

&lt;p&gt;Sure there will be challenges too, but they won't be as big or as painful as the other challenges you'd face with an SPA.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¶It may hurt customisability
&lt;/h3&gt;

&lt;p&gt;As I mentioned earlier, the reason I got into Vue at all was because other tech I was using required me to. In both Statamic and Laravel Nova, the choice of Vue—well, not specifically Vue, but rather a reactive front-end framework—made sense because &lt;em&gt;at the time&lt;/em&gt; it really was the best way to build flexible, reactive front-ends.&lt;/p&gt;

&lt;p&gt;And both of those tools needed that power and have become fantastic tools because of it.&lt;/p&gt;

&lt;p&gt;But there is one pain point that it's created that's quite hard to escape: &lt;strong&gt;the customisation story for each of these is harder because of it&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;How so?&lt;/p&gt;

&lt;p&gt;Basically, because each tool needs to build the assets to ship their product. And once they're built it's hard for third-parties to build on what's already there.&lt;/p&gt;

&lt;p&gt;How is it harder? Let's say I'm creating a Statamic add-on that allows CMS owners to post to social media from their control panel. As Statamic uses Vue and already has a bunch of components I can leverage, I am going to use some of them.&lt;/p&gt;

&lt;p&gt;But I'm also going to add some of my own functionality that doesn't already exist within Statamic. Now what happens? Well I build the Javascript... but wait. I can't change the bundled JS that's part of Statamic core.&lt;/p&gt;

&lt;p&gt;I have to build my own JS and load it at the right time, something I'm not in control of. Thankfully the Statamic team (building on tooling from the Vue &amp;amp; JS community) have worked hard to &lt;a href="https://statamic.dev/extending/addons#assets" rel="noopener noreferrer"&gt;make this relatively easy&lt;/a&gt;, but my tool choice is now limited by what they support - if they're using Vue 2, I have to use Vue 2; if I don't like Vite or Webpack, tough luck.&lt;/p&gt;

&lt;p&gt;And on top of that, the builds have to happen &lt;em&gt;at the client's end&lt;/em&gt;, which means we're now offloading some of the responsibility of making this whole thing work to people who don't need or want to know anything about this stuff. They just want to install your thing and get on with their jobs and lives.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Why&lt;/em&gt; is this such a pain though? It used to be (in other platforms) that I could just load some extra JS file into the admin interface and do what I want.&lt;/p&gt;

&lt;p&gt;Honestly, we probably should never have been doing that either. Hands up, how many of you have seen a WordPress installation that tries to load 2 or more different versions of jQuery? 🙋🏼‍♂️&lt;/p&gt;

&lt;p&gt;So these build tools go some way to alleviating &lt;em&gt;some&lt;/em&gt; problems, but in the process have introduced so many layers of protection and abstraction that it presents a brain-melting, Japanese puzzle box to unlock.&lt;/p&gt;

&lt;p&gt;And all this JavaScript flying around is really unsafe, because JavaScript is completely malleable on the client side.&lt;/p&gt;

&lt;p&gt;That's meant library creators have had to go to some unusual lengths to protect the state of the application and encapsulate the code in attempts to make it safer and more portable.&lt;/p&gt;

&lt;p&gt;I won't pretend to understand all of the requirements, pre-requisites and implications for why built JavaScript assets are packaged up in a complex soup of function calls and obfuscated code, but suffice to say this makes building on top of pre-existing code that much harder.&lt;/p&gt;

&lt;p&gt;The web standards track is working to make this easier: we have &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Web_components" rel="noopener noreferrer"&gt;Web Components&lt;/a&gt; and &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules" rel="noopener noreferrer"&gt;module&lt;/a&gt; starting to come through which should alleviate some of this.&lt;/p&gt;

&lt;p&gt;But if you're not building with those standard in play—I understand, it might not be possible because of browser support etc—and you want to expose your user's to third-party plugins/add-ons, then &lt;em&gt;you've&lt;/em&gt; got to figure out how to make it easy for other developers.&lt;/p&gt;

&lt;p&gt;Some of that's going to require the specific implementation, the other part is going to be documentation. No matter how you cut it, it's going to be harder to get right than if you had server-side rendered views that you allow your third-party developers to load at runtime.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¶Performance will suffer
&lt;/h3&gt;

&lt;p&gt;This isn't really an &lt;em&gt;extra&lt;/em&gt; reason as Greg did touch on this a little already, but I wanted to go harder on performance.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;You should never choose to build an SPA because of some supposed performance benefit.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That is the wrong hill to try and defend for many reasons, but primarily because you've got the whole of the web stack—on horses, with bazookas—nipping at your heels.&lt;/p&gt;

&lt;p&gt;Sure, it may take a little while for web standards to get ratified and then rolled out, but the reality is that it's &lt;em&gt;only&lt;/em&gt; a matter of time.&lt;/p&gt;

&lt;p&gt;We now have wide browser support for &lt;a href="https://en.wikipedia.org/wiki/HTTP/3" rel="noopener noreferrer"&gt;QUIC / HTTP/3&lt;/a&gt; (which brings faster downloads and reduced server load) and things like &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/103" rel="noopener noreferrer"&gt;&lt;code&gt;103 Early Hints&lt;/code&gt;&lt;/a&gt; response headers (which let us tell browsers what they should prioritise pre-loading), making the standard, non-SPA web even more performant. (And yes, some of this benefits SPAs too!)&lt;/p&gt;

&lt;p&gt;Sure, you can argue some of this advancement may have been &lt;em&gt;driven&lt;/em&gt; by SPAs and their apparent benefits. But there's some inevitability to all of this (both the appearance of SPAs and the advancement of HTTP) which makes the whole argument moot in my opinion.&lt;/p&gt;

&lt;p&gt;As adoption and overall performance of the web platform increases, SPAs will even start to feel slow in comparison. Some feel slow already!&lt;/p&gt;

&lt;p&gt;That's because so much of the heavy lifting is left to the userland threads of the in-browser JavaScript engine instead of the lower-level compiled languages, the ones used to build the core browser engine itself (C++, Rust, Swift etc).&lt;/p&gt;

&lt;p&gt;That translates to a poorer experience in your app, and a penalty for your users.&lt;/p&gt;

&lt;p&gt;While it's not impossible for JavaScript to be as fast or faster than the actual browser it's running in, it's just such a long way for it to get there &lt;strong&gt;it's a no-brainer at this stage to let the browser do what the browser does best&lt;/strong&gt; instead of trying to replicate all of that in JS.&lt;/p&gt;

&lt;p&gt;So don't! Use JavaScript the way it was intended: as a sugar-coating to enhance the pages, not to build entire pages.&lt;/p&gt;

&lt;p&gt;I mean, you wouldn't eat a donut made entirely out of sugar, would you?&lt;/p&gt;

&lt;p&gt;Again, in the &lt;em&gt;extreme cases&lt;/em&gt;, maybe you would. Maybe for this donut-sized/-shaped sugar torus, you have an appropriately-sized dough-only counterpart, both of which you consume in close proximity...&lt;/p&gt;

&lt;p&gt;I donut-know where this analogy is going.&lt;/p&gt;

&lt;h2&gt;
  
  
  ¶So what's the alternative?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;You, dear reader, are not in the most extreme case.&lt;/strong&gt; Probably not even close! &lt;strong&gt;And you may never be.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;So, if you haven't started building an SPA, don't!&lt;/p&gt;

&lt;p&gt;Keep your code together in a single application where the front-end is rendered by the back-end, and then you can test and deploy it as a single unit. And yes, you can even do that without Docker 😱&lt;/p&gt;

&lt;p&gt;Create it as a fully server-rendered, multi-page application with page reloads and everything. Go on! I double dare you.&lt;/p&gt;

&lt;p&gt;If you really want/need the reactivity, try something like Livewire, &lt;a href="https://hotwired.dev/" rel="noopener noreferrer"&gt;Hotwire&lt;/a&gt; or &lt;a href="https://htmx.org/" rel="noopener noreferrer"&gt;HTMX&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;You can do this all the way up to many millions of users per day and it will be fine, which you are a long way from.&lt;/p&gt;

&lt;p&gt;Trust me, your front-end will never meaningfully need to move faster than your back-end, and vice-versa.&lt;/p&gt;

&lt;p&gt;If you're already running an SPA and are contemplating bringing the two parts of the donut back together, do it! Bite your lip, close your eyes, and just do it.&lt;/p&gt;

&lt;p&gt;&lt;a href="(https://x.com/dhh/status/1753078515694784821?s=46)"&gt;Relevant&lt;/a&gt;&lt;/p&gt;

</description>
      <category>spa</category>
    </item>
    <item>
      <title>A-A-Ron!</title>
      <dc:creator>Simon Hamp</dc:creator>
      <pubDate>Wed, 20 Sep 2023 00:00:00 +0000</pubDate>
      <link>https://dev.to/simonhamp/a-a-ron-3l5h</link>
      <guid>https://dev.to/simonhamp/a-a-ron-3l5h</guid>
      <description>&lt;p&gt;&lt;a href="https://aaronfrancis.com/" rel="noopener noreferrer"&gt;Aaron Francis&lt;/a&gt; is a rising star in the Laravel community. Over the past couple of years he's rocketed up because he's a genuinely thoughtful, intelligent and funny guy.&lt;/p&gt;

&lt;p&gt;I like him. I met him very briefly at Laracon US this year and I've had some great public and private interactions with him through Twitter. He's an awesome dude.&lt;/p&gt;

&lt;p&gt;I follow a lot of really interesting, smart, funny people, and I respect them all. For me, Aaron is a little different though. I feel an affinity with him that I can't quite describe.&lt;/p&gt;

&lt;p&gt;So many times he's said something on a screencast, podcast, tweet, or in person that I just can't help but do that "mmm-hmmm!" and nod affirmatively, knowingly.&lt;/p&gt;

&lt;p&gt;He speaks to my soul.&lt;/p&gt;

&lt;p&gt;Plus, he's been absolutely booting the (English) football out of the stadium lately!&lt;/p&gt;

&lt;p&gt;He has called this his "Maximum Effort" era, but his approach to it is honestly aligning so hard with how I see things. He knows it won't - &lt;em&gt;can't&lt;/em&gt; - last forever, but he's giving it his absolute best while he can. And I think it's paying off!&lt;/p&gt;

&lt;p&gt;This isn't #hustlin' - it's hard work, balanced. I'm trying to do the same but I still don't get it right. Aaron is setting a great example, and sharing his lessons and mistakes openly and honestly, and I am here for it.&lt;/p&gt;

&lt;p&gt;But he's a bit of a madman:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;He started as an accountant - fully qualified, worked for one of the big accounting firms - but switched to programming early on in his career&lt;/li&gt;
&lt;li&gt;Now he's got a full-time job at PlanetScale&lt;/li&gt;
&lt;li&gt;He MC'd at Laracon US this year and absolutely smashed it!&lt;/li&gt;
&lt;li&gt;He even closed out Laracon with arguably one of the best talks of the whole conference (video above - give it a watch) - I was moved. I could &lt;em&gt;feel&lt;/em&gt; his emotion from the second row&lt;/li&gt;
&lt;li&gt;He did a &lt;a href="https://planetscale.com/learn/courses/mysql-for-developers/introduction/course-introduction" rel="noopener noreferrer"&gt;HUGE video course about MySQL&lt;/a&gt; (hopefully mostly on work time) - hours and hours of top-notch database content available for free! 🤯&lt;/li&gt;
&lt;li&gt;He has a podcast or three, most recently &lt;a href="https://mostlytechnical.com/" rel="noopener noreferrer"&gt;&lt;em&gt;Mostly Technical&lt;/em&gt;&lt;/a&gt; with Ian Landsman which I am really enjoying listening to&lt;/li&gt;
&lt;li&gt;He just released an app - &lt;a href="https://flowtone.app/" rel="noopener noreferrer"&gt;flowtone.app&lt;/a&gt; - with &lt;a href="https://twitter.com/lepikhinb" rel="noopener noreferrer"&gt;Boris Lepikhin&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;He &lt;a href="https://twitter.com/aarondfrancis" rel="noopener noreferrer"&gt;tweets regularly&lt;/a&gt; about interesting topics and engages really positively with everyone, sending out positive vibes, especially in the Laravel community&lt;/li&gt;
&lt;li&gt;He must have a hectic family life besides as he has young twins already and &lt;em&gt;another&lt;/em&gt; set of twins on the way in a few weeks!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Huge props to his wife! She must be an absolute trooper and offering really great support and understanding despite having to care for two little ones and carrying two more besides all the usual stuff that life throws at women. Wow.&lt;/p&gt;

&lt;p&gt;And I know that Aaron's working along with other talented folks, like Boris and &lt;a href="https://twitter.com/jasonlbeggs" rel="noopener noreferrer"&gt;Jason Beggs&lt;/a&gt;, so it's not just him slogging away - he's got help.&lt;/p&gt;

&lt;p&gt;But Aaron deserves a huge hand for putting in the hours, pushing through the tough times, the self-doubt and mithering over which path to take, the &lt;a href="https://twitter.com/aarondfrancis/status/1703497018088259999?s=20" rel="noopener noreferrer"&gt;3am work sessions&lt;/a&gt; (I've been there too many times!)&lt;/p&gt;

&lt;p&gt;👏&lt;/p&gt;

&lt;p&gt;He's a fantastic example in just consistently being nice and thoughtful and positive - he is bringing the kind of energy I want. Which is hard for me: I'm a Brit, a realist and a sarcastic wotsit - a tricky combo to overcome!&lt;/p&gt;

&lt;p&gt;And he has a lovely Texas accent which I am just so jealous of.&lt;/p&gt;

&lt;p&gt;But you know what... even all of that isn't the whole story!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;TODAY&lt;/strong&gt; Aaron is launching &lt;strong&gt;another&lt;/strong&gt; course, a 'meta' screencast &lt;a href="https://screencasting.com/friends/simon" rel="noopener noreferrer"&gt;all about screencasting&lt;/a&gt;&lt;sup id="fnref:1"&gt;1&lt;/sup&gt;! (use code &lt;code&gt;LAUNCHFRIENDS&lt;/code&gt; for a $50 discount)&lt;/p&gt;

&lt;p&gt;This time, it's a paid course that he has created and not for PlanetScale. And it looks incredible! I've been waiting very patiently for this one since he announced it a couple months ago for a number of reasons:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;He has set a high bar for his own screencasts and others (me) rightly want to replicate that&lt;/li&gt;
&lt;li&gt;I've been starting to do more video myself, so I want all those tips and tricks to elevate my own vids&lt;/li&gt;
&lt;li&gt;He's been teasing it with little teardowns&lt;sup id="fnref:2"&gt;2&lt;/sup&gt; of user-submitted videos and dripping some really practical, early access lessons for free&lt;/li&gt;
&lt;li&gt;I just really appreciate the effort and polish he has put in and I think he deserves it, so I'm going to buy it&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I'm hooked. I'm not just a &lt;em&gt;follower&lt;/em&gt; of Aaron, I'm a &lt;strong&gt;fan&lt;/strong&gt; &lt;sup id="fnref:3"&gt;3&lt;/sup&gt;! I'm excited for him and want him to succeed. That's a really rare feeling for me (and I feel super cheesy saying it!) - I generally &lt;em&gt;want&lt;/em&gt; others to succeed, but I am usually happy being a bit of an armchair advocate.&lt;/p&gt;

&lt;p&gt;With Aaron, I'm like: give me a placard, a bell, and fresh pair of lungs...&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Well done, Aaron! You deserve it man.&lt;/strong&gt;&lt;/p&gt;




&lt;ol&gt;
&lt;li&gt;&lt;p&gt;This is an affiliate link ↩&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;He's promised to do a teardown of one of my own screencasts too, so I'm looking forward to seeing that - especially as that was possibly one of the most hastily put together videos ever ↩&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Except for the fact that he's not a Star Wars fan and hasn't seen Andor - you need to watch that! Forget that it's even Star Wars... it's just great TV ↩&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>screencasting</category>
      <category>people</category>
    </item>
    <item>
      <title>Getting background colours to go all the way</title>
      <dc:creator>Simon Hamp</dc:creator>
      <pubDate>Thu, 14 Sep 2023 00:00:00 +0000</pubDate>
      <link>https://dev.to/simonhamp/getting-background-colours-to-go-all-the-way-10p7</link>
      <guid>https://dev.to/simonhamp/getting-background-colours-to-go-all-the-way-10p7</guid>
      <description>&lt;ul&gt;
&lt;li&gt;
The problem

&lt;ul&gt;
&lt;li&gt;Why is this happening?&lt;/li&gt;
&lt;li&gt;Back to why...&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;There is a solution!&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;I'm pretty proud of the &lt;a href="https://gitamic.simonhamp.me" rel="noopener noreferrer"&gt;Gitamic&lt;/a&gt; diff viewer. It's not perfect (and probably never will be thanks to different browser rendering engines), but it can handle some pretty gnarly diffs quite rapidly.&lt;/p&gt;

&lt;p&gt;("Quite rapidly" being somewhat subject to your perspective)&lt;/p&gt;

&lt;p&gt;Of course, a lot of this is down to browsers rendering engines getting faster and faster. So I can't really take any credit.&lt;/p&gt;

&lt;p&gt;But it still took me a while to make it as quick as it is. One thing that I did learn tho:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Don't use a &lt;code&gt;&amp;lt;table&amp;gt;&lt;/code&gt; to render a diff; They are slow as all hell!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;One thing that I 'fixed' (again, subjective) the other day that I want to talk about now is the backgrounds on diff lines.&lt;/p&gt;

&lt;h2&gt;
  
  
  ¶The problem
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F196dykq59ak36wywicsc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F196dykq59ak36wywicsc.png" alt="Diffs in Gitamic" width="704" height="396"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I really wanted the diff viewer to have all the normal visual cues you might be used to from other Git interfaces, like GitHub/Gitlab/Tower etc.&lt;/p&gt;

&lt;p&gt;And for the most part, my first pass at that managed wasn't half bad: background colours, &lt;em&gt;sticky&lt;/em&gt; line numbers, configurable context length, toggleable line wrapping...&lt;/p&gt;

&lt;p&gt;But then one day I saw this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1t5jphodyvvpzpp3pshs.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1t5jphodyvvpzpp3pshs.png" alt="Background colour getting clipped due to overflow" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  ¶Why is this happening?
&lt;/h3&gt;

&lt;p&gt;Well, to explain that, it will help to set the scene a little, because... it's complicated.&lt;/p&gt;

&lt;p&gt;Each diff is made up of lots of &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt;s - "diff-divs", if you will:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the File Card - a panel that presents all the diff chunks from a single file in Git's index (these are collapsible)&lt;/li&gt;
&lt;li&gt;a Chunk panel - a collapsible panel that renders a single chunk - &lt;em&gt;n&lt;/em&gt; lines of changes plus context lines&lt;/li&gt;
&lt;li&gt;the Line Numbers column&lt;/li&gt;
&lt;li&gt;the Lines container - which will hold all of the lines and over which the Line Numbers column will appear to float&lt;/li&gt;
&lt;li&gt;each line of the diff's content - basically one &lt;code&gt;div&lt;/code&gt; per line of output from &lt;code&gt;git diff&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;div class="file"&amp;gt;
  &amp;lt;div class="chunk"&amp;gt;
    &amp;lt;div class="line"&amp;gt;
      &amp;lt;div class="line-numbers"&amp;gt;
        &amp;lt;!-- These are complex for layout reasons --&amp;gt;
      &amp;lt;/div&amp;gt;
      &amp;lt;div class="context"&amp;gt;
        &amp;lt;!-- This line of the diff --&amp;gt;
      &amp;lt;/div&amp;gt;
    &amp;lt;/div&amp;gt;
    &amp;lt;div class="line"&amp;gt;
      &amp;lt;div class="line-numbers"&amp;gt;&amp;lt;/div&amp;gt;
      &amp;lt;div class="old"&amp;gt;&amp;lt;/div&amp;gt;
    &amp;lt;/div&amp;gt;
    &amp;lt;div class="line"&amp;gt;
      &amp;lt;div class="line-numbers"&amp;gt;&amp;lt;/div&amp;gt;
      &amp;lt;div class="new"&amp;gt;&amp;lt;/div&amp;gt;
    &amp;lt;/div&amp;gt;
    &amp;lt;div class="line"&amp;gt;
      &amp;lt;div class="line-numbers"&amp;gt;&amp;lt;/div&amp;gt;
      &amp;lt;div class="context"&amp;gt;&amp;lt;/div&amp;gt;
    &amp;lt;/div&amp;gt;
  &amp;lt;/div&amp;gt;

  &amp;lt;div class="chunk"&amp;gt;
    ...
  &amp;lt;/div&amp;gt;

  ...
&amp;lt;/div&amp;gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is simplified for the sake of this example. In reality, each &lt;code&gt;div.chunk&lt;/code&gt; has more to it, which gives us further constraints that we also need to consider, such as its header.&lt;/p&gt;

&lt;p&gt;(I know on the surface, this looks more complicated than a table, but trust me, your browser can render this wayyyyy faster)&lt;/p&gt;

&lt;p&gt;Each &lt;code&gt;div.file&lt;/code&gt; is a fixed-width card. This card is what creates that neatly contained, white background with a contextual heading. In diffs with many files, this helps the user spot that they're now moving to a different file, as they will see the one card end and a new one begin.&lt;/p&gt;

&lt;p&gt;Fixing the width keeps the card completely visible within the available viewport. Nice.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmueey1tpdjxkjmjg9iis.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmueey1tpdjxkjmjg9iis.png" alt="The diff file card" width="800" height="436"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;However, each &lt;code&gt;div.chunk&lt;/code&gt; needs to be set &lt;code&gt;overflow-x: auto&lt;/code&gt; to allow long lines inside it to be seen and scrolled over.&lt;/p&gt;

&lt;p&gt;If I were to set the overflow on &lt;code&gt;div.file&lt;/code&gt;, then all chunks will be scrolled together.&lt;/p&gt;

&lt;p&gt;That's not desirable from a UX perspective: when I'm looking at one chunk, I don't want another to be scrolling in and out of view.&lt;/p&gt;

&lt;p&gt;What's more, for really big diffs, it will be the cause of some super janky scrolling.&lt;/p&gt;

&lt;p&gt;And we'd also get a whole load of other visual regressions that would need to be solved, introducing even more complexity.&lt;/p&gt;

&lt;p&gt;The backgrounds themselves (which are just &lt;code&gt;background-color&lt;/code&gt;) are applied to the relevant &lt;code&gt;div.line&lt;/code&gt;, based on its type: &lt;code&gt;old&lt;/code&gt;, &lt;code&gt;new&lt;/code&gt;, &lt;code&gt;context&lt;/code&gt;, respectively.&lt;/p&gt;

&lt;p&gt;(For those of you who want to make sure I'm not being completely psychotic - yes, these are generally well split into separate Vue components)&lt;/p&gt;

&lt;h3&gt;
  
  
  ¶Back to why...
&lt;/h3&gt;

&lt;p&gt;In HTML, when a container that has a background colour is inside another container that has a fixed width, the background colour rendering stops where the parent container stops.&lt;/p&gt;

&lt;p&gt;This saves the browser from doing any work it probably doesn't need to do: calculating where the background should be rendering for any elements that &lt;em&gt;in theory&lt;/em&gt; don't have anything visible outside of the visible viewport.&lt;/p&gt;

&lt;p&gt;But, in practice of course, it's entirely possible for some child elements to "pop" out of their parent, especially when you explicitly allow a fixed-width element to overflow (e.g. with &lt;code&gt;overflow-x: auto&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;In that scenario, &lt;em&gt;constrained&lt;/em&gt; children can appear to have their background clipped if other, wider children overflow the container and cause it to scroll.&lt;/p&gt;

&lt;p&gt;It's not a show-stopper, but it's a little unsightly. Not exactly the experience I want for a premium add-on that folks will have paid for.&lt;/p&gt;

&lt;p&gt;But the other - slightly more frustrating - problem this causes is that any &lt;code&gt;sticky&lt;/code&gt; elements, such as the line numbers column, get trapped at that same point; wherever the parent container's 'official' width finishes.&lt;/p&gt;

&lt;p&gt;So for lines that are considerably wider than the parent container's width, you could end up seeing this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8hy6jgx9qhaieanyljb0.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8hy6jgx9qhaieanyljb0.gif" alt="An animation showing line numbers being prevented from floating persistently as the user scrolls horizontally" width="354" height="480"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;See how the line numbers columns stops and slides out of view early?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Why?&lt;/p&gt;

&lt;p&gt;Because the sticky element can't jump out of its container - the parent whose width is fixed to a width that is incorrect.&lt;/p&gt;

&lt;p&gt;So why not just let that parent container go full width?&lt;/p&gt;

&lt;p&gt;That would result in the parent node (in this case, the File Card) being the element that manages the horizontal scroll... which we've already determined would lead to all of the diff chunks scrolling horizontally together.&lt;/p&gt;

&lt;p&gt;And, y'know, it still doesn't solve the problem! There will still be some clipping, it will just be at a different place. In fact, just pushing the problem up the DOM tree only makes things worse for us.&lt;/p&gt;

&lt;p&gt;Don't want. No good.&lt;/p&gt;

&lt;p&gt;No, we need to solve this right here.&lt;/p&gt;

&lt;p&gt;We might be able to introduce more complexity to the DOM and try to find some variation of &lt;code&gt;div&lt;/code&gt;s that allows us to find some magical combination that meets all the requirements and Scotch-tape the whole thing together with a bunch of Javascript... but trust me, performance will suffer on a number of fronts, especially when rendering new diffs or redrawing during scroll.&lt;/p&gt;

&lt;h2&gt;
  
  
  ¶There is a solution!
&lt;/h2&gt;

&lt;p&gt;For me, the solution to this problem lies in combining good old CSS with &lt;em&gt;just a sprinkling&lt;/em&gt; ✨ of Javascript.&lt;/p&gt;

&lt;p&gt;I will admit tho, it's a tad disappointing that CSS can't solve this one alone for us yet - and sadly I'm not sure it ever will.&lt;/p&gt;

&lt;p&gt;Basically, in order to force the background to stretch to the same width for all the lines, we need to explicitly tell the browser that they should all be 'yay wide'.&lt;/p&gt;

&lt;p&gt;In other words, we have to apply a set &lt;code&gt;width&lt;/code&gt; or &lt;code&gt;min-width&lt;/code&gt; to &lt;strong&gt;all&lt;/strong&gt; of them and not rely solely on the browser to work out how wide each &lt;code&gt;div&lt;/code&gt; should be.&lt;/p&gt;

&lt;p&gt;We could hard-code a very wide, fixed width to these to try to account for really long lines... that could even be done in pure CSS and with just a few extra bytes applying that width to the every &lt;code&gt;div.line&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;But then all chunks will be able to scroll... realllllly far... whether they need to or not (blerch) &lt;em&gt;and&lt;/em&gt; I bet there will still be cases where one line goes just a little further than we've allowed for.&lt;/p&gt;

&lt;p&gt;And besides, we've got these super powerful calculators rendering these views - it should be able to work out what the widest line is and make all of them the same width.... right?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2gdwo2svdzvko4axx4y1.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2gdwo2svdzvko4axx4y1.jpg" alt="An Anakin and Padmé meme about overpriced calculators and working out widths of divs" width="500" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But how can we find out what that width should be?&lt;/p&gt;

&lt;p&gt;We could cycle through each element and find the longest one, but there are problems with that: if we have a lot of elements, it's going to be slow. Plus, if the elements aren't always there, timing is going to be an issue as we won't get the widths until they're fully rendered.&lt;/p&gt;

&lt;p&gt;But, for argument's sake, let's say our timing issues are all solved and we can put up with a few extra milliseconds on the render time, how do we even &lt;em&gt;get&lt;/em&gt; the full width of those long lines? It turns out that &lt;code&gt;getClientWidth&lt;/code&gt; and &lt;code&gt;getClientBoundingRects().width&lt;/code&gt; will only give us the &lt;em&gt;visible&lt;/em&gt; width available to the viewport, not the full width.&lt;/p&gt;

&lt;p&gt;Thankfully, the droids we're looking for are captured in the &lt;code&gt;scrollWidth&lt;/code&gt; of the parent - that overflowing sonuvva, &lt;code&gt;div.chunk&lt;/code&gt;, that has created this problem in the first place also has the solution hidden within the depths of its dark DOM-matrix!&lt;/p&gt;

&lt;p&gt;&lt;code&gt;scrollWidth&lt;/code&gt; is what the browser uses to determine how far the scrollbar needs to travel and how big the scrollbar handle needs to be. Thankfully, it applies it to the container that has the &lt;code&gt;overflow-x&lt;/code&gt;, after it's determined how wide its currently-rendered contents are&lt;sup id="fnref:1"&gt;1&lt;/sup&gt;.&lt;/p&gt;

&lt;p&gt;That means we can use it as the explicit width of all of the child elements! 🎉 Awesome!&lt;/p&gt;

&lt;p&gt;It also means there's no need for us to run a loop over all of the &lt;em&gt;n&lt;/em&gt;-long set of &lt;code&gt;div.line&lt;/code&gt; elements.&lt;/p&gt;

&lt;p&gt;We can just grab the &lt;code&gt;scrollWidth&lt;/code&gt; value from the &lt;code&gt;div.chunk&lt;/code&gt; and apply it as an inline style to each &lt;code&gt;div.line&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;div v-for="line in change.lines" ref="lines" class="line"&amp;gt;
  &amp;lt;!-- Line template code here --&amp;gt;
&amp;lt;/div&amp;gt;

&amp;lt;script&amp;gt;
function recalcLineWidths() {
    this.$refs.lines.forEach((line) =&amp;gt; {
        line.style.minWidth = `${this.$refs.chunk.scrollWidth}px`;
    });
}
&amp;lt;/script&amp;gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;(Again, this code is just for demonstration purposes. The actual logic is a little more convoluted.)&lt;/p&gt;

&lt;p&gt;&lt;code&gt;recalcLineWidths&lt;/code&gt; is executed at choice intervals when I know the line widths might have changed, such as when changing from wrapped to non-wrapped text.&lt;/p&gt;

&lt;p&gt;It's still not perfect, but for the 90% use-case, where you just have some files that have really long lines, it does the trick.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;This is coming to Gitamic in an upcoming point release soon.&lt;/strong&gt;&lt;/p&gt;




&lt;ol&gt;
&lt;li&gt;For lots of lines, 'currently-rendered' will mean the timing of your call to &lt;code&gt;scrollWidth&lt;/code&gt; matters immensely, because the value will be recalculated a number times over potentially thousands of nanoseconds. You need to wait until the very end of the render cycle. ↩
&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>vue</category>
      <category>javascript</category>
      <category>css</category>
    </item>
    <item>
      <title>Laravel Nova Import v0.7</title>
      <dc:creator>Simon Hamp</dc:creator>
      <pubDate>Tue, 12 Sep 2023 00:00:00 +0000</pubDate>
      <link>https://dev.to/simonhamp/laravel-nova-import-v07-55gn</link>
      <guid>https://dev.to/simonhamp/laravel-nova-import-v07-55gn</guid>
      <description>&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/6Wxj2XtN22Q"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;I recently spent a little time on my &lt;a href="https://github.com/simonhamp/laravel-nova-csv-import" rel="noopener noreferrer"&gt;Laravel Nova CSV Import&lt;/a&gt; package, one of my main open source packages. This came at the request of a sponsor.&lt;/p&gt;

&lt;p&gt;This gave me the opportunity to level-up some of the UI and spend some time diving into some of the open PRs and issues.&lt;/p&gt;

&lt;p&gt;Please watch the video above for more details about the features that have been added, or &lt;a href="https://github.com/simonhamp/laravel-nova-csv-import/compare/v0.6.7...v0.7.2" rel="noopener noreferrer"&gt;check these changes&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The end result is v0.7. Yep, still not a v1. Even after over 4 years, I've not really had time to flesh it out and test it to get it to a point where it's stable enough to qualify as a v1.&lt;/p&gt;

&lt;p&gt;Despite that, it's been downloaded over 200,000 times, which is staggering to me 🤯&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Nova?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://nova.laravel.com" rel="noopener noreferrer"&gt;Laravel Nova&lt;/a&gt; is a great piece of premium software from the Laravel team and well worth every penny. I've used it since its release and it has made so many tasks easier.&lt;/p&gt;

&lt;p&gt;It provides an excellent pluggable admin panel interface, which is brilliant for building internal tools or as a client admin for just about any kind of database-backed application.&lt;/p&gt;

&lt;p&gt;What's more, it uses &lt;a href="https://vuejs.org/" rel="noopener noreferrer"&gt;Vue&lt;/a&gt; (which I love), so building really rich UIs on it is dead easy, especially since Nova v4.&lt;/p&gt;

&lt;p&gt;I've spent a lot of time with it and I'm proud to be a part of the Nova Internals group that is supporting &lt;a href="https://github.com/davidhemphill" rel="noopener noreferrer"&gt;David&lt;/a&gt; and &lt;a href="https://github.com/crynobone" rel="noopener noreferrer"&gt;Muhammad&lt;/a&gt; in evolving Nova into an even more powerful tool.&lt;/p&gt;

&lt;h2&gt;
  
  
  What about Filament?
&lt;/h2&gt;

&lt;p&gt;I've been watching &lt;a href="https://filamentphp.com" rel="noopener noreferrer"&gt;Filament&lt;/a&gt; closely and have even used it on a couple of projects. I am really excited for that team and the awesome work they're putting into the project seems to be paying off as I see and hear a lot of other engineers raving about Filament, especially &lt;a href="https://v3when.com/" rel="noopener noreferrer"&gt;now that v3 has launched&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I really like where that project is headed too and honestly I'm tempted to port CSV Import there if it's wanted.&lt;/p&gt;

&lt;p&gt;The main difference, of course, is that Filament uses Livewire and Alpine in place of Vue. I love Livewire too and I'm using it more and more. I think it would be an good challenge to build out the two front-ends and maintain them.&lt;/p&gt;

&lt;p&gt;The problem is time - or rather, the lack of it. I fear that I won't have time to maintain both versions concurrently, which means one will always be a little behind.&lt;/p&gt;

&lt;p&gt;If an easy to use, powerful CSV Import tool is what the Filament community wants, I'd love to fill that gap, but let's see if that's needed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Is a package really necessary?
&lt;/h2&gt;

&lt;p&gt;If you can build this with your team for your use-case rapidly enough without needing to depend on a third-party package, I will always advise you to do so! &lt;strong&gt;Fewer dependencies generally means lower risk&lt;/strong&gt; , which means fewer problems.&lt;/p&gt;

&lt;p&gt;We've all experienced dependencies being left behind and going stale, maintainers disappearing seemingly without a trace and no way to get their attention, multiple forks all going in weird and wonderful directions... heck, I've been a bit like that with CSV Import!&lt;/p&gt;

&lt;p&gt;But not every individual or team has the skills, time or resources to build and maintain a powerful CSV import tool - even though that might be what your client/business needs.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If you're already using Nova, CSV Import can have you importing CSV data into your database &lt;strong&gt;in minutes&lt;/strong&gt; , with powerful validation and transformation, batching, and even asynchronous processing&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That's a huge time-saver.&lt;/p&gt;

&lt;p&gt;I guess the main concern is "will it still be around when we've moved onto Nova 5, 6, 7...".&lt;/p&gt;

&lt;p&gt;The only sane answer to that is: &lt;strong&gt;Yes, if you can support its existence financially&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;I believe CSV Import serves an important niche: folks who want an open-ended CSV import utility for admin panels they're building for paying clients.&lt;/p&gt;

&lt;p&gt;As a completely free and open source package, there's literally nothing forcing anyone to contribute anything for the effort that I've put into it over the years.&lt;/p&gt;

&lt;p&gt;All I ask is that if it serves you and enables you to &lt;strong&gt;save money&lt;/strong&gt; or &lt;strong&gt;make money&lt;/strong&gt; by adding this powerful feature to the tools you're building, &lt;a href="https://github.com/sponsors/simonhamp" rel="noopener noreferrer"&gt;please consider sponsoring my efforts&lt;/a&gt; - even with just a small one-off amount - every little helps!&lt;/p&gt;

&lt;p&gt;I will be extremely grateful.&lt;/p&gt;

</description>
      <category>laravel</category>
      <category>csv</category>
      <category>package</category>
    </item>
  </channel>
</rss>
