SEO17 June 20265 min read·866 words

Cron-Driven SEO Audits in Next.js: The System We Built

How we automated weekly SEO audits across 16 production CRMs using Next.js API routes, cron jobs, and Lighthouse CI—catching metadata gaps before they hurt rankings.

TechNova Team

Editorial

Cron-Driven SEO Audits in Next.js: The System We Built

Cron-Driven SEO Audits in Next.js: The System We Built

When you're shipping 16 industry-specific CRMs—from HotelDesk to LegalEase to PharmaCare—keeping tabs on SEO metadata, Core Web Vitals, and canonical tags across hundreds of pages becomes impossible to do manually. Missing a meta description on a pricing page or letting a 404 slip through for three weeks kills conversions silently.

We needed a system that ran weekly audits, flagged regressions, and sent actionable reports to Slack. No SaaS subscription. No third-party dependency that could change pricing or shut down. Just a cron job, Next.js API routes, and Lighthouse CI running in a GitHub Action.

Here's how we built it, the tradeoffs we made, and what we'd do differently.

Cron-Driven SEO Audits in Next.js: The System We Built — illustration 1

Why We Didn't Use Off-the-Shelf Tools

We evaluated Ahrefs, Screaming Frog, and SEMrush. All solid. But:

  • Cost: $200-500/month per project doesn't scale when you're maintaining 16 CRMs plus an ERP.
  • Custom checks: We needed domain-specific validations—like ensuring every legal case page in LegalEase has structured data for FAQPage, or that EventPro's venue pages include LocalBusiness schema.
  • Integration: We wanted audit results to flow directly into our issue tracker and Slack channels, not sit in a dashboard someone has to remember to check.

The trade-off? We own the maintenance. When Lighthouse updates or Next.js changes routing conventions, we adapt. For a remote team building custom software full-time, that's a fair exchange.

The Architecture

The system has three layers:

  1. Scheduled trigger (GitHub Actions cron)
  2. Audit runner (Next.js API route)
  3. Reporter (Slack webhook + optional issue creation)

Layer 1: GitHub Actions Cron

Every Sunday at 3 AM UTC, a GitHub Action fires:

name: Weekly SEO Audit
on:
  schedule:
    - cron: '0 3 * * 0'
  workflow_dispatch:

jobs:
  audit:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Run Lighthouse CI
        run: |
          npm ci
          npm run build
          npx @lhci/cli@latest autorun
      - name: Trigger audit API
        run: |
          curl -X POST https://hoteldesk.technova.team/api/seo-audit \
            -H "Authorization: Bearer ${{ secrets.AUDIT_TOKEN }}"

We use workflow_dispatch so any team member can trigger an audit manually when deploying big changes.

Layer 2: Next.js API Route

The /api/seo-audit endpoint does the heavy lifting:

  • Fetches a sitemap (we generate this dynamically in /api/sitemap.xml using Next.js rewrites)
  • Loops through priority pages (pricing, landing pages, top 20 blog posts by traffic)
  • Runs checks:
    • Meta tags: Title length (50-60 chars), description (120-160 chars), Open Graph tags
    • Headers: Exactly one H1, logical H2-H6 hierarchy
    • Performance: LCP < 2.5s, CLS < 0.1 (parsed from Lighthouse JSON)
    • Structured data: Validates JSON-LD against schema.org types
    • Canonical tags: No self-referencing loops, HTTPS enforcement
    • Image alt text: Every <img> must have non-empty alt

Here's a simplified snippet:

import { NextApiRequest, NextApiResponse } from 'next';
import Anthropic from '@anthropic-ai/sdk';
import axios from 'axios';

const anthropic = new Anthropic({ apiKey: process.env.ANTHROPIC_API_KEY });

export default async function handler(req: NextApiRequest, res: NextApiResponse) {
  if (req.headers.authorization !== `Bearer ${process.env.AUDIT_TOKEN}`) {
    return res.status(401).json({ error: 'Unauthorized' });
  }

  const sitemap = await axios.get('https://hoteldesk.technova.team/api/sitemap.xml');
  const urls = parseSitemap(sitemap.data); // extract <loc> tags

  const results = [];
  for (const url of urls.slice(0, 50)) { // limit to top 50 pages
    const html = await axios.get(url);
    const issues = await runChecks(html.data, url);
    if (issues.length > 0) results.push({ url, issues });
  }

  await sendToSlack(results);
  res.status(200).json({ audited: urls.length, issues: results.length });
}

