<?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: Nicky Christensen</title>
    <description>The latest articles on DEV Community by Nicky Christensen (@nickycdk).</description>
    <link>https://dev.to/nickycdk</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%2F806146%2Fd80b4677-6736-4840-85bc-3276cd0c6f78.jpeg</url>
      <title>DEV Community: Nicky Christensen</title>
      <link>https://dev.to/nickycdk</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/nickycdk"/>
    <language>en</language>
    <item>
      <title>I Audited 50 Websites. Here's What Was Silently Broken</title>
      <dc:creator>Nicky Christensen</dc:creator>
      <pubDate>Sat, 04 Apr 2026 09:07:51 +0000</pubDate>
      <link>https://dev.to/nickycdk/i-audited-50-websites-heres-what-was-silently-broken-3mk7</link>
      <guid>https://dev.to/nickycdk/i-audited-50-websites-heres-what-was-silently-broken-3mk7</guid>
      <description>&lt;p&gt;I ran deep checks on 50 production sites. 23 had silent failures their uptime monitors missed. Here's every failure type, why it happens, and how to check yourself&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Expired or Misconfigured SSL Certificates (8 sites)
&lt;/h2&gt;

&lt;p&gt;The most common failure — and the most avoidable.&lt;/p&gt;

&lt;p&gt;Eight sites had SSL issues. Three had certificates that had expired within the last 30 days. Two had incomplete certificate chains (missing intermediate CA), which meant the site worked in Chrome on desktop but threw security warnings in Safari and on mobile devices. The remaining three had certificates that didn't match the domain — likely from a server migration or load balancer change where someone forgot to update the cert.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why uptime monitors miss this:&lt;/strong&gt; Most ping-based monitors hit the IP address or follow the first redirect. They don't validate the full certificate chain, check expiry, or verify that the certificate matches the domain. The server responds with 200, so the check passes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How common is this?&lt;/strong&gt; According to Keyfactor's 2024 PKI report, 88% of companies experienced an unplanned outage due to an expired certificate in the past two years. Microsoft Teams went down for three hours in 2020 because someone forgot to renew an auth certificate. Epic Games had a 5.5-hour outage from an expired wildcard cert.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How to check yourself:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Check certificate expiry date&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; | openssl s_client &lt;span class="nt"&gt;-servername&lt;/span&gt; yoursite.com &lt;span class="nt"&gt;-connect&lt;/span&gt; yoursite.com:443 2&amp;gt;/dev/null | openssl x509 &lt;span class="nt"&gt;-noout&lt;/span&gt; &lt;span class="nt"&gt;-dates&lt;/span&gt;

&lt;span class="c"&gt;# Check certificate chain completeness&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; | openssl s_client &lt;span class="nt"&gt;-servername&lt;/span&gt; yoursite.com &lt;span class="nt"&gt;-connect&lt;/span&gt; yoursite.com:443 2&amp;gt;/dev/null | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-E&lt;/span&gt; &lt;span class="s2"&gt;"verify return|depth"&lt;/span&gt;

&lt;span class="c"&gt;# Check if cert matches the domain&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; | openssl s_client &lt;span class="nt"&gt;-servername&lt;/span&gt; yoursite.com &lt;span class="nt"&gt;-connect&lt;/span&gt; yoursite.com:443 2&amp;gt;/dev/null | openssl x509 &lt;span class="nt"&gt;-noout&lt;/span&gt; &lt;span class="nt"&gt;-subject&lt;/span&gt; &lt;span class="nt"&gt;-issuer&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If &lt;code&gt;notAfter&lt;/code&gt; is in the past, your visitors are seeing browser warnings. If the chain verification fails, mobile users are getting blocked.&lt;/p&gt;




&lt;h2&gt;
  
  
  2. Stale CDN Content After Deploys (5 sites)
&lt;/h2&gt;

&lt;p&gt;Five sites served HTML or assets that were one or more deployments old. The page loaded. It looked fine to a quick glance. But it was yesterday's version — including a known bug that the team thought they'd already fixed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How it happens:&lt;/strong&gt; The origin server has the new content, but CDN edge nodes are serving cached versions. Cache invalidation either failed, wasn't triggered, or hasn't propagated to all edge locations. This is particularly common with Cloudflare, CloudFront, and Vercel's edge network when cache-control headers aren't set correctly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How nasty is it?&lt;/strong&gt; A 2023 Catchpoint study of 150+ major e-commerce sites found that over 70% of "mysterious" production bugs reported by users were actually stale or inconsistent cached content. The website was working — but the CDN was serving yesterday's reality. As recently as December 2025, a Shopify merchant reported their CDN was serving mismatched product images in search results for weeks.&lt;/p&gt;

&lt;p&gt;One of the sites I checked was serving HTML from 3 deploys ago to users in Europe, while US users saw the current version. The team had no idea because they were all based in the US.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How to check yourself:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Generate a SHA-256 fingerprint of your page content&lt;/span&gt;
curl &lt;span class="nt"&gt;-s&lt;/span&gt; https://yoursite.com | &lt;span class="nb"&gt;sha256sum&lt;/span&gt;

&lt;span class="c"&gt;# Compare with a different region (if you have a VPN)&lt;/span&gt;
&lt;span class="c"&gt;# Or run it again after a deploy — if the hash doesn't change,&lt;/span&gt;
&lt;span class="c"&gt;# your CDN is serving stale content&lt;/span&gt;

&lt;span class="c"&gt;# Check cache headers to see if CDN is even invalidating&lt;/span&gt;
curl &lt;span class="nt"&gt;-sI&lt;/span&gt; https://yoursite.com | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-iE&lt;/span&gt; &lt;span class="s2"&gt;"cache-control|x-cache|age|cf-cache"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the &lt;code&gt;age&lt;/code&gt; header shows a high number after a fresh deploy, or &lt;code&gt;x-cache&lt;/code&gt; says &lt;code&gt;HIT&lt;/code&gt; when you expected new content — your users aren't seeing what you shipped.&lt;/p&gt;




&lt;h2&gt;
  
  
  3. JavaScript Bundles That 404'd (4 sites)
&lt;/h2&gt;

&lt;p&gt;Four sites had their HTML load fine (200 OK), but the JavaScript files it referenced no longer existed on the server.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How it happens:&lt;/strong&gt; A deployment pushes new HTML that references &lt;code&gt;app.3f8a2c.js&lt;/code&gt;, but the CDN edge node still serves the old HTML pointing to &lt;code&gt;app.9d1b4e.js&lt;/code&gt; — which was deleted in the new release. This is the evil cousin of stale CDN content: the HTML is stale, but the assets it points to have been purged.&lt;/p&gt;

