<?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: Marceli Pawliński</title>
    <description>The latest articles on DEV Community by Marceli Pawliński (@marceli).</description>
    <link>https://dev.to/marceli</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%2F4167446%2Fc3b4c9e9-5348-4248-9a2b-3a55bf414e73.jpg</url>
      <title>DEV Community: Marceli Pawliński</title>
      <link>https://dev.to/marceli</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/marceli"/>
    <language>en</language>
    <item>
      <title>Sloth Mode: local Gemma turns a brain dump into one small next step</title>
      <dc:creator>Marceli Pawliński</dc:creator>
      <pubDate>Thu, 22 Oct 2026 08:37:51 +0000</pubDate>
      <link>https://dev.to/marceli/sloth-mode-i-built-a-local-gemma-assistant-so-my-brain-can-be-a-little-lazier-ci4</link>
      <guid>https://dev.to/marceli/sloth-mode-i-built-a-local-gemma-assistant-so-my-brain-can-be-a-little-lazier-ci4</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/hacktoberfest-week3-2026-10-19"&gt;Hacktoberfest Open-Source AI Challenge Week 3: Slow and Steady&lt;/a&gt;.&lt;/em&gt; 🦥&lt;/p&gt;

&lt;p&gt;Pay the electricity bill tomorrow. Read a chapter when I have time. I already tidied the desk.&lt;/p&gt;

&lt;p&gt;A to-do list can hold all three. I still have to decide what matters, what can wait, and what no longer needs doing. On a tired day, organising the list becomes another task on the list.&lt;/p&gt;

&lt;p&gt;I built &lt;strong&gt;Sloth Mode&lt;/strong&gt; to make that first decision smaller: put rough notes in one place, let a local Gemma model suggest a plan, then choose what to do with it. The private notes can stay on the computer doing the thinking.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;Sloth Mode is a task companion for the loose ends you capture before you know what to do with them. Gemma suggests a priority, category, short summary and next action for each selected note. Each suggestion points back to its original note, so you can check the wording before accepting it.&lt;/p&gt;

&lt;p&gt;It is for someone who wants help starting without first maintaining an elaborate productivity system. The model drafts the organisation; the person can edit, ignore or act on it. Sloth Mode does not send messages or execute the suggested tasks.&lt;/p&gt;

&lt;p&gt;There are three ways to explore it:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Route&lt;/th&gt;
&lt;th&gt;What happens&lt;/th&gt;
&lt;th&gt;What you need&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Quiet Lab&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;An illustrative, rules-based preview of the interaction&lt;/td&gt;
&lt;td&gt;A browser; no account or download&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Native Gemma&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Real Gemma 3 GGUF inference through a local Go companion and &lt;code&gt;llama.cpp&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Windows preview or experimental Linux build; separate model/runtime download and explicit browser pairing&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Browser Gemma beta&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;An experimental Gemma 4 E2B path using WebGPU/LiteRT-LM&lt;/td&gt;
&lt;td&gt;Compatible hardware/browser and an approved model download of about 2 GB; wider compatibility is still unverified&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;An optional account holds a &lt;strong&gt;separate&lt;/strong&gt; list of tasks you explicitly save there. Signing in does not silently upload the local inbox or grant access to the companion.&lt;/p&gt;

&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://sloth.marceli.dev/dashboard" rel="noopener noreferrer"&gt;Try the guest workspace →&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Start with Quiet Lab and its sample notes. It is the quickest way to understand the interaction, and it is labelled as a preview: &lt;strong&gt;it does not call Gemma&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Watch the actual local model run
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://raw.githubusercontent.com/marceli1404/sloth-mode/f73cfc4a01b6cbb672cac174aaa004dbe6d0b6fe/docs/evidence/2026-10-24/real-browser-gemma-uncut.mp4" rel="noopener noreferrer"&gt;Download the uncut 41-second recording (MP4, 1.7 MB)&lt;/a&gt;&lt;/strong&gt;&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fw3bdrz3p3kmizvfk7niu.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fw3bdrz3p3kmizvfk7niu.png" alt="Actual browser results from four fictional notes: two Do next suggestions, one Save for later and one No action, with a warning to check timing in the original notes." width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The recording shows a browser paired with the real Go companion, Gemma 3 4B Q4_K_M running through &lt;code&gt;llama.cpp&lt;/code&gt;, and the resulting suggestions. It then checks editing, export and reconnecting after a reload. Clicking Plan to seeing results took &lt;strong&gt;25.063 seconds&lt;/strong&gt;, including model loading and UI polling, with four CPU threads and zero GPU layers. The files were already installed.&lt;/p&gt;

&lt;p&gt;The lab report due before 4 PM today and the borrowed book due tomorrow both become Do next. Optional reading becomes Save for later; an already submitted form becomes No action. Gemma still drops timing from the first two suggestions. The status points to their original notes so the person reviewing the plan can catch it.&lt;/p&gt;

&lt;p&gt;This uses a labelled local copy of the workspace, fictional notes and the production pairing/planning handlers. It is actual model output, with no mocked planning responses, cuts or speed changes. It does &lt;strong&gt;not&lt;/strong&gt; demonstrate a clean installation, model download or machine-wide offline operation. The &lt;a href="https://github.com/marceli1404/sloth-mode/blob/f73cfc4a01b6cbb672cac174aaa004dbe6d0b6fe/docs/evidence/2026-10-24/README.md" rel="noopener noreferrer"&gt;recording notes, raw responses and reproduction steps&lt;/a&gt; make that boundary explicit.&lt;/p&gt;

&lt;p&gt;The earlier promotional overview remains available:&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/GnaEFKQW9Vw" width="710" height="399"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This is a promotional overview, separate from the real-model recording above.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Trying the native path
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Get the &lt;strong&gt;&lt;a href="https://github.com/marceli1404/sloth-mode/actions/runs/40133971950" rel="noopener noreferrer"&gt;refined Windows preview and SHA-256&lt;/a&gt;&lt;/strong&gt; under &lt;strong&gt;Artifacts → SlothMode-Windows-Preview&lt;/strong&gt;. GitHub may require a login. This is an unsigned candidate from PR #34; you can also build from that source.&lt;/li&gt;
&lt;li&gt;Install the companion for your Windows account. Open &lt;strong&gt;Setup &amp;amp; Pairing&lt;/strong&gt;, then pair the browser you trust.&lt;/li&gt;
&lt;li&gt;Separately approve the Gemma model and runtime download. Use fictional notes for your first plan and review the suggestions.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The native model download is several GB, depending on the quantization. An account and Ollama are not required. The &lt;a href="https://github.com/marceli1404/sloth-mode/blob/48ac371f572405051fe1267f4067940902d3f524/docs/WEEK3_JUDGES_QUICKSTART.md" rel="noopener noreferrer"&gt;judges' quickstart&lt;/a&gt; includes an opt-in real-model test for a machine with those files installed.&lt;/p&gt;

