<?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: Kristieene Knowles</title>
    <description>The latest articles on DEV Community by Kristieene Knowles (@webweaversworld).</description>
    <link>https://dev.to/webweaversworld</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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3788309%2Ff599fad3-a221-4c07-8b59-6049fc9a5ead.png</url>
      <title>DEV Community: Kristieene Knowles</title>
      <link>https://dev.to/webweaversworld</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/webweaversworld"/>
    <language>en</language>
    <item>
      <title>I Got Tired of Running Lighthouse Manually, So I Automated It</title>
      <dc:creator>Kristieene Knowles</dc:creator>
      <pubDate>Fri, 24 Jul 2026 14:13:33 +0000</pubDate>
      <link>https://dev.to/webweaversworld/i-got-tired-of-running-lighthouse-manually-so-i-automated-it-1mjl</link>
      <guid>https://dev.to/webweaversworld/i-got-tired-of-running-lighthouse-manually-so-i-automated-it-1mjl</guid>
      <description>&lt;p&gt;Lighthouse has been one of those tools I've used throughout my web development journey.&lt;/p&gt;

&lt;p&gt;For a small website, running a Lighthouse audit manually isn't really a problem.&lt;/p&gt;

&lt;p&gt;Open DevTools, run the audit, look through the results, fix what needs fixing, and move on.&lt;/p&gt;

&lt;p&gt;That works perfectly well when you're dealing with a handful of pages.&lt;/p&gt;

&lt;p&gt;But Web Weavers World isn't really a handful of pages anymore.&lt;/p&gt;

&lt;p&gt;As the site has grown, I've found myself wanting to audit more than just the homepage. There are project pages, showcase pages, tools, experiments, forms, and other parts of the site that can all behave differently.&lt;/p&gt;

&lt;p&gt;Running Lighthouse manually across all of those pages gets repetitive very quickly.&lt;/p&gt;

&lt;p&gt;So, naturally, I automated it.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Problem Wasn't Lighthouse
&lt;/h2&gt;

&lt;p&gt;I want to make something clear first: manual Lighthouse testing is still useful.&lt;/p&gt;

&lt;p&gt;I haven't built this because I think manually running Lighthouse is somehow bad or outdated.&lt;/p&gt;

&lt;p&gt;If I'm working on one page and want to quickly see how it's performing, opening Lighthouse and running an audit is probably still the easiest option.&lt;/p&gt;

&lt;p&gt;The problem appears when I want to ask a slightly different question:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"How is the whole website doing?"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Suddenly, testing one page isn't enough.&lt;/p&gt;

&lt;p&gt;If a website has 5 pages, manually auditing them isn't particularly painful.&lt;/p&gt;

&lt;p&gt;If it has 50, 100, or more URLs, that's a very different workflow.&lt;/p&gt;

&lt;p&gt;At that point I'm not really spending my time analysing Lighthouse anymore.&lt;/p&gt;

&lt;p&gt;I'm spending my time repeatedly launching Lighthouse.&lt;/p&gt;

&lt;p&gt;And repetitive development tasks are increasingly becoming something I look at and think:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Can I automate this?"&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Turning Lighthouse Into a PowerShell Function
&lt;/h2&gt;

&lt;p&gt;My solution was to build a PowerShell Lighthouse auditing function.&lt;/p&gt;

&lt;p&gt;Instead of opening each page individually, I can give the function the pages I want to audit and let it work through them for me.&lt;/p&gt;

&lt;p&gt;More importantly, I added support for sitemap auditing.&lt;/p&gt;

&lt;p&gt;That means I can point it at a site's sitemap, let it collect the URLs, and then run Lighthouse against those pages automatically.&lt;/p&gt;

&lt;p&gt;For Web Weavers World, that changes the workflow completely.&lt;/p&gt;

&lt;p&gt;Instead of:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Audit page.

Wait.

Save results.

Open next page.

Audit page.

Wait.

Repeat.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I can start one audit and let PowerShell work through the site.&lt;/p&gt;

&lt;p&gt;Recently I ran it against my sitemap and watched it pass the 100-page mark.&lt;/p&gt;

&lt;p&gt;At that point my PowerShell window started looking slightly like one of those games where hundreds of filenames fly past while something loads.&lt;/p&gt;

&lt;p&gt;Except this time it was my website being audited.&lt;/p&gt;




&lt;h2&gt;
  
  
  Automation Doesn't Mean Ignoring the Results
&lt;/h2&gt;

&lt;p&gt;This is something I've been thinking about quite a lot recently.&lt;/p&gt;

&lt;p&gt;I've been automating more of my development workflow, but the goal isn't to remove myself from the process.&lt;/p&gt;

&lt;p&gt;It's to remove the repetitive parts.&lt;/p&gt;

&lt;p&gt;Lighthouse still decides what it wants to flag.&lt;/p&gt;

&lt;p&gt;I still have to decide whether those findings matter.&lt;/p&gt;

&lt;p&gt;A warning doesn't automatically mean something needs changing, and a good score doesn't automatically mean a page is perfect.&lt;/p&gt;

&lt;p&gt;The automation simply gives me the information at a much larger scale.&lt;/p&gt;

&lt;p&gt;That's the bit I find useful.&lt;/p&gt;

&lt;p&gt;Instead of spending my attention running the tests, I can spend that attention understanding the results.&lt;/p&gt;




&lt;h2&gt;
  
  
  Then Came the Edge Cases
&lt;/h2&gt;

&lt;p&gt;Of course, automating something that normally expects a human sitting in front of it introduces another problem.&lt;/p&gt;

&lt;p&gt;Things go wrong.&lt;/p&gt;

&lt;p&gt;One of the first things I wanted my auditor to handle properly was failed or unreachable pages.&lt;/p&gt;

&lt;p&gt;When you're manually testing a website and a page doesn't load, you immediately know something has gone wrong.&lt;/p&gt;

&lt;p&gt;An automated process needs to know what to do next.&lt;/p&gt;

&lt;p&gt;I didn't want one broken URL to kill an entire site audit.&lt;/p&gt;

&lt;p&gt;If the auditor has already successfully tested dozens of pages and then encounters one that fails, throwing everything away because of that single page would make the automation considerably less useful.&lt;/p&gt;

&lt;p&gt;So the function can record that a page failed and continue onto the next one.&lt;/p&gt;

