GEMINI LABJP
NANOLITE — Nano Banana 2 Lite is here: Google's fastest and most cost-efficient Gemini Image model, made for running lightweight image generation cheaplyOMNIFLASH — Gemini Omni Flash is in public preview, a natively multimodal model that lets enterprises and developers build custom, dynamic video workflowsAGENTS — Managed Agents expand with background: true for async server-side runs and polling, remote MCP server integration, and refreshing credentials across interactionsMEMORY — The Memory Bank IngestEvents API is generally available, decoupling event ingestion from memory generation so you can stream content continuouslyTHROUGHPUT — Provisioned Throughput now lets you submit up to seven pending orders for the same model and regionDEPRECATE — Image generation models shut down on August 17, and the Grok 4.1 family on the Gemini Enterprise Agent Platform on August 20NANOLITE — Nano Banana 2 Lite is here: Google's fastest and most cost-efficient Gemini Image model, made for running lightweight image generation cheaplyOMNIFLASH — Gemini Omni Flash is in public preview, a natively multimodal model that lets enterprises and developers build custom, dynamic video workflowsAGENTS — Managed Agents expand with background: true for async server-side runs and polling, remote MCP server integration, and refreshing credentials across interactionsMEMORY — The Memory Bank IngestEvents API is generally available, decoupling event ingestion from memory generation so you can stream content continuouslyTHROUGHPUT — Provisioned Throughput now lets you submit up to seven pending orders for the same model and regionDEPRECATE — Image generation models shut down on August 17, and the Grok 4.1 family on the Gemini Enterprise Agent Platform on August 20
Articles/API / SDK
API / SDK/2026-05-27Intermediate

Two Months of Letting Gemini Audit My Internal Links

An implementation note from running internal link integrity checks on my four Lab sites with Gemini 2.5 Flash for two months. What grep missed, how Flash compared to Pro on this task, and the surprises along the way.

Gemini API192Gemini 2.5 Flash5indie developer12internal linkscontent qualityops automation

When you run four Lab sites in parallel, one chore becomes steadily more annoying as the archive grows: confirming that every internal link in your MDX prose actually points to an article that exists. Between Claude Lab and Gemini Lab alone I have close to 1,700 articles, and across the four sites that number is over 3,000. The prose is full of text patterns. Build-time guards catch most issues, but some still slip through.

For the past two months I have been handing this internal link integrity job to Gemini 2.5 Flash. The accuracy was not always what I expected, but folding it into my nightly routine surfaced a category of mismatches I would never have spotted on my own. Here is the implementation and the impressions I am sitting with after eight weeks.

Why hand this to Gemini

At first I thought a simple grep would be enough. Pull every /articles/(category)/(slug) string out of the content directory, check whether the corresponding MDX file exists, done. That handles roughly 95% of cases.

The remaining 5% slips past mechanical checks. Three examples I kept hitting:

  1. The target slug exists, but it is about something completely unrelated to the surrounding paragraph
  2. The anchor text says "Setting up Gemini Code Assist" while the linked article is "Billing for Gemini for Workspace"
  3. There are three articles on the same topic in my archive, and the link points to the oldest one instead of the latest revision

These need context, which is outside what grep can do. My grandfathers on both sides were temple carpenters, and I grew up watching that craft. Whether a thing lasts decades or not is decided in the small joinery you barely notice. Link accuracy maps onto reader trust in the same quiet way, so I decided spending some Gemini tokens here was a fair trade.

The architecture

The implementation is small. For each article we extract its links, then send Gemini the anchor text, the surrounding paragraph from the source article, and the opening of the target article. We ask for a JSON verdict.

import google.generativeai as genai
import re, pathlib, json
 
MODEL = "gemini-2.5-flash"
LINK_RE = re.compile(r"\[([^\]]+)\]\(/articles/([^/]+)/([^)]+)\)")
 
def collect_links(article_path: pathlib.Path):
    text = article_path.read_text(encoding="utf-8")
    return [
        (m.group(1), m.group(2), m.group(3), text)
        for m in LINK_RE.finditer(text)
    ]
 
def review_link(anchor, category, slug, body, target_excerpt):
    prompt = f"""
You are a technical blog editor. Judge whether this link is contextually valid.
 
Anchor text: {anchor}
Source paragraph (200 chars around the link): {body[:200]}
Target article opening (first 400 chars): {target_excerpt[:400]}
 
Return JSON only:
- relevance: float between 0.0 and 1.0
- anchor_match: boolean (does anchor match target content)
- replacement_hint: string suggesting what should replace it, or empty
"""
    model = genai.GenerativeModel(
        MODEL,
        generation_config={"response_mime_type": "application/json"},
    )
    resp = model.generate_content(prompt)
    return json.loads(resp.text)

