Stale directory listings are the primary user trust failure for directories: a restaurant that closed 18 months ago still showing 4.5 stars with no freshness signal sends users to a shuttered door. Schema-org dateModified enables recency scoring by search engines and AI crawlers — but only if the field reflects actual verification, not the creation date. Without automated staleness detection and owner alerts at 90 days, your directory degrades passively: every listing drifts toward inaccuracy while appearing current. Data-integrity and observability taxons both apply here — the system must monitor its own data freshness, not rely on owners to self-report changes.
High because undetected stale listings cause real-world user harm (visiting closed businesses, calling disconnected numbers) and erode the directory's core trust proposition over time.
Add a scheduled route (or Vercel cron job) that queries listings with dateVerified older than 90 days and sends owner alerts. Run it daily.
// src/app/api/cron/stale-listings/route.ts
export async function GET(request: Request) {
// Verify cron secret
if (request.headers.get('Authorization') !== `Bearer ${process.env.CRON_SECRET}`) {
return new Response('Unauthorized', { status: 401 });
}
const ninetyDaysAgo = new Date(Date.now() - 90 * 24 * 60 * 60 * 1000);
const stale = await db.listing.findMany({
where: { dateVerified: { lt: ninetyDaysAgo }, status: 'active' },
select: { id: true, ownerEmail: true, name: true },
});
for (const listing of stale) {
await sendVerificationReminderEmail(listing.ownerEmail, listing.name);
}
return Response.json({ processed: stale.length });
}
Register this route in vercel.json under crons with a daily schedule ("0 9 * * *"). Display a staleness badge on the listing UI when dateVerified is more than 90 days old.
ID: directory-listing-schema.data-freshness.staleness-warnings
Severity: high
What to look for: Enumerate all listings and their last-verified dates. For each, check the codebase or database for a background job, cron task, or webhook that checks listing dateModified or dateVerified. Look for logic that sends warnings when a listing hasn't been verified in 90+ days.
Pass criteria: A background process checks for stale listings (no verification for over 90 days) and sends automated warnings to the listing owner — listings not verified within 90 days must display a staleness warning to users. Report even on pass: "X listings checked, Y flagged as potentially stale."
Fail criteria: No staleness checking exists, or warnings are sent manually.
Skip (N/A) when: There's no concept of listing verification or owner management.
Cross-reference: The verification-timestamp check ensures the timestamp field exists for staleness calculation.
Detail on fail: Example: "No background job exists to detect stale listings" or "Staleness threshold is 180 days instead of 90"
Remediation: Add a scheduled job to check and alert for stale listings:
export async function POST(request) {
const ninetyDaysAgo = new Date(Date.now() - 90 * 24 * 60 * 60 * 1000)
const staleListing = await db.listing.findMany({
where: { dateVerified: { lt: ninetyDaysAgo } }
})
for (const listing of staleListing) {
await sendEmail(listing.ownerEmail, {
subject: 'Your listing verification is expiring'
})
}
return NextResponse.json({ processed: staleListing.length })
}