designlang 6.0.0 → 7.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/FUNDING.yml +1 -0
- package/.github/ISSUE_TEMPLATE/bug_report.yml +62 -0
- package/.github/ISSUE_TEMPLATE/config.yml +8 -0
- package/.github/ISSUE_TEMPLATE/feature_request.yml +28 -0
- package/.vercel/README.txt +11 -0
- package/.vercel/project.json +1 -0
- package/CHANGELOG.md +58 -0
- package/CONTRIBUTING.md +25 -0
- package/README.md +120 -8
- package/bin/design-extract.js +106 -3
- package/chrome-extension/README.md +41 -0
- package/chrome-extension/icons/favicon.svg +7 -0
- package/chrome-extension/icons/icon-128.png +0 -0
- package/chrome-extension/icons/icon-16.png +0 -0
- package/chrome-extension/icons/icon-32.png +0 -0
- package/chrome-extension/icons/icon-48.png +0 -0
- package/chrome-extension/manifest.json +26 -0
- package/chrome-extension/popup.html +167 -0
- package/chrome-extension/popup.js +59 -0
- package/docs/superpowers/plans/2026-04-18-designlang-v7.md +1121 -0
- package/docs/superpowers/specs/2026-04-18-designlang-v7-design.md +150 -0
- package/docs/superpowers/specs/2026-04-18-website-redesign-design.md +120 -0
- package/docs/superpowers/specs/2026-04-19-designlang-v7-1-design.md +111 -0
- package/package.json +5 -4
- package/src/config.js +26 -0
- package/src/crawler.js +136 -2
- package/src/extractors/a11y-remediation.js +47 -0
- package/src/extractors/component-clusters.js +39 -0
- package/src/extractors/css-health.js +151 -0
- package/src/extractors/scoring.js +20 -1
- package/src/extractors/semantic-regions.js +44 -0
- package/src/extractors/stack-fingerprint.js +88 -0
- package/src/formatters/_token-ref.js +44 -0
- package/src/formatters/agent-rules.js +116 -0
- package/src/formatters/android-compose.js +164 -0
- package/src/formatters/dtcg-tokens.js +175 -0
- package/src/formatters/flutter-dart.js +130 -0
- package/src/formatters/ios-swiftui.js +161 -0
- package/src/formatters/markdown.js +25 -0
- package/src/formatters/wordpress.js +183 -0
- package/src/index.js +30 -0
- package/src/mcp/resources.js +64 -0
- package/src/mcp/server.js +110 -0
- package/src/mcp/tools.js +149 -0
- package/src/utils-cookies.js +73 -0
- package/tests/cli.test.js +50 -0
- package/tests/cookies.test.js +98 -0
- package/tests/extractors.test.js +131 -0
- package/tests/formatters.test.js +232 -0
- package/tests/mcp.test.js +68 -0
- package/website/app/api/extract/route.js +216 -56
- package/website/app/components/A11ySlider.js +369 -0
- package/website/app/components/Comparison.js +286 -0
- package/website/app/components/CssHealth.js +243 -0
- package/website/app/components/HeroExtractor.js +455 -0
- package/website/app/components/Marginalia.js +3 -0
- package/website/app/components/McpSection.js +223 -0
- package/website/app/components/PlatformTabs.js +250 -0
- package/website/app/components/RegionsComponents.js +429 -0
- package/website/app/components/Rule.js +13 -0
- package/website/app/components/Specimens.js +237 -0
- package/website/app/components/StructuredData.js +144 -0
- package/website/app/components/TokenBrowser.js +344 -0
- package/website/app/components/token-browser-sample.js +65 -0
- package/website/app/globals.css +415 -633
- package/website/app/icon.svg +7 -0
- package/website/app/layout.js +113 -6
- package/website/app/opengraph-image.js +170 -0
- package/website/app/page.js +325 -148
- package/website/app/robots.js +15 -0
- package/website/app/seo-config.js +82 -0
- package/website/app/sitemap.js +18 -0
- package/website/lib/cache.js +73 -0
- package/website/lib/rate-limit.js +30 -0
- package/website/lib/rate-limit.test.js +55 -0
- package/website/lib/specimens.json +86 -0
- package/website/lib/token-helpers.js +70 -0
- package/website/lib/url-safety.js +103 -0
- package/website/lib/url-safety.test.js +116 -0
- package/website/lib/zip-files.js +15 -0
- package/website/package-lock.json +85 -0
- package/website/package.json +1 -0
- package/website/public/favicon.svg +7 -0
- package/website/public/logo-specimen.svg +76 -0
- package/website/public/mark.svg +12 -0
- package/website/public/site.webmanifest +13 -0
- package/website/app/favicon.ico +0 -0
- package/website/public/file.svg +0 -1
- package/website/public/globe.svg +0 -1
- package/website/public/next.svg +0 -1
- package/website/public/vercel.svg +0 -1
- package/website/public/window.svg +0 -1
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32" role="img" aria-label="designlang">
|
|
2
|
+
<title>designlang</title>
|
|
3
|
+
<rect width="32" height="32" fill="#F3F1EA"/>
|
|
4
|
+
<circle cx="13" cy="20" r="7.5" fill="none" stroke="#0A0908" stroke-width="4.5"/>
|
|
5
|
+
<rect x="19" y="4" width="4.5" height="25" fill="#0A0908"/>
|
|
6
|
+
<rect x="25" y="25" width="4" height="4" fill="#FF4800"/>
|
|
7
|
+
</svg>
|
package/website/app/layout.js
CHANGED
|
@@ -1,17 +1,124 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { Fraunces, Instrument_Sans, JetBrains_Mono } from 'next/font/google';
|
|
2
|
+
import StructuredData from './components/StructuredData';
|
|
3
|
+
import {
|
|
4
|
+
SITE_URL,
|
|
5
|
+
SITE_NAME,
|
|
6
|
+
SITE_TITLE,
|
|
7
|
+
SITE_DESCRIPTION,
|
|
8
|
+
SITE_KEYWORDS,
|
|
9
|
+
} from './seo-config';
|
|
10
|
+
import './globals.css';
|
|
11
|
+
|
|
12
|
+
const fraunces = Fraunces({
|
|
13
|
+
subsets: ['latin'],
|
|
14
|
+
variable: '--font-display',
|
|
15
|
+
display: 'swap',
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
const instrumentSans = Instrument_Sans({
|
|
19
|
+
subsets: ['latin'],
|
|
20
|
+
variable: '--font-body',
|
|
21
|
+
display: 'swap',
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
const mono = JetBrains_Mono({
|
|
25
|
+
subsets: ['latin'],
|
|
26
|
+
variable: '--font-mono',
|
|
27
|
+
display: 'swap',
|
|
28
|
+
});
|
|
2
29
|
|
|
3
30
|
export const metadata = {
|
|
4
|
-
|
|
5
|
-
|
|
31
|
+
metadataBase: new URL(SITE_URL),
|
|
32
|
+
title: {
|
|
33
|
+
default: SITE_TITLE,
|
|
34
|
+
template: '%s \u2014 designlang',
|
|
35
|
+
},
|
|
36
|
+
description: SITE_DESCRIPTION,
|
|
37
|
+
keywords: SITE_KEYWORDS,
|
|
38
|
+
authors: [{ name: 'Manav Arya Singh', url: 'https://manavaryasingh.com' }],
|
|
39
|
+
creator: 'Manav Arya Singh',
|
|
40
|
+
publisher: 'Manav Arya Singh',
|
|
41
|
+
applicationName: SITE_NAME,
|
|
42
|
+
category: 'developer tools',
|
|
43
|
+
classification:
|
|
44
|
+
'design system extractor, design tokens, design-to-code, AI coding agents, MCP server',
|
|
45
|
+
generator: 'Next.js',
|
|
46
|
+
alternates: {
|
|
47
|
+
canonical: SITE_URL,
|
|
48
|
+
},
|
|
49
|
+
openGraph: {
|
|
50
|
+
type: 'website',
|
|
51
|
+
url: SITE_URL,
|
|
52
|
+
siteName: SITE_NAME,
|
|
53
|
+
title: SITE_TITLE,
|
|
54
|
+
description: SITE_DESCRIPTION,
|
|
55
|
+
locale: 'en_US',
|
|
56
|
+
images: [
|
|
57
|
+
{
|
|
58
|
+
url: '/opengraph-image',
|
|
59
|
+
width: 1200,
|
|
60
|
+
height: 630,
|
|
61
|
+
alt:
|
|
62
|
+
'designlang specimen card \u2014 a lowercase d mark with one extracted orange token, the wordmark designlang in Fraunces, and a five-swatch palette strip.',
|
|
63
|
+
type: 'image/png',
|
|
64
|
+
},
|
|
65
|
+
],
|
|
66
|
+
},
|
|
67
|
+
twitter: {
|
|
68
|
+
card: 'summary_large_image',
|
|
69
|
+
title: SITE_TITLE,
|
|
70
|
+
description: SITE_DESCRIPTION,
|
|
71
|
+
images: ['/opengraph-image'],
|
|
72
|
+
creator: '@manavaryasingh',
|
|
73
|
+
site: '@manavaryasingh',
|
|
74
|
+
},
|
|
75
|
+
robots: {
|
|
76
|
+
index: true,
|
|
77
|
+
follow: true,
|
|
78
|
+
nocache: false,
|
|
79
|
+
googleBot: {
|
|
80
|
+
index: true,
|
|
81
|
+
follow: true,
|
|
82
|
+
'max-image-preview': 'large',
|
|
83
|
+
'max-snippet': -1,
|
|
84
|
+
'max-video-preview': -1,
|
|
85
|
+
},
|
|
86
|
+
},
|
|
87
|
+
icons: {
|
|
88
|
+
icon: [
|
|
89
|
+
{ url: '/icon.svg', type: 'image/svg+xml' },
|
|
90
|
+
{ url: '/favicon.svg', type: 'image/svg+xml' },
|
|
91
|
+
],
|
|
92
|
+
shortcut: '/icon.svg',
|
|
93
|
+
apple: '/icon.svg',
|
|
94
|
+
},
|
|
95
|
+
manifest: '/site.webmanifest',
|
|
96
|
+
formatDetection: {
|
|
97
|
+
email: false,
|
|
98
|
+
address: false,
|
|
99
|
+
telephone: false,
|
|
100
|
+
},
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
export const viewport = {
|
|
104
|
+
themeColor: '#F3F1EA',
|
|
105
|
+
width: 'device-width',
|
|
106
|
+
initialScale: 1,
|
|
107
|
+
colorScheme: 'light',
|
|
6
108
|
};
|
|
7
109
|
|
|
8
110
|
export default function RootLayout({ children }) {
|
|
9
111
|
return (
|
|
10
|
-
<html
|
|
112
|
+
<html
|
|
113
|
+
lang="en"
|
|
114
|
+
className={`${fraunces.variable} ${instrumentSans.variable} ${mono.variable}`}
|
|
115
|
+
>
|
|
11
116
|
<head>
|
|
12
117
|
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
|
13
|
-
<link rel="
|
|
14
|
-
<link href="https://
|
|
118
|
+
<link rel="dns-prefetch" href="https://fonts.gstatic.com" />
|
|
119
|
+
<link rel="author" href="https://manavaryasingh.com" />
|
|
120
|
+
<link rel="me" href="https://github.com/Manavarya09" />
|
|
121
|
+
<StructuredData />
|
|
15
122
|
</head>
|
|
16
123
|
<body>{children}</body>
|
|
17
124
|
</html>
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
import { ImageResponse } from 'next/og';
|
|
2
|
+
|
|
3
|
+
export const runtime = 'nodejs';
|
|
4
|
+
export const alt =
|
|
5
|
+
'designlang specimen card. A lowercase d built from a ring, a stem, and one extracted orange token, next to the wordmark designlang in Fraunces with a molten-orange period, and a five-swatch palette strip.';
|
|
6
|
+
export const size = { width: 1200, height: 630 };
|
|
7
|
+
export const contentType = 'image/png';
|
|
8
|
+
|
|
9
|
+
const PAPER = '#F3F1EA';
|
|
10
|
+
const INK = '#0A0908';
|
|
11
|
+
const INK_2 = '#403C34';
|
|
12
|
+
const INK_3 = '#8B8778';
|
|
13
|
+
const ACCENT = '#FF4800';
|
|
14
|
+
|
|
15
|
+
export default async function OpengraphImage() {
|
|
16
|
+
return new ImageResponse(
|
|
17
|
+
(
|
|
18
|
+
<div
|
|
19
|
+
style={{
|
|
20
|
+
width: '100%',
|
|
21
|
+
height: '100%',
|
|
22
|
+
background: PAPER,
|
|
23
|
+
color: INK,
|
|
24
|
+
display: 'flex',
|
|
25
|
+
flexDirection: 'column',
|
|
26
|
+
justifyContent: 'space-between',
|
|
27
|
+
padding: 56,
|
|
28
|
+
fontFamily: 'Georgia, serif',
|
|
29
|
+
border: `2px solid ${INK}`,
|
|
30
|
+
}}
|
|
31
|
+
>
|
|
32
|
+
{/* top caption strip */}
|
|
33
|
+
<div
|
|
34
|
+
style={{
|
|
35
|
+
display: 'flex',
|
|
36
|
+
justifyContent: 'space-between',
|
|
37
|
+
fontFamily: 'ui-monospace, Menlo, monospace',
|
|
38
|
+
fontSize: 16,
|
|
39
|
+
color: INK_2,
|
|
40
|
+
letterSpacing: 2,
|
|
41
|
+
textTransform: 'uppercase',
|
|
42
|
+
}}
|
|
43
|
+
>
|
|
44
|
+
<div style={{ display: 'flex', flexDirection: 'column', gap: 4 }}>
|
|
45
|
+
<span>SPECIMEN / 01</span>
|
|
46
|
+
<span>EXTRACTED 2026</span>
|
|
47
|
+
</div>
|
|
48
|
+
<div style={{ display: 'flex', flexDirection: 'column', gap: 4, textAlign: 'right' }}>
|
|
49
|
+
<span>v7.0</span>
|
|
50
|
+
<span>W3C DTCG</span>
|
|
51
|
+
</div>
|
|
52
|
+
</div>
|
|
53
|
+
|
|
54
|
+
{/* wordmark row */}
|
|
55
|
+
<div style={{ display: 'flex', alignItems: 'center', gap: 48 }}>
|
|
56
|
+
{/* mark */}
|
|
57
|
+
<div
|
|
58
|
+
style={{
|
|
59
|
+
position: 'relative',
|
|
60
|
+
width: 150,
|
|
61
|
+
height: 180,
|
|
62
|
+
display: 'flex',
|
|
63
|
+
}}
|
|
64
|
+
>
|
|
65
|
+
{/* counter ring */}
|
|
66
|
+
<div
|
|
67
|
+
style={{
|
|
68
|
+
position: 'absolute',
|
|
69
|
+
left: 0,
|
|
70
|
+
bottom: 0,
|
|
71
|
+
width: 116,
|
|
72
|
+
height: 116,
|
|
73
|
+
border: `24px solid ${INK}`,
|
|
74
|
+
borderRadius: '50%',
|
|
75
|
+
}}
|
|
76
|
+
/>
|
|
77
|
+
{/* stem */}
|
|
78
|
+
<div
|
|
79
|
+
style={{
|
|
80
|
+
position: 'absolute',
|
|
81
|
+
left: 92,
|
|
82
|
+
top: 0,
|
|
83
|
+
width: 26,
|
|
84
|
+
height: 180,
|
|
85
|
+
background: INK,
|
|
86
|
+
}}
|
|
87
|
+
/>
|
|
88
|
+
{/* extracted token */}
|
|
89
|
+
<div
|
|
90
|
+
style={{
|
|
91
|
+
position: 'absolute',
|
|
92
|
+
left: 122,
|
|
93
|
+
top: 150,
|
|
94
|
+
width: 30,
|
|
95
|
+
height: 30,
|
|
96
|
+
background: ACCENT,
|
|
97
|
+
}}
|
|
98
|
+
/>
|
|
99
|
+
</div>
|
|
100
|
+
|
|
101
|
+
{/* word + tagline */}
|
|
102
|
+
<div style={{ display: 'flex', flexDirection: 'column' }}>
|
|
103
|
+
<div
|
|
104
|
+
style={{
|
|
105
|
+
fontSize: 128,
|
|
106
|
+
lineHeight: 1,
|
|
107
|
+
letterSpacing: -4,
|
|
108
|
+
display: 'flex',
|
|
109
|
+
alignItems: 'baseline',
|
|
110
|
+
}}
|
|
111
|
+
>
|
|
112
|
+
<span style={{ color: INK }}>designlang</span>
|
|
113
|
+
<span style={{ color: ACCENT }}>.</span>
|
|
114
|
+
</div>
|
|
115
|
+
<div
|
|
116
|
+
style={{
|
|
117
|
+
marginTop: 14,
|
|
118
|
+
fontSize: 22,
|
|
119
|
+
fontStyle: 'italic',
|
|
120
|
+
color: INK_2,
|
|
121
|
+
fontFamily: 'Helvetica, Arial, sans-serif',
|
|
122
|
+
}}
|
|
123
|
+
>
|
|
124
|
+
reads a website the way a developer reads a stylesheet.
|
|
125
|
+
</div>
|
|
126
|
+
</div>
|
|
127
|
+
</div>
|
|
128
|
+
|
|
129
|
+
{/* bottom: palette + command */}
|
|
130
|
+
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-end' }}>
|
|
131
|
+
<div style={{ display: 'flex', gap: 14 }}>
|
|
132
|
+
{[INK, INK_2, INK_3, '#D8D3C5', ACCENT].map((c) => (
|
|
133
|
+
<div key={c} style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
|
|
134
|
+
<div style={{ width: 56, height: 56, background: c }} />
|
|
135
|
+
<span
|
|
136
|
+
style={{
|
|
137
|
+
fontFamily: 'ui-monospace, Menlo, monospace',
|
|
138
|
+
fontSize: 12,
|
|
139
|
+
color: INK_2,
|
|
140
|
+
letterSpacing: 1,
|
|
141
|
+
}}
|
|
142
|
+
>
|
|
143
|
+
{c}
|
|
144
|
+
</span>
|
|
145
|
+
</div>
|
|
146
|
+
))}
|
|
147
|
+
</div>
|
|
148
|
+
<div
|
|
149
|
+
style={{
|
|
150
|
+
display: 'flex',
|
|
151
|
+
flexDirection: 'column',
|
|
152
|
+
gap: 6,
|
|
153
|
+
textAlign: 'right',
|
|
154
|
+
fontFamily: 'ui-monospace, Menlo, monospace',
|
|
155
|
+
fontSize: 16,
|
|
156
|
+
letterSpacing: 1.2,
|
|
157
|
+
color: INK_2,
|
|
158
|
+
}}
|
|
159
|
+
>
|
|
160
|
+
<span>$ npx designlang <url></span>
|
|
161
|
+
<span style={{ color: INK_3 }}>MIT · Node ≥ 20 · Playwright</span>
|
|
162
|
+
</div>
|
|
163
|
+
</div>
|
|
164
|
+
</div>
|
|
165
|
+
),
|
|
166
|
+
{
|
|
167
|
+
...size,
|
|
168
|
+
}
|
|
169
|
+
);
|
|
170
|
+
}
|