&lt;p&gt;That distinction matters.&lt;/p&gt;

&lt;p&gt;A failed page is itself useful information.&lt;/p&gt;

&lt;p&gt;A failed audit shouldn't necessarily mean a failed auditing process.&lt;/p&gt;




&lt;h2&gt;
  
  
  Temporary Files Are Still Files
&lt;/h2&gt;

&lt;p&gt;Another interesting part was cleanup.&lt;/p&gt;

&lt;p&gt;Running Lighthouse programmatically creates temporary files and intermediate data that are useful while an audit is running but aren't necessarily things I want hanging around afterwards.&lt;/p&gt;

&lt;p&gt;This produced one slightly terrifying moment.&lt;/p&gt;

&lt;p&gt;During one of my runs I saw output saying files had been removed.&lt;/p&gt;

&lt;p&gt;As a developer who has previously experienced the joy of seeing unexpected "deleted" messages appear in a terminal, that wording gets your attention very quickly.&lt;/p&gt;

&lt;p&gt;Thankfully, it was doing exactly what it was supposed to do.&lt;/p&gt;

&lt;p&gt;It was cleaning up its own temporary files.&lt;/p&gt;

&lt;p&gt;But it highlighted another part of automation that I think is easy to overlook.&lt;/p&gt;

&lt;p&gt;Cleanup is part of the feature.&lt;/p&gt;

&lt;p&gt;Creating temporary files is fine.&lt;/p&gt;

&lt;p&gt;Leaving temporary files scattered around after every audit isn't.&lt;/p&gt;

&lt;p&gt;So the auditing process doesn't just need to know how to start.&lt;/p&gt;

&lt;p&gt;It needs to know how to finish cleanly as well.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Interesting Part Is Scale
&lt;/h2&gt;

&lt;p&gt;The actual Lighthouse tests haven't fundamentally changed.&lt;/p&gt;

&lt;p&gt;I'm still using Lighthouse.&lt;/p&gt;

&lt;p&gt;I'm still looking at performance, accessibility, best practices, SEO, and the other information it provides.&lt;/p&gt;

&lt;p&gt;What has changed is the scale at which I can use it.&lt;/p&gt;

&lt;p&gt;That's something I've started noticing with quite a few of my development tools.&lt;/p&gt;

&lt;p&gt;A manual workflow can be perfectly good and still stop being practical as a project grows.&lt;/p&gt;

&lt;p&gt;The question isn't always:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Is there something wrong with this workflow?"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Sometimes the better question is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Does this workflow still scale?"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;For manually auditing one page, yes.&lt;/p&gt;

&lt;p&gt;For repeatedly auditing an entire site, not really.&lt;/p&gt;

&lt;p&gt;And that's where automation becomes useful.&lt;/p&gt;




&lt;h2&gt;
  
  
  What I've Learnt From Building It
&lt;/h2&gt;

&lt;p&gt;One of the biggest things I've learnt from building development utilities like this is that the main feature is usually the easy part.&lt;/p&gt;

&lt;p&gt;"Run Lighthouse against a list of URLs" sounds straightforward.&lt;/p&gt;

&lt;p&gt;And conceptually, it is.&lt;/p&gt;

&lt;p&gt;But a useful tool has to deal with everything around that happy path.&lt;/p&gt;

&lt;p&gt;What happens when a page fails?&lt;/p&gt;

&lt;p&gt;What happens when a URL can't be reached?&lt;/p&gt;

&lt;p&gt;What happens to temporary files?&lt;/p&gt;

&lt;p&gt;Should one failure stop everything else?&lt;/p&gt;

&lt;p&gt;How do I make the final results useful instead of producing a mountain of raw output?&lt;/p&gt;

&lt;p&gt;Those edge cases are what turn a script that works on my machine once into something I can actually rely on.&lt;/p&gt;

&lt;p&gt;And I think that's probably my main takeaway from this project.&lt;/p&gt;




&lt;h2&gt;
  
  
  Automate the Repetition, Keep the Decisions
&lt;/h2&gt;

&lt;p&gt;I don't think every development task needs automation.&lt;/p&gt;

&lt;p&gt;Sometimes clicking a button is genuinely easier than building a system to click the button for you.&lt;/p&gt;

&lt;p&gt;But once I notice myself doing the same predictable process dozens of times, that's usually a sign that it's worth reconsidering the workflow.&lt;/p&gt;

&lt;p&gt;Lighthouse is a good example.&lt;/p&gt;

&lt;p&gt;Manual auditing hasn't become bad.&lt;/p&gt;

&lt;p&gt;My website simply grew beyond the point where manually running every audit was the best use of my time.&lt;/p&gt;

&lt;p&gt;So now PowerShell handles the repetitive part.&lt;/p&gt;

&lt;p&gt;Lighthouse handles the auditing.&lt;/p&gt;

&lt;p&gt;And I get to focus on the bit that actually needs a developer:&lt;/p&gt;

&lt;p&gt;Deciding what to do with the results.&lt;/p&gt;

&lt;p&gt;Sometimes automation doesn't need to replace a tool.&lt;/p&gt;

&lt;p&gt;It just needs to make an existing tool easier to use at scale.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>lighthouse</category>
      <category>automation</category>
      <category>powershell</category>
    </item>
    <item>
      <title>From Project Feature to Reusable Package – Building My Dynamic Theme Kit</title>
      <dc:creator>Kristieene Knowles</dc:creator>
      <pubDate>Tue, 14 Jul 2026 13:06:44 +0000</pubDate>
      <link>https://dev.to/webweaversworld/from-project-feature-to-reusable-package-building-my-dynamic-theme-kit-3ogp</link>
      <guid>https://dev.to/webweaversworld/from-project-feature-to-reusable-package-building-my-dynamic-theme-kit-3ogp</guid>
      <description>&lt;p&gt;One of my recent goals has been making my code more reusable instead of solving the same problem in every project.&lt;/p&gt;

&lt;p&gt;A good example of that is my &lt;strong&gt;Dynamic Theme Kit (DTK)&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;DTK didn't begin life as a package.&lt;/p&gt;

&lt;p&gt;It started as the theming engine inside my &lt;strong&gt;One Piece Tracker&lt;/strong&gt; project.&lt;/p&gt;

