
Security News
arXiv Is Rate Limiting Authors Following a Flood of AI Slop Submissions
arXiv now limits authors to two submissions a month as AI slop overwhelms moderators, delays good papers, and sparks debate over applying the limit to everyone.
@ultimat3/seo
Advanced tools
Enforced SEO: typed meta, JSON-LD, sitemap, robots, feeds, responsive images, perf budgets
SEO is enforced, not documented: every rule below is an assert* that throws a coded
SeoError with the route file and the exact edit, never a lint warning.
x verify's seo step (packages/cli/src/verify-checks.ts) runs validateMeta over every
site/ route, so missing, duplicate and over-long meta fail the gate As of 2026-09-23. Canonical
checks are skipped there — an app declares no base URL — and JSON-LD, sitemaps and robots are
enforced where they are built: each builder throws.
| Code | Trigger | Why it is fatal |
|---|---|---|
X_SEO_META_MISSING | a site/ route with no meta.title or meta.description | a page with no description gets a snippet Google invents; that is the one string you cannot fix after launch |
X_SEO_DUPLICATE_META | two routes share a title or description | duplicate meta makes the pages compete with each other, and the wrong one wins |
X_SEO_META_TOO_LONG | title > 60 chars, description > 160 | the tail is truncated in results — the words are paid for and never read |
X_SEO_CANONICAL_MISMATCH | meta.canonical does not resolve to the route's own URL | a wrong canonical de-indexes the page in favour of another |
X_LD_INVALID | a JSON-LD node missing a required schema.org field | invalid structured data drops the rich result silently |
X_SITEMAP_TOO_LARGE | the sitemap index exceeds 50,000 files | past the protocol limit the whole sitemap is discarded |
X_SITEMAP_ENTRY_INVALID | a page's lastmod is not a Date or ISO 8601 with a zone, or its locales names a locale the sitemap is not built for | a wrong date teaches a crawler to distrust every date in the file; a typo'd locale drops the page from one silently |
Performance budgets are not here: x verify's budgets step is @ultimat3/cli's
checkBudgets, over the route manifest and the build's own stats, and it throws
@ultimat3/render's X_BUDGET_EXCEEDED. This package is tier 1 and cannot see a build's bytes.
Every error names the exact route file and the exact edit:
X_SEO_META_MISSING: a site/ route is missing required metadata
cause: apps/web/site/about/page.tsx (route "/about") has no meta.description
fix: add description to defineRoute({ meta }) in apps/web/site/about/page.tsx
Every error class src/index.ts exports, for instanceof inside one process. Across a wire or
a job boundary the class is gone and the code is what survives — match on that.
| Class | Code | Declared in |
|---|---|---|
SeoError | any SeoErrorCode — SEO_ERROR_CODES | src/errors.ts |
| File | Owns |
|---|---|
meta.ts | the metadata model, renderMeta() → head tags: title template, canonical, robots, og:*, twitter:*, hreflang + x-default, theme-color per colour scheme. robots: { index: false } withdraws every og:*, article:* and twitter:* tag — declared or derived; there is no social switch |
validate.ts | the build gate — validateMeta() (--json-shaped) and assertMeta() |
ld.ts | typed JSON-LD builders; required fields are required in the input type |
sitemap.ts | buildSitemap() from the route table + each route's prerender(), per-locale alternates. One urlset at /sitemap.xml; past a cap (SITEMAP_MAX_URLS 50,000, SITEMAP_MAX_BYTES 50 MB) the index stays /sitemap.xml and the parts are /sitemaps/<n>.xml (SITEMAP_PARTS_DIR). With sections it is always an index of /sitemaps/<name>-<n>.xml — see below |
sitemap-sections.ts | sectionOf(path, sections): which named section a page files under (/blog/**, /blog/*, exact), first match wins, else pages |
sitemap-datetime.ts | sitemapDatetime(value, now): a page's lastmod as W3C Datetime in UTC, or undefined — a zoneless time is not a date here |
sitemap-xml.ts | the <urlset> and <sitemapindex> XML, and paginate() — files that each fit both caps |
robots.ts | buildRobots(), environment-aware and fail-closed; disallow reaches every group, and a User-agent: * group is emitted for it when none is declared |
rss.ts | buildFeed() → RSS 2.0 + Atom + JSON Feed from one item list. Channel author/copyright/icon → Atom <author>/<rights>/<icon>; an item author → Atom <author>, RSS <author> when it has an email, <dc:creator> when it does not; an item image → Atom <link rel="enclosure">, RSS <media:content medium="image">. Extra RSS namespaces are declared only when used |
feed-dates.ts | the one place a feed timestamp is parsed or formatted — an item date that will not parse is absent, never Invalid Date and never a crash |
images.ts | srcset widths (never past the intrinsic width or MAX_IMAGE_WIDTH, 8192), modern formats before the original — DEFAULT_FORMATS is what the built-in driver encodes (webp); pass formats: FORMAT_ORDER for AVIF behind a CDN driver — inlined intrinsic dimensions, and parseImageQuery() — reads a minted URL back into a transform request |
image-driver.ts | ImageTransformDriver + builtinImageDriver(): the variant bytes and the blur placeholder |
ld.Article({ headline: 'Ship it', author: { name: 'Ada' } });
// ^ error: Property 'datePublished' is missing — required by schema.org
A missing datePublished is a compile error, not a Search Console warning three
weeks later.
import { buildSitemap, type RouteRecord } from '@ultimat3/seo';
declare const routes: readonly RouteRecord[];
await buildSitemap(routes, {
baseUrl: 'https://notificado.co',
locales: ['es-co', 'en'],
defaultLocale: 'es-co',
maxUrls: 1000, // page size; default 50,000
sections: [{ name: 'blog', match: '/blog/**' }], // omitted: one urlset
disallow: ['/panel'], // robots.txt rules: never listed
});
// → index /sitemap.xml · files /sitemaps/pages-1.xml, /sitemaps/blog-1.xml, /sitemaps/blog-2.xml …
| Rule | |
|---|---|
| a page | RouteRecord.prerender() answers '/blog/a' or a SitemapPage — { path, lastmod?, locales? }. expandRoutePages() reads both; expandRoute() still answers paths |
lastmod | a Date or ISO 8601 with a zone, written in UTC. No zone, or no date: X_SITEMAP_ENTRY_INVALID. After now: clamped to now — one row from a clock a second ahead must not fail every page, and a future date is one a crawler stops believing |
locales | per page, else RouteRecord.locales, else all. One <url> per listed locale, hreflang among those only; x-default only when the default is listed; a page left in one locale of several carries no alternates; [] lists it nowhere. An unknown name is X_SITEMAP_ENTRY_INVALID |
| sections | matched on the unprefixed path, so a page and its locale copies share a file. pages (reserved) first, then declaration order; inside one, sorted by path. Numbered from 1; an empty one writes nothing; the index <lastmod> of a child is the newest inside it (SitemapFile.lastmod) |
| no sections | byte-for-byte the output before sections existed — sitemap-sections.test.ts pins the hash |
| names | sections and maxUrls are refused by @ultimat3/core's sitemapSectionIssues, the validator defineConfig runs for seo.sitemap |
Only the literal string production in ULTIMATE_ENV / NODE_ENV opts a deploy
into indexing. The environment is @ultimat3/core's Environment and its reader
is core's — this package owns no second one. A branch deploy (staging), a
laptop, a typo and an unset variable are all "not production", and each emits:
User-agent: *
Disallow: /
No sitemap line either — advertising one invites the crawl that was just refused.
builtinImageDriver({ read }) is the one built-in ImageTransformDriver, and it runs
@ultimat3/core's pipeline — zero dependencies, no sharp, no native binary.
const images = builtinImageDriver({ read: (src) => Bun.file(`public${src}`).bytes() });
// a 1200x630 source
await images.transform({ src: '/img/hero.png', width: 640 });
// → { bytes, contentType: 'image/png', width: 640, height: 336 }
await images.blurPlaceholder('/img/hero.png');
// → 'data:image/png;base64,…'
| decodes | png, jpeg, webp, gif |
| encodes | png, jpeg, webp |
| probes only | avif, svg — intrinsic size, never a transform |
The two lists are @ultimat3/core's DECODABLE_FORMATS and ENCODABLE_FORMATS
(packages/core/src/image/pipeline.ts), As of 2026-10.
read is required. src is a string and only the app knows whether it is a path, a
storage key or a URL. Guessing would mean a filesystem read off a URL-shaped string.format → the source's format is kept when the pipeline can write it, PNG otherwise. A
logo never grows a black background because nobody passed a format.format: 'avif' → X_IMAGE_UNSUPPORTED, with the fix line. That <source> needs a CDN
driver, so responsiveImage() does not offer it unless asked (formats: FORMAT_ORDER): a
browser picks the first <source> it supports and does not fall back from an error.width/height are probed off the output bytes, never echoed from the request. A width
above the intrinsic one clamps to the source and reports the source's size, so the box the
browser reserves is the box the bytes fill.blurPlaceholder() returns a PNG data: URI at most 32px on its long edge, ready for
ImageInput.blurDataUrl.images.ts mints ?w=&f= query strings; parseImageQuery() is the only place that reads one
back, so a server route never hand-rolls its own parsing of what responsiveImage() wrote.
const query = parseImageQuery(new URL(req.url).searchParams);
// null: none of w/f/q was present — a plain asset read, not a transform.
if (query !== null) {
await images.transform({
src,
// `?f=webp` alone still needs a width, and the source's own is the only one that resizes
// nothing the caller did not ask to resize.
width: query.width ?? intrinsicWidth,
// Spread, not `format: query.format`: `TransformRequest` declares both keys optional and
// `exactOptionalPropertyTypes` refuses an explicit `undefined`. Forward all three or `?q=75`
// parses and is then silently dropped.
...(query.format === undefined ? {} : { format: query.format }),
...(query.quality === undefined ? {} : { quality: query.quality }),
});
}
null means no transform was asked for. A present-but-unusable w or q — empty, 0,
negative, fractional, longer than an exact integer, or q over 100 — throws
X_IMAGE_QUERY_INVALID instead: serving the untransformed original against a ?w=320 URL is
the layout shift this contract exists to prevent.f is not checked against real format names here. ?f=potato parses fine; transform()
is what refuses an unencodable format, with X_IMAGE_UNSUPPORTED.IMAGE_QUERY_KEYS ({ width: 'w', format: 'f', quality: 'q' }) is the one spelling of the
three keys — defaultUrlFor and parseImageQuery both read it, so the two can never drift.export const config = defineRoute({
render: 'isr',
prerender: () => db.posts.slugs(),
meta: ({ post }) => ({
title: post.title,
titleTemplate: '%s — Ultimate',
description: post.excerpt,
og: { type: 'article', image: post.cover, publishedTime: post.publishedAt },
alternates: post.locales.map((l) => ({ hreflang: l, href: `/${l}/blog/${post.slug}` })),
ld: [ld.Article({ headline: post.title, datePublished: post.publishedAt, author: post.author })],
}),
budget: { js: '0kb' },
});
bun test # meta, validation, JSON-LD, sitemap, robots, feeds, images, error codes
bun run typecheck
FAQs
Enforced SEO: typed meta, JSON-LD, sitemap, robots, feeds, responsive images, perf budgets
The npm package @ultimat3/seo receives a total of 4,624 weekly downloads. As such, @ultimat3/seo popularity was classified as popular.
We found that @ultimat3/seo demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.

Security News
arXiv now limits authors to two submissions a month as AI slop overwhelms moderators, delays good papers, and sparks debate over applying the limit to everyone.

Research
/Security News
A new GhostAction wave hits hundreds of GitHub repos, expanding CI/CD secret theft to cloud and AI credentials in source code and git history.

Research
/Security News
Tensorlake npm SDK version 0.5.144 was compromised in a ChainDrop / Shai-Hulud attack, delivering credential-stealing malware.