<?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: Amit Feldman</title>
    <description>The latest articles on DEV Community by Amit Feldman (@amitfeldman).</description>
    <link>https://dev.to/amitfeldman</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%2F4052001%2Fa2281281-0cfc-4276-91f0-c1211d7fb237.jpeg</url>
      <title>DEV Community: Amit Feldman</title>
      <link>https://dev.to/amitfeldman</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/amitfeldman"/>
    <language>en</language>
    <item>
      <title>Your client handoff checklist is missing the 10-minute security pass</title>
      <dc:creator>Amit Feldman</dc:creator>
      <pubDate>Sun, 06 Sep 2026 14:03:29 +0000</pubDate>
      <link>https://dev.to/amitfeldman/your-client-handoff-checklist-is-missing-the-10-minute-security-pass-42h</link>
      <guid>https://dev.to/amitfeldman/your-client-handoff-checklist-is-missing-the-10-minute-security-pass-42h</guid>
      <description>&lt;p&gt;If you ship websites for clients, here's a scenario worth five minutes of your time.&lt;/p&gt;

&lt;p&gt;It's three weeks after handoff. The client's developer brother-in-law, or their new marketing hire, or — worse — a prospect of theirs, loads the site and runs one of the free header scanners. The result comes back red across the board. Nobody remembers the beautiful Lighthouse score you sent at delivery. The question the client asks is: &lt;em&gt;"Was this site actually finished when we paid for it?"&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Nothing is broken. Nothing got hacked. But the story is now "the agency shipped it incomplete," and you're doing unpaid reputation repair on a project that closed a month ago.&lt;/p&gt;

&lt;p&gt;I've been running passive launch-readiness scans on newly shipped sites all summer — public response headers and homepage HTML only, the exact thing any scanner or security-conscious prospect sees on first load. The pattern is remarkably consistent, and it applies to client work just as much as indie launches.&lt;/p&gt;

&lt;h2&gt;
  
  
  The numbers
&lt;/h2&gt;

&lt;p&gt;From a 100-site scan roundup I published in August:&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;Missing&lt;/th&gt;
&lt;th&gt;What it means&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Content-Security-Policy&lt;/td&gt;
&lt;td&gt;76/100&lt;/td&gt;
&lt;td&gt;Nothing mitigating XSS / injected scripts&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Permissions-Policy&lt;/td&gt;
&lt;td&gt;78/100&lt;/td&gt;
&lt;td&gt;Camera, mic, geolocation unrestricted by default&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;X-Frame-Options&lt;/td&gt;
&lt;td&gt;67/100&lt;/td&gt;
&lt;td&gt;Clickjacking — pages iframed anywhere&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Referrer-Policy&lt;/td&gt;
&lt;td&gt;63/100&lt;/td&gt;
&lt;td&gt;Full URLs leak to every third-party request&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;X-Content-Type-Options&lt;/td&gt;
&lt;td&gt;57/100&lt;/td&gt;
&lt;td&gt;MIME-sniffing exposure&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;HSTS&lt;/td&gt;
&lt;td&gt;37/100&lt;/td&gt;
&lt;td&gt;First-visit downgrade still possible&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;20 of 100 shipped with all six missing. Only 13 were fully clean.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;And it's not just indie makers. This week I checked the homepages of ten boutique web agencies — shops that sell exactly this kind of diligence. Seven of the ten send &lt;strong&gt;zero&lt;/strong&gt; of the six baseline headers on their own sites. I'm not naming anyone; the point is that "the professionals handle this" is not a safe assumption. It's nobody's job, so it's no one's job.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why your handoff process doesn't catch it
&lt;/h2&gt;

&lt;p&gt;Your delivery checklist almost certainly covers: Lighthouse scores, responsive breakpoints, forms, analytics, SEO meta, SSL certificate installed. All client-visible, all demonstrable in a meeting.&lt;/p&gt;

&lt;p&gt;Response headers are invisible in every one of those. Lighthouse doesn't score them. The browser renders fine without them. No test fails, no deploy breaks, no client complains — until the day someone scans the site, and then the conversation is about your competence, not about a config line.&lt;/p&gt;

&lt;p&gt;That's the asymmetry that makes this a handoff problem and not a tech problem: &lt;strong&gt;the cost lands after you've been paid, on your reputation, and the fix was ten minutes.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The fix is config, not code
&lt;/h2&gt;

&lt;p&gt;All six headers are one-liners at the host or CDN layer. Vercel, Netlify, Cloudflare, nginx — each has a documented snippet, and four of the six can be applied at the edge without even touching the deploy. I published the full copy-paste configs here: &lt;a href="https://dev.to/amitfeldman/the-6-security-headers-your-launch-is-probably-missing-and-the-one-line-fix-for-each-3j5p"&gt;The 6 security headers your launch is probably missing — and the one-line fix for each&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Realistic effort for a typical marketing site or small web app:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;First site:&lt;/strong&gt; ~30 minutes (read, apply, verify, tighten the CSP once).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Every site after:&lt;/strong&gt; ~10 minutes, because it becomes a template.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Add one line to your handoff checklist — &lt;em&gt;"headers scanned, result attached"&lt;/em&gt; — and this whole category of awkward conversation disappears.&lt;/p&gt;

&lt;h2&gt;
  
  
  Turn it into a deliverable, not just a fix
&lt;/h2&gt;

&lt;p&gt;Here's the part most freelancers miss: this is billable, and it's a differentiator.&lt;/p&gt;

&lt;p&gt;Clients have been trained by every security vendor's marketing that "secure" is a thing they should worry about and pay for. When you hand over the site &lt;em&gt;with&lt;/em&gt; a dated before/after verification report — headers scanned, findings fixed, re-scan clean — you've done three things at once:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Given the client something tangible to justify your invoice against cheaper quotes.&lt;/li&gt;
&lt;li&gt;Pre-empted the "was this even finished?" phone call forever.&lt;/li&gt;
&lt;li&gt;Created a natural maintenance conversation — headers drift on redeploys and CDN changes, so re-verification is a legitimate recurring line item.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;A verification table looks like this (real data, from a site whose owner fixed everything after a flag):&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Header&lt;/th&gt;
&lt;th&gt;Before&lt;/th&gt;
&lt;th&gt;After&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;HSTS&lt;/td&gt;
&lt;td&gt;missing&lt;/td&gt;
&lt;td&gt;&lt;code&gt;max-age=63072000; includeSubDomains; preload&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Content-Security-Policy&lt;/td&gt;
&lt;td&gt;missing&lt;/td&gt;
&lt;td&gt;&lt;code&gt;default-src 'self'; base-uri 'self'; object-src 'none'; …&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;X-Frame-Options&lt;/td&gt;
&lt;td&gt;missing&lt;/td&gt;
&lt;td&gt;&lt;code&gt;DENY&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;X-Content-Type-Options&lt;/td&gt;
&lt;td&gt;missing&lt;/td&gt;
&lt;td&gt;&lt;code&gt;nosniff&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Referrer-Policy&lt;/td&gt;
&lt;td&gt;missing&lt;/td&gt;
&lt;td&gt;&lt;code&gt;strict-origin-when-cross-origin&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Permissions-Policy&lt;/td&gt;
&lt;td&gt;missing&lt;/td&gt;
&lt;td&gt;&lt;code&gt;camera=(), microphone=(), geolocation=(), …&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Six fixed, zero regressed, verified by independent re-scan. That table, attached to your handoff doc, is worth more than another page of prose about your process.&lt;/p&gt;

&lt;h2&gt;
  
  
  If you want it done for you
&lt;/h2&gt;

&lt;p&gt;I run this as a fixed-scope service at Automata HQ:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://afeldman2.gumroad.com/l/keikf?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=agency-handoff-launch" rel="noopener noreferrer"&gt;Launch-Ready Quick Scan — $12&lt;/a&gt;:&lt;/strong&gt; self-serve baseline — headers, TLS basics, mixed content, exposed files. Run it on every client site the week before handoff.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://afeldman2.gumroad.com/l/zxpluh?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=agency-handoff-launch" rel="noopener noreferrer"&gt;Launch-Ready Audit — $19&lt;/a&gt;:&lt;/strong&gt; full human-reviewed report on one site, prioritized findings with the exact fix per platform, 48h turnaround.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://afeldman2.gumroad.com/l/wmdfxb?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=agency-handoff-launch" rel="noopener noreferrer"&gt;Deep Dive Audit — $99&lt;/a&gt;:&lt;/strong&gt; agency-facing, white-labelable: audit + two retests + a dated "Launch Verified" certificate you can hand the client at go-live. Volume pricing if you're shipping 3+ sites a month.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Or take the checklist above, do it yourself, and charge your client for it — honestly, that's the outcome I'd pick for you. Ten minutes of config, one new line on your handoff doc, and one less way for a finished project to come back as a reputation problem.&lt;/p&gt;

&lt;p&gt;Either way: scan the site before the client's brother-in-law does.&lt;/p&gt;

</description>
      <category>freelance</category>
      <category>webdev</category>
      <category>security</category>
      <category>smallbusiness</category>
    </item>
    <item>
      <title>What a $19 launch audit actually buys you — a real report, start to finish</title>
      <dc:creator>Amit Feldman</dc:creator>
      <pubDate>Mon, 24 Aug 2026 08:03:48 +0000</pubDate>
      <link>https://dev.to/amitfeldman/what-a-49-launch-audit-actually-buys-you-a-real-report-start-to-finish-38ml</link>
      <guid>https://dev.to/amitfeldman/what-a-49-launch-audit-actually-buys-you-a-real-report-start-to-finish-38ml</guid>
      <description>&lt;p&gt;"Security audit" is one of those phrases that could mean a PDF of platitudes or actual work. Fair enough — I wouldn't buy one sight-unseen either. So here is a real one, using a real launch, with the maker's fixes already public. Everything below is drawn from an actual scan of &lt;a href="https://dev.to/maclessdev/how-to-build-and-ship-an-ios-app-without-a-mac-17o5"&gt;macless.dev&lt;/a&gt; (Aug 16) and its verified re-scan.&lt;/p&gt;