&lt;p&gt;The result: a blank white page. Or a page that looks half-loaded — the header renders from server-side HTML, but nothing interactive works because the client-side JavaScript never boots.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;This is extremely common with SPAs.&lt;/strong&gt; Netlify's support forums have hundreds of threads about it. AWS Amplify has a known issue where NextJS static pages stop working after deploy because JavaScript files return 404. It happens any time users have cached HTML from a previous deploy that references JS bundles that no longer exist.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How to check yourself:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Fetch the HTML and check every script source&lt;/span&gt;
curl &lt;span class="nt"&gt;-s&lt;/span&gt; https://yoursite.com | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-oP&lt;/span&gt; &lt;span class="s1"&gt;'src="[^"]*\.js"'&lt;/span&gt; | &lt;span class="k"&gt;while &lt;/span&gt;&lt;span class="nb"&gt;read&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; src&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
  &lt;/span&gt;&lt;span class="nv"&gt;url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$src&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-oP&lt;/span&gt; &lt;span class="s1"&gt;'"[^"]*"'&lt;/span&gt; | &lt;span class="nb"&gt;tr&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'"'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$url&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; http&lt;span class="k"&gt;*&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
    &lt;/span&gt;&lt;span class="nv"&gt;url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"https://yoursite.com&lt;/span&gt;&lt;span class="nv"&gt;$url&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
  &lt;span class="k"&gt;fi
  &lt;/span&gt;&lt;span class="nv"&gt;status&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;curl &lt;span class="nt"&gt;-o&lt;/span&gt; /dev/null &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="nt"&gt;-w&lt;/span&gt; &lt;span class="s2"&gt;"%{http_code}"&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$url&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
  &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$status&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$url&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="k"&gt;done&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If any of those return 404, your users are seeing a broken page while your uptime monitor shows green.&lt;/p&gt;




&lt;h2&gt;
  
  
  4. Redirect Chains and Loops (3 sites)
&lt;/h2&gt;

&lt;p&gt;Three sites had redirect chains — sequences of 301/302 redirects that either took too many hops or looped entirely.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The worst example:&lt;/strong&gt; A site redirected HTTP → HTTPS → www → non-www → HTTPS again, creating a loop. Every visitor hit this loop. The browser gives up after 20 redirects and shows &lt;code&gt;ERR_TOO_MANY_REDIRECTS&lt;/code&gt;. The uptime monitor? It only followed the first redirect, got a 301, and marked it as "up."&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How it happens:&lt;/strong&gt; Conflicting redirect rules between the web server (nginx/Apache), the CDN (Cloudflare page rules), and the application (.htaccess or middleware). Someone adds a "force HTTPS" rule in Cloudflare &lt;em&gt;and&lt;/em&gt; in nginx, or a "redirect to www" rule in the CDN that conflicts with a "redirect to non-www" rule in the application.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How to check yourself:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Follow all redirects and show the chain&lt;/span&gt;
curl &lt;span class="nt"&gt;-sIL&lt;/span&gt; https://yoursite.com 2&amp;gt;&amp;amp;1 | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-iE&lt;/span&gt; &lt;span class="s2"&gt;"^(HTTP/|location:)"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you see more than 2 redirects, something is misconfigured. If you see the same URL appear twice, you have a loop.&lt;/p&gt;




&lt;h2&gt;
  
  
  5. WordPress Plugin Conflicts / White Screen of Death (2 sites)
&lt;/h2&gt;

&lt;p&gt;Two WordPress sites rendered a completely blank page — the infamous White Screen of Death (WSOD). The server returned 200 OK with an empty HTML body. Both had recently updated plugins.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How common is this?&lt;/strong&gt; It's one of the most searched WordPress errors on the internet. It happens when a plugin update introduces a PHP fatal error, exceeds the server's memory limit, or conflicts with another plugin or the active theme. The server doesn't crash — PHP catches the fatal error and returns an empty response with a 200 status code.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The specific cases I found:&lt;/strong&gt; One site had updated a page builder plugin (Elementor) that conflicted with a custom theme. The other had a WooCommerce extension that exceeded the PHP memory limit after an update. Both sites had been showing a blank page for over 48 hours without the site owners knowing — because their uptime monitor said the server was responding fine.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How to check yourself:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Check if the page has any actual content&lt;/span&gt;
&lt;span class="nv"&gt;content_length&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;curl &lt;span class="nt"&gt;-s&lt;/span&gt; https://yoursite.com | &lt;span class="nb"&gt;wc&lt;/span&gt; &lt;span class="nt"&gt;-c&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Response body: &lt;/span&gt;&lt;span class="nv"&gt;$content_length&lt;/span&gt;&lt;span class="s2"&gt; bytes"&lt;/span&gt;
&lt;span class="c"&gt;# If this is under 500 bytes for a full page, something is very wrong&lt;/span&gt;

&lt;span class="c"&gt;# Check for PHP errors in the response headers&lt;/span&gt;
curl &lt;span class="nt"&gt;-sI&lt;/span&gt; https://yoursite.com | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-iE&lt;/span&gt; &lt;span class="s2"&gt;"x-php|x-powered|content-length"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  6. Mixed Content Blocking (1 site)
&lt;/h2&gt;

&lt;p&gt;One site served its main page over HTTPS but loaded images and a font file over HTTP. Modern browsers block mixed content silently — no error page, no console warning for the user. The images just don't load, and the font falls back to a system font.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How it happens:&lt;/strong&gt; Usually after an SSL migration. The site moves to HTTPS, but some hardcoded &lt;code&gt;http://&lt;/code&gt; references remain in the database (common in WordPress), in a template file, or in a third-party embed. It can also happen when a CDN or image hosting service changes its URL scheme.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How to check yourself:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Find HTTP resources on an HTTPS page&lt;/span&gt;
curl &lt;span class="nt"&gt;-s&lt;/span&gt; https://yoursite.com | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-oP&lt;/span&gt; &lt;span class="s1"&gt;'(src|href)="http://[^"]*"'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If that returns anything, those resources are being blocked by the browser and your visitors aren't seeing them.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Pattern
&lt;/h2&gt;

&lt;p&gt;Here's what all 23 failures had in common:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The server was up. The HTTP status code was 200. The uptime monitor said green.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Traditional uptime monitoring checks one thing: did the server respond? That's a useful signal — but it's the &lt;em&gt;minimum&lt;/em&gt; signal. It tells you the infrastructure is alive. It tells you nothing about whether the &lt;em&gt;application&lt;/em&gt; works.&lt;/p&gt;

&lt;p&gt;And the numbers back this up. 85% of website bugs are first detected by users, not by monitoring tools. Not because monitoring doesn't exist — but because it's checking the wrong thing.&lt;/p&gt;

&lt;p&gt;The gap between "server responds" and "site works for users" is where all 23 of these failures lived. And it's exactly the gap that most teams don't monitor.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Real Monitoring Looks Like
&lt;/h2&gt;

&lt;p&gt;After running this audit, the checks that actually caught problems were:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;SSL certificate validation&lt;/strong&gt; — Is the cert valid, unexpired, chain complete, and matching the domain? Not just "does the connection work."&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Asset integrity checks&lt;/strong&gt; — Does every script and stylesheet referenced in the HTML actually load with the correct status code?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Content fingerprinting&lt;/strong&gt; — Is the content what you expect, or is the CDN serving a stale version? A SHA-256 hash of the response body catches silent content drift.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Redirect chain resolution&lt;/strong&gt; — Does the URL resolve cleanly in ≤2 hops, or does it loop?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Response body validation&lt;/strong&gt; — Is the page actually rendering content, or is it a 200 OK with an empty body?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Multi-region checks&lt;/strong&gt; — A site can be broken in Frankfurt but fine in Virginia. Single-location checks miss regional CDN failures entirely.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is what I built &lt;a href="https://getsitewatch.com?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=audited-50-websites" rel="noopener noreferrer"&gt;Sitewatch&lt;/a&gt; to do — run all of these checks continuously, from multiple regions, and alert when something breaks at the &lt;em&gt;application layer&lt;/em&gt;, not just the infrastructure layer. Free for 1 site, no credit card.&lt;/p&gt;