function runChecks(html: string, url: string): string[] {
  const issues = [];
  const titleMatch = html.match(/<title>(.*?)<\/title>/);
  if (!titleMatch || titleMatch[1].length < 30) {
    issues.push('Title tag missing or too short');
  }
  // ... 15 more checks
  return issues;
}

For complex checks—like analyzing whether a blog post's keyword density is natural or spammy—we pipe the HTML into Claude via the Anthropic API. This is overkill for most audits, but for our AI agent specialties landing pages, where we need nuanced copywriting feedback, it's worth the token cost.

Cron-Driven SEO Audits in Next.js: The System We Built — illustration 2

Layer 3: Slack Reporting

When issues are found, we post to a dedicated #seo-alerts channel:

🚨 SEO Audit – 12 issues found

❌ /pricing – Missing meta description
❌ /blog/custom-crm-development – LCP 3.2s (target: <2.5s)
⚠️ /products/legalease – H1 appears twice
✅ 47 pages passed

Full report: https://github.com/technova/hoteldesk/actions/runs/123456

For critical issues (missing canonicals, broken structured data), we auto-create GitHub issues with the seo label.

What We Learned

1. Start with the 20% that matters

We initially tried to audit everything—internal link graph, keyword cannibalization, backlink profiles. It took 40 minutes to run and produced 200-line Slack messages no one read.

Now we focus on:

  • Metadata completeness (title, description, OG tags)
  • Core Web Vitals (LCP, CLS, FID)
  • Structured data validity
  • Mobile usability (viewport tag, font sizes)

These four categories catch 80% of real SEO problems.

2. Lighthouse in CI is flaky

Running Lighthouse in GitHub Actions gives inconsistent scores because:

  • Shared runners have variable CPU
  • Network conditions fluctuate
  • Cold starts on serverless functions skew metrics

We run each audit three times and take the median. It adds 90 seconds but eliminates false positives.

3. Alerting fatigue is real

In the first month, we got Slack pings for every warning. Team ignored them within a week.

Now we only alert on:

  • New issues (regression since last audit)
  • Critical severity (missing title tag, 404 errors)
  • Trends (LCP degrading for 3 consecutive weeks)

Everything else goes to a weekly digest.

When This Approach Makes Sense

This system works for us because:

  • We already have Next.js infrastructure across all projects
  • We ship features weekly and need continuous validation
  • Our team has bandwidth to maintain custom tooling
  • We're building products where SEO directly impacts user acquisition (HotelDesk gets 60% of signups from organic search)

If you're a solo founder or early-stage startup, start with a SaaS tool. The opportunity cost of building this is real. But if you're at the scale where you're managing multiple domains, running experiments, or need compliance-specific checks (HIPAA for PharmaCare, GDPR for EU deployments), owning your audit pipeline pays off.

Next Steps

We're adding:

  • Competitor tracking: Scrape top 3 SERP competitors weekly, flag when they outrank us on target keywords
  • Content freshness: Auto-flag blog posts older than 12 months with declining traffic
  • International SEO: Validate hreflang tags across our 6 regional deployments

The codebase is internal, but if you're building something similar and want to compare notes, we're on X @TechNovaTeam.

SEO at scale isn't about chasing algorithm updates. It's about catching the unglamorous mistakes—the missing alt tag, the slow API call, the duplicate canonical—before they compound. Automate the boring stuff so you can focus on writing content that actually helps users.

That's the real competitive advantage.

Tagged#seo#nextjs#automation#cron#lighthouse#monitoring

About the author

TechNova Team

A remote-first custom software studio shipping CRMs, ERPs, and AI agents to SMBs worldwide. Field notes from people actually building it.

Get started

Ready to ship the software your business actually runs on?

Tell us what you're building. We respond within one business day with a clear plan, price, and timeline.

16 industry CRMs shipped96+ clients · 14 countriesRemote-first · Global delivery