&lt;p&gt;As that project grew, so did the theme system. It eventually reached the point where I realised I wasn't building a theme engine for one application anymore—I was building something that could be useful everywhere.&lt;/p&gt;

&lt;p&gt;Instead of copying pieces of code into future projects, I decided it was time to extract it into its own standalone package.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 1 – Extracting it
&lt;/h2&gt;

&lt;p&gt;At first I thought this would mostly be moving files around.&lt;/p&gt;

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

&lt;p&gt;The real challenge wasn't writing new code—it was separating reusable logic from application-specific logic.&lt;/p&gt;

&lt;p&gt;That meant identifying everything that genuinely belonged to the theme engine and leaving behind everything that only existed because One Piece Tracker happened to need it.&lt;/p&gt;

&lt;p&gt;After several rounds of refactoring, I ended up with a package whose only responsibility is generating theme variables.&lt;/p&gt;

&lt;p&gt;It doesn't try to style an application.&lt;/p&gt;

&lt;p&gt;It simply exposes CSS variables that each project can consume however it wants.&lt;/p&gt;

&lt;p&gt;That separation of responsibilities immediately made the whole design cleaner.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 2 – Making it genuinely reusable
&lt;/h2&gt;

&lt;p&gt;Extracting the code wasn't enough.&lt;/p&gt;

&lt;p&gt;The next challenge was proving it wasn't secretly relying on assumptions from the original project.&lt;/p&gt;

&lt;p&gt;I wanted integrating DTK to be as lightweight as possible.&lt;/p&gt;

&lt;p&gt;Ideally, another project should only need to include the kit, provide a palette configuration, and continue styling itself normally.&lt;/p&gt;

&lt;p&gt;That meant improving the documentation, simplifying the configuration, removing unnecessary coupling, and making sure DTK wasn't making decisions that belonged to the application itself.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 3 – Libraries expose your assumptions
&lt;/h2&gt;

&lt;p&gt;The biggest surprise came once I started using DTK in other projects.&lt;/p&gt;

&lt;p&gt;Every integration uncovered another assumption I'd accidentally baked into the original implementation.&lt;/p&gt;

&lt;p&gt;One project still used an older CSS variable.&lt;/p&gt;

&lt;p&gt;Another highlighted that gradient backgrounds needed different handling.&lt;/p&gt;

&lt;p&gt;Another showed that parts of my documentation only made sense because I already knew how the original project worked.&lt;/p&gt;

&lt;p&gt;None of those were bugs.&lt;/p&gt;

&lt;p&gt;They were assumptions.&lt;/p&gt;

&lt;p&gt;Every time I removed one, DTK became less like "theme code extracted from another project" and more like a toolkit that could genuinely stand on its own.&lt;/p&gt;

&lt;p&gt;Those smaller projects became the perfect test environment.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 4 – Integrating it into Web Weavers World
&lt;/h2&gt;

&lt;p&gt;Once I was confident DTK was genuinely reusable, I integrated it into my business website, &lt;strong&gt;Web Weavers World&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;This felt like the real test.&lt;/p&gt;

&lt;p&gt;Unlike my smaller experiments, this is the website that represents my work as a developer.&lt;/p&gt;

&lt;p&gt;I didn't just want the themes to work—I wanted the integration to feel natural.&lt;/p&gt;

&lt;p&gt;Seeing the site switch themes using a completely standalone package was a satisfying moment.&lt;/p&gt;

&lt;p&gt;Even better, I realised future themes no longer require changes throughout the application.&lt;/p&gt;

&lt;p&gt;Adding another theme is now largely a matter of adding another palette.&lt;/p&gt;

&lt;p&gt;That's exactly what I'd hoped to achieve when I first started extracting the code.&lt;/p&gt;




&lt;h2&gt;
  
  
  Lessons learned
&lt;/h2&gt;

&lt;p&gt;Extracting a feature into a reusable package is much harder than building it for a single application.&lt;/p&gt;

&lt;p&gt;The difficult part isn't the code.&lt;/p&gt;

&lt;p&gt;It's removing assumptions.&lt;/p&gt;

&lt;p&gt;Questions like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Is this variable actually generic?&lt;/li&gt;
&lt;li&gt;Does this behaviour belong in the package or the application?&lt;/li&gt;
&lt;li&gt;Am I solving a reusable problem or a project-specific one?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;became much more important than writing new functionality.&lt;/p&gt;

&lt;p&gt;More importantly, the process has changed how I think about development.&lt;/p&gt;

&lt;p&gt;Instead of asking:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"How do I build this feature?"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I increasingly find myself asking:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Could this become something I can reuse in every future project?"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That small change in mindset has probably been the biggest benefit of building DTK.&lt;/p&gt;

&lt;p&gt;Sometimes the best refactor isn't making code shorter.&lt;/p&gt;

&lt;p&gt;It's making code useful more than once.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>css</category>
      <category>javascript</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Entering My Automation Era (Without Letting AI Build My Code)</title>
      <dc:creator>Kristieene Knowles</dc:creator>
      <pubDate>Thu, 04 Jun 2026 05:59:04 +0000</pubDate>
      <link>https://dev.to/webweaversworld/entering-my-automation-era-without-letting-ai-build-my-code-aal</link>
      <guid>https://dev.to/webweaversworld/entering-my-automation-era-without-letting-ai-build-my-code-aal</guid>
      <description>&lt;p&gt;On 30th June 2025, I started my web development journey. At the time, my focus was simple: learn the fundamentals, build websites, solve problems, and improve with every project. Like most developers starting out, I spent my days learning HTML, CSS, JavaScript, accessibility, responsive design, deployment, debugging, and occasionally breaking things in ways I didn't think were possible.&lt;/p&gt;

&lt;p&gt;Fast forward to today, and I've realised I've entered a new phase of development.&lt;/p&gt;

&lt;p&gt;Not an "AI builds everything for me" phase.&lt;/p&gt;

&lt;p&gt;An automation phase.&lt;/p&gt;

&lt;p&gt;When people hear the word automation, they often assume it means handing over your codebase and hoping for the best. For me, it's been the opposite. I still design my websites, write the functionality, make the architectural decisions, and review everything that matters. The websites are still mine. What has changed is that I've started automating the repetitive tasks around development rather than development itself.&lt;/p&gt;

