惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

aimingoo的专栏
aimingoo的专栏
腾讯CDC
Y
Y Combinator Blog
L
LangChain Blog
B
Blog
U
Unit 42
P
Proofpoint News Feed
G
Google Developers Blog
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
博客园 - 【当耐特】
WordPress大学
WordPress大学
月光博客
月光博客
Vercel News
Vercel News
雷峰网
雷峰网
T
The Blog of Author Tim Ferriss
MyScale Blog
MyScale Blog
大猫的无限游戏
大猫的无限游戏
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
酷 壳 – CoolShell
酷 壳 – CoolShell
Blog — PlanetScale
Blog — PlanetScale
博客园 - 司徒正美
云风的 BLOG
云风的 BLOG
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
博客园 - 叶小钗

DEV Community

Authentication Security Deep Dive: From Brute Force to Salted Hashing (With Java Examples) Why AI Systems Don’t Fail — They Drift Spilling beans for how i learn for exam😁"Reinforcement Learning Cheat Sheet" I Replaced Chrome with Safari for AI Browser Automation. Here's What Broke (and What Finally Worked) How Python Borrows Other People's Work The $40 Architecture: Processing 1 Billion API Requests with 99.99% Uptime Vibe Coding: A Workflow Guide (From Zero to SaaS) Most webhook security guides protect the wrong side. The scary part is delivery. Headless CMS for TanStack Start: Build a Blog with Cosmic EU Age Verification App "Hacked in 2 Minutes" — What Actually Happened Comfy Cloud’s delete function does not actually remove files Running AI Models on GPU Cloud Servers: A Beginner Guide Event-driven media intelligence with AWS Step Functions and Bedrock I scored 500 AI prompts across 8 quality dimensions — here's what broke How to Call Google Gemini API from Next.js (Free Tier, No Backend Needed) The Portal Protocol: Reclaiming Human Connection in the Age of AI How to Fix Your Team's Scattered Knowledge Problem With a Self-Hosted Forum Intro to tc Cloud Functors: A Graph-First Mental Model for the Modern Cloud Designing Multi-Tenant Backends With Both Ownership and Team Access I Built a Neumorphic CSS Library with 77+ Components — Here's What I Learned PostgreSQL Performance Optimization: Why Connection Pooling Is Critical at Scale Cómo construí un SaaS multi-rubro para gestionar expensas en Argentina con FastAPI + Vue 3 🚀 I Built an Ethical Hacking Scanner Tool – Open Source Project I Replaced /usage and /context in Claude Code With a Single Statusline A Pythonic Way to Handle Emails (IMAP/SMTP) with Auto-Discovery and AI-Ready Design I Collected 8.9 Million Polymarket Price Points — Here's What I Found About How Markets Really Move EcoTrack AI — Carbon Footprint Tracker & Dashboard Everyone's Using AI. No One Agrees How. 5 self-hosted ebook managers worth trying in 2026 Building Your First AI Agent with LangChain: From Chatbot to Autonomous Assistant
I built a GitHub Action that fails CI when your meta tags...
hey atlas · 2026-06-27 · via DEV Community

hey atlas

Google retired the Structured Data Testing Tool. X killed its Card Validator. Facebook's debugger is behind a login. So in 2026 there is no fast way to catch a busted <title> or a missing og:image before it ships to production. You find out when the page is live and the LinkedIn share renders as a grey box.

I kept shipping that exact bug, so I put the check in CI. It's a zero-dependency GitHub Action.

What it does

It lints the <head> of a page — a local HTML file or a live URL — and exits non-zero when the SEO and social-share tags are broken or missing, so the build goes red.

- uses: atlashey-collab/seo-meta-action@v1
  with:
    target: index.html        # a file path OR a https:// URL
    fail-on-warning: false     # set true to also fail on warnings

It checks the tags that actually move rankings and share previews:

  • <title> — present, non-empty, ~30-60 chars, exactly one
  • meta description — present, ~120-160 chars, no duplicates
  • exactly one <h1>
  • absolute <link rel="canonical">
  • viewport, charset, <html lang>
  • accidental robots: noindex (the silent traffic killer)
  • Open Graph: og:title, og:description, og:image, og:url, og:type
  • twitter:card

Errors fail the job by default. Warnings only fail it when you flip fail-on-warning: true, so you can adopt it gradually instead of turning your whole repo red on day one.

Two design choices that mattered

No dependencies. It's a single Python 3 file parsed with the stdlib html.parser. No pip install, nothing to pin, nothing to get a CVE next quarter. You can also run it locally:

python3 validate_meta.py page.html
python3 validate_meta.py https://example.com/ --fail-on-warning

Opinionated length windows. Title 30-60 and description 120-160 are the windows Google renders before it truncates in desktop SERPs. The linter warns outside them instead of erroring, because a 62-char title isn't broken — it's just getting clipped, and you should know.

It immediately caught my own bug

The first thing I did was point it at my own site. It flagged a tools page with a 73-char title (truncated in search), a 186-char description (truncated), and — embarrassingly — a missing og:image and twitter:card. Four real issues I'd shipped and never noticed. Two-minute fix, but I'd never have caught them by eye.

That's the whole pitch: the boring tags are the ones nobody re-checks after the first commit, and they're exactly the ones that quietly cost you clicks.

It's MIT-licensed. Repo, full check list, and the local CLI are here: https://github.com/atlashey-collab/seo-meta-action

If you bake it into a pipeline and hit an edge case it mis-flags, open an issue — I want the defaults to be genuinely correct, not just opinionated.