&lt;h2&gt;
  
  
  Quick Audit Checklist
&lt;/h2&gt;

&lt;p&gt;You don't need a tool to start. Run these against any production site right now:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Check SSL certificate expiry and chain with &lt;code&gt;openssl s_client&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Verify every &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;link&amp;gt;&lt;/code&gt; resource returns 200&lt;/li&gt;
&lt;li&gt;Follow the full redirect chain with &lt;code&gt;curl -sIL&lt;/code&gt; — max 2 hops, no loops&lt;/li&gt;
&lt;li&gt;Hash the response body with &lt;code&gt;sha256sum&lt;/code&gt; before and after a deploy&lt;/li&gt;
&lt;li&gt;Check response body size — under 500 bytes means something is wrong&lt;/li&gt;
&lt;li&gt;Repeat from a different geographic location&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If any check fails — you just found a bug your uptime monitor has been ignoring.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Have you found similar silent failures in production? Drop a comment — I'm collecting these for a follow-up post.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>monitoring</category>
      <category>devops</category>
      <category>startup</category>
    </item>
    <item>
      <title>My Claude Code Setup: Skills, Agents, and the Config File That Changed Everything</title>
      <dc:creator>Nicky Christensen</dc:creator>
      <pubDate>Sat, 28 Mar 2026 18:43:36 +0000</pubDate>
      <link>https://dev.to/nickycdk/my-claude-code-setup-skills-agents-and-the-config-file-that-changed-everything-1lek</link>
      <guid>https://dev.to/nickycdk/my-claude-code-setup-skills-agents-and-the-config-file-that-changed-everything-1lek</guid>
      <description>&lt;h2&gt;
  
  
  CLAUDE.md — The Non-Negotiable
&lt;/h2&gt;

&lt;p&gt;A &lt;code&gt;CLAUDE.md&lt;/code&gt; file in your project root. Claude Code reads it at the start of every session. It's onboarding docs for your AI pair programmer.&lt;/p&gt;

&lt;p&gt;What goes in it: your stack (specific versions, not just "Vue"), file structure, naming conventions, component patterns, error handling approach, available commands.&lt;/p&gt;

&lt;p&gt;Without it, Claude guesses. With it, Claude follows &lt;em&gt;your&lt;/em&gt; architecture.&lt;/p&gt;

&lt;p&gt;Keep it under 200 lines. Move detailed docs to separate files and reference them with &lt;code&gt;@filename&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If you do one thing from this post, create this file. 30 minutes of work. Hours saved per session.&lt;/p&gt;




&lt;h2&gt;
  
  
  Skills — Load Expertise, Not Context
&lt;/h2&gt;

&lt;p&gt;Skills live in &lt;code&gt;.claude/skills/&lt;/code&gt;. They're markdown files that give Claude specialized knowledge for specific tasks — but only when relevant.&lt;/p&gt;

&lt;p&gt;The difference from CLAUDE.md: CLAUDE.md loads every session. Skills load on demand. You don't bloat your context with PDF generation instructions when you're writing API routes.&lt;/p&gt;

&lt;p&gt;The real power: &lt;strong&gt;write skills for your own domain.&lt;/strong&gt; I wrote one for my product's detection rule format. The exact structure, fields, validation patterns, naming conventions. Now every new rule comes out perfectly structured. No re-explaining. No drift.&lt;/p&gt;

&lt;p&gt;Community skills and plugins exist too. The ecosystem is growing fast.&lt;/p&gt;




&lt;h2&gt;
  
  
  Subagents — Parallel Work
&lt;/h2&gt;

&lt;p&gt;Claude Code can spawn subagents — independent processes with their own context and tools.&lt;/p&gt;

&lt;p&gt;Building a feature but also need to refactor tests? Kick off a subagent for the tests. It works in a git worktree (isolated copy of your repo), so zero conflict risk. You keep working on the feature.&lt;/p&gt;

&lt;p&gt;I use them for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Parallel code reviews&lt;/li&gt;
&lt;li&gt;Running test suites while developing&lt;/li&gt;
&lt;li&gt;Research tasks that need deep exploration&lt;/li&gt;
&lt;li&gt;Verification passes on generated code&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Subagents access skills too. So a subagent loads domain knowledge, does its work, returns results. You're orchestrating a team, not managing a chatbot.&lt;/p&gt;




&lt;h2&gt;
  
  
  Plan Mode — Think Before You Generate
&lt;/h2&gt;

&lt;p&gt;Start in plan mode for anything non-trivial. Describe what you need. Let Claude explore the codebase, identify touch points, produce a plan. Review the plan. &lt;em&gt;Then&lt;/em&gt; switch to implementation.&lt;/p&gt;

&lt;p&gt;This prevents the most expensive failure mode: generating code that solves the wrong problem. Planning costs minutes. Rewriting costs hours.&lt;/p&gt;

&lt;p&gt;I document the plan in a separate file that Claude references during implementation. Every prompt becomes a step against a plan, not an open-ended request.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Setup in Practice
&lt;/h2&gt;

&lt;p&gt;Here's what this looks like end-to-end:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;CLAUDE.md&lt;/strong&gt; tells Claude my stack, conventions, patterns&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Plan mode&lt;/strong&gt; produces a reviewed implementation plan&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Skills&lt;/strong&gt; load domain-specific knowledge for the task&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Focused prompts&lt;/strong&gt; implement one step at a time against the plan&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Subagents&lt;/strong&gt; handle parallel work without context switching&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Each piece is useful alone. Together they compound. Claude Code goes from "generates code" to "follows my development process."&lt;/p&gt;




&lt;h2&gt;
  
  
  What I Shipped With This
&lt;/h2&gt;

&lt;p&gt;I built &lt;a href="https://getsitewatch.com" rel="noopener noreferrer"&gt;Sitewatch&lt;/a&gt; with this exact workflow — a monitoring platform that detects when websites return &lt;code&gt;200 OK&lt;/code&gt; but are actually broken for users. Broken JS bundles after deploys, MIME type mismatches, stale CDN content, redirect loops. The failures uptime tools miss.&lt;/p&gt;

&lt;p&gt;Claude Code wrote ~60-70% of the codebase. The detection logic — the brain of the product — came from me. The setup above is how I maintained quality while moving at that speed.&lt;/p&gt;

&lt;p&gt;Free tier for 1 site if you want to try it: &lt;a href="https://getsitewatch.com" rel="noopener noreferrer"&gt;getsitewatch.com&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;p&gt;Stop prompting harder. Start setting up better.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create a &lt;code&gt;CLAUDE.md&lt;/code&gt; — today&lt;/li&gt;
&lt;li&gt;Write a skill for your most common task&lt;/li&gt;
&lt;li&gt;Make a slash command for your most repeated workflow&lt;/li&gt;
&lt;li&gt;Use plan mode for anything bigger than a single file&lt;/li&gt;
&lt;li&gt;Use subagents when tasks can run in parallel&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The developers getting the most out of Claude Code aren't the best prompters. They're the ones with the best setup.&lt;/p&gt;