Turning on response_mime_type="application/json" cut almost all of the parsing failures I was getting in the early days. I initially routed every link through gemini-2.5-pro, but once I compared verdict quality against the price, Flash turned out to be the better fit for this kind of work. I now only escalate to Pro for the roughly 5% of links that land in the grey zone (relevance between 0.3 and 0.7). Clear misses get decided by Flash on the spot.

Verdicts are written out as YAML logs under _link_review/YYYY-MM-DD.yml per site. To avoid spending tokens twice on the same URL, the runner skips any link that has been judged within the past seven days.

What two months of running this revealed

The job runs nightly at 02:30 JST and only inspects links inside articles that were pushed earlier that day. Across the four sites that comes out to roughly 60 to 80 links per night. In token costs, it lands around 1,000 yen per month, which is well within what I am willing to spend on indie ops.

There were real misjudgements. Gemini can be too strict about synonyms. Some nights it treats "Function Calling" and "tool invocation" as unrelated concepts. Loosening the threshold introduces noise from the opposite direction. I am still tuning that balance by hand.

The pleasant surprises outweighed the misses. On more than one night, while checking internal links, Gemini also noticed that an external reference URL was pointing at a deprecated documentation page. The prompt does not ask for that, but the model reads the target opening and sometimes notices its own banner saying "this page is outdated." A grep would never catch this.

The other quiet win was getting an outside view of my own writing tics. Gemini's review notes started flagging things like "this article mixes 'indie developer', 'personal developer', and 'solo dev' for the same concept" or "this anchor reuses the raw slug instead of a human title." I never asked for stylistic feedback, but Flash in particular kept volunteering it, more often than Pro did.

If you want to try this on your own blog

If you set up something similar, do not aim it at the entire archive on day one. Start with the last month of articles. When the scope reaches older content, the model gets pulled around by the drift in your own terminology and the verdicts become less stable.

The other thing I learned is to treat the output as a review queue, not as an auto-fix list. For a blog where the precision of technical vocabulary matters, you want a human looking at every rewrite. I now skim last night's queue while my coffee is brewing and apply only the clear-cut fixes by hand.

On the cost side, I did try gemini-2.5-flash-lite once. Cheaper per token, but the relevance scores clustered noticeably around 0.5, which is exactly the wrong place for a binary "is this link okay or not" question. For this use case, locking the model to Flash made the daily operation easier in the end.

What comes next

The next plan is to reuse this pipeline for Crashlytics report triage. The idea is to fetch the daily crash report through Claude in Chrome, hand it to Gemini, and have it classify scope and severity. I have been shipping apps as an indie since 2014, and there have been more than a few crashes I caught later than I should have. Automating that triage is high on my list.

Internal link integrity is unglamorous work, but it adds up. Every time a reader clicks through and finds the page actually matches what the anchor promised, that is trust quietly compounding. If any of this is useful for your own setup, I would be glad. Thanks for reading this far.

Share

Thank You for Reading

Gemini Lab is ad-free, supported entirely by members like you. We publish practical guides daily with implementation code, benchmarks, and production-ready patterns. If you've found it useful, we'd love to have you on board.

  • Copy-paste ready implementation code
  • New advanced guides published daily
  • $5/mo or $10 for lifetime access
View Membership →

If you found this article helpful, a small tip ($1.50) would mean a lot to us. Your support helps keep this site ad-free and covers server and hosting costs.

Related Articles

API / SDK2026-06-28
Read Video with Timestamps in the Gemini API: Pull Just the Scene You Need
Hunting for 'where was that step?' in a screen recording or app demo is a chore. Here is how to use Gemini API video understanding to pull just the right scene with timestamps, plus a design that keeps tokens down with FPS and resolution.
API / SDK2026-06-20
Catching Gemini Model Deprecations in CI Before They Bite
Build a small guard that scans your codebase for hardcoded Gemini model IDs, cross-checks shutdown deadlines, and turns CI red before a model quietly disappears.
API / SDK2026-06-03
Recording Provenance for Gemini Output — Designing for Reproducibility and Audit
Before you lose track of which model and prompt produced an output months later: how to stamp provenance metadata onto Gemini generations so quality investigations and model migrations stay reproducible.
📚RECOMMENDED BOOKS
Build a Large Language Model (From Scratch)
Sebastian Raschka
LLM Dev
Prompt Engineering for LLMs
Berryman & Ziegler
Prompting
AI Engineering
Chip Huyen
AI Eng
* Contains affiliate links
See all →