&lt;p&gt;On 24 October I also refined the installer. Its old preview clipped text and made it too hard to see what would happen next. The &lt;a href="https://github.com/marceli1404/sloth-mode/pull/34" rel="noopener noreferrer"&gt;new candidate in PR #34&lt;/a&gt; separates installation, browser pairing and the optional model download, with readable status and a layout that fits the monitor. The linked candidate passes Linux, Windows and cloud CI plus CodeQL checks. A full clean-profile installation and pairing run for this candidate is still pending.&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F36ftt7evur4hn2k3356r.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F36ftt7evur4hn2k3356r.jpg" alt="Sloth Mode's refined native Windows installer, with three setup steps, an optional sign-in launch checkbox and a primary Install &amp;amp; open button. The window is labelled as a layout preview with installation actions inactive." width="800" height="642"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The actual native UI in a safe layout fixture. This image demonstrates the interface, not a completed installation or inference run.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Code
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/marceli1404/sloth-mode/tree/511bc0fe58479896adcac475951b5a6c3a8e3087" rel="noopener noreferrer"&gt;Source for the tested Windows candidate&lt;/a&gt;&lt;/strong&gt; · &lt;a href="https://github.com/marceli1404/sloth-mode" rel="noopener noreferrer"&gt;Repository main&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The Go companion is in &lt;code&gt;connector/&lt;/code&gt;, the Windows installer in &lt;code&gt;installer/&lt;/code&gt;, the browser workspace in &lt;code&gt;web/&lt;/code&gt;, and the reference account service in &lt;code&gt;cloud/&lt;/code&gt;. Application code is MIT-licensed; Gemma weights and the runtime retain their own terms.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://github.com/marceli1404/sloth-mode/commit/0a51feca7a22a0b3ce06a5585740c8219f842e70" rel="noopener noreferrer"&gt;first commit&lt;/a&gt; is dated 20 October 2026, inside the Week 3 build window. The &lt;a href="https://github.com/marceli1404/sloth-mode/pull/34" rel="noopener noreferrer"&gt;installer refinement and evaluation files&lt;/a&gt; are reviewable separately from main. The live website is deployed separately too; cloning the reference account Worker does not recreate every production account binding.&lt;/p&gt;

&lt;h2&gt;
  
  
  How I Built It
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Keep the private work on the computer
&lt;/h3&gt;

&lt;p&gt;The native path is straightforward:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Browser workspace
  -&amp;gt; explicit pairing with 127.0.0.1
  -&amp;gt; Go companion reads selected local notes
  -&amp;gt; Gemma 3 GGUF runs through llama.cpp
  -&amp;gt; validate structured suggestions and original note IDs
  -&amp;gt; show the plan for a person to review
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Model weights and runtime archives are downloaded separately after approval and checked against expected hashes. The local service binds to loopback. A cloud sign-in is not a replacement for pairing with that service.&lt;/p&gt;

&lt;p&gt;The validator checks IDs and structure before accepting a plan. It can reject an invented or duplicate note ID. It cannot prove that a fluent summary kept every important detail.&lt;/p&gt;

&lt;h3&gt;
  
  
  Valid JSON is not a good plan
&lt;/h3&gt;

&lt;p&gt;The first three-note run made the bill less urgent and treated optional reading as requiring no action. Explicit priority rules and examples helped, but another run paired an actionable bill with “No action needed.” That was a useful reminder to check both the label and the proposed action.&lt;/p&gt;

&lt;p&gt;On 24 October I froze &lt;strong&gt;12 new fictional notes and their expected priorities before inference&lt;/strong&gt;, then ran the baseline and candidate once each with the same existing model, four CPU threads, zero GPU layers and temperature zero.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Check&lt;/th&gt;
&lt;th&gt;Baseline&lt;/th&gt;
&lt;th&gt;Candidate&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Matches the predefined priority&lt;/td&gt;
&lt;td&gt;9/12&lt;/td&gt;
&lt;td&gt;12/12&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Repeats recognised timing in the summary or next action&lt;/td&gt;
&lt;td&gt;0/9&lt;/td&gt;
&lt;td&gt;1/9&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Restoring explicit priority rules helped this small set. The second row is the unresolved problem: correct labels can hide missing details. A limited English phrase check now flags actionable suggestions that omit recognised timing and points back to their source notes. All &lt;strong&gt;seven&lt;/strong&gt; such omissions in the candidate's recorded output trigger that warning. It does not calculate dates, understand every deadline or repair the model's wording.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://github.com/marceli1404/sloth-mode/blob/f73cfc4a01b6cbb672cac174aaa004dbe6d0b6fe/docs/evidence/2026-10-24/inputs.json" rel="noopener noreferrer"&gt;frozen inputs&lt;/a&gt;, &lt;a href="https://github.com/marceli1404/sloth-mode/blob/f73cfc4a01b6cbb672cac174aaa004dbe6d0b6fe/docs/evidence/2026-10-24/candidate-results.json" rel="noopener noreferrer"&gt;raw candidate output&lt;/a&gt; and &lt;a href="https://github.com/marceli1404/sloth-mode/blob/f73cfc4a01b6cbb672cac174aaa004dbe6d0b6fe/docs/evidence/2026-10-24/README.md" rel="noopener noreferrer"&gt;scoring method&lt;/a&gt; are public. Categories were not scored. These 12 examples are functional checks, not a representative accuracy benchmark or a measurement of effort saved.&lt;/p&gt;

&lt;p&gt;The older evaluation is a different 12-note set: its baseline matched 12/12 priorities, while a timing-preservation experiment fell to 11/12. Those &lt;a href="https://github.com/marceli1404/sloth-mode/tree/564f4a3dd5364cfe191eb22b3dcd40cc5a4be5ba/docs/evaluation" rel="noopener noreferrer"&gt;historical inputs and outputs&lt;/a&gt; remain published, including their missing prompt snapshot. I keep them separate from the new frozen comparison.&lt;/p&gt;

&lt;h3&gt;
  
  
  Keep suggestions attached to the right draft
&lt;/h3&gt;

&lt;p&gt;A person can edit a note while a local model is still thinking. Applying the old answer to the new wording would make the plan misleading. The companion now checks the entire input snapshot under the storage lock before saving suggestions. If any input was edited, completed, deleted or already classified, it rejects the batch without saving a partial plan. Capturing an unrelated new note is allowed. Regression tests cover those cases and confirm that rejected batches leave the notes file unchanged.&lt;/p&gt;

&lt;h3&gt;
  
  
  Setup deserves the same care
&lt;/h3&gt;

&lt;p&gt;A local model is not useful if getting it running feels like another project. The installer refinement uses explicit font roles, consistent backgrounds and DPI-aware fitting. Installation and update work run off the UI thread, failed replacement can restore the previous app, and starting a process alone does not count as success: the installer checks the companion's local health response.&lt;/p&gt;

&lt;p&gt;The new candidate passes &lt;strong&gt;12 installer tests&lt;/strong&gt;, connector tests, Windows builds and static analysis. Text fitting and window bounds are checked at multiple scales; the native layout, Tab focus and Escape were also inspected. Those checks do not substitute for installing the candidate on a clean profile. The &lt;a href="https://github.com/marceli1404/sloth-mode/blob/f7eccd89470a16b604fe50e2c0c9010cc0f470fa/docs/INSTALLER_REFINEMENT_2026-10-24.md" rel="noopener noreferrer"&gt;verification report&lt;/a&gt; distinguishes them.&lt;/p&gt;

&lt;p&gt;Final preparation also caught a Q6 output-format failure: Gemma combined priority and category as &lt;code&gt;now/work&lt;/code&gt;. I replaced the shorthand examples, constrained decoding to the expected schema, and retested the failing fictional note through the live site. The &lt;a href="https://github.com/marceli1404/sloth-mode/blob/f49c05c7a1813e1eab2633c9afa3b5111df60354/docs/FINAL_ACCEPTANCE_2026-10-24.md" rel="noopener noreferrer"&gt;acceptance notes&lt;/a&gt; include a three-note CPU run and distinguish an existing-profile upgrade from clean-install and offline testing.&lt;/p&gt;

&lt;p&gt;On 25 October, the final local Windows build passed an existing-profile upgrade, normal exit and relaunch, live-browser reconnect and real Q6 CPU inference with a fictional note. The installed executable matched its packaged checksum; personal notes and the launch-at-sign-in setting were unchanged. The model still omitted timing from that note, and the live UI flagged the omission beside its source. The &lt;a href="https://github.com/marceli1404/sloth-mode/blob/f49c05c7a1813e1eab2633c9afa3b5111df60354/docs/FINAL_ACCEPTANCE_2026-10-24.md#final-installed-candidate-acceptance--25-october" rel="noopener noreferrer"&gt;final installed-build report and synthetic output&lt;/a&gt; record what passed. This was not a clean-profile or network-off test, and the separately compiled CI download was not installed in that run.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Does Open Innovation Matter?
&lt;/h2&gt;