&lt;p&gt;That about wraps it up!&lt;/p&gt;

</description>
    </item>
    <item>
      <title>AI Wrote 70% of My Production Codebase. Here's Why That Actually Worked.</title>
      <dc:creator>Nicky Christensen</dc:creator>
      <pubDate>Fri, 27 Mar 2026 11:44:50 +0000</pubDate>
      <link>https://dev.to/nickycdk/ai-wrote-70-of-my-production-codebase-heres-why-that-actually-worked-2bmd</link>
      <guid>https://dev.to/nickycdk/ai-wrote-70-of-my-production-codebase-heres-why-that-actually-worked-2bmd</guid>
      <description>&lt;p&gt;I used Claude Code to build &lt;a href="https://getsitewatch.com" rel="noopener noreferrer"&gt;Sitewatch&lt;/a&gt; — a monitoring platform that catches when websites return &lt;code&gt;200 OK&lt;/code&gt; but are actually broken. Not a side project. A real SaaS, in production, with paying users.&lt;/p&gt;

&lt;p&gt;AI wrote roughly 60-70% of the codebase. Here are the things I wish someone had told me before I started.&lt;/p&gt;




&lt;h2&gt;
  
  
  1. Planning matters more than prompting
&lt;/h2&gt;

&lt;p&gt;This is the single biggest lesson and the one I almost learned too late.&lt;/p&gt;

&lt;p&gt;Early on, I'd open Claude Code and start prompting. "Build the check scheduling system." "Add retry logic." "Create the alerting pipeline." And it would. Working code, every time. The problem showed up three weeks in — I had a codebase full of features that each worked individually but didn't fit together. Different error handling patterns. Inconsistent data models. State flowing in three different directions.&lt;/p&gt;

&lt;p&gt;I had to stop and rewrite the architecture. That cost me more time than if I'd planned it from the start.&lt;/p&gt;

&lt;p&gt;Now my workflow is: plan first, prompt second. I think through data models, module boundaries, API surfaces, and error conventions &lt;em&gt;before&lt;/em&gt; Claude Code writes anything. I write it down as a spec. Then I hand it pieces of the spec, one at a time.&lt;/p&gt;

&lt;p&gt;The difference is enormous. Same tool, completely different outcomes.&lt;/p&gt;




&lt;h2&gt;
  
  
  2. The first 80% takes minutes. The last 20% takes your brain.
&lt;/h2&gt;

&lt;p&gt;This is the productivity pattern nobody warns you about.&lt;/p&gt;

&lt;p&gt;I'd describe a feature — "add multi-region check support with independent retry confirmation per region" — and Claude Code would produce a working implementation in minutes. Maybe 80% done. The remaining 20% — edge cases, failure modes, integration with existing code, the weird thing that happens when two regions disagree — that still required my experience.&lt;/p&gt;

&lt;p&gt;That 80/20 split is incredibly valuable. But you have to know it's coming. If you assume the first output is done, you'll ship bugs.&lt;/p&gt;




&lt;h2&gt;
  
  
  3. Establish your patterns early — then Claude Code follows them
&lt;/h2&gt;

&lt;p&gt;Once I had a consistent way of structuring API handlers, formatting errors, writing composables, and handling state — Claude Code replicated those patterns reliably. It picks up conventions from your codebase and follows them.&lt;/p&gt;

&lt;p&gt;But it has to &lt;em&gt;see&lt;/em&gt; them first. If your first few files are inconsistent, Claude Code will be too. Build the first few things yourself with intentional patterns. Let the AI learn from your codebase. Then it scales those patterns across everything else.&lt;/p&gt;

&lt;p&gt;This is the secret to a Claude Code codebase that feels coherent instead of stitched together.&lt;/p&gt;




&lt;h2&gt;
  
  
  4. Domain expertise can't be delegated
&lt;/h2&gt;

&lt;p&gt;Sitewatch needs to understand HTTP at a level most developers never think about. How CDNs rewrite MIME types. Why a &lt;code&gt;200 OK&lt;/code&gt; can mean "your site is completely broken." When a redirect chain is looping only for specific cookie states. Why the same page can return different content from different edge locations.&lt;/p&gt;

&lt;p&gt;Claude Code could write the plumbing around all of this. But the actual detection rules — the logic that makes the product valuable — came from my head. That's not a limitation of the tool. That's the nature of domain expertise. AI handles the &lt;em&gt;how&lt;/em&gt;. You provide the &lt;em&gt;what&lt;/em&gt; and &lt;em&gt;why&lt;/em&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  5. Test generation is the most underrated feature
&lt;/h2&gt;

&lt;p&gt;Everyone talks about Claude Code writing features. Nobody talks about how good it is at writing tests.&lt;/p&gt;

&lt;p&gt;I'd point it at existing code and say "write comprehensive tests for this module, including edge cases." And it would generate tests I hadn't thought of. Race conditions I'd missed. Boundary values I'd overlooked. Error paths I'd assumed were unreachable.&lt;/p&gt;

&lt;p&gt;For a solo builder who knows they should test more but never has time — this was the single biggest quality improvement.&lt;/p&gt;




&lt;h2&gt;
  
  
  6. Review intensity should scale with stakes
&lt;/h2&gt;

&lt;p&gt;I don't hold Claude Code back from anything. It handles more than you'd expect, including complex logic. But my review process isn't uniform.&lt;/p&gt;

&lt;p&gt;Boilerplate scaffolding? Quick scan. Database migrations? Check the schema. API route for a new feature? Read it carefully. Core detection logic that determines whether a site is flagged as broken? Line by line, every time.&lt;/p&gt;

&lt;p&gt;The tool is good enough for everything. Your review discipline needs to match the risk.&lt;/p&gt;




&lt;h2&gt;
  
  
  7. Shipping faster means you need to verify faster
&lt;/h2&gt;

&lt;p&gt;This one surprised me.&lt;/p&gt;

&lt;p&gt;When you build with Claude Code, your development speed increases dramatically. Features that would have taken a week take days. But your production failure rate doesn't change — you're still deploying to the same CDNs, the same edge networks, the same infrastructure that's always been unpredictable.&lt;/p&gt;

&lt;p&gt;So you ship more code, more often, to the same fragile production environment. Without better production verification, you're just creating more opportunities for things to break silently.&lt;/p&gt;

&lt;p&gt;This is actually what motivated me to build Sitewatch in the first place. The faster I shipped, the more I needed to know — immediately — when something broke. Not "the server returned 200." Whether the site &lt;em&gt;actually works&lt;/em&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  What I built with it
&lt;/h2&gt;