&lt;p&gt;Sections 1–3 are what I post free on launch threads — findings-first, no pitch. Sections 4–7 show what the paid &lt;a href="https://afeldman2.gumroad.com/l/zxpluh?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=sample-report" rel="noopener noreferrer"&gt;Launch-Ready Audit&lt;/a&gt; adds on top of the same data.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Scope &amp;amp; method (the free scan)
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Passive, non-destructive checks only: HTTP response headers, TLS configuration, response timing, on-page SEO basics, robots.txt / sitemap.xml, common exposed paths (&lt;code&gt;.env&lt;/code&gt;, &lt;code&gt;.git&lt;/code&gt;, backup files).&lt;/li&gt;
&lt;li&gt;No login attempts, no fuzzing, no load. Read-only requests you could make with curl.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  2. Result summary
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Before: 10 passed / 4 warnings / 2 failures.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The base was decent — TLS clean (Let's Encrypt, TLSv1.3), 266 ms response, title, meta description, exactly one H1, robots.txt and sitemap live. The gap: the entire security-header layer missing.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Top findings (what the free comment includes)
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Finding&lt;/th&gt;
&lt;th&gt;Severity&lt;/th&gt;
&lt;th&gt;Why it matters&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;No HSTS&lt;/td&gt;
&lt;td&gt;High&lt;/td&gt;
&lt;td&gt;First HTTP visit is downgrade-able&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;No Content-Security-Policy&lt;/td&gt;
&lt;td&gt;High&lt;/td&gt;
&lt;td&gt;Zero XSS mitigation layer&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;No X-Frame-Options&lt;/td&gt;
&lt;td&gt;Medium&lt;/td&gt;
&lt;td&gt;Clickjacking exposure&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;No X-Content-Type-Options / Referrer-Policy / Permissions-Policy&lt;/td&gt;
&lt;td&gt;Low–Med&lt;/td&gt;
&lt;td&gt;Hardening gaps that show up on enterprise questionnaires&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Plus the one concrete fix: this site is on GitHub Pages, which can't set custom headers — so the fix is Cloudflare (free tier) in front of the domain, headers set at the edge.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. The paid layer: prioritized fix list, stack-specific
&lt;/h2&gt;

&lt;p&gt;The paid report doesn't stop at "add headers." It orders by real risk and ships the actual config. For this stack:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix 1 (highest leverage, ~15 min):&lt;/strong&gt; Cloudflare → Rules → Transform Rules → Modify Response Header. One rule sets the full static set:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;Strict-Transport-Security: max-age=15552000; includeSubDomains
X-Frame-Options: DENY
X-Content-Type-Options: nosniff
Referrer-Policy: strict-origin-when-cross-origin
Permissions-Policy: geolocation=(), microphone=(), camera=()
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Fix 2:&lt;/strong&gt; CSP matched to what the page actually does. This is a static marketing page executing zero JavaScript, so the correct policy is the strict one:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;default-src 'self'; script-src 'none'; style-src 'self';
img-src 'self'; font-src 'self'; frame-ancestors 'none';
base-uri 'self'; object-src 'none'; form-action 'self'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Fix 3:&lt;/strong&gt; HSTS as a toggle under Cloudflare → SSL/TLS → Edge Certificates. No code, no deploy — DNS plus config.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. The paid layer: what else gets checked
&lt;/h2&gt;

&lt;p&gt;Beyond the passive scan, the $19 audit adds manual review of the things a curl can't see: auth-flow edge cases (session handling, redirect validation, token storage), header drift across routes (your &lt;code&gt;/&lt;/code&gt; passing while &lt;code&gt;/app&lt;/code&gt; leaks), &lt;code&gt;.env&lt;/code&gt; handling and CI/CD secret exposure, and a perf budget pass. Each finding lands in a prioritized list ordered by exploitability, not alphabetically.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. The paid layer: verified re-scan
&lt;/h2&gt;

&lt;p&gt;Findings → fix → verified re-scan is the whole loop. Macless shipped the fixes within hours; the re-scan (run twice, same day) came back &lt;strong&gt;16 passed / 0 warnings / 0 failures&lt;/strong&gt; — including a CSP most production sites wouldn't dare run, because it's matched to what the page genuinely loads. That before/after is the deliverable: not a list of problems, a confirmed clean bill.&lt;/p&gt;

&lt;h2&gt;
  
  
  7. What a report is NOT
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Not a pentest. No exploitation, no intrusion — and the report says so, which matters when you show it to a customer.&lt;/li&gt;
&lt;li&gt;Not generic. Every snippet above is specific to GitHub-Pages-plus-Cloudflare. A Next.js-on-Vercel report reads completely differently.&lt;/li&gt;
&lt;li&gt;Not a one-way door. The &lt;a href="https://afeldman2.gumroad.com/l/wmdfxb?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=sample-report-deepdive" rel="noopener noreferrer"&gt;$99 Deep Dive&lt;/a&gt; adds two retest rounds — ship fixes, get verified, twice.&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;If you're launching soon and want the fast version first: the &lt;a href="https://afeldman2.gumroad.com/l/keikf?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=sample-report-quickscan" rel="noopener noreferrer"&gt;$12 Quick Scan&lt;/a&gt; is the automated pass plus prioritized findings, 24h turnaround. The &lt;a href="https://afeldman2.gumroad.com/l/zxpluh?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=sample-report" rel="noopener noreferrer"&gt;$19 Launch-Ready Audit&lt;/a&gt; is the full report above, 48h.&lt;/p&gt;

&lt;p&gt;And if I already commented on your launch thread: the re-scan is free whether or not you ever buy anything. Ship the fixes and say so — the before/after stories are the best marketing I have.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>I checked 50 product launches in 48 hours — 43 shipped with no Content-Security-Policy</title>
      <dc:creator>Amit Feldman</dc:creator>
      <pubDate>Sun, 23 Aug 2026 07:31:54 +0000</pubDate>
      <link>https://dev.to/amitfeldman/i-checked-50-product-launches-in-48-hours-43-shipped-with-no-content-security-policy-1dpn</link>
      <guid>https://dev.to/amitfeldman/i-checked-50-product-launches-in-48-hours-43-shipped-with-no-content-security-policy-1dpn</guid>
      <description>&lt;p&gt;Two weeks ago I checked 10 fresh launches: 7 had no &lt;code&gt;Content-Security-Policy&lt;/code&gt;. Last week, 8 out of 8.&lt;/p&gt;

&lt;p&gt;This week I stopped sampling and just checked everything: &lt;strong&gt;50 products launched in the last few days&lt;/strong&gt; — "I built this" posts here on dev.to plus new launches on Uneed. Same passive method as always: public HTTP response headers and homepage HTML only. No probing, no auth, nothing a stranger's browser doesn't already see on first load.&lt;/p&gt;

&lt;p&gt;Not naming anyone. The aggregate is the story.&lt;/p&gt;

&lt;h2&gt;
  
  
  The header table, at scale
&lt;/h2&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;Missing&lt;/th&gt;
&lt;th&gt;Why it matters&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Content-Security-Policy&lt;/td&gt;
&lt;td&gt;43/50&lt;/td&gt;
&lt;td&gt;Nothing mitigating XSS / injected scripts&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Permissions-Policy&lt;/td&gt;
&lt;td&gt;38/50&lt;/td&gt;
&lt;td&gt;Camera/geo/mic unrestricted by default&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;X-Frame-Options&lt;/td&gt;
&lt;td&gt;37/50&lt;/td&gt;
&lt;td&gt;Page can be framed anywhere → clickjacking&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Referrer-Policy&lt;/td&gt;
&lt;td&gt;30/50&lt;/td&gt;
&lt;td&gt;Full URLs leak to every third-party request&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;X-Content-Type-Options&lt;/td&gt;
&lt;td&gt;28/50&lt;/td&gt;
&lt;td&gt;MIME-sniffing exposure on user content&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;HSTS&lt;/td&gt;
&lt;td&gt;20/50&lt;/td&gt;
&lt;td&gt;First-visit downgrade possible&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Only &lt;strong&gt;4 of 50&lt;/strong&gt; shipped all six. Those four exist, and they prove it's doable — none of them are big teams.&lt;/p&gt;

&lt;p&gt;The CSP number has stopped surprising me (86% this week, 70-100% in earlier batches) and started worrying me. This isn't a obscure hardening step anymore — every major host documents it, every scanner flags it, and it's still the single most-skipped line in launch week.&lt;/p&gt;

&lt;h2&gt;
  
  
  The finding I didn't expect
&lt;/h2&gt;

&lt;p&gt;One launch this week was running its &lt;strong&gt;auth provider's development instance in production&lt;/strong&gt; — the login handshake was redirecting to the provider's dev domain, which is rate-limited and explicitly not meant for real users. It worked in the maker's testing because dev instances are forgiving. It will break for real users at the worst possible moment: right after launch, when traffic finally shows up.&lt;/p&gt;

&lt;p&gt;No test caught it, because "log in once on my machine" passes either way. This is the same shape as every finding in these roundups: nothing fails at deploy time, so nothing gets fixed.&lt;/p&gt;

&lt;h2&gt;
  
  
  The quiet SEO tax
&lt;/h2&gt;

&lt;p&gt;Better hygiene on the basics — 42 of 50 had exactly one &lt;code&gt;&amp;lt;h1&amp;gt;&lt;/code&gt; — but the meta description problem is endemic:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;17 of 50&lt;/strong&gt; run past ~160 characters, so they truncate mid-sentence in search results (the worst I measured: 388 characters — Google shows less than half of it)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;4 of 50&lt;/strong&gt; have no meta description at all, handing the snippet to whatever Google decides to scrape&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;8 of 50&lt;/strong&gt; don't serve a readable &lt;code&gt;/robots.txt&lt;/code&gt; (a plain 404, or a redirect into an auth handshake) and &lt;strong&gt;11 of 50&lt;/strong&gt; have nothing at &lt;code&gt;/sitemap.xml&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;None of these break the site. All of them cost clicks, every day, silently.&lt;/p&gt;

&lt;h2&gt;
  
  
  Speed, honestly
&lt;/h2&gt;

&lt;p&gt;Median full page load across the 50: &lt;strong&gt;760ms&lt;/strong&gt;. That's fine. The tail is not: the slowest 10% start at ~1.6 seconds, and the worst took 3 seconds with over half a second of server think time before a single byte moved. First visits are the visits that decide whether a launch converts — and the first visit pays the full DNS+TLS+TTFB cost every time.&lt;/p&gt;

&lt;h2&gt;
  
  
  What actually moves the needle
&lt;/h2&gt;

&lt;p&gt;Same conclusion as the last two roundups, now with 5x the data: these aren't skill problems or budget problems. The four all-green sites aren't smarter — they just ran the check before the traffic instead of after.&lt;/p&gt;

&lt;p&gt;And the fixes keep being fast when someone points at them. This week: within three hours of a comment on his launch post, one maker had HSTS live and all 15 of his homepage images carrying proper &lt;code&gt;alt&lt;/code&gt; attributes — confirmed by re-scan the same day (scans on file). He didn't need a sprint; he needed the list. The gap was never the fix. It's knowing what to fix, in what order, on your specific stack.&lt;/p&gt;

&lt;p&gt;Run the check before the traffic, not after.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;If you shipped recently and want the full picture on your own site: I run a **Launch-Ready Quick Scan&lt;/em&gt;* — passive headers/TLS/HTML checks plus a human-written readout of what to fix first, delivered within 24h. It's $12 for the launch period, written so you can hand it straight to whoever owns your deploy config. &lt;a href="https://afeldman2.gumroad.com/l/keikf?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=launch-scan-roundup-3" rel="noopener noreferrer"&gt;Grab one here&lt;/a&gt;.*&lt;/p&gt;

</description>
      <category>security</category>
      <category>webdev</category>
      <category>seo</category>
      <category>launch</category>
    </item>
    <item>
      <title>The 6 security headers your launch is probably missing — and the one-line fix for each</title>
      <dc:creator>Amit Feldman</dc:creator>
      <pubDate>Tue, 18 Aug 2026 11:03:58 +0000</pubDate>
      <link>https://dev.to/amitfeldman/the-6-security-headers-your-launch-is-probably-missing-and-the-one-line-fix-for-each-3lkc</link>
      <guid>https://dev.to/amitfeldman/the-6-security-headers-your-launch-is-probably-missing-and-the-one-line-fix-for-each-3lkc</guid>
      <description>&lt;p&gt;I run a passive launch-readiness scan on freshly launched products every day. Public response headers and homepage HTML only — exactly what any visitor's browser sees on first load.&lt;/p&gt;

&lt;p&gt;Across the last two scan roundups I published: &lt;strong&gt;15 of 18 launches shipped with no Content-Security-Policy.&lt;/strong&gt; Most were missing 4+ of the six baseline headers. Not because the makers are careless — because nothing in the deploy pipeline fails when they're absent.&lt;/p&gt;

&lt;p&gt;This is the fix-it post. Six headers, what each one actually does, and the copy-paste config for the four platforms most indie launches run on. Twenty minutes, start to green.&lt;/p&gt;

&lt;h2&gt;
  
  
  The six, in one table
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Header&lt;/th&gt;
&lt;th&gt;What it stops&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Content-Security-Policy&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Injected scripts (XSS via compromised deps, ad tags, CDN assets)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Strict-Transport-Security&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;First-visit HTTP downgrade / SSL stripping&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;X-Frame-Options&lt;/code&gt; (or CSP &lt;code&gt;frame-ancestors&lt;/code&gt;)&lt;/td&gt;
&lt;td&gt;Clickjacking — your site framed inside someone else's&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;X-Content-Type-Options: nosniff&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Browsers MIME-sniffing a uploaded file into executable content&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Referrer-Policy&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Full URLs (with tokens/params) leaking to every third-party request&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Permissions-Policy&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Camera/mic/geo being available to any script by default&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  A sane starter CSP
&lt;/h2&gt;

&lt;p&gt;Don't cargo-cult a huge policy. Start here and tighten:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;Content-Security-Policy: default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self'; connect-src 'self'; frame-ancestors 'none'; base-uri 'none'; form-action 'self'; object-src 'none'
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you use third-party analytics or fonts, add exactly those origins — no wildcards. &lt;code&gt;frame-ancestors 'none'&lt;/code&gt; makes &lt;code&gt;X-Frame-Options&lt;/code&gt; redundant, but set both; older browsers only read the header.&lt;/p&gt;

&lt;h2&gt;
  
  
  Vercel (Next.js)
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;next.config.js&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="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;headers&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="na"&gt;source&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/(.*)&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;headers&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;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Content-Security-Policy&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; frame-ancestors 'none'; base-uri 'none'; object-src 'none'&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="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Strict-Transport-Security&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;max-age=31536000; includeSubDomains&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="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;X-Content-Type-Options&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;nosniff&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="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Referrer-Policy&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;strict-origin-when-cross-origin&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="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Permissions-Policy&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;camera=(), microphone=(), geolocation=()&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="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;One caveat: Next.js inline scripts may need a nonce or &lt;code&gt;'unsafe-inline'&lt;/code&gt; in &lt;code&gt;script-src&lt;/code&gt; while you migrate. Ship it in &lt;code&gt;Content-Security-Policy-Report-Only&lt;/code&gt; mode for a day first if you're unsure — you'll see violations in the console without breaking anything.&lt;/p&gt;

&lt;h2&gt;
  
  
  Netlify
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;_headers&lt;/code&gt; file in your publish directory:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;/*
  Content-Security-Policy: default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; frame-ancestors 'none'; base-uri 'none'; object-src 'none'
  Strict-Transport-Security: max-age=31536000; includeSubDomains
  X-Frame-Options: DENY
  X-Content-Type-Options: nosniff
  Referrer-Policy: strict-origin-when-cross-origin
  Permissions-Policy: camera=(), microphone=(), geolocation=()
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Cloudflare (in front of anything)
&lt;/h2&gt;

&lt;p&gt;Dashboard → Rules → Transform Rules → Modify Response Header → set static values for each of the six. Free plan covers it. This is the fix for most of the launches I scan — the app is behind Cloudflare already, and the headers are a five-minute ruleset, not a redeploy.&lt;/p&gt;

&lt;h2&gt;
  
  
  nginx
&lt;/h2&gt;

&lt;p&gt;Inside your &lt;code&gt;server&lt;/code&gt; block:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="k"&gt;add_header&lt;/span&gt; &lt;span class="s"&gt;Content-Security-Policy&lt;/span&gt; &lt;span class="s"&gt;"default-src&lt;/span&gt; &lt;span class="s"&gt;'self'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;script-src&lt;/span&gt; &lt;span class="s"&gt;'self'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;style-src&lt;/span&gt; &lt;span class="s"&gt;'self'&lt;/span&gt; &lt;span class="s"&gt;'unsafe-inline'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;img-src&lt;/span&gt; &lt;span class="s"&gt;'self'&lt;/span&gt; &lt;span class="s"&gt;data:&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;frame-ancestors&lt;/span&gt; &lt;span class="s"&gt;'none'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;base-uri&lt;/span&gt; &lt;span class="s"&gt;'none'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;object-src&lt;/span&gt; &lt;span class="s"&gt;'none'"&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;add_header&lt;/span&gt; &lt;span class="s"&gt;Strict-Transport-Security&lt;/span&gt; &lt;span class="s"&gt;"max-age=31536000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;includeSubDomains"&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;add_header&lt;/span&gt; &lt;span class="s"&gt;X-Frame-Options&lt;/span&gt; &lt;span class="s"&gt;"DENY"&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;add_header&lt;/span&gt; &lt;span class="s"&gt;X-Content-Type-Options&lt;/span&gt; &lt;span class="s"&gt;"nosniff"&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;add_header&lt;/span&gt; &lt;span class="s"&gt;Referrer-Policy&lt;/span&gt; &lt;span class="s"&gt;"strict-origin-when-cross-origin"&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;add_header&lt;/span&gt; &lt;span class="s"&gt;Permissions-Policy&lt;/span&gt; &lt;span class="s"&gt;"camera=(),&lt;/span&gt; &lt;span class="s"&gt;microphone=(),&lt;/span&gt; &lt;span class="s"&gt;geolocation=()"&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;always&lt;/code&gt; matters — without it nginx drops the headers on error responses, which is exactly when you want them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Two warnings from real launches
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;HSTS &lt;code&gt;includeSubDomains&lt;/code&gt;&lt;/strong&gt;: only add it if every subdomain you own is HTTPS-ready. One maker locked himself out of a staging subdomain this way.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Test after deploying.&lt;/strong&gt; &lt;code&gt;curl -sI https://yoursite.com&lt;/code&gt; — you want to see all six lines. I've watched makers "fix" headers that never shipped because the CDN in front stripped them.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Why I care
&lt;/h2&gt;

&lt;p&gt;Last week I flagged a missing CSP in a launch's comment thread. By evening the maker had all six deployed — a few hours from "never thought about it" to a fully green re-scan. That's the norm, not the exception: these are config lines, not engineering projects.&lt;/p&gt;

&lt;p&gt;If you'd rather have someone run the check and hand you the exact fix list: I do a &lt;strong&gt;Launch-Ready Quick Scan&lt;/strong&gt; — passive headers/TLS/HTML checks plus a written readout of what to fix first, delivered within 24h. It's $12 during launch period. &lt;a href="https://afeldman2.gumroad.com/l/keikf?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=headers-fix-guide" rel="noopener noreferrer"&gt;Grab one here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;But honestly, the configs above are the whole job for most sites. Steal them.&lt;/p&gt;

</description>
      <category>security</category>
      <category>webdev</category>
      <category>devops</category>
      <category>beginners</category>
    </item>
    <item>
      <title>All six security headers fixed in a day — the Macless before/after</title>
      <dc:creator>Amit Feldman</dc:creator>
      <pubDate>Sun, 16 Aug 2026 15:04:11 +0000</pubDate>
      <link>https://dev.to/amitfeldman/all-six-security-headers-fixed-in-a-day-the-macless-beforeafter-5343</link>
      <guid>https://dev.to/amitfeldman/all-six-security-headers-fixed-in-a-day-the-macless-beforeafter-5343</guid>
      <description>&lt;p&gt;Earlier today I left a findings-first comment on a launch writeup here: a passive scan of the product's site, the top findings with the concrete fix, and an offer of a free re-scan once deployed. No pitch — the scan is the conversation.&lt;/p&gt;

&lt;p&gt;The maker read it, put Cloudflare in front of his GitHub Pages site, and closed every single finding within hours. This is the before/after.&lt;/p&gt;

&lt;h2&gt;
  
  
  The launch
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://dev.to/maclessdev/how-to-build-and-ship-an-ios-app-without-a-mac-17o5"&gt;Macless&lt;/a&gt; by &lt;a class="mentioned-user" href="https://dev.to/maclessdev"&gt;@maclessdev&lt;/a&gt; — a GitHub-Actions pipeline, signing scripts, and notes for building and submitting an iOS app to the App Store without owning a Mac. The marketing page lives at macless.dev, hosted on GitHub Pages.&lt;/p&gt;

&lt;h2&gt;
  
  
  Before (scan, Aug 16): 10 passed / 4 warnings / 2 failures
&lt;/h2&gt;

&lt;p&gt;The base was decent: TLS clean (Let's Encrypt, TLSv1.3), fast response (266 ms), title, meta description, exactly one H1, robots.txt and sitemap.xml live.&lt;/p&gt;

&lt;p&gt;The gap was the entire security-header layer — all six missing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;No HSTS&lt;/strong&gt; — every first visit over HTTP was downgrade-able&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No Content-Security-Policy&lt;/strong&gt; — no XSS mitigation layer at all&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No X-Frame-Options&lt;/strong&gt; — clickjacking exposure&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;No X-Content-Type-Options, Referrer-Policy, Permissions-Policy&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The frustrating part: none of this is application work. GitHub Pages doesn't let you set custom headers, full stop — so the fix isn't a code change, it's an architecture tweak.&lt;/p&gt;

&lt;h2&gt;
  
  
  The fix: Cloudflare in front, two Transform Rules
&lt;/h2&gt;

&lt;p&gt;He put Cloudflare in front of the Pages site (free tier) and set the headers at the edge with Transform Rules — no deploy, no code, DNS plus config.&lt;/p&gt;

&lt;h2&gt;
  
  
  After (re-scan, same day — verified twice): 16 passed / 0 warnings / 0 failures
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;HSTS&lt;/strong&gt;: &lt;code&gt;max-age=15552000&lt;/code&gt; (180 days)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CSP&lt;/strong&gt;: &lt;code&gt;default-src 'self'; script-src 'none'; style-src 'self'; img-src 'self'; font-src 'self'; frame-ancestors 'none'; base-uri 'self'; object-src 'none'; form-action 'self'&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;X-Frame-Options: DENY&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;X-Content-Type-Options: nosniff&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Referrer-Policy: strict-origin-when-cross-origin&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Permissions-Policy&lt;/strong&gt;: geolocation, microphone, camera all locked down&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That CSP deserves a second look. &lt;code&gt;script-src 'none'&lt;/code&gt; is bolder than most production sites dare to run — it says this page executes zero JavaScript, which for a static marketing page is exactly true and exactly right. &lt;code&gt;frame-ancestors 'none'&lt;/code&gt; plus XFO DENY is belt-and-suspenders clickjacking defense. This isn't a header set copied from a blog post; it's a header set matched to what the page actually does.&lt;/p&gt;

&lt;h2&gt;
  
  
  Three takeaways for anyone launching on GitHub Pages
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. Pages can't set headers — put a proxy in front.&lt;/strong&gt; GitHub Pages serves your files and nothing else. If your launch page lives there, the security-header layer doesn't exist until you add Cloudflare (or any CDN that can mutate response headers) in front of it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. The fix is a Transform Rule, not a sprint.&lt;/strong&gt; Cloudflare → Rules → Transform Rules → Modify Response Header. One rule can set every static header. Total elapsed work: minutes. The entire "after" column above required zero commits.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Match CSP to reality, then tighten.&lt;/strong&gt; A static page can run &lt;code&gt;script-src 'none'&lt;/code&gt;. An app shell can't. Start from what the page genuinely loads, enforce that, and resist the urge to cargo-cult a permissive policy you saw elsewhere.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why I'm telling this story
&lt;/h2&gt;

&lt;p&gt;Because this is the loop that works: findings → fix → verified re-scan. &lt;a class="mentioned-user" href="https://dev.to/maclessdev"&gt;@maclessdev&lt;/a&gt; didn't pay anyone for this — the first scan and the re-scan were free, and his launch page now passes checks that show up verbatim in enterprise security questionnaires.&lt;/p&gt;

&lt;p&gt;I run these scans findings-first on launch posts here regardless of whether anyone buys anything. If you want the full deep pass — auth-flow edge cases, header drift across routes, perf budget, prioritized fix list with stack-specific snippets — that's the Launch-Ready Audit ($19, 48h turnaround): &lt;a href="https://afeldman2.gumroad.com/l/zxpluh?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=casestudy-macless" rel="noopener noreferrer"&gt;https://afeldman2.gumroad.com/l/zxpluh?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=casestudy-macless&lt;/a&gt;&lt;br&gt;
The Deep Dive ($99) adds a written remediation plan + re-scan verification: &lt;a href="https://afeldman2.gumroad.com/l/wmdfxb?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=casestudy-macless-deepdive" rel="noopener noreferrer"&gt;https://afeldman2.gumroad.com/l/wmdfxb?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=casestudy-macless-deepdive&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And if I commented on your launch and you've shipped the fixes, say so in the thread. The re-scan is free, and if the before/after is this clean, I'll write about yours next.&lt;/p&gt;




&lt;h2&gt;
  
  
  Postscript (September 2026): the layer a header scan can't see
&lt;/h2&gt;

&lt;p&gt;After this article went live, &lt;a class="mentioned-user" href="https://dev.to/maclessdev"&gt;@maclessdev&lt;/a&gt; took the same findings-first loop one level deeper — into the CI pipeline itself, which for Macless &lt;em&gt;is&lt;/em&gt; the product (signing certificates, App Store Connect keys, GitHub Actions workflows). He ran the pass himself and it turned up two real gaps, both now fixed:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;No explicit &lt;code&gt;permissions:&lt;/code&gt; block on the workflows.&lt;/strong&gt; Older repos lean on the default &lt;code&gt;GITHUB_TOKEN&lt;/code&gt; scope, which is broader than most people assume. Explicit per-workflow permissions close that.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No &lt;code&gt;.gitignore&lt;/code&gt; covering signing material.&lt;/strong&gt; One stray &lt;code&gt;git add -A&lt;/code&gt; and a cert or provisioning profile is in history forever.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Worth stating plainly: the header scan in this article says nothing about any of that. A page can be 16/16 green while a workflow dumps secrets into logs or a token is scoped wider than it needs to be. The checks that caught these: full git history on both repos for committed certs/keys (none, ever), how secrets reach the workflows (environment variables, never shell strings), whether anything logs them (no), and &lt;code&gt;GITHUB_TOKEN&lt;/code&gt; scoping. His signing credentials live in encrypted GitHub secrets, and none of the workflows trigger on pull requests — which is the usual way a public repo leaks them.&lt;/p&gt;

&lt;p&gt;If your product's crown jewels live in a pipeline and not on the marketing page, that second pass is the one that matters.&lt;/p&gt;

</description>
      <category>security</category>
      <category>webdev</category>
      <category>launch</category>
      <category>startup</category>
    </item>
    <item>
      <title>5 tools launched this week promising "your data never leaves your browser" — none shipped the header that enforces it</title>
      <dc:creator>Amit Feldman</dc:creator>
      <pubDate>Sun, 16 Aug 2026 13:12:38 +0000</pubDate>
      <link>https://dev.to/amitfeldman/5-tools-launched-this-week-promising-your-data-never-leaves-your-browser-none-shipped-the-c2b</link>
      <guid>https://dev.to/amitfeldman/5-tools-launched-this-week-promising-your-data-never-leaves-your-browser-none-shipped-the-c2b</guid>
      <description>&lt;p&gt;A week ago I ran a passive launch-readiness check on 10 freshly launched products and published the pattern: 7 out of 10 shipped with no &lt;code&gt;Content-Security-Policy&lt;/code&gt; at all.&lt;/p&gt;

&lt;p&gt;This week I did it again — 8 products that launched in the last ~24 hours, all "I built this" posts by solo makers. Same method: public HTTP response headers and homepage HTML only. No probing, no auth, nothing intrusive. Exactly what any scanner, prospect, or security-conscious customer sees on a single page load.&lt;/p&gt;

&lt;p&gt;I'm not naming anyone again. The pattern is the point — and this week the pattern got sharper.&lt;/p&gt;

&lt;h2&gt;
  
  
  The results
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;8 out of 8&lt;/strong&gt; shipped with no &lt;code&gt;Content-Security-Policy&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Not 7 out of 10 this time. All of them.&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;Missing&lt;/th&gt;
&lt;th&gt;Why it matters&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Content-Security-Policy&lt;/td&gt;
&lt;td&gt;8/8&lt;/td&gt;
&lt;td&gt;Nothing mitigating XSS / injected scripts&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;X-Frame-Options&lt;/td&gt;
&lt;td&gt;7/8&lt;/td&gt;
&lt;td&gt;Site can be framed anywhere → clickjacking&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Permissions-Policy&lt;/td&gt;
&lt;td&gt;7/8&lt;/td&gt;
&lt;td&gt;Camera/geo/mic unrestricted by default&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;HSTS&lt;/td&gt;
&lt;td&gt;6/8&lt;/td&gt;
&lt;td&gt;First-visit downgrade possible&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Referrer-Policy&lt;/td&gt;
&lt;td&gt;6/8&lt;/td&gt;
&lt;td&gt;Full URLs leak to every third-party request&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;X-Content-Type-Options&lt;/td&gt;
&lt;td&gt;6/8&lt;/td&gt;
&lt;td&gt;MIME-sniffing exposure on user content&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;One product came genuinely close — 5 of 6 headers present, HSTS set for two years, missing only the CSP. That's the closest anyone got.&lt;/p&gt;

&lt;h2&gt;
  
  
  The part that made me write this
&lt;/h2&gt;

&lt;p&gt;Here's the sharper pattern: &lt;strong&gt;5 of the 8 tools pitch privacy as the product.&lt;/strong&gt; "Runs in your browser." "Nothing uploaded." "Private by design." Client-side processing is the headline feature — it's in their titles and their hero copy.&lt;/p&gt;

&lt;p&gt;And every one of them shipped without the one header that actually enforces that promise.&lt;/p&gt;

&lt;p&gt;A CSP is what stops an injected script — a compromised dependency, a malicious ad tag, a poisoned CDN asset — from reading the data your users just trusted never leaves their browser. Without it, "nothing leaves your browser" is a marketing sentence, not an enforced property. One bad script tag away from being false.&lt;/p&gt;

&lt;p&gt;None of these makers are careless. Client-side processing is real engineering, and they did it. The gap is that the last mile — telling the browser "only run scripts I explicitly allow" — is a config line nobody wrote, because no test fails and no deploy breaks when it's missing.&lt;/p&gt;

&lt;h2&gt;
  
  
  The good news: same-day fixes are real
&lt;/h2&gt;

&lt;p&gt;Yesterday I flagged a missing CSP and HSTS in the comments of one maker's launch post. By the evening he'd deployed all six security headers — CSP locked down to &lt;code&gt;script-src 'none'&lt;/code&gt;, HSTS for 180 days, the full set. His re-scan came back completely green: 16 checks passed, 0 warnings, 0 failures.&lt;/p&gt;

&lt;p&gt;Total elapsed time from "never thought about it" to "fully locked down": a few hours, in the middle of launch day.&lt;/p&gt;

&lt;p&gt;That's the actual story of these failures. Not skill, not budget — just that launch week has a hundred things in it and headers are item #101. Every fix above is a one-line config at the host or CDN layer: Vercel, Netlify, Cloudflare, nginx, all have a documented snippet.&lt;/p&gt;

&lt;h2&gt;
  
  
  The SEO side, quickly
&lt;/h2&gt;

&lt;p&gt;Better than last week — 7 of 8 had exactly one &lt;code&gt;&amp;lt;h1&amp;gt;&lt;/code&gt; and a real canonical. Remaining nits:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;One homepage had &lt;strong&gt;two &lt;code&gt;&amp;lt;h1&amp;gt;&lt;/code&gt; tags&lt;/strong&gt; — splitting your best keyword slot against itself&lt;/li&gt;
&lt;li&gt;One meta description ran &lt;strong&gt;178 characters&lt;/strong&gt; — truncates mid-sentence in search results (~160 limit)&lt;/li&gt;
&lt;li&gt;One page took &lt;strong&gt;2.9 seconds&lt;/strong&gt; to respond, with 836ms of server think time — first impression spent staring at a blank tab&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What I'd do (and did)
&lt;/h2&gt;

&lt;p&gt;Same rule as last week: a launch isn't done when the deploy succeeds — it's done when the thing a stranger's browser receives passes a baseline. Run the check before the traffic, not after.&lt;/p&gt;

&lt;p&gt;If you shipped recently and want the full picture: I run a &lt;strong&gt;Launch-Ready Quick Scan&lt;/strong&gt; — passive headers/TLS/HTML checks plus a human-written readout of what to fix first, delivered within 24h. It's $12 for the launch period, written so you can hand it straight to whoever owns your deploy config. &lt;a href="https://afeldman2.gumroad.com/l/keikf?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=launch-scan-roundup-2" rel="noopener noreferrer"&gt;Grab one here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;And if your product's pitch is "private, runs in your browser": the CSP is the difference between promising it and enforcing it. Twenty minutes tonight.&lt;/p&gt;

</description>
      <category>security</category>
      <category>privacy</category>
      <category>webdev</category>
      <category>startup</category>
    </item>
    <item>
      <title>I re-scanned the launches I flagged last week — here's who actually shipped the fixes</title>
      <dc:creator>Amit Feldman</dc:creator>
      <pubDate>Sun, 16 Aug 2026 09:05:27 +0000</pubDate>
      <link>https://dev.to/amitfeldman/i-re-scanned-the-launches-i-flagged-last-week-heres-who-actually-shipped-the-fixes-514k</link>
      <guid>https://dev.to/amitfeldman/i-re-scanned-the-launches-i-flagged-last-week-heres-who-actually-shipped-the-fixes-514k</guid>
      <description>&lt;p&gt;For the past two weeks I've been running passive, read-only security scans on products that launch here on dev.to, and posting the findings publicly with the concrete fix for each. No pitch in the first touch — the scan is the conversation, and I always offer a free re-scan once fixes are deployed.&lt;/p&gt;

&lt;p&gt;The part I didn't expect: how many makers actually shipped the fixes. This is the verification roundup — real before/after numbers from the re-scans.&lt;/p&gt;

&lt;h2&gt;
  
  
  The pattern across ~100 launches
&lt;/h2&gt;

&lt;p&gt;The headline finding from the &lt;a href="https://dev.to/amitfeldman/i-ran-a-passive-security-check-on-100-freshly-launched-products-here-s-what-actually-breaks-1jpn"&gt;broader sweep&lt;/a&gt; hasn't changed: the most common failure is a missing &lt;strong&gt;Content-Security-Policy&lt;/strong&gt; — roughly 7 in 10 launches — followed by missing HSTS. Both are one-line fixes. Almost nobody ships them on day one.&lt;/p&gt;

&lt;h2&gt;
  
  
  Maker 1: Loop — full remediation in under 24 hours
&lt;/h2&gt;

&lt;p&gt;The fastest turnaround so far. &lt;a href="https://dev.to/jammyvibez/i-built-a-social-app-where-developers-can-share-code-fork-each-others-snippets-and-co-write-4lgl"&gt;Loop&lt;/a&gt; (Next.js on Vercel) launched with &lt;strong&gt;7 passed / 5 warnings / 4 failures&lt;/strong&gt;: no CSP, no X-Frame-Options, no nosniff, and — because the app renders client-side only — no title, meta description or h1 for crawlers and link-unfurlers.&lt;/p&gt;

&lt;p&gt;Under 24 hours later the re-scan read &lt;strong&gt;15 passed / 1 warning / 0 failures&lt;/strong&gt;. Every failing header closed. I wrote up the &lt;a href="https://dev.to/amitfeldman/one-maker-fixed-every-security-header-on-his-launch-in-24-hours-heres-the-beforeafter-5f7a"&gt;full before/after as a case study&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Maker 2: Macless — 5 of 6 headers live within hours
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://macless.dev" rel="noopener noreferrer"&gt;Macless&lt;/a&gt; (ship an iOS app without a Mac) launched on GitHub Pages with all six security headers missing. GitHub Pages gives you no header control — so the maker put Cloudflare in front of the domain and used a &lt;strong&gt;Transform Rule&lt;/strong&gt; to set headers at the edge.&lt;/p&gt;

&lt;p&gt;My re-scan verified, live:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;X-Frame-Options: DENY&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;X-Content-Type-Options: nosniff&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Referrer-Policy: strict-origin-when-cross-origin&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Permissions-Policy&lt;/code&gt; locked down&lt;/li&gt;
&lt;li&gt;HSTS on, 180-day max-age&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Five of six, in hours. The one still open is the CSP — which is also the one doing the actual XSS work. Same fix path: one more Transform Rule, start with a tight &lt;code&gt;default-src 'self'&lt;/code&gt; and loosen only what breaks. If you're on GitHub Pages, this CDN-front pattern is the way — Pages itself will never give you these headers.&lt;/p&gt;

&lt;h2&gt;
  
  
  Maker 3: PlaygroundAPI — rescan reads 15 passed / 1 warning / 0 failures
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://playground-api-xi.vercel.app" rel="noopener noreferrer"&gt;PlaygroundAPI&lt;/a&gt; — a free sandboxed mock REST &amp;amp; GraphQL service — came back essentially clean on verification: HSTS at &lt;code&gt;max-age=63072000; includeSubDomains; preload&lt;/code&gt;, CSP defined, X-Frame-Options DENY, nosniff, Referrer-Policy and Permissions-Policy all live, TLS 1.3, 267 ms total response. The interesting surface left is the API itself — auth-flow edge cases like token expiry/reuse and session isolation — which is a manual review, not a scanner finding.&lt;/p&gt;

&lt;h2&gt;
  
  
  Maker 4: the platform-constraint case
&lt;/h2&gt;

&lt;p&gt;One launch on a &lt;code&gt;.streamlit.app&lt;/code&gt; subdomain verified their fix but hit a wall: on a platform subdomain you don't control the edge, so granular CSP and HSTS enforcement isn't yours to set. Their plan — move to a custom domain with Cloudflare and use Transform Rules — is the correct one, and the same pattern Macless used above. Platform subdomains are fine for demos; if you're collecting real users, the custom domain is part of the security posture, not just branding.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I take from this
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Makers fix things fast when the fix is concrete.&lt;/strong&gt; Every deployed fix above came from a findings comment that included the exact header line or rule to add, not a generic "you should harden your headers."&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The CDN-front pattern solves the two hardest hosting cases&lt;/strong&gt; (GitHub Pages, platform subdomains) with the same move: Cloudflare in front, Transform Rules at the edge.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CSP is still the last one standing.&lt;/strong&gt; It's the highest-value header and the one everyone defers, because a tight CSP can break inline scripts. Ship a report-only policy first (&lt;code&gt;Content-Security-Policy-Report-Only&lt;/code&gt;), watch what fires, then enforce.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Findings on launch posts stay free — the re-scan verification too. If I flagged your launch and you've shipped the fixes, reply on your thread and I'll re-run the check and post the verified numbers, same as above.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;I build &lt;a href="https://dev.to/amitfeldman/i-built-a-cli-to-stop-myself-from-committing-api-keys-and-broken-envs-into-ci-3o2o"&gt;envcheck&lt;/a&gt;, a .env validator and secret-leak scanner for CI — the scans above run on the same engine.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>cybersecurity</category>
      <category>infosec</category>
      <category>security</category>
    </item>
    <item>
      <title>I ran a passive security check on 100 freshly launched products — 1 in 5 shipped with zero security headers</title>
      <dc:creator>Amit Feldman</dc:creator>
      <pubDate>Fri, 07 Aug 2026 22:05:07 +0000</pubDate>
      <link>https://dev.to/amitfeldman/i-ran-a-passive-security-check-on-100-freshly-launched-products-1-in-5-shipped-with-zero-security-5bn8</link>
      <guid>https://dev.to/amitfeldman/i-ran-a-passive-security-check-on-100-freshly-launched-products-1-in-5-shipped-with-zero-security-5bn8</guid>
      <description>&lt;p&gt;Last week I posted the results of checking 10 products that had just launched. The pattern was so consistent that I kept going. This is the follow-up: &lt;strong&gt;100 products&lt;/strong&gt;, all launched within roughly the past week, pulled from Product Hunt, dev.to launch posts, r/SideProject, Peerlist, Microlaunch, Uneed, and a couple of launch directories.&lt;/p&gt;

&lt;p&gt;Same rules as before — passive only. Public HTTP response headers and homepage HTML, the exact thing any scanner, prospect, or security-conscious customer sees when your site loads once. No probing, no auth attempts, nothing intrusive.&lt;/p&gt;

&lt;p&gt;And same as before: I'm not naming anyone who failed. The point is the pattern, not the callout.&lt;/p&gt;

&lt;h2&gt;
  
  
  The results
&lt;/h2&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;Missing&lt;/th&gt;
&lt;th&gt;What it means&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Content-Security-Policy&lt;/td&gt;
&lt;td&gt;76/100&lt;/td&gt;
&lt;td&gt;Nothing mitigating XSS / injected scripts&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Permissions-Policy&lt;/td&gt;
&lt;td&gt;78/100&lt;/td&gt;
&lt;td&gt;Camera, mic, geolocation unrestricted by default&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;X-Frame-Options&lt;/td&gt;
&lt;td&gt;67/100&lt;/td&gt;
&lt;td&gt;Pages can be iframed anywhere → clickjacking&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Referrer-Policy&lt;/td&gt;
&lt;td&gt;63/100&lt;/td&gt;
&lt;td&gt;Full URLs leak to every third-party request&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;X-Content-Type-Options&lt;/td&gt;
&lt;td&gt;57/100&lt;/td&gt;
&lt;td&gt;MIME-sniffing exposure on user content&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;HSTS&lt;/td&gt;
&lt;td&gt;37/100&lt;/td&gt;
&lt;td&gt;First-visit downgrade still possible&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Two numbers that surprised me even after the first batch:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;20 out of 100 shipped with all six missing.&lt;/strong&gt; Not one obscure header — every single baseline protection absent. These weren't broken products; several were polished, well-designed launches with real traction.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Only 13 out of 100 were fully clean.&lt;/strong&gt; And consistent with the first batch, the clean ones skewed toward small solo projects, not the bigger teams. "More people at launch" does not mean "someone checked."&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this keeps happening
&lt;/h2&gt;

&lt;p&gt;None of these are code fixes. Every one is a config line at the host or CDN layer — Vercel, Netlify, Cloudflare, nginx, all of them have a documented snippet, and most can apply it at the edge without a deploy. The failure mode isn't skill. Launch week has a hundred things in it and "headers" is item #101. There's no test that fails, no deploy that breaks, no user who complains. The site just quietly tells every visitor's browser: &lt;em&gt;no rules, do whatever.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;That's exactly the class of problem that only gets caught by something that checks, every time, automatically — because humans are bad at "every time."&lt;/p&gt;

&lt;h2&gt;
  
  
  It's fixable fast — I watched it happen
&lt;/h2&gt;

&lt;p&gt;The most common pushback I got last week was "sure, but who has time during launch week?" So here's the counterexample: one maker I flagged went and fixed &lt;strong&gt;every&lt;/strong&gt; missing header within 24 hours — full before/after, verified by re-scan. I wrote it up here: &lt;a href="https://dev.to/amitfeldman/one-maker-fixed-every-security-header-on-his-launch-in-24-hours-heres-the-beforeafter-5f7a"&gt;One maker fixed every security header on his launch in 24 hours — here's the before/after&lt;/a&gt;. His site went from 5 findings to zero while I slept.&lt;/p&gt;

&lt;p&gt;If you're behind Cloudflare, four of the six are a single Transform Rule (Modify Response Header) at the edge — no code change, no deploy. HSTS starts at a short &lt;code&gt;max-age&lt;/code&gt; (3600) and steps up once verified. CSP is the one that takes actual care with a SPA, but &lt;code&gt;default-src 'self'&lt;/code&gt; plus your API origins is a safe start, and &lt;code&gt;Content-Security-Policy-Report-Only&lt;/code&gt; lets you measure before you enforce.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I'd do differently (and do)
&lt;/h2&gt;

&lt;p&gt;My rule hasn't changed: a launch isn't done when the deploy succeeds — it's done when the thing a stranger's browser receives passes a baseline. 87 out of 100 launches this week hadn't run that check.&lt;/p&gt;

&lt;p&gt;If you shipped something recently and want to know where you stand: I run a &lt;strong&gt;Launch-Ready Quick Scan&lt;/strong&gt; — passive headers/TLS/HTML checks plus a human-written readout of what to fix first, delivered within 24h. It's $12 for the launch period, written so you can hand it straight to whoever owns your deploy config. &lt;a href="https://afeldman2.gumroad.com/l/keikf?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=launch-scan-100" rel="noopener noreferrer"&gt;Grab one here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;And if you're pre-launch: the six headers above are a 20-minute fix tonight. Do it before the traffic, not after.&lt;/p&gt;

</description>
      <category>security</category>
      <category>webdev</category>
      <category>saas</category>
      <category>startup</category>
    </item>
    <item>
      <title>One maker fixed every security header on his launch in 24 hours — here's the before/after</title>
      <dc:creator>Amit Feldman</dc:creator>
      <pubDate>Fri, 07 Aug 2026 09:50:55 +0000</pubDate>
      <link>https://dev.to/amitfeldman/one-maker-fixed-every-security-header-on-his-launch-in-24-hours-heres-the-beforeafter-5f7a</link>
      <guid>https://dev.to/amitfeldman/one-maker-fixed-every-security-header-on-his-launch-in-24-hours-heres-the-beforeafter-5f7a</guid>
      <description>&lt;p&gt;A week ago I started leaving findings-first comments on launch posts here: I run a passive scan of the product's site, post the top findings with the concrete fix, and offer a free re-scan once it's deployed. No pitch in the first touch — the scan is the conversation.&lt;/p&gt;

&lt;p&gt;This week one maker did the thing every security person wishes more teams would do: he read the findings, deployed the fixes the same day, and asked for the re-scan. This is the before/after, with his permission-worthy win on full display.&lt;/p&gt;

&lt;h2&gt;
  
  
  The launch
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://dev.to/jammyvibez/i-built-a-social-app-where-developers-can-share-code-fork-each-others-snippets-and-co-write-4lgl"&gt;Loop&lt;/a&gt; by &lt;a class="mentioned-user" href="https://dev.to/jammyvibez"&gt;@jammyvibez&lt;/a&gt; — a collaborative social app where developers share code, fork snippets, and co-write posts live. A Next.js app on Vercel, launched here on August 5th.&lt;/p&gt;

&lt;h2&gt;
  
  
  Before (scan, Aug 5): 7 passed / 5 warnings / 4 failures
&lt;/h2&gt;

&lt;p&gt;The good news first: HSTS was already strong (&lt;code&gt;max-age=63072000; includeSubDomains; preload&lt;/code&gt;), TLS was clean, robots.txt and sitemap.xml were live.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;No Content-Security-Policy&lt;/strong&gt; — the single highest-value header for an app that renders user-generated content&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No X-Frame-Options&lt;/strong&gt; — clickjacking exposure on every page&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;No X-Content-Type-Options, Referrer-Policy, Permissions-Policy&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No &lt;code&gt;&amp;lt;title&amp;gt;&lt;/code&gt;, no meta description, no &lt;code&gt;&amp;lt;h1&amp;gt;&lt;/code&gt;&lt;/strong&gt; — the app renders client-side only, so crawlers and link-unfurlers saw an empty shell&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That last cluster matters more than people think: every link preview of his launch — in Discord, Slack, X, iMessage — was generating from nothing.&lt;/p&gt;

&lt;h2&gt;
  
  
  After (re-scan, Aug 6): 15 passed / 1 warning / 0 failures
&lt;/h2&gt;

&lt;p&gt;Under 24 hours later:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;CSP live&lt;/strong&gt;: &lt;code&gt;default-src 'self'&lt;/code&gt; with an explicit allowlist for the two third-party origins the app actually loads (Stripe.js and Vercel Analytics)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;X-Frame-Options: DENY&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;X-Content-Type-Options: nosniff&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Referrer-Policy: strict-origin-when-cross-origin&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Permissions-Policy&lt;/strong&gt;: camera/microphone scoped to self, geolocation/payment/usb locked down&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Title&lt;/strong&gt; (39 chars), &lt;strong&gt;meta description&lt;/strong&gt; (145 chars), exactly &lt;strong&gt;one H1&lt;/strong&gt; — the page now renders its metadata server-side&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The remaining backlog, which he has in writing: &lt;code&gt;script-src&lt;/code&gt; still carries &lt;code&gt;'unsafe-inline' 'unsafe-eval'&lt;/code&gt; (a Next.js hydration constraint you close with nonces when it matters), and TTFB is ~2.1s cold. Neither is a launch blocker. Both are honest items on a real list.&lt;/p&gt;

&lt;h2&gt;
  
  
  Three takeaways for anyone launching this week
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. Headers are a config file, not a sprint.&lt;/strong&gt; On Vercel it's a &lt;code&gt;headers()&lt;/code&gt; block in &lt;code&gt;next.config.js&lt;/code&gt; or entries in &lt;code&gt;vercel.json&lt;/code&gt;. On Netlify it's a &lt;code&gt;_headers&lt;/code&gt; file. Behind Cloudflare it's one Transform Rule at the edge — no deploy at all. The entire "after" column above was one commit.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. If your app is client-rendered, your metadata doesn't exist.&lt;/strong&gt; Crawlers, link unfurlers, and most social scrapers don't execute JavaScript. SSR/SSG your &lt;code&gt;&amp;lt;title&amp;gt;&lt;/code&gt;, meta description, and at least one &lt;code&gt;&amp;lt;h1&amp;gt;&lt;/code&gt; — or accept that every share of your launch looks blank.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Ship CSP in report-only mode first.&lt;/strong&gt; &lt;code&gt;Content-Security-Policy-Report-Only&lt;/code&gt; tells you what would break without breaking it. Let violation reports collect for a few days, allowlist what you actually load, then enforce. Loop's CSP is a good enforced end-state: &lt;code&gt;default-src 'self'&lt;/code&gt; plus exactly the origins you use.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why I'm telling this story
&lt;/h2&gt;

&lt;p&gt;Because this is the loop that works: findings → fix → verified re-scan. &lt;a class="mentioned-user" href="https://dev.to/jammyvibez"&gt;@jammyvibez&lt;/a&gt; didn't pay anyone for this — the first scan and the re-scan were free, and now his launch passes checks that show up verbatim in enterprise security questionnaires.&lt;/p&gt;

&lt;p&gt;I run these scans as &lt;a href="https://afeldman2.gumroad.com/l/keikf?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=casestudy-loopapp" rel="noopener noreferrer"&gt;Launch-Ready Quick Scans&lt;/a&gt; — $12 during launch period, top findings plus the full report — and I keep commenting findings-first on launch posts here regardless. If I commented on yours and you've shipped the fixes, say so in the thread. The re-scan is free, and if the before/after is this clean, I'll write about yours next.&lt;/p&gt;

</description>
      <category>security</category>
      <category>webdev</category>
      <category>saas</category>
      <category>startup</category>
    </item>
    <item>
      <title>I ran a passive security check on 10 products that launched this week — 7 failed the same one-line fix</title>
      <dc:creator>Amit Feldman</dc:creator>
      <pubDate>Wed, 05 Aug 2026 00:05:18 +0000</pubDate>
      <link>https://dev.to/amitfeldman/i-ran-a-passive-security-check-on-10-products-that-launched-this-week-7-failed-the-same-one-line-1ie1</link>
      <guid>https://dev.to/amitfeldman/i-ran-a-passive-security-check-on-10-products-that-launched-this-week-7-failed-the-same-one-line-1ie1</guid>
      <description>&lt;p&gt;This week I did something I've been meaning to do for a while: I took 10 products that launched in the last 48 hours — a mix of Product Hunt launches and "I built this" posts on Reddit — and ran a passive launch-readiness check on each one.&lt;/p&gt;

&lt;p&gt;Passive means exactly that: public HTTP response headers and homepage HTML only. No probing, no auth attempts, nothing intrusive — the same thing any scanner, prospect, or security-conscious customer sees when they load your site once.&lt;/p&gt;

&lt;p&gt;I'm not naming anyone. The point isn't to call out individual makers — it's that the failures were so consistent they form a pattern worth publishing.&lt;/p&gt;

&lt;h2&gt;
  
  
  The results
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;7 out of 10&lt;/strong&gt; shipped with no &lt;code&gt;Content-Security-Policy&lt;/code&gt; header at all.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3 out of 10&lt;/strong&gt; were missing &lt;code&gt;Strict-Transport-Security&lt;/code&gt; — including one product ranked #1 on Product Hunt the day it launched.&lt;/p&gt;

&lt;p&gt;Across the 10 sites, the most common gaps, in order:&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;Failed&lt;/th&gt;
&lt;th&gt;Why it matters&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Content-Security-Policy&lt;/td&gt;
&lt;td&gt;7/10&lt;/td&gt;
&lt;td&gt;Nothing mitigating XSS / injected scripts&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Referrer-Policy&lt;/td&gt;
&lt;td&gt;6/10&lt;/td&gt;
&lt;td&gt;Full URLs leak to every third-party request&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Permissions-Policy&lt;/td&gt;
&lt;td&gt;6/10&lt;/td&gt;
&lt;td&gt;Camera/geo/mic features unrestricted by default&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;X-Frame-Options&lt;/td&gt;
&lt;td&gt;6/10&lt;/td&gt;
&lt;td&gt;Site can be framed anywhere → clickjacking&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;X-Content-Type-Options&lt;/td&gt;
&lt;td&gt;6/10&lt;/td&gt;
&lt;td&gt;MIME-sniffing exposure on user content&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;HSTS&lt;/td&gt;
&lt;td&gt;3/10&lt;/td&gt;
&lt;td&gt;First-visit downgrade possible&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Two products were genuinely clean — all six headers present, HSTS with preload. Both were small solo projects, which killed my assumption that "bigger launch = better hygiene."&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this keeps happening
&lt;/h2&gt;

&lt;p&gt;None of these are code fixes. Every one is a one-line config change at the host or CDN layer — Vercel, Netlify, Cloudflare, nginx, all of them have a documented snippet for it. The failure mode isn't skill, it's that launch week has a hundred things in it and "headers" is item #101. There's no test that fails, no deploy that breaks, no user who complains. The site just quietly tells every visitor's browser "no rules, do whatever."&lt;/p&gt;

&lt;p&gt;That's exactly the class of problem that only gets caught by something that checks, every time, automatically — because humans are bad at "every time."&lt;/p&gt;

&lt;h2&gt;
  
  
  The SEO side wasn't much better
&lt;/h2&gt;

&lt;p&gt;While I was in the HTML I checked the basics too:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;2/10 homepages had &lt;strong&gt;no &lt;code&gt;&amp;lt;h1&amp;gt;&lt;/code&gt;&lt;/strong&gt; — your single best keyword slot, empty&lt;/li&gt;
&lt;li&gt;Meta descriptions over 200 chars (truncates at ~160 in search results) on half of them&lt;/li&gt;
&lt;li&gt;One product had a meta description of &lt;strong&gt;2,701 characters&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Missing &lt;code&gt;alt&lt;/code&gt; text on the majority of images on 8/10 sites&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Again: not skill. Just nobody checked.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I'd do differently (and did)
&lt;/h2&gt;

&lt;p&gt;I run these checks on every launch now, including my own. My rule is simple: a launch isn't done when the deploy succeeds — it's done when the thing a stranger's browser receives passes a baseline.&lt;/p&gt;

&lt;p&gt;If you shipped something recently and want to know where you stand: I run a &lt;strong&gt;Launch-Ready Quick Scan&lt;/strong&gt; — passive headers/TLS/HTML checks plus a human-written readout of what to fix first, delivered within 24h. It's $29 for the launch period (normally $49), and the report is written so you can hand it straight to whoever owns your deploy config. &lt;a href="https://afeldman2.gumroad.com/l/keikf?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=launch-scan-roundup" rel="noopener noreferrer"&gt;Grab one here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;And if you're pre-launch: the six headers above are a 20-minute fix tonight. Do it before the traffic, not after.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>I run a one-person company — here are the 54 prompts I actually reuse</title>
      <dc:creator>Amit Feldman</dc:creator>
      <pubDate>Thu, 30 Jul 2026 07:43:36 +0000</pubDate>
      <link>https://dev.to/amitfeldman/i-run-a-one-person-company-here-are-the-54-prompts-i-actually-reuse-4h0h</link>
      <guid>https://dev.to/amitfeldman/i-run-a-one-person-company-here-are-the-54-prompts-i-actually-reuse-4h0h</guid>
      <description>&lt;h2&gt;
  
  
  Four jobs before lunch
&lt;/h2&gt;

&lt;p&gt;A normal Tuesday for me: 9am I'm a developer, 11am I'm writing landing page copy, 1pm I'm on a discovery call pretending I have a sales process, 3pm an angry email lands and I'm support, 5pm I'm doing the invoicing I've been avoiding since Friday.&lt;/p&gt;

&lt;p&gt;The work isn't the expensive part. The &lt;em&gt;switching&lt;/em&gt; is. Every hop lands me in front of a blank page in a role I'm mediocre at, and I lose fifteen minutes just working out what good even looks like here. Four hops a day, five days a week. That's most of a working day a week spent staring.&lt;/p&gt;

&lt;p&gt;So I did what everyone does now: I asked an AI assistant. "Help me write a cold email." "How should I price this?" And I got exactly what you'd expect — competent, structureless mush. Advice that sounds like a LinkedIn post. The problem wasn't the model. It was that I was asking like someone who didn't know the domain, because in that particular hour, I didn't.&lt;/p&gt;

&lt;p&gt;The fix turned out to be boring: stop asking questions, start pasting &lt;em&gt;briefs&lt;/em&gt;. A prompt that names a framework, hands over real numbers, sets constraints, and demands a decision rule at the end gets back something I can act on. One that doesn't gets a fortune cookie.&lt;/p&gt;

&lt;p&gt;I kept the ones that worked in a file. That file is now 54 prompts across the six jobs I actually do — validation, marketing, sales, ops, finance, support — and I've packaged it up. Here are three of them in full, so you can judge the pattern yourself.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. The prompt I run before I build anything
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;When to use this:&lt;/strong&gt; when you're in love with an idea and need a hostile reviewer to try to kill it before the market does.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Act as a skeptical seed-stage investor who has seen 1,000 pitches and passed on
most of them. Here is my idea:

[DESCRIBE THE IDEA IN 3–5 SENTENCES: who it's for, the problem, the solution,
and how it makes money]

Tear it apart. Specifically:
1. Name the 3 assumptions most likely to be fatally wrong, ranked by
   (likelihood of being wrong) × (damage if wrong).
2. For each, describe the cheapest test (under $100 and under one week) that
   would produce real evidence either way.
3. List who already solves this and why customers might prefer the status quo,
   spreadsheets, or doing nothing.
4. Tell me what evidence would change your mind from "pass" to "curious."

Be direct. Do not soften the critique and do not end with encouragement.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Why it works: the ranking formula stops the model listing ten generic risks and forces a prioritisation. "Under $100 and under one week" converts criticism into this week's to-do list. And the last line matters more than it looks — without it you get a paragraph of encouragement at the end that quietly undoes the whole exercise.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. The prompt that gets my week back
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;When to use this:&lt;/strong&gt; when your week disappears into repetitive admin and you need to know what to automate first.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;You are an automation consultant. I'm a solo founder. Here is how I
actually spent my time last week, with hours per task:

[PASTE YOUR TASK LIST, e.g. "answering support emails 4h, invoicing 1h,
scheduling social posts 2h, sales calls 5h, writing content 4h…"]

1. Score every task on two axes: repetitiveness (how rule-based is it)
   and founder-necessity (does it need MY judgment/relationship).
2. Sort all tasks into four quadrants: automate now, delegate, keep
   but time-box, and eliminate.
3. For the top 3 "automate now" candidates, rank by ROI =
   (hours saved per month) ÷ (setup effort), and describe the
   automation for each: trigger, steps, tools ([MY STACK, e.g. "Gmail,
   Stripe, Notion, Zapier/Make"]), and failure mode to watch.
4. Estimate total hours recovered per month and tell me the ONE
   automation to build this week.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Why it works: it runs on &lt;em&gt;your&lt;/em&gt; logged hours, not a hypothetical founder's, so the output can't be generic. And step 4 is the whole point — a list of twelve automation ideas is another form of paralysis. I want one.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. The prompt for the email I shouldn't send at 11pm
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;When to use this:&lt;/strong&gt; when a furious email lands and your first-draft reply would make things worse.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;You are a customer-success lead who specializes in saving angry
customers. My product: [PRODUCT DESCRIPTION]. Here is the customer's
message:

[PASTE THE ANGRY MESSAGE]

And here is what actually happened / what I can offer: [FACTS + WHAT
YOU CAN DO: refund, fix timeline, workaround, nothing].

Write my reply:
1. First, tell me privately (not for the customer): is this customer
   right? What did we likely get wrong?
2. The reply itself, under 150 words: acknowledge the specific
   failure without legal-speak or "we're sorry you feel that way",
   take ownership of what's genuinely ours, state what I'm doing
   about it with a concrete action and date, and make the remedy
   (if any) without them having to ask again.
3. One sentence I must NOT send (the defensive thing I'm tempted to
   say) and why.
4. A follow-up note to send [N] days later checking the fix landed —
   this is where angry customers become loyal ones.
5. The product/process fix I should make so this exact ticket never
   happens again.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Step 1 and step 3 are why I still use this one. The private read on whether the customer is &lt;em&gt;right&lt;/em&gt; usually deflates my defensiveness before I've written a word, and naming the sentence I'm tempted to send is unnervingly accurate about every time.&lt;/p&gt;

&lt;p&gt;They're also built to chain: interview notes from the Mom Test script feed the testimonial-to-copy miner, whose output feeds the landing-page hero prompt. Outputs become inputs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Who this is not for
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;If you already have a playbook, skip it.&lt;/strong&gt; Someone who's run sales or done pricing work professionally will find their own frameworks in here with the serial numbers filed off. The pack is for people covering six roles badly, not one role well.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It's prompts, not software.&lt;/strong&gt; Markdown files plus one print-ready HTML page. Nothing runs, nothing integrates, no accounts. If you want a tool, this isn't one.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The placeholders are work.&lt;/strong&gt; Every prompt wants real numbers, real quotes, real transcripts. Fill them with vagueness and you get vagueness back — the specificity is doing the heavy lifting, not the wording.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It won't make the decision for you.&lt;/strong&gt; Several prompts deliberately end in a scorecard or a pass/fail rule. That's a structured argument to react to, not an answer.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Getting it
&lt;/h2&gt;

&lt;p&gt;The Solo Founder's AI Prompt Pack is $19 on Gumroad: &lt;strong&gt;&lt;a href="https://afeldman2.gumroad.com/l/zdyxz?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=promptpack-launch" rel="noopener noreferrer"&gt;https://afeldman2.gumroad.com/l/zdyxz?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=promptpack-launch&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;54 prompts across six categories, organised Markdown for daily copy-paste plus a single styled HTML file you can print to PDF. Works with any assistant that takes a long prompt — ChatGPT, Claude, Gemini, whatever you already pay for.&lt;/p&gt;

&lt;p&gt;And if you just take the three above and never buy anything: genuinely fine. The pattern — name a framework, hand over real data, constrain the output, demand a decision rule — is the part worth stealing.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>I built a one-command website auditor because discovery calls were eating my afternoons</title>
      <dc:creator>Amit Feldman</dc:creator>
      <pubDate>Thu, 30 Jul 2026 06:08:23 +0000</pubDate>
      <link>https://dev.to/amitfeldman/i-built-a-one-command-website-auditor-because-discovery-calls-were-eating-my-afternoons-45p3</link>
      <guid>https://dev.to/amitfeldman/i-built-a-one-command-website-auditor-because-discovery-calls-were-eating-my-afternoons-45p3</guid>
      <description>&lt;h2&gt;
  
  
  The discovery-call scramble
&lt;/h2&gt;

&lt;p&gt;If you freelance or run a small agency, you know this moment: a prospect gets on a call and asks, "So what's wrong with our current site?" And you need a credible, concrete answer — not "well, I'd have to dig into it," and not forty minutes of manually opening dev tools, checking headers with curl, running PageSpeed, and eyeballing the source for a meta description.&lt;/p&gt;

&lt;p&gt;I got tired of the scramble, so I wrote it down as a checklist, then turned the checklist into a script. It's called &lt;strong&gt;siteprobe&lt;/strong&gt;: one Python file, zero dependencies, standard library only. Point it at a URL and it audits the things clients actually care about — speed, security headers, TLS certificate, and on-page SEO — in about five seconds. Add one flag and it emits a polished HTML report you can attach to a proposal.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python3 siteprobe.py https://example.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No install, no API keys, no accounts. Python 3.9+ is the only requirement.&lt;/p&gt;

&lt;h2&gt;
  
  
  What one run actually tells you
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Speed, broken down usefully.&lt;/strong&gt; "Your site is slow" is useless; "your TLS handshake is 800ms because the cert chain is misconfigured" is a fix. siteprobe measures with raw sockets and reports each phase separately:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;⏱ Timing
  DNS resolution     12 ms
  TCP connect        34 ms
  TLS handshake      87 ms
  Time to first byte 412 ms
  Total              545 ms
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Security headers, with fixes.&lt;/strong&gt; It checks the six headers on every audit checklist — HSTS, Content-Security-Policy, X-Frame-Options, X-Content-Type-Options, Referrer-Policy, Permissions-Policy — and every missing one comes back as a PASS/WARN/FAIL finding with copy-paste fix advice, not just "missing."&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;TLS certificate expiry.&lt;/strong&gt; Issuer, expiry date, days remaining, negotiated protocol and cipher. It warns under 30 days and fails on expired. If you've ever had a client's site go down because nobody tracked a cert renewal, you know why this is its own line item.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;On-page SEO signals.&lt;/strong&gt; Title tag (with length check), meta description, H1 count, images missing &lt;code&gt;alt&lt;/code&gt; attributes, canonical link, viewport meta — plus live checks that &lt;code&gt;/robots.txt&lt;/code&gt; and &lt;code&gt;/sitemap.xml&lt;/code&gt; actually exist and respond.&lt;/p&gt;

&lt;p&gt;The terminal output ends with a summary count, so a run looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;✓ 9 passed   ⚠ 3 warnings   ✗ 2 failed
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Follows redirects automatically too (up to 10 hops, with the per-hop status codes shown), so &lt;code&gt;python3 siteprobe.py http://github.com&lt;/code&gt; tells you the whole story of the redirect chain.&lt;/p&gt;

&lt;h2&gt;
  
  
  The part that's actually worth paying for
&lt;/h2&gt;

&lt;p&gt;The terminal audit is nice. The deliverable is the point:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python3 siteprobe.py https://client-site.com &lt;span class="nt"&gt;--html&lt;/span&gt; report.html
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;--html&lt;/code&gt; writes a self-contained HTML report — inline CSS, no external assets, no branding to strip out — with styled tables and an overall verdict banner at the top. It's designed to be forwarded to a client or attached to an invoice exactly as it lands on disk. The discovery-call scramble becomes: run one command before the call, attach the report to the proposal after it.&lt;/p&gt;

&lt;p&gt;It's also cron/CI-friendly. Exit codes are 0 (all passed), 1 (warnings only), 2 (at least one failure), so a weekly cron job that re-audits your client sites and alerts on exit code 2 is about four lines of crontab. That turns a one-off audit into ongoing monitoring — cert expiry warnings especially.&lt;/p&gt;

&lt;h2&gt;
  
  
  Honest limitations
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;It's not a crawler.&lt;/strong&gt; siteprobe audits the URL you give it (plus robots.txt and sitemap.xml). It doesn't spider the whole site, so per-page SEO issues on page 47 won't show up.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;TTFB, not full rendering.&lt;/strong&gt; The timing is server response, measured with raw sockets. It doesn't run a headless browser, so Core Web Vitals, layout shift, and JS-bundle bloat are out of scope — that's Lighthouse/PageSpeed territory, and the two tools complement each other fine.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Header checks are presence-and-sanity, not policy review.&lt;/strong&gt; It will tell you CSP is missing; it won't audit whether your existing CSP is well-designed.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Single URL per run.&lt;/strong&gt; Script it in a loop if you want a batch; there's no built-in site list mode.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Getting it
&lt;/h2&gt;

&lt;p&gt;siteprobe is $12 (pay-what-you-want, $12 minimum) on Gumroad: &lt;strong&gt;&lt;a href="https://afeldman2.gumroad.com/l/chwsxj?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=siteprobe-launch" rel="noopener noreferrer"&gt;https://afeldman2.gumroad.com/l/chwsxj?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=siteprobe-launch&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You get the single MIT-licensed Python file plus a test suite that spins up a local HTTP server and covers fetching, timing, redirects, header detection, SEO parsing, and HTML report rendering — no network needed to verify it works. If one audit report helps you close one proposal, it's paid for itself several times over.&lt;/p&gt;

</description>
      <category>automation</category>
      <category>freelance</category>
      <category>productivity</category>
      <category>python</category>
    </item>
  </channel>
</rss>