&lt;p&gt;For a private task inbox, where the model runs matters. Open-weight Gemma and &lt;code&gt;llama.cpp&lt;/code&gt; let the companion process the notes locally, without a hosted inference account or a per-prompt API bill. There are still costs: memory, storage, electricity and the initial download.&lt;/p&gt;

&lt;p&gt;It also lets me inspect the prompt, change quantization and runtime settings, and repeat the same fictional cases. The deadline failure above is visible in the published output. Someone else can study it or change the handling rather than trusting a screenshot of the best result.&lt;/p&gt;

&lt;p&gt;After downloading the model and runtime, native inference can run without an internet connection. Earlier Windows previews have an &lt;a href="https://github.com/marceli1404/sloth-mode/issues/8#issuecomment-6328830871" rel="noopener noreferrer"&gt;owner-reported successful offline/restart/persistence check&lt;/a&gt;. That is one person's report on older builds; the final local build has passed the upgrade and CPU checks above, while independent clean-profile and offline acceptance remain open. The hosted website and account services continue to need connectivity.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Lazy Payoff
&lt;/h2&gt;

&lt;p&gt;The effort I want to remove is the sorting between “I should remember this” and “here is one thing I can start.” Gemma drafts priorities and next actions so I have something small to review.&lt;/p&gt;

&lt;p&gt;I have not measured minutes saved per day or run a multi-user study. My evidence is narrower: a real browser-to-model recording, predefined fictional examples with their failures, a working guest preview, and owner experience on one Windows environment. A useful next study would compare manual sorting with assisted sorting on the same fictional backlog, including review time, mistakes and setup cost.&lt;/p&gt;

&lt;p&gt;This is still a public beta. Signed installers, independent native security review, wider Linux/GPU coverage, a clean-install recording and independent offline acceptance remain unfinished. Browser Gemma is experimental. The &lt;a href="https://github.com/marceli1404/sloth-mode/blob/main/docs/RELEASE_VALIDATION.md" rel="noopener noreferrer"&gt;release checklist&lt;/a&gt; keeps those gaps visible.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prize Categories
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Best Use of Gemma.&lt;/strong&gt; Gemma does the native task planning, with its suggestions tied to the notes that prompted them. The browser beta explores a separate Gemma execution path; the no-download preview is clearly labelled as illustrative.&lt;/p&gt;

&lt;p&gt;If that sounds useful, &lt;a href="https://sloth.marceli.dev/dashboard" rel="noopener noreferrer"&gt;try the guest workspace&lt;/a&gt; or &lt;a href="https://github.com/marceli1404/sloth-mode/issues/30" rel="noopener noreferrer"&gt;report what breaks&lt;/a&gt; using fictional notes. I wanted a tool that makes the next task feel smaller. That is the test I want Sloth Mode to pass.&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>hf26challenge</category>
      <category>ai</category>
      <category>opensource</category>
    </item>
    <item>
      <title>A Browser Automation CLI Is a Security Boundary, Not Just a Convenience Tool</title>
      <dc:creator>Marceli Pawliński</dc:creator>
      <pubDate>Sat, 10 Oct 2026 13:59:43 +0000</pubDate>
      <link>https://dev.to/marceli/a-browser-automation-cli-is-a-security-boundary-not-just-a-convenience-tool-4h2b</link>
      <guid>https://dev.to/marceli/a-browser-automation-cli-is-a-security-boundary-not-just-a-convenience-tool-4h2b</guid>
      <description>&lt;p&gt;I like tools that make tedious tasks shorter. One of my projects, &lt;a href="https://github.com/marceli1404/browser-harness" rel="noopener noreferrer"&gt;browser-harness&lt;/a&gt;, is a command-line wrapper around browser automation: open a page, extract text, take a screenshot, fill a form, or run JavaScript in a page. Building it exposed different parts of how browsers work.&lt;/p&gt;

&lt;p&gt;But reviewing a browser tool through a security lens raises a less comfortable question: &lt;strong&gt;who gets to decide what the browser is allowed to do?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That matters even more when an AI agent is choosing commands. An automated workflow might accept the next URL or instruction without questioning it.&lt;/p&gt;

&lt;p&gt;This article is a review of the design trade-offs visible in my public repository, not an announcement that I've fixed them all. The standalone project is kept for reference; its README points to &lt;code&gt;system-automation&lt;/code&gt; for newer development.&lt;/p&gt;

&lt;h2&gt;
  
  
  The convenience is real
&lt;/h2&gt;

&lt;p&gt;The CLI exposes commands such as &lt;code&gt;open&lt;/code&gt;, &lt;code&gt;text&lt;/code&gt;, &lt;code&gt;screenshot&lt;/code&gt;, &lt;code&gt;fill&lt;/code&gt;, &lt;code&gt;cookies&lt;/code&gt;, and &lt;code&gt;exec&lt;/code&gt;. Those operations look like small, separate utilities, but they share something important: each is acting with the authority of a browser process.&lt;/p&gt;

&lt;p&gt;Screenshots can capture sensitive information; cookies can reveal sessions; forms can change remote state. Page JavaScript gives the caller access to the live document and browser APIs.&lt;/p&gt;

&lt;p&gt;Those capabilities are useful. The problem is treating them as interchangeable without distinguishing observation from action.&lt;/p&gt;

&lt;h2&gt;
  
  
  Read-only is a useful distinction, but not a guarantee
&lt;/h2&gt;

&lt;p&gt;For an agent, I would start by dividing browser operations into three groups:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Observation:&lt;/strong&gt; read a page title, extract visible text, inspect public metadata.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Potentially sensitive observation:&lt;/strong&gt; screenshots, cookies, authenticated page content.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;State-changing or privileged actions:&lt;/strong&gt; form submissions, clicks that trigger transactions, downloads, arbitrary page JavaScript.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The categories aren't perfect: even a GET request may have side effects, and screenshots can reveal private information. But explicit categories are better than none.&lt;/p&gt;

&lt;p&gt;A practical interface could label an action before execution and require an additional approval step for sensitive reads or writes. Logs could then record the action, target origin, category and approval.&lt;/p&gt;

&lt;h2&gt;
  
  
  A URL is input, not permission
&lt;/h2&gt;

&lt;p&gt;One weakness to watch for in any browser automation interface is unrestricted navigation. If an agent receives a URL from an untrusted page and immediately opens it, the page has influenced where the agent goes next.&lt;/p&gt;

&lt;p&gt;An allowlist can reduce that risk. At minimum, normalise and parse the destination before comparing it with the permitted origins:&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;isAllowedDestination&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;allowedOrigins&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;url&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;URL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;false&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="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;protocol&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;protocol&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;http:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
    &lt;span class="nx"&gt;allowedOrigins&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;has&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;origin&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 is only a starting point. Real implementations also need to check redirects, DNS and network destinations where relevant, and the difference between a public website and a local or private address. A valid URL is not necessarily a permitted destination.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;exec&lt;/code&gt; changes the trust model
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;exec&lt;/code&gt; command in my repository is a useful example. It accepts JavaScript to run in the page context. That's flexible for debugging and extracting information, but it also means the caller is no longer limited to a small set of predefined operations.&lt;/p&gt;

&lt;p&gt;If the caller is an AI agent that has read instructions from a webpage, the risk is not simply that the agent might make a mistake. The webpage may contain instructions designed to redirect the agent's behaviour. That's a prompt-injection problem crossing into browser privileges.&lt;/p&gt;

&lt;p&gt;For a safer agent-facing design, I would avoid offering unrestricted script execution as the default. Prefer narrowly scoped commands with defined inputs and outputs. If arbitrary execution is necessary, keep it behind a separate permission boundary, restrict the environment, and record exactly what was run. Cookie export needs similarly strict treatment.&lt;/p&gt;

&lt;h2&gt;
  
  
  Headless browser flags deserve attention too
&lt;/h2&gt;