&lt;p&gt;Over the past few months, I've been building up a collection of GitHub Actions, repository audits, validation checks, reporting tools, and AI-assisted review workflows. My repositories now contain security scanning, dependency auditing, workflow validation, issue prioritisation reports, documentation updates, repository health checks, and automated quality reports. None of these tools are writing client projects for me. Instead, they're acting as a second set of eyes, constantly reviewing things that would otherwise require manual effort.&lt;/p&gt;

&lt;h2&gt;
  
  
  AI As A Team Member, Not A Replacement
&lt;/h2&gt;

&lt;p&gt;One of the biggest mindset shifts I've had is moving away from asking:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Can AI build this for me?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;and instead asking:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Can automation help me verify this?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;As a solo developer, I don't have a dedicated QA engineer, security reviewer, documentation writer, or DevOps team. That's usually just... me.&lt;/p&gt;

&lt;p&gt;Automation helps bridge that gap.&lt;/p&gt;

&lt;p&gt;A GitHub Action can run checks while I'm asleep. An automated report can highlight issues before they become problems. An AI review can spot patterns I might miss after staring at the same code for hours. None of that removes my responsibility as the developer; it simply gives me more visibility into what's happening across the codebase.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Review Era
&lt;/h2&gt;

&lt;p&gt;The interesting thing is that most of my automation isn't focused on creating code.&lt;/p&gt;

&lt;p&gt;It's focused on reviewing code.&lt;/p&gt;

&lt;p&gt;That's where I've found the biggest value.&lt;/p&gt;

&lt;p&gt;The more automation I add, the more involved I become in the actual development process. Instead of spending time on repetitive checks, I spend more time making decisions, reviewing results, improving architecture, and focusing on the user experience. Automation hasn't reduced my responsibility as a developer; it's given me better tools to manage it.&lt;/p&gt;

&lt;p&gt;That small change in thinking—moving from code generation to code verification—has probably saved me more time than any code-generation tool ever could.&lt;/p&gt;

&lt;h2&gt;
  
  
  Looking Back
&lt;/h2&gt;

&lt;p&gt;If you had told me on 30th June 2025 that I'd eventually have automated audits, repository health reports, workflow validation, issue prioritisation, monitoring, and AI-assisted review processes running across my projects, I probably wouldn't have believed you.&lt;/p&gt;

&lt;p&gt;At the time, I was just trying to make websites work.&lt;/p&gt;

&lt;p&gt;Today, I'm building systems that help keep those websites healthy.&lt;/p&gt;

&lt;p&gt;And honestly, that's been one of the most rewarding parts of my development journey so far.&lt;/p&gt;

&lt;p&gt;The code is still mine.&lt;/p&gt;

&lt;p&gt;The decisions are still mine.&lt;/p&gt;

&lt;p&gt;The responsibility is still mine.&lt;/p&gt;

&lt;p&gt;I've just built myself a really efficient team.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>automation</category>
      <category>github</category>
      <category>productivity</category>
    </item>
    <item>
      <title>That Moment You See ‘Deleting…’ in Git Bash</title>
      <dc:creator>Kristieene Knowles</dc:creator>
      <pubDate>Wed, 04 Mar 2026 20:51:34 +0000</pubDate>
      <link>https://dev.to/webweaversworld/that-moment-you-see-deleting-in-git-bash-38a7</link>
      <guid>https://dev.to/webweaversworld/that-moment-you-see-deleting-in-git-bash-38a7</guid>
      <description>&lt;p&gt;The Fear of Using Git Bash Too Early in Your Dev Journey&lt;/p&gt;

&lt;p&gt;When I first started learning development about six months ago, Git Bash felt like stepping into a control room full of buttons I didn’t understand.&lt;/p&gt;

&lt;p&gt;I had connected Git to my local VS Code environment and thought:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Okay, this must be what developers use… I’ll just follow along.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The problem was that I didn’t actually understand the commands I was running.&lt;/p&gt;

&lt;p&gt;One day I ran a command in Git Bash and suddenly my terminal started printing lines that included words like “deleting”.&lt;/p&gt;

&lt;p&gt;My brain instantly went into panic mode.&lt;/p&gt;

&lt;p&gt;Not deleting in the repo.&lt;/p&gt;

&lt;p&gt;Deleting in my actual Windows file system.&lt;/p&gt;

&lt;p&gt;Inside my /htdocs/ folder.&lt;/p&gt;

&lt;p&gt;At that moment I realised something important about Git:&lt;/p&gt;

&lt;p&gt;Git is powerful — but if you don’t understand what a command does, it can be terrifying.&lt;/p&gt;

&lt;p&gt;I aborted the command as quickly as I could, but by then the damage had already started.&lt;/p&gt;

&lt;p&gt;For a few seconds I genuinely thought I had just lost my entire working project.&lt;/p&gt;

&lt;p&gt;Thankfully, I had a backup, so I restored everything and carried on.&lt;/p&gt;

&lt;p&gt;But that moment taught me two lessons that stuck with me.&lt;/p&gt;




&lt;h2&gt;
  
  
  Lesson 1 — Git Isn’t Dangerous, Ignorance Is
&lt;/h2&gt;

&lt;p&gt;Git commands can look intimidating because they operate at a very powerful level of your file system.&lt;/p&gt;

&lt;p&gt;When you see words like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;reset&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;clean&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rm&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;delete&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;…it feels like you're about to destroy your project.&lt;/p&gt;

&lt;p&gt;But Git isn't the enemy.&lt;/p&gt;

&lt;p&gt;Running commands without understanding them is.&lt;/p&gt;

&lt;p&gt;Once I slowed down and actually learned what commands like checkout, pull, and reset do, Git stopped feeling scary and started feeling like a safety net.&lt;/p&gt;




&lt;h2&gt;
  
  
  Lesson 2 — Always Backup Your Work
&lt;/h2&gt;

&lt;p&gt;The real hero of that moment was my backup.&lt;/p&gt;

&lt;p&gt;If I hadn’t had one, I genuinely could have lost hours (or days) of work.&lt;/p&gt;

&lt;p&gt;After that experience, I decided to automate the process.&lt;/p&gt;

&lt;p&gt;I created a small PowerShell script that automatically backs up my /htdocs/ folder, so I always have a copy of my working files.&lt;/p&gt;

&lt;p&gt;Now backups happen without me even thinking about them.&lt;/p&gt;