&lt;p&gt;Since the whole article is about building Sitewatch with Claude Code — here's what it actually does.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://getsitewatch.com" rel="noopener noreferrer"&gt;Sitewatch&lt;/a&gt; detects when your website returns &lt;code&gt;200 OK&lt;/code&gt; but is functionally broken. The kind of failures that traditional uptime monitors completely miss:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Your deploy goes through but your CDN serves stale HTML referencing deleted JavaScript bundles — blank page, green dashboard&lt;/li&gt;
&lt;li&gt;Your JS file gets served with &lt;code&gt;Content-Type: text/html&lt;/code&gt; and the browser silently blocks it — app looks loaded, nothing works&lt;/li&gt;
&lt;li&gt;A redirect loop kills the page but monitoring only sees the first &lt;code&gt;301&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Your CDN returns a branded error page with &lt;code&gt;200 OK&lt;/code&gt; instead of your actual content&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;What Sitewatch does:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Verifies that assets your HTML references load with correct status and MIME type&lt;/li&gt;
&lt;li&gt;Follows redirect chains to completion&lt;/li&gt;
&lt;li&gt;Fingerprints content to detect silent changes&lt;/li&gt;
&lt;li&gt;Checks from multiple regions to catch CDN edge divergence&lt;/li&gt;
&lt;li&gt;Classifies root cause with stack-specific fix guidance&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;For developers:&lt;/strong&gt; catches the deploy failures your uptime tool misses. Free tier, one site, 30 seconds to set up.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;For agencies&lt;/strong&gt; managing 25-100+ client sites: continuous verification across all sites, multiple regions, root cause classification. Stop finding out from client emails.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pricing:&lt;/strong&gt; Free (1 site) · $9/mo (25 sites) · $19/mo (100 sites)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://getsitewatch.com" rel="noopener noreferrer"&gt;Give it a try →&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;That about wraps it up! If you found this useful, leave a comment or connect with me on &lt;a href="https://twitter.com/nickycdk" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt; | &lt;a href="https://www.linkedin.com/in/dknickychristensen" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt; or visit my &lt;a href="https://nickychristensen.dk" rel="noopener noreferrer"&gt;website&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>claudecode</category>
      <category>webdev</category>
      <category>javascript</category>
    </item>
    <item>
      <title>[Boost]</title>
      <dc:creator>Nicky Christensen</dc:creator>
      <pubDate>Fri, 27 Mar 2026 09:03:07 +0000</pubDate>
      <link>https://dev.to/nickycdk/-4m38</link>
      <guid>https://dev.to/nickycdk/-4m38</guid>
      <description>&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/sitewatch/your-ci-is-green-your-site-might-not-be-1gng" class="crayons-story__hidden-navigation-link"&gt;Your CI Is Green. Your Site Might Not Be.&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/sitewatch" class="crayons-avatar  crayons-avatar--l  "&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%2Fuser%2Fprofile_image%2F3844486%2F90af6851-c32d-48f6-a35b-3f4475706a06.png" alt="sitewatch profile" class="crayons-avatar__image"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/sitewatch" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Sitewatch
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Sitewatch
                
              
              &lt;div id="story-author-preview-content-3413461" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/sitewatch" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&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%2Fuser%2Fprofile_image%2F3844486%2F90af6851-c32d-48f6-a35b-3f4475706a06.png" class="crayons-avatar__image" alt=""&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Sitewatch&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/sitewatch/your-ci-is-green-your-site-might-not-be-1gng" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Mar 27&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/sitewatch/your-ci-is-green-your-site-might-not-be-1gng" id="article-link-3413461"&gt;
          Your CI Is Green. Your Site Might Not Be.
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/webdev"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;webdev&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/devops"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;devops&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/monitoring"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;monitoring&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/startup"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;startup&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/sitewatch/your-ci-is-green-your-site-might-not-be-1gng" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/exploding-head-daceb38d627e6ae9b730f36a1e390fca556a4289d5a41abb2c35068ad3e2c4b5.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/multi-unicorn-b44d6f8c23cdd00964192bedc38af3e82463978aa611b4365bd33a0f1f4f3e97.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;11&lt;span class="hidden s:inline"&gt; reactions&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/sitewatch/your-ci-is-green-your-site-might-not-be-1gng#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              Comments


              &lt;span class="hidden s:inline"&gt;Add Comment&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            6 min read
          &lt;/small&gt;
            
              &lt;span class="bm-initial"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success"&gt;
                

              &lt;/span&gt;
            
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


</description>
      <category>webdev</category>
      <category>devops</category>
      <category>monitoring</category>
      <category>startup</category>
    </item>
    <item>
      <title>I Built a Monitoring Tool Because Uptime Checks Kept Lying to Me</title>
      <dc:creator>Nicky Christensen</dc:creator>
      <pubDate>Thu, 26 Mar 2026 14:18:02 +0000</pubDate>
      <link>https://dev.to/nickycdk/i-built-a-monitoring-tool-because-uptime-checks-kept-lying-to-me-35mf</link>
      <guid>https://dev.to/nickycdk/i-built-a-monitoring-tool-because-uptime-checks-kept-lying-to-me-35mf</guid>
      <description>&lt;p&gt;If you deploy sites to Netlify, Vercel, Cloudflare Pages or pretty much any modern platform — you've probably set up some kind of uptime monitoring. Ping every minute, get an alert if the server doesn't respond. Pretty standard stuff.&lt;/p&gt;

&lt;p&gt;I had the same setup across all my sites. And for a long time, I thought I was covered.&lt;/p&gt;

&lt;p&gt;I wasn't.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem
&lt;/h2&gt;

&lt;p&gt;A few months back I pushed an update to one of my Nuxt apps on Netlify. Build passed, deploy preview looked fine, dashboard showed green. I moved on.&lt;/p&gt;

&lt;p&gt;Turns out the site was broken for hours. Not &lt;em&gt;down&lt;/em&gt; — the server was responding just fine. &lt;code&gt;200 OK&lt;/code&gt; on every request. But the JavaScript bundle the page needed wasn't loading, so the entire app was a blank page.&lt;/p&gt;

&lt;p&gt;Here's what happened: the new deploy generated fresh hashed bundles. &lt;code&gt;main.c8d13.js&lt;/code&gt; replaced &lt;code&gt;main.a4f2c.js&lt;/code&gt;. But some CDN edge nodes were still serving the old HTML, which referenced the old filename. Browser tries to fetch &lt;code&gt;main.a4f2c.js&lt;/code&gt;, gets a &lt;code&gt;404&lt;/code&gt;, and nothing renders.&lt;/p&gt;

&lt;p&gt;My uptime monitor? Green the entire time. Because the HTML document loaded. &lt;code&gt;200 OK&lt;/code&gt;. Job done, as far as it was concerned.&lt;/p&gt;

&lt;h2&gt;
  
  
  It Keeps Happening
&lt;/h2&gt;

&lt;p&gt;Once I started paying attention, I found this happens a lot more than you'd expect:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;MIME type mismatches&lt;/strong&gt; — Your JS file gets served as &lt;code&gt;text/html&lt;/code&gt; by the CDN. Browser silently refuses to execute it. No console error you'd notice unless you're specifically looking. I had this on one of my sites behind Cloudflare for &lt;em&gt;days&lt;/em&gt; without knowing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Redirect chains that loop&lt;/strong&gt; — CDN redirect + origin redirect + app redirect that conflict with each other. Browser hits the hop limit and gives up. Uptime tool sees the first &lt;code&gt;301&lt;/code&gt; and moves on.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;DNS still pointing at old infrastructure&lt;/strong&gt; — After a migration, a subdomain resolves to the old origin. It responds with stale content from months ago. Technically "up." Practically useless.&lt;/p&gt;

&lt;p&gt;All return &lt;code&gt;200&lt;/code&gt;. All invisible to standard monitoring.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why I Built Sitewatch
&lt;/h2&gt;