&lt;p&gt;The current public &lt;code&gt;browser.js&lt;/code&gt; includes a launch configuration with &lt;code&gt;--no-sandbox&lt;/code&gt;. This is common in constrained container examples, but it is not a security improvement. Removing the browser sandbox weakens an important layer of isolation.&lt;/p&gt;

&lt;p&gt;A production design should prefer running with the sandbox enabled wherever the environment supports it. If a deployment genuinely requires a different configuration, that exception should be documented and constrained by other isolation measures. Convenience flags can outlive their original justification.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I would test before trusting an agent with it
&lt;/h2&gt;

&lt;p&gt;I would build a small test matrix rather than rely on one happy-path demo:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A normal page with a valid title and visible text.&lt;/li&gt;
&lt;li&gt;A page that redirects to an origin outside the allowlist.&lt;/li&gt;
&lt;li&gt;A page containing instructions that try to change the agent's task.&lt;/li&gt;
&lt;li&gt;A form where submission must be explicitly authorised.&lt;/li&gt;
&lt;li&gt;An authenticated page containing data that must not appear in logs.&lt;/li&gt;
&lt;li&gt;A navigation timeout or browser crash, followed by cleanup.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Those are proposed tests, not results I'm claiming to have run. Each should have an expected decision and an observable reason for it. A blocked action is a successful outcome when blocking was the intended policy.&lt;/p&gt;

&lt;h2&gt;
  
  
  The lesson I keep returning to
&lt;/h2&gt;

&lt;p&gt;Automation is often described in terms of what it can do. I think the more useful question is what it should refuse to do without additional context.&lt;/p&gt;

&lt;p&gt;Building browser-harness helped me understand the mechanics of controlling a browser. Reviewing it this way makes the next design problem clearer: a good agent tool needs capabilities, but it also needs boundaries, predictable failures, and evidence of what happened.&lt;/p&gt;

&lt;p&gt;The repository is public if you want to inspect the commands and make your own assessment: &lt;a href="https://github.com/marceli1404/browser-harness" rel="noopener noreferrer"&gt;marceli1404/browser-harness&lt;/a&gt;. I'd be interested in how other developers separate safe inspection from privileged browser actions.&lt;/p&gt;

</description>
      <category>security</category>
      <category>javascript</category>
      <category>webdev</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Why a 200 OK Doesn't Mean Your Website Is Healthy</title>
      <dc:creator>Marceli Pawliński</dc:creator>
      <pubDate>Fri, 09 Oct 2026 08:57:55 +0000</pubDate>
      <link>https://dev.to/marceli/why-a-200-ok-doesnt-mean-your-website-is-healthy-2044</link>
      <guid>https://dev.to/marceli/why-a-200-ok-doesnt-mean-your-website-is-healthy-2044</guid>
      <description>&lt;p&gt;I used to think that checking whether a website worked was fairly straightforward: send a request, get a successful response, and move on.&lt;/p&gt;

&lt;p&gt;The more I work on web tooling, the less useful that definition feels.&lt;/p&gt;

&lt;p&gt;An HTTP &lt;code&gt;200 OK&lt;/code&gt; response answers one narrow question: &lt;strong&gt;did the server successfully handle this particular HTTP request?&lt;/strong&gt; It does not tell you whether the website is secure, accessible, fast, searchable, or even useful to a visitor.&lt;/p&gt;

&lt;p&gt;That distinction is part of what interests me about building &lt;a href="https://zenith.me.uk" rel="noopener noreferrer"&gt;Zenith&lt;/a&gt;, a project focused on monitoring and improving websites. A meaningful website check needs to look beyond a green status indicator.&lt;/p&gt;

&lt;p&gt;Here are five layers I would examine, and how I'd begin testing them.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Availability isn't the same as usability
&lt;/h2&gt;

&lt;p&gt;Try:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-I&lt;/span&gt; https://example.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The response can tell you about status codes and headers. It cannot tell you whether a sign-in button works, whether a critical API fails after the page loads, or whether a JavaScript error prevents users from completing an action.&lt;/p&gt;

&lt;p&gt;In fact, &lt;code&gt;curl -I&lt;/code&gt; makes a HEAD request. Some servers handle HEAD differently from GET, so it's useful as a quick inspection tool, not as complete proof of normal page behaviour.&lt;/p&gt;

&lt;p&gt;For a more realistic picture, check more than one endpoint and include an actual browser journey. For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Can the homepage load?&lt;/li&gt;
&lt;li&gt;Can a visitor navigate to an important page?&lt;/li&gt;
&lt;li&gt;Can a non-destructive form validation flow complete?&lt;/li&gt;
&lt;li&gt;Does the browser report failed requests or JavaScript errors?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;An uptime check is a starting point, not a quality score.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. HTTPS is necessary, but it doesn't finish the security job
&lt;/h2&gt;

&lt;p&gt;A padlock indicates that a connection is protected by TLS under the browser's trust rules. That's important. It isn't a certificate of application security.&lt;/p&gt;

&lt;p&gt;Look at response headers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-sSI&lt;/span&gt; https://example.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Things worth reviewing include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Strict-Transport-Security:&lt;/strong&gt; helps instruct browsers to use HTTPS for future connections.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Content-Security-Policy:&lt;/strong&gt; can reduce the impact of certain injection attacks when configured carefully.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;X-Content-Type-Options:&lt;/strong&gt; with &lt;code&gt;nosniff&lt;/code&gt;, can prevent some MIME-type confusion.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cookie attributes:&lt;/strong&gt; &lt;code&gt;Secure&lt;/code&gt;, &lt;code&gt;HttpOnly&lt;/code&gt;, and &lt;code&gt;SameSite&lt;/code&gt; matter for session handling.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Presence isn't enough. For example, a CSP that broadly permits unsafe inline scripts may provide less protection than its name suggests. And missing a header does not automatically mean a site is exploitable: context matters.&lt;/p&gt;

&lt;p&gt;Also, please don't run intrusive security scans against sites you don't own or have permission to assess. Public response-header inspection and authorised testing are different things from attempting exploitation.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Accessibility can't be reduced to one automated score
&lt;/h2&gt;

&lt;p&gt;Automated accessibility testing is excellent at catching certain problems: missing accessible names, insufficient contrast in some contexts, structural errors, and more.&lt;/p&gt;

&lt;p&gt;But a passing automated test doesn't mean someone can actually use the interface with a keyboard or screen reader.&lt;/p&gt;

&lt;p&gt;A simple manual starting point:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Put down the mouse.&lt;/li&gt;
&lt;li&gt;Use Tab and Shift+Tab to move between controls.&lt;/li&gt;
&lt;li&gt;Check whether the focus indicator is visible.&lt;/li&gt;
&lt;li&gt;Try the main interaction using the keyboard alone.&lt;/li&gt;
&lt;li&gt;Verify that errors are understandable and connected to the appropriate inputs.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;An interface can look polished and still exclude people. I think that should be considered a functional bug, not just a design issue.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Performance depends on the user, not just the server
&lt;/h2&gt;

&lt;p&gt;A fast server response isn't necessarily a fast experience.&lt;/p&gt;

&lt;p&gt;There are differences between receiving the initial HTML, displaying meaningful content, and making the page responsive to interaction. Large images, render-blocking resources, third-party scripts, and heavy client-side work can change what visitors experience.&lt;/p&gt;

&lt;p&gt;For an initial lab measurement, use Lighthouse in Chrome DevTools. For real-user context, look at Core Web Vitals such as Largest Contentful Paint, Interaction to Next Paint and Cumulative Layout Shift.&lt;/p&gt;

&lt;p&gt;I would always record the device, network conditions, URL, time, and measurement method. Otherwise it becomes too easy to compare two numbers that aren't really comparable.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Being online doesn't mean being discoverable
&lt;/h2&gt;

&lt;p&gt;A search engine has to find, crawl, render where necessary, and understand a page before ranking becomes relevant.&lt;/p&gt;

