{"id":"8zjiflcd51cr562","title":"How to build your freelance web design career from the ground up","slug":"build-freelance-web-design-career","summary":"Freelance web design works when you treat it like a service business, not a portfolio contest. The basics are positioning, proof, process, and delivering work clients can trust.","imageUrl":"https://briancrabtree.me/images/journal-build-freelance-web-design-career.webp","category":"Career","date":"12/01/2025","featured":false,"likes":49,"author":"Brian Crabtree","content":"<h2>The fallacy of the single page application</h2>\n\n<p>For a few years, the industry collectively decided that everything needed to be a Single Page Application. We pushed the entire rendering logic to the client, forcing the user’s browser to download a massive JavaScript payload, parse it, execute it, and then fetch data before painting a single pixel of meaningful content. It was madness. We traded the reliability of the server for the unpredictability of the client device. This approach might work for a dashboard behind a corporate firewall where you control the hardware, but on the open web, where users are on spotty 4G connections with five-year-old Android phones, it is a disaster.</p>\n\n<p>The solution isn't to retreat entirely to the server-rendered monoliths of the past, effectively returning to PHP 4 patterns with better syntax. The answer lies in hybridity. We need frameworks that allow us to choose the right rendering strategy for the specific piece of content we are serving. This is where the concept of composable architecture becomes more than just a buzzword. It is the practical application of using the right tool for the specific job, rather than trying to hammer a screw with a wrench. Modern meta-frameworks like Next.js or SvelteKit are finally giving us the controls to make these decisions granularly, page by page, or even component by component.</p>\n\n<h2>Server side rendering and the cost of freshness</h2>\n\n<p>Let’s talk about Server-Side Rendering (SSR) without the marketing fluff. SSR is expensive. Every time a user requests a page, your server has to wake up, fetch data from a database, template that data into HTML, and spit it out. That costs CPU cycles, and CPU cycles cost money. However, for dynamic content where freshness is non-negotiable—think stock tickers, user dashboards, or inventory levels—it is the only viable option. The benefit here is the Time to First Byte and First Contentful Paint. You are handing the browser a fully formed document. The user sees the content immediately, even if the JavaScript hasn't initialized yet to make the buttons clicky.</p>\n\n<p>The mistake I see junior architects make is defaulting to SSR for everything. There is absolutely no reason to render your \"About Us\" page or a blog post from three years ago on every single request. That content is dead. It is static. Rendering it dynamically is just burning money and adding latency. This is where we need to be cynical about our resource usage. If the data hasn't changed, the HTML shouldn't change. We should be caching aggressively, pushing computation to build time rather than request time whenever humanly possible.</p>\n\n<h2>Static generation and the edge</h2>\n\n<p>This brings us to Static Site Generation (SSG), which is really just a fancy way of saying \"caching HTML files.\" This is the most resilient way to build a website. If your database explodes, your API layer goes down, or your backend developers push a breaking change on a Friday afternoon, your static pages will keep serving. They are just files on a Content Delivery Network (CDN). They are immutable. They are incredibly fast because they are served from an edge node physically close to the user.</p>\n\n<p>The challenge has always been build times. If you have ten thousand pages, waiting for a rebuild every time you fix a typo is agonizing. This is where Incremental Static Regeneration (ISR) comes into play. It allows us to retain the benefits of static hosting while updating content in the background as traffic hits the page. It is a pragmatic compromise. You get the speed of static with the freshness of dynamic, assuming you can tolerate your content being stale for a few seconds. For 99% of use cases, that lag is irrelevant. If you aren't building high-frequency trading software, your users can wait sixty seconds to see the corrected spelling of a product description.</p>\n\n<h2>The hydration nightmare</h2>\n\n<p>We cannot discuss modern rendering without addressing the elephant in the room: hydration. This is the process where the client-side JavaScript takes over the HTML rendered by the server. It sounds seamless in theory, but in practice, it is often a source of tremendous frustration. You have likely experienced the \"uncanny valley\" of web loading, where a button appears on the screen but refuses to click because the main thread is locked up trying to hydrate the rest of the application. It feels broken. It creates rage clicks.</p>\n\n<p>Hydration mismatches are another joy of this architecture. If the server renders one thing (say, a timestamp based on the server's clock) and the client renders something else (based on the browser's clock), the framework panics. It throws out the server's work and re-renders from scratch, causing a layout shift that ruins the user experience and negates the performance benefits of SSR. To mitigate this, we have to be incredibly disciplined about component consistency. We need to ensure that our output is deterministic. We must avoid accessing browser-specific APIs like `window` or `localStorage` during that initial render pass. It requires a level of rigor that many teams simply fail to enforce.</p>\n\n<h2>Decoupling content from code</h2>\n\n<p>Beyond the rendering layer, the most significant shift in resilient architecture is the move toward Headless CMS solutions. I have spent enough time fighting with WordPress loops and Drupal views to know that tight coupling between your data and your presentation is a ticking time bomb. When your content lives inside your display logic, a redesign requires a migration. A simple reskin becomes a rewrite.</p>\n\n<p>By treating content purely as data—consumable via GraphQL or REST—we separate the concerns of the editorial team from the engineering team. The editors get a structured interface to input data, and we get a clean JSON object to do with as we please. This allows us to use that same content for the website, the mobile app, and whatever IoT toaster screen comes out next week. It forces us to think in terms of content models rather than page layouts. However, this only works if you model the content correctly. If you just give the marketing team a giant rich text field and let them paste HTML blobs, you have defeated the purpose. You have just built a headless mess.</p>\n\n<h2>The imperative of the pipeline</h2>\n\n<p>Finally, none of this matters if you cannot ship reliable code. The infrastructure that supports these complex architectures is just as critical as the code itself. I am talking about CI/CD pipelines that actually test things. In a composable world where your frontend is separate from your backend, which is separate from your content, integration testing is the only thing standing between you and a blank white screen.</p>\n\n<p>We need automated checks that verify the build, run linting rules to catch sloppy code, and perform end-to-end tests on critical user paths. If the build fails, the deploy stops. It is that simple. We cannot rely on manual QA to catch regression bugs in a distributed system. The complexity is too high. A robust pipeline gives you the confidence to deploy on a Tuesday morning without fearing that you have just taken down the checkout flow. It transforms deployment from a scary event into a boring, routine background process.</p>\n\n<p>Building for the web today is harder than it used to be, but it is also capable of much more. The key is to resist the urge to over-engineer. Use SSR where you need data, use SSG where you need speed, and treat your content like the valuable asset it is. Stop trying to impress other developers with your stack and start impressing users with how fast your site loads. For a related angle I keep coming back to, see <a href=\"/journal/how-this-site-is-built/\">How This Site Is Built (Reference Stack)</a>.</p>","tags":["Core Web Vitals","JavaScript Bundling Optimization","Server-Side Rendering SEO","Lighthouse Performance Audits","Headless CMS SEO"],"views":108}