&lt;p&gt;I looked around for tools that caught this stuff. Most uptime monitors check if the server responds — and that's it. Some offer headless browser checks with Puppeteer, but they're slow, expensive, and fragile at any real scale. Not great when you're watching a bunch of sites.&lt;/p&gt;

&lt;p&gt;What I needed was something in between. Goes deeper than a status code check, doesn't require a full browser session. Catches the broken deploy, the MIME type issue, the redirect loop — automatically.&lt;/p&gt;

&lt;p&gt;So I built &lt;a href="https://getsitewatch.com" rel="noopener noreferrer"&gt;Sitewatch&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What It Does
&lt;/h2&gt;

&lt;p&gt;Instead of just checking if your server responds, Sitewatch verifies whether your site actually &lt;em&gt;works&lt;/em&gt;:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Asset verification&lt;/strong&gt; — It fetches your page, parses the HTML, finds your JS and CSS bundle references, and checks each one. Correct status code? Correct MIME type? Actually loadable? If your HTML references a script that 404s or gets served as &lt;code&gt;text/html&lt;/code&gt;, you get alerted.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Full redirect chain resolution&lt;/strong&gt; — Follows redirects all the way to the final destination. Catches loops, unexpected landings, and chains that time out.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Content fingerprinting&lt;/strong&gt; — Generates hashes of your page content and tracks them over time. If your homepage suddenly returns completely different content (stale cache, CDN error page that returns &lt;code&gt;200&lt;/code&gt;), the fingerprint shift triggers an alert.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Multi-region checks&lt;/strong&gt; — CDN failures are often edge-specific. Your site works from Europe but serves broken assets in Asia. Sitewatch checks from multiple locations.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Confirmation before alerting&lt;/strong&gt; — Uses a retry model before firing alerts. No 3am wake-ups because of a transient CDN blip.&lt;/p&gt;

&lt;p&gt;It also classifies the &lt;em&gt;root cause&lt;/em&gt; — infrastructure, deploy artifact, DNS, CDN config — so you know where to look instead of just knowing "something broke."&lt;/p&gt;

&lt;h2&gt;
  
  
  Some Technical Decisions
&lt;/h2&gt;

&lt;p&gt;A few choices that might be relevant if you've thought about building something similar:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;No headless browser.&lt;/strong&gt; It's tempting because it's "real" rendering, but it doesn't scale well. Sitewatch parses HTML and makes targeted follow-up requests for critical assets. Gets you the meaningful signal without the overhead.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Stack detection.&lt;/strong&gt; Different frameworks break differently. A Nuxt app has different failure patterns than a WordPress site or a Rails app behind Nginx. Sitewatch detects the tech stack from response headers and adjusts what it checks for.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Alert deduplication.&lt;/strong&gt; If the same issue persists across checks, you don't want repeated alerts. Content fingerprints with a cooldown window — you get notified when something breaks and again when it's resolved, not every 5 minutes in between.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try It
&lt;/h2&gt;

&lt;p&gt;If you're running sites on modern deployment platforms — especially if you're managing multiple — this is a blind spot worth covering.&lt;/p&gt;

&lt;p&gt;There's a free tier for one site. Takes about 30 seconds to set up: &lt;a href="https://getsitewatch.com" rel="noopener noreferrer"&gt;getsitewatch.com&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;That about wraps it up! If you found this useful, I'd love to know — leave a comment or connect with me on &lt;a href="https://twitter.com/nickycdk" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt; | &lt;a href="https://www.linkedin.com/in/dknickychristensen" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt; or visit my &lt;a href="https://nickychristensen.dk" rel="noopener noreferrer"&gt;website&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>frontend</category>
      <category>javascript</category>
      <category>webdev</category>
      <category>startup</category>
    </item>
    <item>
      <title>7 Habits Of Highly Effective Developers</title>
      <dc:creator>Nicky Christensen</dc:creator>
      <pubDate>Sun, 20 Feb 2022 13:51:11 +0000</pubDate>
      <link>https://dev.to/nickycdk/7-habits-of-highly-effective-developers-267m</link>
      <guid>https://dev.to/nickycdk/7-habits-of-highly-effective-developers-267m</guid>
      <description>&lt;p&gt;Practical advice for becoming more effective and productive&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%2F0mlreqcpjcgwxc9epayk.jpeg" 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%2F0mlreqcpjcgwxc9epayk.jpeg" alt=" " width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Have you ever heard of the book called The 7 Habits of Highly Effective People? It's a book written by Stephen Covey which is about productivity and bettering yourself. You learn more about some key core set of values and ideas that you can develop to help solve personal and professional problems with an integrated and principle-centered approach. &lt;/p&gt;

&lt;p&gt;If you haven't already read this book, I urge you to do so.&lt;/p&gt;

&lt;p&gt;I believe all people can benefit from having positive habits, though today I will try and focus on why you as a developer can benefit from positive habits that enable you to be more effective as a developer and a human being.&lt;/p&gt;

&lt;p&gt;I've been in the tech industry for around 15 years, and I know there's a lot of opinions on what makes a good developer.&lt;br&gt;
This article isn't so much about being a good or great developer, but more about how to be an effective developer, how to get most of the day so you can become the best version of yourself and get more shit done!&lt;/p&gt;

&lt;p&gt;Throughout my years in the industry, I've picked up a few things around what is making great developers highly effective.&lt;/p&gt;

&lt;p&gt;Let's take a look at the habits.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Learn new things
&lt;/h2&gt;

&lt;p&gt;To become a great and effective developer, you need to have a focus on always developing your own skillset. If you procrastinate, you will never become effective, nor great for that matter. Effective developers find solutions to problems with knowledge. Knowledge comes from experience and learning things, therefore, it's essential to keep your mind open for learning new things continuously.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Have a focus on being healthy
&lt;/h2&gt;

&lt;p&gt;I'm a big fan of this habit. A good and healthy lifestyle will provide you with a much clearer mind and a lot more energy in you every day.&lt;/p&gt;

&lt;p&gt;Studies show that living an unhealthy lifestyle where eating healthy and exercising is NOT a part of life, people are likely to be more prone to heart failures, vulnerable to obesity, suffer from tiredness, have a harder ability to absorb information, and are generally in the higher risk of getting sick.&lt;/p&gt;

&lt;p&gt;Taking good care of body and mind with a healthy lifestyle will make you more effective and productive not only as a developer but as a human being in general.&lt;br&gt;
Go for a run, go for a swim, take a trip down to the fitness club, think about what you eat. If you are not used to doing exercise, it might be hard in the beginning, but in the long run, you'll love it.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Has a focus on value, not problems
&lt;/h2&gt;

&lt;p&gt;Effective developers focus on value, rather than on problems. There will always be bugs, issues, etc, but having the ability to and habit in trying to identify the things that bring the most value for the end-user will help you in being more effective. You might not be the most effective in the type of solving the most bugs, but the ones solved, are the bugs that bring the most value to the end-user, which will end the end be perceived as being most effective.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Take this for example:&lt;/strong&gt;&lt;br&gt;
A Customer wants a notification whenever the battery is drained. Why?&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%2Fu2ndb0buvin2jzf7xuj2.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%2Fu2ndb0buvin2jzf7xuj2.png" alt=" " width="800" height="519"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Solution: Notification service that can help prevent running out of battery&lt;/p&gt;