&lt;p&gt;Some straightforward checks:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-I&lt;/span&gt; https://example.com/robots.txt
curl &lt;span class="nt"&gt;-I&lt;/span&gt; https://example.com/sitemap.xml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Those paths are useful places to look, not universal guarantees. A site may use different sitemap locations, and a successful response does not prove correct content.&lt;/p&gt;

&lt;p&gt;I would also review canonical URLs, titles, meta descriptions, redirect behaviour, indexing directives, and whether important content can be accessed without relying on fragile client-side behaviour.&lt;/p&gt;

&lt;h2&gt;
  
  
  The part I find most useful: evidence before scores
&lt;/h2&gt;

&lt;p&gt;One tempting approach is to merge all these checks into a single score out of 100.&lt;/p&gt;

&lt;p&gt;Scores can be helpful for prioritisation, but they can also hide important details. A critical security configuration problem should not disappear because the site has excellent SEO or performance metrics.&lt;/p&gt;

&lt;p&gt;For every finding, I think a useful report should answer four questions:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;What was observed?&lt;/strong&gt; Include the exact URL, response, test or reproducible behaviour.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Why might it matter?&lt;/strong&gt; Explain the consequence without overstating it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;What should change?&lt;/strong&gt; Give a concrete, proportionate next step.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;How do we verify the fix?&lt;/strong&gt; Repeat the same test, and add a stronger check if needed.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That last point matters most to me. Identifying problems is easy to celebrate. Demonstrating that a change actually solved one is more useful.&lt;/p&gt;

&lt;p&gt;I'm still learning how to make these kinds of checks reliable and understandable. Building website tools keeps revealing the difference between what a system &lt;em&gt;appears&lt;/em&gt; to be doing and what we can actually verify.&lt;/p&gt;

&lt;p&gt;A &lt;code&gt;200 OK&lt;/code&gt; response is good news.&lt;/p&gt;

&lt;p&gt;It just isn't the whole story.&lt;/p&gt;




&lt;p&gt;I'm &lt;a href="https://github.com/marceli1404" rel="noopener noreferrer"&gt;Marceli Pawliński&lt;/a&gt;. I build and experiment with software, cybersecurity, AI and website infrastructure. My main project is &lt;a href="https://zenith.me.uk" rel="noopener noreferrer"&gt;Zenith&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>security</category>
      <category>a11y</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Curiosity Over Comfort</title>
      <dc:creator>Marceli Pawliński</dc:creator>
      <pubDate>Tue, 06 Oct 2026 21:47:16 +0000</pubDate>
      <link>https://dev.to/marceli/curiosity-over-comfort-5cki</link>
      <guid>https://dev.to/marceli/curiosity-over-comfort-5cki</guid>
      <description>&lt;h1&gt;
  
  
  I’m More Interested in Why Things Break Than Why They Work
&lt;/h1&gt;

&lt;p&gt;I don’t think I became interested in technology because I wanted to build apps.&lt;/p&gt;

&lt;p&gt;I think I became interested because I wanted to understand things.&lt;/p&gt;

&lt;p&gt;There’s a difference.&lt;/p&gt;

&lt;p&gt;When something works exactly as expected, there usually isn’t much mystery left.&lt;/p&gt;

&lt;p&gt;You press a button, something happens, and you move on.&lt;/p&gt;

&lt;p&gt;But when something breaks, everything becomes more interesting.&lt;/p&gt;

&lt;p&gt;Why did it fail?&lt;/p&gt;

&lt;p&gt;Was the assumption wrong?&lt;/p&gt;

&lt;p&gt;Was the system badly designed?&lt;/p&gt;

&lt;p&gt;Did someone trust something they shouldn’t have?&lt;/p&gt;

&lt;p&gt;Was the problem in the interface, the network, the database, the user, or somewhere deeper?&lt;/p&gt;

&lt;p&gt;That way of thinking has probably shaped most of what I build.&lt;/p&gt;

&lt;h2&gt;
  
  
  I Like the Parts People Usually Ignore
&lt;/h2&gt;

&lt;p&gt;A lot of software is designed to hide complexity.&lt;/p&gt;

&lt;p&gt;That is normally a good thing.&lt;/p&gt;

&lt;p&gt;Most people do not care how a request is routed, how authentication is validated, how a database transaction is handled or how an AI model receives context.&lt;/p&gt;

&lt;p&gt;They just want the thing to work.&lt;/p&gt;

&lt;p&gt;I tend to get interested in the hidden part.&lt;/p&gt;

&lt;p&gt;I want to know what happens between clicking a button and getting a result.&lt;/p&gt;

&lt;p&gt;I want to know what happens when that process is interrupted.&lt;/p&gt;

&lt;p&gt;I want to know what assumptions the developer made and what happens if those assumptions are wrong.&lt;/p&gt;

&lt;p&gt;That is part of why cybersecurity became interesting to me.&lt;/p&gt;

&lt;p&gt;Security often lives in the gap between what a system appears to do and what it actually allows.&lt;/p&gt;

&lt;h2&gt;
  
  
  Building Things Is Mostly Discovering What You Don’t Know
&lt;/h2&gt;

&lt;p&gt;One of the strangest things about programming is that the more I learn, the less I feel like I know.&lt;/p&gt;

&lt;p&gt;When I started building websites, a website felt fairly simple.&lt;/p&gt;

&lt;p&gt;Frontend.&lt;/p&gt;

&lt;p&gt;Backend.&lt;/p&gt;

&lt;p&gt;Database.&lt;/p&gt;

&lt;p&gt;Done.&lt;/p&gt;

&lt;p&gt;Then you start learning about authentication, caching, queues, rate limits, browser behaviour, network failures, accessibility, search engines, deployment, monitoring, observability and security.&lt;/p&gt;

&lt;p&gt;Suddenly a “simple website” doesn’t seem simple anymore.&lt;/p&gt;

&lt;p&gt;The same thing happened when I started experimenting with AI.&lt;/p&gt;

&lt;p&gt;At first, the interesting part was the model.&lt;/p&gt;

&lt;p&gt;Which one is smarter?&lt;/p&gt;

&lt;p&gt;Which one is faster?&lt;/p&gt;

&lt;p&gt;Which one can run locally?&lt;/p&gt;

&lt;p&gt;Eventually the model became only one small part of the problem.&lt;/p&gt;

&lt;p&gt;A model can be extremely intelligent and still be useless if the system around it is badly designed.&lt;/p&gt;

&lt;p&gt;It needs context.&lt;/p&gt;

&lt;p&gt;It needs tools.&lt;/p&gt;

&lt;p&gt;It needs boundaries.&lt;/p&gt;

&lt;p&gt;It needs a way to fail safely.&lt;/p&gt;

&lt;p&gt;It needs to know what it is allowed to do.&lt;/p&gt;

&lt;p&gt;That is where things get much more interesting.&lt;/p&gt;

&lt;h2&gt;
  
  
  I Don’t Really Separate Learning From Building
&lt;/h2&gt;

&lt;p&gt;I’ve never been very good at learning something just because I’m supposed to know it.&lt;/p&gt;

&lt;p&gt;I understand things much better when I need them.&lt;/p&gt;

&lt;p&gt;If I need a database for a project, I learn about databases.&lt;/p&gt;

&lt;p&gt;If authentication breaks, I learn more about authentication.&lt;/p&gt;

&lt;p&gt;If a website is slow, I start learning about performance.&lt;/p&gt;

&lt;p&gt;If a deployment fails, I learn what the infrastructure is actually doing.&lt;/p&gt;

&lt;p&gt;That process is sometimes inefficient.&lt;/p&gt;

&lt;p&gt;I’ll probably make mistakes that someone with more experience would avoid immediately.&lt;/p&gt;

&lt;p&gt;But those mistakes normally stick with me.&lt;/p&gt;

&lt;p&gt;There is a big difference between reading that something is a bad idea and spending six hours discovering why it is a bad idea.&lt;/p&gt;

&lt;h2&gt;
  
  
  Zenith Is Really an Excuse to Learn
&lt;/h2&gt;

