<?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: Umut Güngör</title>
    <description>The latest articles on DEV Community by Umut Güngör (@umutgungor).</description>
    <link>https://dev.to/umutgungor</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%2F4187347%2F6c46e582-f280-43bb-91fa-2302f13603f4.jpg</url>
      <title>DEV Community: Umut Güngör</title>
      <link>https://dev.to/umutgungor</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/umutgungor"/>
    <language>en</language>
    <item>
      <title>Catch Broken Markdown Links and #Anchors Offline Before They Hit Production with DeadLinkFinder</title>
      <dc:creator>Umut Güngör</dc:creator>
      <pubDate>Fri, 16 Oct 2026 10:57:38 +0000</pubDate>
      <link>https://dev.to/umutgungor/catch-broken-markdown-links-and-anchors-offline-before-they-hit-production-with-deadlinkfinder-2g42</link>
      <guid>https://dev.to/umutgungor/catch-broken-markdown-links-and-anchors-offline-before-they-hit-production-with-deadlinkfinder-2g42</guid>
      <description>&lt;p&gt;Documentation rots quietly. You rename a file, refactor a section heading in your &lt;code&gt;README.md&lt;/code&gt;, or move a diagram into a new folder—and suddenly your documentation is full of dead relative links and broken &lt;code&gt;#heading-anchors&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Code review rarely catches these because nobody manually clicks every link and table-of-contents anchor in every pull request.&lt;/p&gt;

&lt;p&gt;That is why I built &lt;strong&gt;&lt;a href="https://umutgungorr.com/projects/deadlinkfinder" rel="noopener noreferrer"&gt;DeadLinkFinder&lt;/a&gt;&lt;/strong&gt;—a fast, &lt;strong&gt;zero-dependency&lt;/strong&gt; Python CLI that verifies local Markdown links, image assets, GitHub-flavored heading anchors, and optional external URLs before they reach production.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Existing Link Checkers Frustrated Me
&lt;/h2&gt;

&lt;p&gt;When I looked for a link linter for my repositories, I kept running into three problems:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Heavy runtime dependencies:&lt;/strong&gt; Installing a full Node.js or headless browser stack just to check if &lt;code&gt;../docs/architecture.md&lt;/code&gt; exists in a Python repo felt unnecessary.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;False positives on GitHub &lt;code&gt;#anchors&lt;/code&gt;:&lt;/strong&gt; GitHub's heading slug algorithm has specific rules around punctuation, Unicode characters, emojis, and duplicate headings (&lt;code&gt;#install&lt;/code&gt;, &lt;code&gt;#install-1&lt;/code&gt;). Naive regex checkers constantly fail on valid anchors.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Detection without diagnosis:&lt;/strong&gt; Telling me &lt;code&gt;"Target not found"&lt;/code&gt; is only half the job. If I made a typo in a 40-heading document, the tool should tell me what I probably meant.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Quick Start
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;DeadLinkFinder&lt;/code&gt; uses only the Python standard library (&lt;code&gt;re&lt;/code&gt;, &lt;code&gt;pathlib&lt;/code&gt;, &lt;code&gt;difflib&lt;/code&gt;, &lt;code&gt;urllib&lt;/code&gt;), meaning zero external dependencies to audit or maintain.&lt;/p&gt;

&lt;p&gt;Install it directly from &lt;a href="https://pypi.org/project/deadlinkfinder/" rel="noopener noreferrer"&gt;PyPI&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;deadlinkfinder
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run it against any directory or Markdown file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;deadlinkfinder docs/ README.md
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Example terminal output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ deadlinkfinder docs/

🔍 DeadLinkFinder - Verifying documentation integrity...

[!] DLF-001  ERROR    docs/getting-started.md:28
    Target not found: '../guides/setup.md'
    Suggestion: Did you mean '../guides/install-setup.md'?

[!] DLF-002  ERROR    README.md:64
    Anchor not found: '#configuration-option'
    Suggestion: Did you mean '#configuration-options'?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Key Features Built for CI/CD
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Offline-First with Fuzzy Suggestions (&lt;code&gt;difflib&lt;/code&gt;)
&lt;/h3&gt;