&lt;p&gt;That one small script removed an enormous amount of stress from my workflow.&lt;/p&gt;




&lt;h2&gt;
  
  
  Lesson 3 — Fear Is Part of the Learning Curve
&lt;/h2&gt;

&lt;p&gt;Looking back, the fear I felt in that moment was actually part of the learning process.&lt;/p&gt;

&lt;p&gt;Every developer eventually reaches a point where they realise:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Tools like Git aren’t just version control — they’re power tools.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And power tools require respect.&lt;/p&gt;

&lt;p&gt;Once you understand them, they stop being scary and start being incredibly useful.&lt;/p&gt;




&lt;p&gt;Final Advice for New Developers&lt;/p&gt;

&lt;p&gt;If you're just starting with Git:&lt;/p&gt;

&lt;p&gt;Don’t blindly copy commands from tutorials&lt;/p&gt;

&lt;p&gt;Take time to understand what each command does&lt;/p&gt;

&lt;p&gt;Always keep backups of your important work&lt;/p&gt;

&lt;p&gt;Because one day you will see the word “deleting” fly past in a terminal…&lt;/p&gt;

&lt;p&gt;…and your heart will skip a beat.&lt;/p&gt;

&lt;p&gt;Trust me on that.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>bash</category>
      <category>github</category>
      <category>git</category>
    </item>
    <item>
      <title>I Built My Own dev.to Feed Page Instead of Embedding a Widget</title>
      <dc:creator>Kristieene Knowles</dc:creator>
      <pubDate>Sat, 28 Feb 2026 20:21:11 +0000</pubDate>
      <link>https://dev.to/webweaversworld/i-built-my-own-devto-feed-page-instead-of-embedding-a-widget-fa5</link>
      <guid>https://dev.to/webweaversworld/i-built-my-own-devto-feed-page-instead-of-embedding-a-widget-fa5</guid>
      <description>&lt;p&gt;There’s an easy way to show your dev.to posts on your website.&lt;/p&gt;

&lt;p&gt;You paste in a widget.&lt;br&gt;
You let it render.&lt;br&gt;
You move on.&lt;/p&gt;

&lt;p&gt;I almost did that.&lt;/p&gt;

&lt;p&gt;But the more I looked at it, the more it felt slightly disconnected from how I build everything else.&lt;/p&gt;

&lt;p&gt;So I didn’t embed it.&lt;/p&gt;

&lt;p&gt;I built my own feed page instead.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why I Didn’t Use the Widget
&lt;/h2&gt;

&lt;p&gt;This wasn’t about avoiding convenience.&lt;/p&gt;

&lt;p&gt;It was about consistency.&lt;/p&gt;

&lt;p&gt;My site is fully hand-built — HTML, CSS, JavaScript, structured layouts, injection layers, theme handling. Everything is intentional.&lt;/p&gt;

&lt;p&gt;Dropping in a third-party widget would have worked, but it wouldn’t have felt like part of the system.&lt;/p&gt;

&lt;p&gt;It would’ve been something sitting inside it.&lt;/p&gt;

&lt;p&gt;And that difference matters more than it sounds.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Approach
&lt;/h2&gt;

&lt;p&gt;dev.to provides a public RSS feed. That’s data.&lt;/p&gt;

&lt;p&gt;So instead of embedding a UI component, I fetched the feed, parsed the XML, and rendered the posts as native components on my site.&lt;/p&gt;

&lt;p&gt;No iframe.&lt;br&gt;
No external styling.&lt;br&gt;
No layout overrides.&lt;/p&gt;

&lt;p&gt;Just data → structured objects → my own card components.&lt;/p&gt;

&lt;p&gt;That means:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The posts match my design system&lt;/li&gt;
&lt;li&gt;The spacing, typography, and hover states are consistent&lt;/li&gt;
&lt;li&gt;The performance impact is minimal&lt;/li&gt;
&lt;li&gt;The page works whether someone is logged into dev.to or not&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It feels integrated rather than attached.&lt;/p&gt;




&lt;h2&gt;
  
  
  What I Like About This Pattern
&lt;/h2&gt;

&lt;p&gt;RSS is simple.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It’s stable.&lt;/li&gt;
&lt;li&gt;It’s predictable.&lt;/li&gt;
&lt;li&gt;It doesn’t try to control your layout.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That separation — content from presentation — is powerful.&lt;/p&gt;

&lt;p&gt;dev.to handles publishing and discovery.&lt;br&gt;
My site handles display and brand.&lt;/p&gt;

&lt;p&gt;Both do what they’re good at.&lt;/p&gt;




&lt;h2&gt;
  
  
  A Small Architectural Win
&lt;/h2&gt;

&lt;p&gt;This isn’t a huge feature.&lt;/p&gt;

&lt;p&gt;It’s not complex.&lt;/p&gt;

&lt;p&gt;But it reinforces something I’ve been learning while building everything from scratch:&lt;/p&gt;

&lt;p&gt;Control over the surface area of your site makes everything cleaner long term.&lt;/p&gt;

&lt;p&gt;When you own the presentation layer, you’re not negotiating with someone else’s styles, scripts, or structure.&lt;/p&gt;

&lt;p&gt;You’re just working with data.&lt;/p&gt;

&lt;p&gt;And I prefer building that way.&lt;/p&gt;




&lt;p&gt;If you’re building a personal site and want your blog content there too, consider pulling the feed instead of embedding the widget.&lt;/p&gt;

&lt;p&gt;It’s a small change — but it keeps your architecture intentional.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>rss</category>
      <category>frontend</category>
    </item>
    <item>
      <title>I Built My Own Wordle Engine to Support How I Actually Think</title>
      <dc:creator>Kristieene Knowles</dc:creator>
      <pubDate>Sat, 28 Feb 2026 10:30:56 +0000</pubDate>
      <link>https://dev.to/webweaversworld/i-built-my-own-wordle-engine-to-support-how-i-actually-think-4igd</link>
      <guid>https://dev.to/webweaversworld/i-built-my-own-wordle-engine-to-support-how-i-actually-think-4igd</guid>
      <description>&lt;h2&gt;
  
  
  Why I Built My Own Wordle
&lt;/h2&gt;

&lt;p&gt;Like a lot of developers, I enjoy Wordle.&lt;br&gt;
But after playing for a while, I realised I didn’t just want to play it — I wanted to understand it.&lt;/p&gt;