&lt;p&gt;A good exercise for getting better at this is trying to make use of the 5 whys and incorporate this in your day-to-day. Learn more about the 5 whys here and here.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Don't over-engineer
&lt;/h2&gt;

&lt;p&gt;Effective developers and people know when to apply which methodology to X problem. They always try to simplify things to be as understandable as possible and don't end up over-engineering a solution.&lt;/p&gt;

&lt;p&gt;Good and effective projects are the ones with simplified implementations, easy to maintain, easy to understand.&lt;br&gt;
A complex design that is over-engineered is very likely to lead to difficulties in implementing new functionalities. It makes maintenance a nightmare and turns seemingly simple code into a sh*tshow of complexity.&lt;/p&gt;

&lt;p&gt;To overcome this, try not to write unnecessary code and always try looking for simple and elegant solutions. It will make you more effective and productive.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Involve yourself with smart people.
&lt;/h3&gt;

&lt;p&gt;This habit is definitely not only limited to developers, but all effective people in general. If you want to be effective and great, you need to involve yourself around smart people. Look around the room you're in right now. Do you suspect you're the smartest person in it? If so, go find a different room. It will change your life.&lt;/p&gt;

&lt;p&gt;Involving yourself around smart people will make you smarter. They make you better. They spark interest and introduce you to new concepts, ideas, culture, people, and much more. In short, they know where the good stuff is or how to help find it.&lt;br&gt;
If you don't know where to start on this, I recommend you read this article from Leonard Kim: &lt;a href="https://medium.com/the-mission/how-do-i-surround-myself-with-people-who-are-smarter-than-me-d26f9f25d12d" rel="noopener noreferrer"&gt;https://medium.com/the-mission/how-do-i-surround-myself-with-people-who-are-smarter-than-me-d26f9f25d12d&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Be proactive
&lt;/h2&gt;

&lt;p&gt;Effective developers always try to be proactive. A good idea is trying to be better at focusing on what is in your control, rather than what you can't control. Taking a proactive approach to things, and making other people aware. Put in an effort and use the necessary energy at becoming better at this.&lt;/p&gt;

&lt;p&gt;An example of being proactive could be the following: Be Responsible for Great Requirements - Don't blame others for poor requirements. Instead, work with the team to fully analyze the requirements to ensure they are complete, accurate, and meet the needs of the customer. Take the responsibility it requires you to do, and help others. If you do this, you and the people around you will become more efficient.&lt;/p&gt;

&lt;h2&gt;
  
  
  7. Prioritizing the work
&lt;/h2&gt;

&lt;p&gt;Prioritizing work &amp;amp; work effort is critical. You must prioritize the work that gives high business value. That is the ideal situation, right? Effective people are good at this, knowing which features give the highest business value, but can be done with low/minimal efforts (Time vs Business value)&lt;br&gt;
You must apply effort to the most important things first, followed by less important things. For example, everyone will generally agree that creating reusable and easily maintainable code is important. &lt;/p&gt;

&lt;p&gt;However, in an effort to do this, developers have a tendency to "gold plate/over-engineer". "Gold plating or over-engineering" is when a developer adds bells and whistles to the feature that were not asked for and can easily increase the complexity and estimated hours needed to deliver the work. Be very careful with this. This does not add that necessary value vs the time spent.&lt;/p&gt;

&lt;p&gt;Was it a good investment doing the bells and whistles then? Probably not. You need to become good a prioritizing work, and also know the concept of business value vs time spent.&lt;/p&gt;




&lt;p&gt;Having good habits in your every day can be very powerful. It will benefit not only you but everyone around you. I truly believe that incorporating good habits will make you more effective. It will help you excel as a person and a developer.&lt;br&gt;
As Stephen Covey says in his book:&lt;/p&gt;

&lt;p&gt;"I am not a product of my circumstances. I am a&lt;br&gt;
product of my decisions."&lt;/p&gt;

&lt;p&gt;Start today, Try challenging yourself as of today, start practicing these habits. It will be hard, but worth it. I am sure of it. &lt;br&gt;
Check back in a year, and see for yourself how much development you have made as a person.&lt;/p&gt;

&lt;p&gt;I would love to hear your thoughts and if you have any valuable habits that make you feel like an effective developer? Share your comment in the section below. If you like this article do pass it forward and share it with your friends and peers.&lt;/p&gt;

&lt;p&gt;Thanks for reading and I hope you liked the article.&lt;/p&gt;

&lt;p&gt;If you’d like to catch up with me sometime, follow me on &lt;a href="https://nickychristensen.medium.com/" rel="noopener noreferrer"&gt;Medium&lt;/a&gt; | &lt;a href="https://twitter.com/nickycdk" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt; | &lt;a href="https://www.linkedin.com/in/dknickychristensen/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt; or simply visit my &lt;a href="https://nickychristensen.dk" rel="noopener noreferrer"&gt;website&lt;/a&gt; (That is in Danish)&lt;/p&gt;




&lt;p&gt;Thanks for reading and I hope you liked the article, if so, please help support me by hitting that clap button or subscribing.&lt;/p&gt;

</description>
      <category>softwaredevelopment</category>
      <category>frontend</category>
      <category>javascript</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Typescript Generics explained in 2 minutes</title>
      <dc:creator>Nicky Christensen</dc:creator>
      <pubDate>Thu, 03 Feb 2022 20:20:12 +0000</pubDate>
      <link>https://dev.to/nickycdk/typescript-generics-explained-in-2-minutes-24ib</link>
      <guid>https://dev.to/nickycdk/typescript-generics-explained-in-2-minutes-24ib</guid>
      <description>&lt;p&gt;TypeScript is powerful, it can make your code a lot more stable, readable, easier to refactor and so much more.&lt;/p&gt;

&lt;p&gt;TypeScript has &lt;em&gt;&lt;strong&gt;Generics&lt;/strong&gt;&lt;/em&gt; which are super useful when wanting to write clean and reusable pieces of code. Generics offer a way for developers to create reusable code and it works in a way to make components work with any data type and not be restricted to a single data type.&lt;/p&gt;

&lt;p&gt;Given that you are in this article, I’m expecting you already know the basics of TypeScript, and want to know more about Generics in TypeScript so I won't go deep into an explanation around TypeScript itself.&lt;/p&gt;

