Files
Manav Arya Singh 100cea608a feat(v12.2): designlang battle + design-score badges
Two ships on top of the v12.1 Grade flywheel.

`designlang battle <urlA> <urlB>` — head-to-head graded card, parallel
extraction, dimension-by-dimension bar table with verdict + win/tie/loss
tally. Self-contained HTML, also emits .battle.md and .battle.json.

Design-score SVG badges:
- `designlang grade --badge` writes *-badge.svg locally
- New formatter src/formatters/badge.js — shields.io style, color by
  letter grade, accessible (aria-label, role=img), Verdana-width math so
  it renders identically across GitHub / npm / arbitrary markdown
- Live endpoint at website/app/api/badge/[host]/route.js — reuses the
  same blob cache /api/extract writes to, edge-cached 6h with 24h SWR
  for friendly behavior under GitHub's image proxy
- Friendly URL rewrites: /badge/<host> and /badge/<host>.svg → /api/badge/<host>

Why both: Grade is the artifact, Battle is the viral content layer
("Stripe vs Vercel — guess who lost"), Badge is the permanent
distribution layer (every README adoption is a backlink to a live
grade page).

13 new tests (336 total, all passing). Cover battle markup, score
comparison thresholds, SVG escaping, grade-color mapping, missing-score
handling.

Website: bumps v12.1 → v12.2 across home/gallery/spec/features/permalink,
adds /features#battle section, swaps Grade CTA chip to Battle.
2026-05-02 23:29:36 +04:00

23 lines
631 B
JavaScript

/** @type {import('next').NextConfig} */
const nextConfig = {
turbopack: {},
webpack: (config, { isServer }) => {
if (isServer) {
// Don't bundle playwright — emit require('playwright-core') at runtime instead
config.externals.push({
'playwright': 'commonjs playwright-core',
});
}
return config;
},
// Friendly badge URLs: /badge/stripe.com → /api/badge/stripe.com
async rewrites() {
return [
{ source: '/badge/:host', destination: '/api/badge/:host' },
{ source: '/badge/:host.svg', destination: '/api/badge/:host' },
];
},
};
export default nextConfig;