&lt;p&gt;So instead of cloning a template, I built my own Wordle engine from scratch.&lt;/p&gt;

&lt;p&gt;Not because the world needed another clone.&lt;/p&gt;

&lt;p&gt;But because I wanted:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Full control over the word pool&lt;/li&gt;
&lt;li&gt;Seeded daily logic I understood completely&lt;/li&gt;
&lt;li&gt;A stats system I could extend cleanly&lt;/li&gt;
&lt;li&gt;And a version that reflected how I actually think when solving puzzles&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That’s how Web Weavers Wordle started.&lt;/p&gt;


&lt;h2&gt;
  
  
  Custom Word Pool (Under 1k → Nearly 6k Words)
&lt;/h2&gt;

&lt;p&gt;Originally, my word list was tiny — under 1,000 entries.&lt;/p&gt;

&lt;p&gt;It worked, but it felt constrained.&lt;/p&gt;

&lt;p&gt;So I rebuilt the dictionary layer entirely.&lt;/p&gt;

&lt;p&gt;Instead of a single static list, I moved to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Separate &lt;code&gt;.txt&lt;/code&gt; files per word length&lt;/li&gt;
&lt;li&gt;Dynamic loading&lt;/li&gt;
&lt;li&gt;A combined &lt;code&gt;VALID_SET&lt;/code&gt; for fast validation&lt;/li&gt;
&lt;li&gt;Per-length counts for UI stats&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The pool is now just under 6,000 words, all curated to match the theme (every answer starts with W).&lt;/p&gt;

&lt;p&gt;It’s modular, scalable, and easy to extend — without bloating the main script.&lt;/p&gt;

&lt;p&gt;That refactor alone made the project feel like a proper engine instead of a weekend experiment.&lt;/p&gt;


&lt;h2&gt;
  
  
  Daily Logic (Seeded, Predictable, Controlled)
&lt;/h2&gt;

&lt;p&gt;For the daily mode, I didn’t want randomness.&lt;/p&gt;

&lt;p&gt;I implemented seeded selection based on the local date:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;seedFromDate&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;d&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getFullYear&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;10000&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getMonth&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getDate&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This means:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Everyone gets the same word on the same day&lt;/li&gt;
&lt;li&gt;The day flips at local midnight&lt;/li&gt;
&lt;li&gt;No server needed&lt;/li&gt;
&lt;li&gt;No external API calls&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It’s deterministic and self-contained.&lt;/p&gt;

&lt;p&gt;Which is exactly how I like my systems.&lt;/p&gt;




&lt;h2&gt;
  
  
  The UX Gap I Noticed
&lt;/h2&gt;

&lt;p&gt;This is where it got interesting.&lt;/p&gt;

&lt;p&gt;When solving Wordle, I don’t like filling unknown spaces with random letters.&lt;/p&gt;

&lt;p&gt;Before, if I was thinking through a word like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;W _ S T _
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I would temporarily type something like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;W W S T W
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Just to fill the row visually.&lt;/p&gt;

&lt;p&gt;But that felt wrong.&lt;/p&gt;

&lt;p&gt;Those letters weren’t information — they were noise.&lt;/p&gt;

&lt;p&gt;So I added a new state.&lt;/p&gt;

&lt;p&gt;A manual &lt;code&gt;?&lt;/code&gt; placeholder.&lt;/p&gt;

&lt;p&gt;Now I can type:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;W ? S T ?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Visually preserves structure&lt;/li&gt;
&lt;li&gt;Doesn’t affect validation&lt;/li&gt;
&lt;li&gt;Cannot be submitted&lt;/li&gt;
&lt;li&gt;Acts as a deliberate “unknown” marker&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It sounds tiny.&lt;/p&gt;

&lt;p&gt;But it fundamentally changed how the puzzle feels to solve.&lt;/p&gt;

&lt;p&gt;It added an intentional “thinking state” between blank and evaluated.&lt;/p&gt;

&lt;p&gt;And I haven’t seen other clones do that.&lt;/p&gt;




&lt;h2&gt;
  
  
  What I Didn’t Build (Yet)
&lt;/h2&gt;

&lt;p&gt;I considered expanding daily mode to every word length.&lt;/p&gt;

&lt;p&gt;Technically, it would be easy.&lt;/p&gt;

&lt;p&gt;Architecturally? It touches:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Stats storage&lt;/li&gt;
&lt;li&gt;Streak logic&lt;/li&gt;
&lt;li&gt;UI distribution trees&lt;/li&gt;
&lt;li&gt;LocalStorage keys&lt;/li&gt;
&lt;li&gt;Share formatting&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So I didn’t.&lt;/p&gt;

&lt;p&gt;The current version is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Stable.&lt;/li&gt;
&lt;li&gt;Clean.&lt;/li&gt;
&lt;li&gt;Focused.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I’d rather refine than expand.&lt;/p&gt;




&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;This project started as curiosity.&lt;/p&gt;

&lt;p&gt;It’s now a modular, seeded, PWA-enabled Wordle engine with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Nearly 6,000 words&lt;/li&gt;
&lt;li&gt;Custom daily logic&lt;/li&gt;
&lt;li&gt;Clean stats tracking&lt;/li&gt;
&lt;li&gt;Share image generation&lt;/li&gt;
&lt;li&gt;And a small UX improvement I genuinely love&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Sometimes the best way to understand a system is to rebuild it.&lt;/p&gt;

&lt;p&gt;And sometimes rebuilding it lets you improve it in small, meaningful ways.&lt;/p&gt;




&lt;p&gt;The live version is here, if you'd like to try it; &lt;a href="https://webweaversworld.co.uk/html/main/wordle/index.html" rel="noopener noreferrer"&gt;https://webweaversworld.co.uk/html/main/wordle/index.html&lt;/a&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>gamedev</category>
      <category>indiedev</category>
    </item>
    <item>
      <title>When Regex Meets the DOM (And Suddenly It’s Not Simple Anymore)</title>
      <dc:creator>Kristieene Knowles</dc:creator>
      <pubDate>Thu, 26 Feb 2026 10:03:46 +0000</pubDate>
      <link>https://dev.to/webweaversworld/when-regex-meets-the-dom-and-suddenly-its-not-simple-anymore-1lpa</link>
      <guid>https://dev.to/webweaversworld/when-regex-meets-the-dom-and-suddenly-its-not-simple-anymore-1lpa</guid>
      <description>&lt;p&gt;I recently built a custom in-page “Ctrl + F”-style search and highlight feature.&lt;/p&gt;