&lt;p&gt;My main project, &lt;a href="https://zenith.me.uk/" rel="noopener noreferrer"&gt;Zenith&lt;/a&gt;, is technically a website monitoring and improvement platform.&lt;/p&gt;

&lt;p&gt;But for me, it is also an excuse to keep exploring problems.&lt;/p&gt;

&lt;p&gt;Security.&lt;/p&gt;

&lt;p&gt;Performance.&lt;/p&gt;

&lt;p&gt;Accessibility.&lt;/p&gt;

&lt;p&gt;SEO.&lt;/p&gt;

&lt;p&gt;Infrastructure.&lt;/p&gt;

&lt;p&gt;Automation.&lt;/p&gt;

&lt;p&gt;AI.&lt;/p&gt;

&lt;p&gt;Databases.&lt;/p&gt;

&lt;p&gt;Product design.&lt;/p&gt;

&lt;p&gt;They all meet in one project.&lt;/p&gt;

&lt;p&gt;I could probably make Zenith much smaller and easier to build.&lt;/p&gt;

&lt;p&gt;That would also make it less interesting.&lt;/p&gt;

&lt;p&gt;I like projects that slowly force me outside what I already know.&lt;/p&gt;

&lt;h2&gt;
  
  
  Open Source Changed How I See Programming
&lt;/h2&gt;

&lt;p&gt;Building your own projects gives you complete control.&lt;/p&gt;

&lt;p&gt;That is both useful and dangerous.&lt;/p&gt;

&lt;p&gt;If something is badly designed, you can always rewrite everything around it.&lt;/p&gt;

&lt;p&gt;Open source removes that freedom.&lt;/p&gt;

&lt;p&gt;When you contribute to someone else’s project, the question is not:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;“How would I build this?”&lt;/strong&gt;&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;“Why did they build it this way?”&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You have to understand before changing.&lt;/p&gt;

&lt;p&gt;You have to work with existing conventions.&lt;/p&gt;

&lt;p&gt;You have to think about the people who already depend on the code.&lt;/p&gt;

&lt;p&gt;I like that.&lt;/p&gt;

&lt;p&gt;It makes programming feel less like writing instructions for a computer and more like working inside a system built by people.&lt;/p&gt;

&lt;h2&gt;
  
  
  I’m Still Figuring Out What I Want to Become
&lt;/h2&gt;

&lt;p&gt;I’m interested in computer science, cybersecurity, AI and systems engineering.&lt;/p&gt;

&lt;p&gt;That is a fairly wide answer.&lt;/p&gt;

&lt;p&gt;For now, I’m okay with that.&lt;/p&gt;

&lt;p&gt;I don’t think I need to decide exactly what I want to specialise in yet.&lt;/p&gt;

&lt;p&gt;I would rather keep following the problems that make me curious.&lt;/p&gt;

&lt;p&gt;The common theme seems to be systems.&lt;/p&gt;

&lt;p&gt;Not just how to build them, but how they behave when something unexpected happens.&lt;/p&gt;

&lt;p&gt;That could mean security.&lt;/p&gt;

&lt;p&gt;It could mean infrastructure.&lt;/p&gt;

&lt;p&gt;It could mean AI systems.&lt;/p&gt;

&lt;p&gt;It could end up being something I haven’t discovered yet.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Goal Isn’t to Know Everything
&lt;/h2&gt;

&lt;p&gt;I used to think being good at technology meant knowing the answer.&lt;/p&gt;

&lt;p&gt;Now I think it is more about knowing what to do when you don’t.&lt;/p&gt;

&lt;p&gt;Can you break a problem apart?&lt;/p&gt;

&lt;p&gt;Can you find the part you don’t understand?&lt;/p&gt;

&lt;p&gt;Can you test your assumptions?&lt;/p&gt;

&lt;p&gt;Can you admit when an idea was wrong?&lt;/p&gt;

&lt;p&gt;Can you keep going when the first solution doesn’t work?&lt;/p&gt;

&lt;p&gt;That matters more to me now than memorising every framework or programming language.&lt;/p&gt;

&lt;p&gt;Technology changes too quickly for that anyway.&lt;/p&gt;

&lt;p&gt;There will always be another tool.&lt;/p&gt;

&lt;p&gt;Another language.&lt;/p&gt;

&lt;p&gt;Another model.&lt;/p&gt;

&lt;p&gt;Another platform.&lt;/p&gt;

&lt;p&gt;The useful part is learning how to learn.&lt;/p&gt;

&lt;p&gt;And preferably building something interesting while doing it.&lt;/p&gt;




&lt;p&gt;I’m Marceli Pawliński.&lt;/p&gt;

&lt;p&gt;I build software, experiment with AI, contribute to open source and spend an unreasonable amount of time trying to understand why things behave the way they do.&lt;/p&gt;

&lt;p&gt;Most of the time, the best place to start is when something breaks.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>webdev</category>
      <category>programming</category>
      <category>productivity</category>
    </item>
    <item>
      <title>About Me: Building, Breaking and Learning Through Software</title>
      <dc:creator>Marceli Pawliński</dc:creator>
      <pubDate>Tue, 06 Oct 2026 21:33:56 +0000</pubDate>
      <link>https://dev.to/marceli/about-me-building-breaking-and-learning-through-software-3el5</link>
      <guid>https://dev.to/marceli/about-me-building-breaking-and-learning-through-software-3el5</guid>
      <description>&lt;h1&gt;
  
  
  About Me: Building, Breaking and Learning Through Software
&lt;/h1&gt;

&lt;p&gt;Hi, I’m Marceli Pawliński.&lt;/p&gt;

&lt;p&gt;I’m a student from Scotland interested in computer science, cybersecurity, artificial intelligence and software engineering.&lt;/p&gt;

&lt;p&gt;Most of what I know has come from building things, breaking them, fixing them, and then realising there was probably a better way to build them in the first place.&lt;/p&gt;

&lt;h2&gt;
  
  
  How I Got Into Computing
&lt;/h2&gt;

&lt;p&gt;Computers have been part of my life for as long as I can remember.&lt;/p&gt;

&lt;p&gt;Over time, that turned from simply using technology into wanting to understand what was happening underneath it.&lt;/p&gt;

&lt;p&gt;I started experimenting with programming, websites, servers, local AI models and cybersecurity.&lt;/p&gt;

&lt;p&gt;The more I learned, the more interested I became in what happens when systems stop behaving the way they are supposed to.&lt;/p&gt;

&lt;p&gt;That is probably the part of computing I enjoy most.&lt;/p&gt;

&lt;p&gt;A system working correctly is useful.&lt;/p&gt;

&lt;p&gt;A system failing in an unexpected way is interesting.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Build
&lt;/h2&gt;

&lt;p&gt;My main project at the moment is &lt;strong&gt;Zenith&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Zenith is a platform designed around one idea:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Monitor, improve and grow your website.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It brings together website monitoring, security checks, performance analysis, accessibility, SEO and growth opportunities.&lt;/p&gt;

&lt;p&gt;Building Zenith has pushed me into areas I probably would not have explored otherwise, including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Cloudflare Workers&lt;/li&gt;
&lt;li&gt;databases&lt;/li&gt;
&lt;li&gt;authentication&lt;/li&gt;
&lt;li&gt;queues&lt;/li&gt;
&lt;li&gt;APIs&lt;/li&gt;
&lt;li&gt;scheduled jobs&lt;/li&gt;
&lt;li&gt;browser automation&lt;/li&gt;
&lt;li&gt;security headers&lt;/li&gt;
&lt;li&gt;rate limiting&lt;/li&gt;
&lt;li&gt;website auditing&lt;/li&gt;
&lt;li&gt;AI-assisted analysis&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It has also taught me that building a product is very different from building a feature.&lt;/p&gt;

&lt;p&gt;A feature can work perfectly on its own and still make no sense inside the wider system.&lt;/p&gt;

&lt;h2&gt;
  
  
  Open Source
&lt;/h2&gt;

&lt;p&gt;I also spend a lot of time on GitHub.&lt;/p&gt;