&lt;p&gt;Consider the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;let courses = [];
const fetchCourseTemplates = async () =&amp;gt; {
  isLoading = true;
  const companyId = '123';
  try {
    courses = await getAllDocuments(`course_templates/${companyId}/templates`);
    isLoading = false;
  } catch (e) {
    isLoading = false;
    throw new Error('Cant load templates: ' + e);
  }
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The function we are calling will look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Our reuseable function to get data
export const getAllDocuments = async (collectionName: string) =&amp;gt; {
  const documents = [];
  const querySnapshot = await getDocs(collection(db, collectionName));
  querySnapshot.forEach((doc) =&amp;gt; {
    const data = doc.data();
    documents.push({
      id: doc.id,
      ...data
    });
  });

  return documents;
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With the above code, you are fetching some data from an API, passing a parameter on where to fetch the data (In this case, a reference to a collection in Firebase). The data passed back from the function are stored in a variable. All good, right?&lt;/p&gt;

&lt;p&gt;Not quite. You see, if you have a reusable function to fetch data from a collection, you never know which type of data you are actually getting back. Well, you may know now but TypeScript doesn’t.&lt;/p&gt;

&lt;p&gt;Imagine you are using this function to retrieve all kinds of different documents from different places in Firebase, the data you get returned will most likely be different from time to time. So how do we make TypeScript happy?&lt;/p&gt;

&lt;h2&gt;
  
  
  Introducing Generics
&lt;/h2&gt;

&lt;p&gt;Generics will help you in this case. You can extend the function to use generics, and when calling the function, you specify which type of data you are working with. This will make TypeScript understand.&lt;/p&gt;

&lt;p&gt;Let’s take the above code and see how it would look using Generics.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;let courses: Course[] = [];
const fetchCourseTemplates = async () =&amp;gt; {
  isLoading = true;
  const companyId = '123';
  try {
    courses = await getAllDocuments&amp;lt;Course&amp;gt;(`course_templates/${companyId}/templates`);
    isLoading = false;
  } catch (e) {
    isLoading = false;
    throw new Error('Cant load templates: ' + e);
  }
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The main difference here is in the await. You might notice the &lt;strong&gt;&lt;/strong&gt;. This is basically me passing a type to the function, telling TypeScript what data the function should work with. Let's take a look at the next function&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Our reuseable function to get data
export const getAllDocuments = async &amp;lt;T&amp;gt;(collectionName: string) =&amp;gt; {
  const documents: T[] = [];
  const querySnapshot = await getDocs(collection(db, collectionName));
  querySnapshot.forEach((doc) =&amp;gt; {
    const data = doc.data();
    documents.push({
      ...data
    } as T);
  });

  return documents;
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice after the async keyword, I do . This is me getting the type back I called the function with. Further down, you will see that the array I’m creating should be of the type I passed on (We passed Course). When we are returning, TypeScript now knows that I’m returning whatever type I provided. In our cases, it would return an array of courses, because we passed Courses as our type in the &lt;em&gt;&lt;strong&gt;fetchCourseTemplates&lt;/strong&gt;&lt;/em&gt; function.&lt;/p&gt;

&lt;p&gt;That about wraps it up! I hope you understood the above.&lt;br&gt;
Of course, there is a lot more to generics and many more use cases than what I just showed, but hopefully, it gave you a basic understanding and you can see why it is powerful.&lt;/p&gt;

&lt;p&gt;If you’d like to catch up with me sometime, follow me on &lt;a href="https://nickychristensen.medium.com/" rel="noopener noreferrer"&gt;Medium&lt;/a&gt; | &lt;a href="https://twitter.com/nickycdk" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt; | &lt;a href="https://www.linkedin.com/in/dknickychristensen/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt; or simply visit my &lt;a href="https://nickychristensen.dk" rel="noopener noreferrer"&gt;website&lt;/a&gt; (That is in Danish)&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>javascript</category>
      <category>frontend</category>
      <category>softwaredevelopmen</category>
    </item>
    <item>
      <title>TypeScript Interfaces Explained in 2 Minutes</title>
      <dc:creator>Nicky Christensen</dc:creator>
      <pubDate>Sun, 30 Jan 2022 12:24:05 +0000</pubDate>
      <link>https://dev.to/nickycdk/typescript-interfaces-explained-in-2-minutes-2ogb</link>
      <guid>https://dev.to/nickycdk/typescript-interfaces-explained-in-2-minutes-2ogb</guid>
      <description>&lt;p&gt;My first article on dev.to, Yay! In this article, I'll show you what an interface is and how to create and use interfaces in your own projects.&lt;/p&gt;

&lt;p&gt;As you may already know, JavaScript is not a type-safe language per definition. To get that cool type safety, you need to use tools like TypeScript to help you out.&lt;br&gt;
TypeScript is a superset of JavaScript that introduces new features and helpful improvements to the JavaScript language.&lt;/p&gt;

&lt;p&gt;By using TypeScript in your codebase, you can easily spot or avoid errors early and get rid of errors in compilation time which is pretty awesome. At first glance, TypeScript can seem hard and scary, but once you’ve spent some time with it, I’ll bet you that you’ll really love it.&lt;/p&gt;
&lt;h2&gt;
  
  
  Interfaces
&lt;/h2&gt;

&lt;p&gt;An Interface in TypeScript acts more or less like a blueprint for an object. It defines information about property names in objects and their values. This can help out the TypeScript compiler in validating your objects, so you don’t define objects in the wrong format.&lt;/p&gt;

&lt;p&gt;You define an interface by using the interface keyword in a typescript file (.ts). Take a look at the following example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;interface Course {
  title: string;
  description: string;
  createdAt: Date;
  updatedAt: Date;
  price: number;
  currency: string;
  isActive: boolean;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With this, you have defined an interface which can act like a blueprint for an object:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const webCourse: Course = {
  title: 'Typescript Basics',
  description: 'A course about Typescript',
  createdAt: new Date(),
  updatedAt: new Date(),
  price: 10,
  currency: 'USD',
  isActive: true
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In interfaces, you can also specify any property as optional by using the ? or by adding undefined as a value.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;interface Course {
  title: string;
  description: string;
  createdAt: Date;
  updatedAt: Date;
  price?: number; //Optional
  currency: string | undefined; //Optional
  isActive: boolean;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This means you can now create an object without a price and currency in this example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const webCourse: Course = {
  title: 'Typescript Basics',
  description: 'A course about Typescript',
  createdAt: new Date(),
  updatedAt: new Date(),
  isActive: true
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can also have interfaces that extend other interfaces which can be quite useful sometimes.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;interface BaseCourse {
  title: string;
  description: string;
  createdAt: Date;
  updatedAt: Date;
  price?: number; //Optional
  currency: string | undefined; //Optional
  isActive: boolean;
}

interface FootballCourse extends BaseCourse {
  coach: string;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see here, we have defined a BaseCourse and FootballCourse. FootballCourse extends from the BaseCourse allowing us to utilize the BaseCourse interface and then just extending it with whatever properties we need&lt;/p&gt;

&lt;p&gt;Another cool thing is that you can define properties as readonly, meaning that if you create an object and later on try to overwrite the property, the typescript compiler will throw an error as you have defined it as readonly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;interface BaseCourse {
  readonly title: string; //Read only
  description: string;
  createdAt: Date;
  updatedAt: Date;
  price?: number; //Optional
  currency: string | undefined; //Optional
  isActive: boolean;
}

interface FootballCourse extends BaseCourse {
  coach: string;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will throw an error:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const webCourse: FootballCourse = {
  title: 'Typescript Basics',
  description: 'A course about Typescript',
  createdAt: new Date(),
  updatedAt: new Date(),
  isActive: true,
  coach: 'Nicky Christensen'
};

webCourse.title = 'A new title'; //ERROR
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you’d like to catch up with me sometime, follow me on &lt;a href="https://twitter.com/nickycdk" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt; | &lt;a href="https://www.linkedin.com/in/dknickychristensen/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt; or simply visit my &lt;a href="https://nickychristensen.dk" rel="noopener noreferrer"&gt;website&lt;/a&gt; (That is in Danish)&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>javascript</category>
      <category>frontend</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