&lt;p&gt;The goal sounded simple:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Support multi-word queries&lt;/li&gt;
&lt;li&gt;Prefer full phrase matches&lt;/li&gt;
&lt;li&gt;Fall back to individual token matches&lt;/li&gt;
&lt;li&gt;Highlight results in the DOM&lt;/li&gt;
&lt;li&gt;Skip &lt;code&gt;&amp;lt;code&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;pre&amp;gt;&lt;/code&gt; blocks&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In my head?&lt;/p&gt;

&lt;p&gt;“Easy. Just build a regex.”&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Build the Regex
&lt;/h2&gt;

&lt;p&gt;If a user searches:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;power shell
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I generate a pattern like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;power&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="nx"&gt;u00A0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="nx"&gt;shell&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="nx"&gt;power&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="nx"&gt;shell&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The logic:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Try to match the full phrase first&lt;/li&gt;
&lt;li&gt;If that fails, match individual tokens&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;On paper? Clean.&lt;/p&gt;

&lt;p&gt;In isolation? Works.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 2: Enter the DOM
&lt;/h2&gt;

&lt;p&gt;This is where things escalated.&lt;/p&gt;

&lt;p&gt;Instead of just running &lt;code&gt;string.match()&lt;/code&gt;, I had to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Walk the DOM&lt;/li&gt;
&lt;li&gt;Avoid header UI&lt;/li&gt;
&lt;li&gt;Avoid &lt;code&gt;&amp;lt;pre&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;code&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;style&amp;gt;&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Avoid breaking syntax highlighting&lt;/li&gt;
&lt;li&gt;Replace only text nodes&lt;/li&gt;
&lt;li&gt;Preserve structure&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That meant using a &lt;code&gt;TreeWalker&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;walker&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createTreeWalker&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;root&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;NodeFilter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;SHOW_TEXT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;acceptNode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;p&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;parentElement&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;NodeFilter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;FILTER_REJECT&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;closest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;code, pre, script, style&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;NodeFilter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;FILTER_REJECT&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;NodeFilter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;FILTER_ACCEPT&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we’re not just doing regex.&lt;br&gt;
We’re doing controlled DOM mutation.&lt;/p&gt;


&lt;h2&gt;
  
  
  Step 3: The Alternation Problem
&lt;/h2&gt;

&lt;p&gt;This is where it got interesting.&lt;/p&gt;

&lt;p&gt;Even though the phrase appears first in the alternation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;phrase|token1|token2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The engine still happily matches:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;power&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;shell&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;PowerShell&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Depending on context.&lt;/p&gt;

&lt;p&gt;So now the problem isn’t “regex syntax”.&lt;/p&gt;

&lt;p&gt;It’s:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Overlapping matches&lt;/li&gt;
&lt;li&gt;Execution order&lt;/li&gt;
&lt;li&gt;Resetting lastIndex&lt;/li&gt;
&lt;li&gt;Avoiding double mutation&lt;/li&gt;
&lt;li&gt;Preventing nested &lt;code&gt;&amp;lt;mark&amp;gt;&lt;/code&gt; elements&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Step 4: Two Passes?
&lt;/h2&gt;

&lt;p&gt;At one point I thought:&lt;/p&gt;

&lt;p&gt;Maybe this shouldn’t be one regex.&lt;/p&gt;

&lt;p&gt;Maybe the logic should be:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Try phrase match&lt;/li&gt;
&lt;li&gt;If none found, then try token match&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Which sounds simple…&lt;/p&gt;

&lt;p&gt;Until you realise your DOM has already been mutated once.&lt;/p&gt;

&lt;p&gt;Now you’re managing state across passes.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Realisation
&lt;/h2&gt;

&lt;p&gt;I understand JavaScript logic.&lt;/p&gt;

&lt;p&gt;I understand regex.&lt;/p&gt;

&lt;p&gt;But applying that logic safely across a live DOM tree?&lt;/p&gt;

&lt;p&gt;That’s a different tier of problem.&lt;/p&gt;

&lt;p&gt;Regex is deterministic.&lt;br&gt;
The DOM is structural and stateful.&lt;/p&gt;

&lt;p&gt;And once you start replacing text nodes, everything becomes delicate.&lt;/p&gt;




&lt;p&gt;What I Learned&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Regex problems are easy in isolation.&lt;/li&gt;
&lt;li&gt;DOM mutation problems are easy in isolation.&lt;/li&gt;
&lt;li&gt;Combining them multiplies complexity.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Also:&lt;/p&gt;

&lt;p&gt;The line between “simple feature” and “mini search engine” is very thin.&lt;/p&gt;

&lt;p&gt;Where I Am Now&lt;/p&gt;

&lt;p&gt;The search works.&lt;/p&gt;

&lt;p&gt;Mostly.&lt;/p&gt;

&lt;p&gt;It highlights.&lt;br&gt;
It skips protected blocks.&lt;br&gt;
It respects structure.&lt;/p&gt;

&lt;p&gt;But it’s not a browser-level &lt;code&gt;Ctrl + F&lt;/code&gt;.&lt;br&gt;
Not yet.&lt;/p&gt;

&lt;p&gt;And that’s the interesting part.&lt;/p&gt;

&lt;p&gt;I now respect the DOM far more than I did before.&lt;/p&gt;

&lt;p&gt;And I never thought I’d say this sentence naturally:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I get the logic of JavaScript.&lt;br&gt;
Making that logic behave predictably inside a living DOM tree is the real challenge.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;There’s still refinement to do.&lt;br&gt;
Edge cases to tame.&lt;br&gt;
State to simplify.&lt;/p&gt;

&lt;p&gt;But that’s the line between “feature complete” and “actually robust.”&lt;/p&gt;

&lt;p&gt;And I’m somewhere in the middle of that line.&lt;/p&gt;