&lt;p&gt;My GitHub is a mixture of personal projects, experiments and contributions to other repositories.&lt;/p&gt;

&lt;p&gt;One project I’ve been working on is &lt;strong&gt;browser-harness&lt;/strong&gt;, where I’ve been exploring how AI systems can interact more reliably with websites and browser interfaces.&lt;/p&gt;

&lt;p&gt;I also enjoy contributing to existing open-source projects.&lt;/p&gt;

&lt;p&gt;Working on someone else’s code is very different from starting from an empty file.&lt;/p&gt;

&lt;p&gt;You have to understand why something was built a certain way before deciding how to change it.&lt;/p&gt;

&lt;p&gt;Sometimes a useful contribution is only a tiny fix.&lt;/p&gt;

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

&lt;h2&gt;
  
  
  AI and Local Models
&lt;/h2&gt;

&lt;p&gt;I started properly experimenting with large language models around 2023.&lt;/p&gt;

&lt;p&gt;Since then I’ve worked with tools and models including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ollama&lt;/li&gt;
&lt;li&gt;llama.cpp&lt;/li&gt;
&lt;li&gt;LM Studio&lt;/li&gt;
&lt;li&gt;Qwen&lt;/li&gt;
&lt;li&gt;Llama&lt;/li&gt;
&lt;li&gt;DeepSeek&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;At first I was mainly interested in the models themselves.&lt;/p&gt;

&lt;p&gt;Eventually I became more interested in everything around them.&lt;/p&gt;

&lt;p&gt;How does an AI use tools?&lt;/p&gt;

&lt;p&gt;How do you give it permissions safely?&lt;/p&gt;

&lt;p&gt;How does it interact with browsers?&lt;/p&gt;

&lt;p&gt;How do you handle memory?&lt;/p&gt;

&lt;p&gt;How do you stop an automated system from doing something it shouldn’t?&lt;/p&gt;

&lt;p&gt;How do you make it reliable when the real world is unpredictable?&lt;/p&gt;

&lt;p&gt;Those questions are much more interesting to me than simply asking which model has the highest benchmark score.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cybersecurity
&lt;/h2&gt;

&lt;p&gt;Cybersecurity is another major interest of mine.&lt;/p&gt;

&lt;p&gt;I especially like looking at the difference between how secure something appears and how secure it actually is.&lt;/p&gt;

&lt;p&gt;A polished login page does not necessarily mean the backend is secure.&lt;/p&gt;

&lt;p&gt;A website having HTTPS does not mean everything behind it is configured correctly.&lt;/p&gt;

&lt;p&gt;A security feature existing does not mean it has been implemented properly.&lt;/p&gt;

&lt;p&gt;That way of thinking has changed how I approach software development in general.&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;“Does this work?”&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I also try to ask:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;“How could this fail?”&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Learning Outside School
&lt;/h2&gt;

&lt;p&gt;I’m currently studying subjects including Maths and Computer Science, but a lot of my technical learning happens outside the classroom.&lt;/p&gt;

&lt;p&gt;I experiment with my own infrastructure, contribute to GitHub projects, build websites, run local AI models and work through technical certifications.&lt;/p&gt;

&lt;p&gt;I’ve also completed learning in areas including AI literacy and introductory cybersecurity.&lt;/p&gt;

&lt;p&gt;I like structured learning, but I learn best when I can actually use something.&lt;/p&gt;

&lt;p&gt;Reading about databases is useful.&lt;/p&gt;

&lt;p&gt;Designing one badly, discovering the problems and then fixing it teaches you something different.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Want to Do
&lt;/h2&gt;

&lt;p&gt;Long term, I want to work somewhere around the intersection of:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;AI, cybersecurity, systems and computer science.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I’m still figuring out exactly what that looks like.&lt;/p&gt;

&lt;p&gt;That is partly why I build so many different things.&lt;/p&gt;

&lt;p&gt;Every project gives me a slightly better idea of what I enjoy, what I’m good at, and what I still need to understand.&lt;/p&gt;

&lt;p&gt;Right now, I’m focused on improving Zenith, contributing more to open source and continuing to build projects that force me to learn things I don’t already know.&lt;/p&gt;

&lt;p&gt;If something breaks along the way, that normally makes it more interesting.&lt;/p&gt;




&lt;h3&gt;
  
  
  Find me
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;GitHub:&lt;/strong&gt; github.com/marceli1404&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Website:&lt;/strong&gt; marcelipawlinski.co.uk&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Zenith:&lt;/strong&gt; zenith.me.uk&lt;/p&gt;

&lt;p&gt;I’ll be writing here about software development, cybersecurity, AI, open source, website infrastructure and whatever I happen to be experimenting with next.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>webdev</category>
      <category>programming</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Building Zenith: What I’ve Learned From Turning Side Projects Into Real Software</title>
      <dc:creator>Marceli Pawliński</dc:creator>
      <pubDate>Tue, 06 Oct 2026 21:30:18 +0000</pubDate>
      <link>https://dev.to/marceli/building-zenith-what-ive-learned-from-turning-side-projects-into-real-software-30h5</link>
      <guid>https://dev.to/marceli/building-zenith-what-ive-learned-from-turning-side-projects-into-real-software-30h5</guid>
      <description>&lt;h1&gt;
  
  
  Building Zenith: What I’ve Learned From Turning Side Projects Into Real Software
&lt;/h1&gt;

&lt;p&gt;I’ve built a lot of small projects over the years.&lt;/p&gt;

&lt;p&gt;Some lasted a few hours. Some turned into GitHub repositories I still work on. Others eventually became part of something much bigger.&lt;/p&gt;

&lt;p&gt;Zenith is probably the best example of that.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Zenith?
&lt;/h2&gt;

&lt;p&gt;Zenith started from a fairly simple idea:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What if checking the health of a website didn’t require five different tools?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A website can be online and still have plenty wrong with it.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;weak security headers&lt;/li&gt;
&lt;li&gt;accessibility problems&lt;/li&gt;
&lt;li&gt;poor performance&lt;/li&gt;
&lt;li&gt;broken redirects&lt;/li&gt;
&lt;li&gt;missing SEO metadata&lt;/li&gt;
&lt;li&gt;bad configuration&lt;/li&gt;
&lt;li&gt;opportunities for growth that nobody notices&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Zenith is my attempt at bringing those things together.&lt;/p&gt;

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

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Monitor, improve and grow your website.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Rather than treating security, performance, SEO and accessibility as completely separate problems, I wanted to build something that looks at a website as one system.&lt;/p&gt;

&lt;p&gt;That idea has changed quite a bit while I’ve been developing it.&lt;/p&gt;

&lt;p&gt;And that has probably taught me more than the original idea ever did.&lt;/p&gt;

&lt;h2&gt;
  
  
  Building Things Changes How You Think
&lt;/h2&gt;

&lt;p&gt;When I first started programming, getting something to work felt like the main objective.&lt;/p&gt;

&lt;p&gt;If the page loaded, the API responded and the button did what it was supposed to do, that was a success.&lt;/p&gt;

&lt;p&gt;I don’t really think that way anymore.&lt;/p&gt;

&lt;p&gt;Now I usually start asking questions like:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why does this work?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What happens when it doesn’t?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What happens if someone sends a request the interface never expected?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What happens when ten thousand requests arrive instead of ten?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That shift has made security and systems engineering much more interesting to me.&lt;/p&gt;

&lt;p&gt;A login page can look completely secure from the browser while the backend behind it has serious problems.&lt;/p&gt;

&lt;p&gt;A security header can exist while being configured in a way that makes it almost useless.&lt;/p&gt;

&lt;p&gt;A website can score well in one audit while still giving users a terrible experience.&lt;/p&gt;

&lt;p&gt;The interesting part is normally somewhere underneath the surface.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Stack Behind Zenith
&lt;/h2&gt;

&lt;p&gt;A lot of Zenith has been built around Cloudflare infrastructure.&lt;/p&gt;