&lt;p&gt;By default, &lt;code&gt;DeadLinkFinder&lt;/code&gt; runs &lt;strong&gt;100% offline&lt;/strong&gt; in milliseconds. It checks local file paths, image references (&lt;code&gt;![alt](./assets/demo.png)&lt;/code&gt;), and cross-file anchors (&lt;code&gt;./guide.md#installation&lt;/code&gt;). Whenever a target or anchor is missing, it uses &lt;code&gt;difflib&lt;/code&gt; to suggest the closest existing file or heading slug.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. GitHub-Compatible Heading Anchor Engine
&lt;/h3&gt;

&lt;p&gt;Whether your headings contain Turkish characters, emojis, inline code backticks, or repeated section titles across a document, the anchor resolver mirrors GitHub's exact slug generation rules.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Native SARIF v2.1.0 &amp;amp; JSON Output
&lt;/h3&gt;

&lt;p&gt;Want inline annotations directly on your GitHub Pull Requests or GitHub Code Scanning dashboard? Generate a SARIF report with deterministic line fingerprints:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;deadlinkfinder &lt;span class="nb"&gt;.&lt;/span&gt; &lt;span class="nt"&gt;--format&lt;/span&gt; sarif &lt;span class="nt"&gt;--output&lt;/span&gt; results.sarif
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or use &lt;code&gt;--format json&lt;/code&gt; for custom CI pipelines and pre-commit hooks.&lt;/p&gt;




&lt;h2&gt;
  
  
  Part of a Zero-Dependency CLI Suite
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;DeadLinkFinder&lt;/code&gt; is part of my open-source suite of zero-dependency developer tools, alongside &lt;a href="https://umutgungorr.com/blog/cli-tools-that-earn-trust" rel="noopener noreferrer"&gt;EnvDoctor&lt;/a&gt; (for &lt;code&gt;.env&lt;/code&gt; contract auditing) and &lt;a href="https://umutgungorr.com/projects/tokenguard" rel="noopener noreferrer"&gt;TokenGuard&lt;/a&gt; (for pre-commit secret scanning).&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Case Study &amp;amp; Architecture Notes:&lt;/strong&gt; &lt;a href="https://umutgungorr.com/projects/deadlinkfinder" rel="noopener noreferrer"&gt;umutgungorr.com/projects/deadlinkfinder&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Source Code (GitHub):&lt;/strong&gt; &lt;a href="https://github.com/umutgungorr/deadlinkfinder" rel="noopener noreferrer"&gt;github.com/umutgungorr/deadlinkfinder&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;PyPI Package:&lt;/strong&gt; &lt;a href="https://pypi.org/project/deadlinkfinder/" rel="noopener noreferrer"&gt;pypi.org/project/deadlinkfinder&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;More Engineering Articles &amp;amp; Projects:&lt;/strong&gt; &lt;a href="https://umutgungorr.com/" rel="noopener noreferrer"&gt;Umut Güngör — umutgungorr.com&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you maintain open-source documentation or internal engineering wikis, give &lt;code&gt;deadlinkfinder&lt;/code&gt; a spin in your CI pipeline—feedback and issues are always welcome!&lt;/p&gt;

</description>
      <category>python</category>
      <category>cli</category>
      <category>opensource</category>
      <category>documentation</category>
    </item>
    <item>
      <title>Stop Breaking Production: How to Audit and Sync .env Files with EnvDoctor</title>
      <dc:creator>Umut Güngör</dc:creator>
      <pubDate>Thu, 15 Oct 2026 18:56:15 +0000</pubDate>
      <link>https://dev.to/umutgungor/stop-breaking-production-how-to-audit-and-sync-env-files-with-envdoctor-fmp</link>
      <guid>https://dev.to/umutgungor/stop-breaking-production-how-to-audit-and-sync-env-files-with-envdoctor-fmp</guid>
      <description>&lt;p&gt;Every developer has been there: your code passes all local tests, you deploy to staging or production, and the application immediately crashes with KeyError: DATABASE_URL or an undefined environment variable.&lt;/p&gt;

&lt;p&gt;As projects grow, maintaining .env files across different environments becomes painful:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;.env.example drifts out of sync with actual code requirements.&lt;/li&gt;
&lt;li&gt;New variables get added by teammates without documentation.&lt;/li&gt;
&lt;li&gt;Secret leaks happen when templates aren't audited properly.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To solve this deterministically with zero bloat, I built &lt;strong&gt;&lt;a href="https://github.com/umutgungorr/envdoctor" rel="noopener noreferrer"&gt;EnvDoctor&lt;/a&gt;&lt;/strong&gt; — a zero-dependency Python CLI tool designed to audit, synchronize, and validate environment configurations.&lt;/p&gt;




&lt;h3&gt;
  
  
  What Does EnvDoctor Do?
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;check&lt;/strong&gt;: Compares your active .env against .env.example and flags missing or extraneous keys before you deploy.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;sync&lt;/strong&gt;: Safely merges new keys into .env.example without touching secrets or sensitive values.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;audit&lt;/strong&gt;: Scans your codebase with regex patterns to find environment variable calls that aren't declared in your documentation templates.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Example audit run:&lt;br&gt;
$ envdoctor audit --strict&lt;br&gt;
[PASS] .env matches .env.example&lt;br&gt;
[WARN] Found undeclared variable in src/config.py: CACHE_TTL&lt;/p&gt;




&lt;h3&gt;
  
  
  Why Zero Dependencies?
&lt;/h3&gt;

&lt;p&gt;CLI diagnostic tools should not add 50MB of third-party packages to your environment just to inspect text files. EnvDoctor relies entirely on the Python Standard Library, making it fast, secure, and instant to run in GitHub Actions or Docker entrypoints.&lt;/p&gt;




&lt;h3&gt;
  
  
  Links &amp;amp; Resources
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;GitHub Repository&lt;/strong&gt;: &lt;a href="https://github.com/umutgungorr/envdoctor" rel="noopener noreferrer"&gt;github.com/umutgungorr/envdoctor&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Author Portfolio &amp;amp; Systems&lt;/strong&gt;: &lt;a href="https://umutgungorr.com" rel="noopener noreferrer"&gt;Umut Güngör (umutgungorr.com)&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deep Dive &amp;amp; Benchmarks&lt;/strong&gt;: &lt;a href="https://umutgungorr.com/blog/cli-tools-that-earn-trust" rel="noopener noreferrer"&gt;Read full case study on umutgungorr.com&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Feel free to star the repo, test it on your projects, and share your feedback!&lt;/p&gt;

</description>
      <category>python</category>
      <category>devops</category>
      <category>opensource</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