</description>
      <category>regex</category>
      <category>javascript</category>
      <category>webdev</category>
      <category>frontend</category>
    </item>
    <item>
      <title>I Learned More Building One Testimonial System Than From Months of Tutorials</title>
      <dc:creator>Kristieene Knowles</dc:creator>
      <pubDate>Wed, 25 Feb 2026 06:10:40 +0000</pubDate>
      <link>https://dev.to/webweaversworld/i-learned-more-building-one-testimonial-system-than-from-months-of-tutorials-23oo</link>
      <guid>https://dev.to/webweaversworld/i-learned-more-building-one-testimonial-system-than-from-months-of-tutorials-23oo</guid>
      <description>&lt;p&gt;When I first got into web development, it was very much the “web” side of things that pulled me in.&lt;/p&gt;

&lt;p&gt;HTML. CSS. Making something appear on a screen from nothing.&lt;/p&gt;

&lt;p&gt;There’s something powerful about writing a few lines of code and seeing it come alive in a browser. That never really gets old.&lt;/p&gt;

&lt;p&gt;But over time, something shifted.&lt;/p&gt;

&lt;p&gt;I started caring less about just how things looked… and more about how they &lt;em&gt;worked&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;The logic.&lt;br&gt;&lt;br&gt;
The structure.&lt;br&gt;&lt;br&gt;
The “why is this doing that?” moments.&lt;/p&gt;

&lt;p&gt;Recently, I built my own testimonial system for my site. On the surface, that sounds simple. Just a form and some displayed text, right?&lt;/p&gt;

&lt;p&gt;It wasn’t.&lt;/p&gt;

&lt;p&gt;I had to think about:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How the data gets stored
&lt;/li&gt;
&lt;li&gt;How to structure it properly
&lt;/li&gt;
&lt;li&gt;Validation
&lt;/li&gt;
&lt;li&gt;Preventing abuse
&lt;/li&gt;
&lt;li&gt;Connecting front-end to database
&lt;/li&gt;
&lt;li&gt;Triggering actions after submission
&lt;/li&gt;
&lt;li&gt;And making sure it all behaves in production, not just locally
&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;There were moments where I broke it.&lt;br&gt;
Moments where I misunderstood how APIs worked.&lt;br&gt;
Moments where I thought I’d finished… only to realise I hadn’t accounted for edge cases.&lt;/p&gt;

&lt;p&gt;But that’s where the learning really happened.&lt;/p&gt;

&lt;p&gt;I realised something important:&lt;/p&gt;

&lt;p&gt;You don’t become “full-stack” by calling yourself full-stack.&lt;/p&gt;

&lt;p&gt;You become it by building things that force you to learn the layers underneath.&lt;/p&gt;

&lt;p&gt;What started as “I want a testimonials page” turned into:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Working with databases
&lt;/li&gt;
&lt;li&gt;Understanding data flow
&lt;/li&gt;
&lt;li&gt;Thinking about security
&lt;/li&gt;
&lt;li&gt;Writing logic I didn’t think I could write a few years ago &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And honestly? That’s been the most satisfying part.&lt;/p&gt;

&lt;p&gt;Not the polished UI.&lt;br&gt;
Not the final version.&lt;/p&gt;

&lt;p&gt;The messy middle.&lt;/p&gt;

&lt;p&gt;The debugging.&lt;br&gt;
The rewrites.&lt;br&gt;
The moments where something finally clicks.&lt;/p&gt;

&lt;p&gt;I’m still learning. A lot.&lt;/p&gt;

&lt;p&gt;But every time I build something that stretches me a bit further than last time, I feel like I’m actually becoming the developer I wanted to be when I was younger.&lt;/p&gt;

&lt;p&gt;And that’s a good feeling.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>fullstack</category>
      <category>learning</category>
      <category>database</category>
    </item>
    <item>
      <title>Why I Still Build Websites From Scratch in 2026</title>
      <dc:creator>Kristieene Knowles</dc:creator>
      <pubDate>Tue, 24 Feb 2026 05:15:08 +0000</pubDate>
      <link>https://dev.to/webweaversworld/why-i-still-build-websites-from-scratch-in-2026-1b3m</link>
      <guid>https://dev.to/webweaversworld/why-i-still-build-websites-from-scratch-in-2026-1b3m</guid>
      <description>&lt;p&gt;In a world of drag-and-drop builders, AI site generators, and one-click themes, choosing to build websites from scratch can feel unnecessary.&lt;/p&gt;

&lt;p&gt;But I still do.&lt;/p&gt;

&lt;p&gt;I run an independent studio, Web Weavers World, where every site is hand-coded. No templates. No visual builders. No plugin stacks layered on top of each other.&lt;/p&gt;

&lt;p&gt;That’s not because modern tools are “bad.” They’re incredibly useful. They solve real problems.&lt;/p&gt;

&lt;p&gt;I just value control.&lt;/p&gt;

&lt;p&gt;When I build from scratch, I know exactly:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What loads and when&lt;/li&gt;
&lt;li&gt;Why a layout behaves the way it does&lt;/li&gt;
&lt;li&gt;How performance is impacted&lt;/li&gt;
&lt;li&gt;What the accessibility trade-offs are&lt;/li&gt;
&lt;li&gt;Which scripts are truly necessary&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There’s no mystery layer.&lt;/p&gt;

&lt;p&gt;Performance matters to me. Not just Lighthouse scores, but real-world responsiveness. Clean architecture matters. Maintainability matters. Accessibility matters.&lt;/p&gt;

&lt;p&gt;And honestly ~ I enjoy it.&lt;/p&gt;

&lt;p&gt;There’s something satisfying about understanding every moving part of a system you built. From the CSS structure to the backend logic to the analytics tracking.&lt;/p&gt;

&lt;p&gt;It also forces better decisions.&lt;/p&gt;

&lt;p&gt;When you don’t have a plugin to solve everything, you think more carefully about whether something needs to exist at all.&lt;/p&gt;

&lt;p&gt;That constraint is valuable.&lt;/p&gt;

&lt;p&gt;I’m not anti-tool. I use modern workflows, automation, and analytics daily. But I choose intentional complexity over hidden complexity.&lt;/p&gt;

&lt;p&gt;That’s why I still build websites from scratch in 2026.&lt;/p&gt;

&lt;p&gt;Curious how others approach this ~ are you all-in on frameworks and builders, or do you still enjoy the raw build process too?&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>frontend</category>
      <category>performance</category>
      <category>indiedev</category>
    </item>
  </channel>
</rss>