&lt;p&gt;I’ve experimented with things including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Cloudflare Workers&lt;/li&gt;
&lt;li&gt;D1&lt;/li&gt;
&lt;li&gt;R2&lt;/li&gt;
&lt;li&gt;Queues&lt;/li&gt;
&lt;li&gt;scheduled jobs&lt;/li&gt;
&lt;li&gt;rate limiting&lt;/li&gt;
&lt;li&gt;authentication&lt;/li&gt;
&lt;li&gt;bot protection&lt;/li&gt;
&lt;li&gt;browser-based website analysis&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;One thing I like about this architecture is that it forces me to think about software differently.&lt;/p&gt;

&lt;p&gt;Instead of having one large server doing everything, you start thinking about individual services, boundaries, failures and communication between components.&lt;/p&gt;

&lt;p&gt;That introduces new problems.&lt;/p&gt;

&lt;p&gt;But those problems are interesting.&lt;/p&gt;

&lt;p&gt;What happens when a scan fails halfway through?&lt;/p&gt;

&lt;p&gt;What gets retried?&lt;/p&gt;

&lt;p&gt;What should be stored?&lt;/p&gt;

&lt;p&gt;How much should be trusted?&lt;/p&gt;

&lt;p&gt;What happens if one part of the system becomes unavailable?&lt;/p&gt;

&lt;p&gt;Those are the kinds of questions I want to get better at answering.&lt;/p&gt;

&lt;h2&gt;
  
  
  Open Source Has Been Just as Important
&lt;/h2&gt;

&lt;p&gt;A lot of what I’ve learned has also come from GitHub.&lt;/p&gt;

&lt;p&gt;My profile contains a mixture of personal experiments, website tooling and contributions to other projects.&lt;/p&gt;

&lt;p&gt;One project I’ve been experimenting with is &lt;strong&gt;browser-harness&lt;/strong&gt;, which explores ways of making browser interaction easier for AI systems and automated agents.&lt;/p&gt;

&lt;p&gt;I’m particularly interested in the gap between:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“An AI model understands what it should do.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;and&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“The AI model can reliably interact with a real application and actually do it.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Real websites are messy.&lt;/p&gt;

&lt;p&gt;Forms behave differently.&lt;/p&gt;

&lt;p&gt;Interfaces change.&lt;/p&gt;

&lt;p&gt;Authentication exists.&lt;/p&gt;

&lt;p&gt;Errors happen.&lt;/p&gt;

&lt;p&gt;Pages contain information intended for humans rather than machines.&lt;/p&gt;

&lt;p&gt;Making AI systems interact reliably with that environment is a surprisingly interesting engineering problem.&lt;/p&gt;

&lt;p&gt;I’ve also spent time looking through existing open-source projects, fixing smaller issues and submitting contributions.&lt;/p&gt;

&lt;p&gt;Those smaller changes are useful because they force you to work inside someone else’s decisions.&lt;/p&gt;

&lt;p&gt;You can’t redesign everything.&lt;/p&gt;

&lt;p&gt;You have to understand the project first.&lt;/p&gt;

&lt;p&gt;Sometimes the best contribution is only a few lines of code.&lt;/p&gt;

&lt;h2&gt;
  
  
  AI Got Me Interested in Systems, Not Just AI
&lt;/h2&gt;

&lt;p&gt;I first started seriously experimenting with large language models around 2023.&lt;/p&gt;

&lt;p&gt;Since then I’ve tried different local models, inference tools and hardware setups.&lt;/p&gt;

&lt;p&gt;I’ve used things like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;llama.cpp&lt;/li&gt;
&lt;li&gt;Ollama&lt;/li&gt;
&lt;li&gt;LM Studio&lt;/li&gt;
&lt;li&gt;Qwen&lt;/li&gt;
&lt;li&gt;Llama models&lt;/li&gt;
&lt;li&gt;DeepSeek models&lt;/li&gt;
&lt;li&gt;local GPU inference&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;At first, most of my attention was on the models themselves.&lt;/p&gt;

&lt;p&gt;How large are they?&lt;/p&gt;

&lt;p&gt;How much VRAM do they need?&lt;/p&gt;

&lt;p&gt;How quickly can they generate tokens?&lt;/p&gt;

&lt;p&gt;How good are they at coding?&lt;/p&gt;

&lt;p&gt;Eventually I became more interested in everything surrounding the model.&lt;/p&gt;

&lt;p&gt;Routing.&lt;/p&gt;

&lt;p&gt;Tool use.&lt;/p&gt;

&lt;p&gt;Memory.&lt;/p&gt;

&lt;p&gt;Security.&lt;/p&gt;

&lt;p&gt;Permissions.&lt;/p&gt;

&lt;p&gt;Browser interaction.&lt;/p&gt;

&lt;p&gt;Infrastructure.&lt;/p&gt;

&lt;p&gt;APIs.&lt;/p&gt;

&lt;p&gt;Failure handling.&lt;/p&gt;

&lt;p&gt;A capable model by itself isn’t necessarily a capable system.&lt;/p&gt;

&lt;p&gt;The engineering around it matters just as much.&lt;/p&gt;

&lt;h2&gt;
  
  
  I Still Build Things That Fail
&lt;/h2&gt;

&lt;p&gt;A lot of my projects don't work perfectly the first time.&lt;/p&gt;

&lt;p&gt;Sometimes the architecture is wrong.&lt;/p&gt;

&lt;p&gt;Sometimes I massively overcomplicate something.&lt;/p&gt;

&lt;p&gt;Sometimes I build a feature and later realise it shouldn't exist.&lt;/p&gt;

&lt;p&gt;Sometimes I rewrite something that technically worked because I finally understand why the first version was bad.&lt;/p&gt;

&lt;p&gt;I think that is one of the best parts of building your own projects.&lt;/p&gt;

&lt;p&gt;There’s nowhere to hide.&lt;/p&gt;

&lt;p&gt;If your database design is terrible, eventually you have to deal with it.&lt;/p&gt;

&lt;p&gt;If your authentication flow is badly designed, you eventually discover why that matters.&lt;/p&gt;

&lt;p&gt;If your interface is confusing, real users will find things you thought were obvious completely incomprehensible.&lt;/p&gt;

&lt;p&gt;Every failure exposes something you didn’t understand before.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I’m Working Toward
&lt;/h2&gt;

&lt;p&gt;I’m particularly interested in the overlap between:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;computer science, cybersecurity, artificial intelligence and distributed systems.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Zenith happens to touch nearly all of those areas.&lt;/p&gt;

&lt;p&gt;There’s website analysis.&lt;/p&gt;

&lt;p&gt;There’s infrastructure.&lt;/p&gt;

&lt;p&gt;There’s security.&lt;/p&gt;

&lt;p&gt;There’s automation.&lt;/p&gt;

&lt;p&gt;There’s data.&lt;/p&gt;

&lt;p&gt;There’s AI.&lt;/p&gt;

&lt;p&gt;And most importantly, there are plenty of problems I still don’t know how to solve properly.&lt;/p&gt;

&lt;p&gt;That’s probably why I keep working on it.&lt;/p&gt;

&lt;p&gt;I don't just want to know how to make software work.&lt;/p&gt;

&lt;p&gt;I want to understand why it works, where it breaks, and how to build it better the next time.&lt;/p&gt;




&lt;p&gt;You can follow my projects on GitHub:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;github.com/marceli1404&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;And Zenith is available at:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://zenith.me.uk" rel="noopener noreferrer"&gt;https://zenith.me.uk&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I’ll be writing more about the architecture behind Zenith, security mistakes I’ve found while building web applications, local AI experiments, and the things I learn from contributing to open-source projects.&lt;/p&gt;

&lt;p&gt;If you work on similar things, I’d love to hear what you’re building.&lt;/p&gt;

</description>
      <category>buildinpublic</category>
      <category>softwaredevelopment</category>
      <category>startup</category>
      <category>ai</category>
    </item>
  </channel>
</rss>
