vercel-seo-audit 2.1.0 → 2.2.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/README.md CHANGED
@@ -171,6 +171,8 @@ Then just run `vercel-seo-audit` with no arguments. CLI flags always override co
171
171
  * `noindex` via meta tags **and** `X-Robots-Tag` header
172
172
  * Missing `title`, `description`, `charset`, `viewport`
173
173
  * Open Graph basics: `og:title`, `og:description`, `og:image`
174
+ * Broken or relative `og:image` URL validation
175
+ * Twitter Card: `twitter:card`, `twitter:image` presence and validation
174
176
 
175
177
  ### Favicon
176
178
 
@@ -216,6 +218,20 @@ Progress is printed to stderr as each page is crawled.
216
218
  * Duplicate hreflang values
217
219
  * Missing reciprocal links (page A→B but B doesn't→A)
218
220
 
221
+ ### Security Headers
222
+
223
+ * Missing `Strict-Transport-Security` (HSTS)
224
+ * Missing `X-Content-Type-Options: nosniff`
225
+ * Missing frame protection (`X-Frame-Options` or CSP `frame-ancestors`)
226
+ * Missing `Referrer-Policy`
227
+
228
+ ### Performance Hints
229
+
230
+ * HTML document size (warning > 1 MB, info > 500 KB)
231
+ * Render-blocking `<script>` tags in `<head>` without `async`/`defer`
232
+ * Large inline `<style>` blocks (> 50 KB)
233
+ * Missing `<link rel="preconnect">` for third-party origins
234
+
219
235
  ### Next.js / Vercel
220
236
 
221
237
  * Detect Vercel deployment
@@ -328,20 +344,20 @@ npx vercel-seo-audit https://your-site.com --report md
328
344
  * [x] ~~`--user-agent` presets (`googlebot`, `bingbot`)~~
329
345
  * [x] ~~`--report` to write `report.json` / `report.md`~~
330
346
  * [x] ~~GitHub Action marketplace wrapper~~
331
- * [x] ~~`--diff` to compare audit runs and detect regressions~~
347
+ * [x] ~~`--diff` to compare two audit runs and detect regressions~~
332
348
  * [x] ~~Structured data / JSON-LD validation~~
333
349
  * [x] ~~`--crawl` mode to audit all pages from sitemap~~
334
350
  * [x] ~~i18n / `hreflang` validation~~
335
351
  * [x] ~~Image SEO checks (missing `alt`, `next/image`, lazy loading)~~
336
352
  * [x] ~~Config file (`.seoauditrc.json`) for project-level defaults~~
353
+ * [x] ~~Open Graph & Twitter Card image validation ([#36](https://github.com/JosephDoUrden/vercel-seo-audit/issues/36))~~
354
+ * [x] ~~Security headers audit ([#37](https://github.com/JosephDoUrden/vercel-seo-audit/issues/37))~~
355
+ * [x] ~~Performance hints (resource size, render-blocking) ([#38](https://github.com/JosephDoUrden/vercel-seo-audit/issues/38))~~
337
356
 
338
357
  ### Up next
339
358
 
340
- * [ ] Open Graph & Twitter Card image validation ([#36](https://github.com/JosephDoUrden/vercel-seo-audit/issues/36)) `good first issue`
341
- * [ ] Security headers audit ([#37](https://github.com/JosephDoUrden/vercel-seo-audit/issues/37)) `good first issue`
342
359
  * [ ] `--ignore` flag and `.seoauditignore` support ([#41](https://github.com/JosephDoUrden/vercel-seo-audit/issues/41)) `good first issue`
343
360
  * [ ] GitHub Actions PR comment integration ([#44](https://github.com/JosephDoUrden/vercel-seo-audit/issues/44)) `good first issue`
344
- * [ ] Performance hints (resource size, render-blocking) ([#38](https://github.com/JosephDoUrden/vercel-seo-audit/issues/38))
345
361
  * [ ] HTML report format with interactive dashboard ([#39](https://github.com/JosephDoUrden/vercel-seo-audit/issues/39))
346
362
  * [ ] `--fix` flag with auto-fix suggestions ([#40](https://github.com/JosephDoUrden/vercel-seo-audit/issues/40))
347
363
  * [ ] Internal broken link checker ([#42](https://github.com/JosephDoUrden/vercel-seo-audit/issues/42))
@@ -9,4 +9,5 @@ export { auditCrawl } from './crawl.js';
9
9
  export { auditI18n } from './i18n.js';
10
10
  export { auditImages } from './images.js';
11
11
  export { auditSecurity } from './security.js';
12
+ export { auditPerformance } from './performance.js';
12
13
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/audit/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACxC,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/audit/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACxC,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC"}
@@ -9,4 +9,5 @@ export { auditCrawl } from './crawl.js';
9
9
  export { auditI18n } from './i18n.js';
10
10
  export { auditImages } from './images.js';
11
11
  export { auditSecurity } from './security.js';
12
+ export { auditPerformance } from './performance.js';
12
13
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/audit/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACxC,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/audit/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACxC,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { AuditContext, AuditFinding } from '../types.js';
2
+ export declare function auditPerformance(ctx: AuditContext): Promise<AuditFinding[]>;
3
+ //# sourceMappingURL=performance.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"performance.d.ts","sourceRoot":"","sources":["../../src/audit/performance.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAM9D,wBAAsB,gBAAgB,CAAC,GAAG,EAAE,YAAY,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,CAkJjF"}
@@ -0,0 +1,137 @@
1
+ import { fetchPage } from '../utils/http.js';
2
+ const KB = 1024;
3
+ const MB = 1024 * KB;
4
+ export async function auditPerformance(ctx) {
5
+ const findings = [];
6
+ const { normalizedUrl, fetchOptions } = ctx;
7
+ let html;
8
+ if (ctx.html) {
9
+ html = ctx.html;
10
+ }
11
+ else {
12
+ try {
13
+ const res = await fetchPage(normalizedUrl, fetchOptions);
14
+ html = res.body;
15
+ }
16
+ catch {
17
+ return findings;
18
+ }
19
+ }
20
+ // 1. HTML size check
21
+ const htmlSize = Buffer.byteLength(html, 'utf-8');
22
+ if (htmlSize > 1 * MB) {
23
+ findings.push({
24
+ code: 'HTML_SIZE_WARNING',
25
+ severity: 'warning',
26
+ category: 'performance',
27
+ message: `HTML document is ${(htmlSize / KB).toFixed(0)} KB (exceeds 1 MB)`,
28
+ explanation: 'Very large HTML documents increase Time to First Byte (TTFB) and slow down parsing, hurting Core Web Vitals and SEO rankings.',
29
+ suggestion: 'Reduce HTML size by deferring non-critical content, paginating long lists, or lazy-loading below-the-fold sections.',
30
+ url: normalizedUrl,
31
+ details: { bytes: htmlSize },
32
+ });
33
+ }
34
+ else if (htmlSize > 500 * KB) {
35
+ findings.push({
36
+ code: 'HTML_SIZE_WARNING',
37
+ severity: 'info',
38
+ category: 'performance',
39
+ message: `HTML document is ${(htmlSize / KB).toFixed(0)} KB (exceeds 500 KB)`,
40
+ explanation: 'Large HTML documents can slow down initial page load and parsing, which may negatively affect Core Web Vitals.',
41
+ suggestion: 'Consider reducing HTML size by deferring non-critical content or lazy-loading below-the-fold sections.',
42
+ url: normalizedUrl,
43
+ details: { bytes: htmlSize },
44
+ });
45
+ }
46
+ // 2. Render-blocking scripts in <head>
47
+ const headMatch = html.match(/<head[\s>]([\s\S]*?)<\/head>/i);
48
+ if (headMatch) {
49
+ const headContent = headMatch[1];
50
+ const scriptRegex = /<script\b([^>]*)>/gi;
51
+ let match;
52
+ while ((match = scriptRegex.exec(headContent)) !== null) {
53
+ const attrs = match[1];
54
+ const hasAsync = /\basync\b/i.test(attrs);
55
+ const hasDefer = /\bdefer\b/i.test(attrs);
56
+ const hasTypeModule = /\btype\s*=\s*["']module["']/i.test(attrs);
57
+ if (!hasAsync && !hasDefer && !hasTypeModule) {
58
+ findings.push({
59
+ code: 'RENDER_BLOCKING_SCRIPT',
60
+ severity: 'warning',
61
+ category: 'performance',
62
+ message: 'Render-blocking <script> found in <head> without async, defer, or type="module"',
63
+ explanation: 'Scripts in <head> without async or defer block HTML parsing until they are downloaded and executed, delaying First Contentful Paint.',
64
+ suggestion: 'Add the async or defer attribute to <script> tags in <head>, or move them to the end of <body>.',
65
+ url: normalizedUrl,
66
+ });
67
+ }
68
+ }
69
+ }
70
+ // 3. Large inline styles
71
+ const styleRegex = /<style\b[^>]*>([\s\S]*?)<\/style>/gi;
72
+ let styleMatch;
73
+ while ((styleMatch = styleRegex.exec(html)) !== null) {
74
+ const styleSize = Buffer.byteLength(styleMatch[1], 'utf-8');
75
+ if (styleSize > 50 * KB) {
76
+ findings.push({
77
+ code: 'LARGE_INLINE_STYLE',
78
+ severity: 'warning',
79
+ category: 'performance',
80
+ message: `Inline <style> block is ${(styleSize / KB).toFixed(0)} KB (exceeds 50 KB)`,
81
+ explanation: 'Large inline style blocks increase HTML size and cannot be cached separately by the browser, slowing down repeat visits.',
82
+ suggestion: 'Extract large CSS into external stylesheets that can be cached independently.',
83
+ url: normalizedUrl,
84
+ details: { bytes: styleSize },
85
+ });
86
+ }
87
+ }
88
+ // 4. Missing preconnect for third-party origins
89
+ const pageOrigin = new URL(normalizedUrl).origin;
90
+ const thirdPartyOrigins = new Set();
91
+ const srcRegex = /<(?:script|link|img)\b[^>]*(?:src|href)\s*=\s*["']([^"']+)["'][^>]*>/gi;
92
+ let srcMatch;
93
+ while ((srcMatch = srcRegex.exec(html)) !== null) {
94
+ try {
95
+ const url = new URL(srcMatch[1], normalizedUrl);
96
+ if (url.origin !== pageOrigin && url.protocol.startsWith('http')) {
97
+ thirdPartyOrigins.add(url.origin);
98
+ }
99
+ }
100
+ catch {
101
+ // ignore invalid URLs
102
+ }
103
+ }
104
+ if (thirdPartyOrigins.size > 0) {
105
+ const preconnectRegex = /<link\b[^>]*rel\s*=\s*["']preconnect["'][^>]*href\s*=\s*["']([^"']+)["'][^>]*>/gi;
106
+ const preconnectHrefFirst = /<link\b[^>]*href\s*=\s*["']([^"']+)["'][^>]*rel\s*=\s*["']preconnect["'][^>]*>/gi;
107
+ const preconnectedOrigins = new Set();
108
+ let pcMatch;
109
+ while ((pcMatch = preconnectRegex.exec(html)) !== null) {
110
+ try {
111
+ preconnectedOrigins.add(new URL(pcMatch[1]).origin);
112
+ }
113
+ catch { /* ignore */ }
114
+ }
115
+ while ((pcMatch = preconnectHrefFirst.exec(html)) !== null) {
116
+ try {
117
+ preconnectedOrigins.add(new URL(pcMatch[1]).origin);
118
+ }
119
+ catch { /* ignore */ }
120
+ }
121
+ const missingOrigins = [...thirdPartyOrigins].filter((o) => !preconnectedOrigins.has(o));
122
+ if (missingOrigins.length > 0) {
123
+ findings.push({
124
+ code: 'MISSING_PRECONNECT',
125
+ severity: 'info',
126
+ category: 'performance',
127
+ message: `No <link rel="preconnect"> for ${missingOrigins.length} third-party origin(s)`,
128
+ explanation: 'Preconnect hints allow the browser to set up connections to third-party origins early, reducing latency for critical resources.',
129
+ suggestion: `Add <link rel="preconnect" href="..."> for: ${missingOrigins.join(', ')}`,
130
+ url: normalizedUrl,
131
+ details: { origins: missingOrigins },
132
+ });
133
+ }
134
+ }
135
+ return findings;
136
+ }
137
+ //# sourceMappingURL=performance.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"performance.js","sourceRoot":"","sources":["../../src/audit/performance.ts"],"names":[],"mappings":"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"}
package/dist/cli.js CHANGED
@@ -11,7 +11,7 @@ const program = new Command();
11
11
  program
12
12
  .name('vercel-seo-audit')
13
13
  .description('Diagnose SEO and indexing issues for Next.js/Vercel websites')
14
- .version('2.1.0') // x-release-please-version
14
+ .version('2.2.0') // x-release-please-version
15
15
  .argument('[url]', 'URL to audit (e.g. https://yusufhan.dev)')
16
16
  .option('--json', 'Output results as JSON')
17
17
  .option('--verbose', 'Show detailed information for each finding')
@@ -1,6 +1,6 @@
1
1
  export declare const DEFAULT_TIMEOUT = 10000;
2
2
  export declare const MAX_REDIRECTS = 20;
3
- export declare const USER_AGENT = "vercel-seo-audit/2.1.0";
3
+ export declare const USER_AGENT = "vercel-seo-audit/2.2.0";
4
4
  export declare const SITEMAP_SAMPLE_SIZE = 10;
5
5
  export declare const COMMON_PAGES: string[];
6
6
  export declare const USER_AGENT_PRESETS: Record<string, string>;
package/dist/constants.js CHANGED
@@ -1,6 +1,6 @@
1
1
  export const DEFAULT_TIMEOUT = 10_000;
2
2
  export const MAX_REDIRECTS = 20;
3
- export const USER_AGENT = 'vercel-seo-audit/2.1.0'; // x-release-please-version
3
+ export const USER_AGENT = 'vercel-seo-audit/2.2.0'; // x-release-please-version
4
4
  export const SITEMAP_SAMPLE_SIZE = 10;
5
5
  export const COMMON_PAGES = ['/about', '/contact', '/blog', '/pricing'];
6
6
  export const USER_AGENT_PRESETS = {
@@ -1 +1 @@
1
- {"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../src/runner.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAIV,WAAW,EAEZ,MAAM,YAAY,CAAC;AAwDpB,wBAAsB,QAAQ,CAC5B,GAAG,EAAE,MAAM,EACX,IAAI,GAAE;IAAE,OAAO,CAAC,EAAE,OAAO,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAO,GACvG,OAAO,CAAC,WAAW,CAAC,CAgDtB"}
1
+ {"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../src/runner.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAIV,WAAW,EAEZ,MAAM,YAAY,CAAC;AA0DpB,wBAAsB,QAAQ,CAC5B,GAAG,EAAE,MAAM,EACX,IAAI,GAAE;IAAE,OAAO,CAAC,EAAE,OAAO,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAO,GACvG,OAAO,CAAC,WAAW,CAAC,CAgDtB"}
package/dist/runner.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { normalizeUrl } from './utils/url.js';
2
- import { auditRedirects, auditRobots, auditSitemap, auditMetadata, auditFavicon, auditNextjs, auditStructuredData, auditCrawl, auditI18n, auditImages, auditSecurity, } from './audit/index.js';
2
+ import { auditRedirects, auditRobots, auditSitemap, auditMetadata, auditFavicon, auditNextjs, auditStructuredData, auditCrawl, auditI18n, auditImages, auditSecurity, auditPerformance, } from './audit/index.js';
3
3
  const phase1Modules = [
4
4
  { name: 'robots', run: auditRobots },
5
5
  { name: 'redirects', run: auditRedirects },
@@ -13,6 +13,7 @@ const phase2Modules = [
13
13
  { name: 'i18n', run: auditI18n },
14
14
  { name: 'images', run: auditImages },
15
15
  { name: 'security', run: auditSecurity },
16
+ { name: 'performance', run: auditPerformance },
16
17
  ];
17
18
  async function runModules(modules, ctx) {
18
19
  const results = await Promise.allSettled(modules.map(async (mod) => {
@@ -1 +1 @@
1
- {"version":3,"file":"runner.js","sourceRoot":"","sources":["../src/runner.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"runner.js","sourceRoot":"","sources":["../src/runner.ts"],"names":[],"mappings":"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"}
package/dist/types.d.ts CHANGED
@@ -8,8 +8,8 @@ export interface SeoAuditConfig {
8
8
  timeout?: number;
9
9
  }
10
10
  export type IssueSeverity = 'error' | 'warning' | 'info' | 'pass';
11
- export type IssueCategory = 'redirect' | 'indexing' | 'metadata' | 'favicon' | 'sitemap' | 'robots' | 'nextjs' | 'structured-data' | 'crawl' | 'i18n' | 'images' | 'security';
12
- export type IssueCode = 'REDIRECT_CHAIN' | 'REDIRECT_LOOP' | 'HTTP_TO_HTTPS_REDIRECT' | 'HTTP_NO_HTTPS_REDIRECT' | 'TRAILING_SLASH_REDIRECT' | 'META_REFRESH_REDIRECT' | 'COMMON_PAGE_REDIRECT' | 'NOINDEX_DETECTED' | 'X_ROBOTS_NOINDEX' | 'CANONICAL_MISSING' | 'CANONICAL_MISMATCH' | 'CANONICAL_EXTERNAL' | 'CHARSET_MISSING' | 'VIEWPORT_MISSING' | 'TITLE_MISSING' | 'DESCRIPTION_MISSING' | 'OG_TITLE_MISSING' | 'OG_DESCRIPTION_MISSING' | 'OG_IMAGE_MISSING' | 'OG_IMAGE_BROKEN' | 'OG_IMAGE_RELATIVE' | 'TWITTER_CARD_MISSING' | 'TWITTER_IMAGE_MISSING' | 'TWITTER_IMAGE_BROKEN' | 'FAVICON_MISSING' | 'FAVICON_CONFLICT' | 'FAVICON_HTML_MISSING' | 'SITEMAP_MISSING' | 'SITEMAP_REDIRECTED' | 'SITEMAP_EMPTY' | 'SITEMAP_INVALID_URL' | 'SITEMAP_URL_ERROR' | 'SITEMAP_ROBOTS_MISMATCH' | 'ROBOTS_MISSING' | 'ROBOTS_BLOCKS_ALL' | 'ROBOTS_BLOCKS_GOOGLEBOT' | 'ROBOTS_NO_SITEMAP' | 'VERCEL_DETECTED' | 'NEXTJS_TRAILING_SLASH_308' | 'MIDDLEWARE_REDIRECT' | 'APP_ROUTER_METADATA' | 'JSONLD_MISSING' | 'JSONLD_INVALID_JSON' | 'JSONLD_MISSING_CONTEXT' | 'JSONLD_MISSING_TYPE' | 'JSONLD_EMPTY_FIELDS' | 'CRAWL_PAGE_ERROR' | 'CRAWL_PAGE_NOINDEX' | 'CRAWL_PAGE_TITLE_MISSING' | 'CRAWL_PAGE_DESCRIPTION_MISSING' | 'CRAWL_PAGE_CANONICAL_MISSING' | 'CRAWL_PAGE_CANONICAL_MISMATCH' | 'CRAWL_PAGE_JSONLD_MISSING' | 'HREFLANG_MISSING' | 'HREFLANG_INVALID_LANG' | 'HREFLANG_MISSING_SELF' | 'HREFLANG_MISSING_XDEFAULT' | 'HREFLANG_MISSING_RECIPROCAL' | 'HREFLANG_DUPLICATE' | 'IMG_MISSING_ALT' | 'IMG_EMPTY_ALT' | 'IMG_NO_NEXT_IMAGE' | 'IMG_NO_LAZY_LOADING' | 'IMG_LARGE_FILE' | 'IMG_MISSING_DIMENSIONS' | 'HSTS_MISSING' | 'CONTENT_TYPE_OPTIONS_MISSING' | 'FRAME_PROTECTION_MISSING' | 'REFERRER_POLICY_MISSING';
11
+ export type IssueCategory = 'redirect' | 'indexing' | 'metadata' | 'favicon' | 'sitemap' | 'robots' | 'nextjs' | 'structured-data' | 'crawl' | 'i18n' | 'images' | 'security' | 'performance';
12
+ export type IssueCode = 'REDIRECT_CHAIN' | 'REDIRECT_LOOP' | 'HTTP_TO_HTTPS_REDIRECT' | 'HTTP_NO_HTTPS_REDIRECT' | 'TRAILING_SLASH_REDIRECT' | 'META_REFRESH_REDIRECT' | 'COMMON_PAGE_REDIRECT' | 'NOINDEX_DETECTED' | 'X_ROBOTS_NOINDEX' | 'CANONICAL_MISSING' | 'CANONICAL_MISMATCH' | 'CANONICAL_EXTERNAL' | 'CHARSET_MISSING' | 'VIEWPORT_MISSING' | 'TITLE_MISSING' | 'DESCRIPTION_MISSING' | 'OG_TITLE_MISSING' | 'OG_DESCRIPTION_MISSING' | 'OG_IMAGE_MISSING' | 'OG_IMAGE_BROKEN' | 'OG_IMAGE_RELATIVE' | 'TWITTER_CARD_MISSING' | 'TWITTER_IMAGE_MISSING' | 'TWITTER_IMAGE_BROKEN' | 'FAVICON_MISSING' | 'FAVICON_CONFLICT' | 'FAVICON_HTML_MISSING' | 'SITEMAP_MISSING' | 'SITEMAP_REDIRECTED' | 'SITEMAP_EMPTY' | 'SITEMAP_INVALID_URL' | 'SITEMAP_URL_ERROR' | 'SITEMAP_ROBOTS_MISMATCH' | 'ROBOTS_MISSING' | 'ROBOTS_BLOCKS_ALL' | 'ROBOTS_BLOCKS_GOOGLEBOT' | 'ROBOTS_NO_SITEMAP' | 'VERCEL_DETECTED' | 'NEXTJS_TRAILING_SLASH_308' | 'MIDDLEWARE_REDIRECT' | 'APP_ROUTER_METADATA' | 'JSONLD_MISSING' | 'JSONLD_INVALID_JSON' | 'JSONLD_MISSING_CONTEXT' | 'JSONLD_MISSING_TYPE' | 'JSONLD_EMPTY_FIELDS' | 'CRAWL_PAGE_ERROR' | 'CRAWL_PAGE_NOINDEX' | 'CRAWL_PAGE_TITLE_MISSING' | 'CRAWL_PAGE_DESCRIPTION_MISSING' | 'CRAWL_PAGE_CANONICAL_MISSING' | 'CRAWL_PAGE_CANONICAL_MISMATCH' | 'CRAWL_PAGE_JSONLD_MISSING' | 'HREFLANG_MISSING' | 'HREFLANG_INVALID_LANG' | 'HREFLANG_MISSING_SELF' | 'HREFLANG_MISSING_XDEFAULT' | 'HREFLANG_MISSING_RECIPROCAL' | 'HREFLANG_DUPLICATE' | 'IMG_MISSING_ALT' | 'IMG_EMPTY_ALT' | 'IMG_NO_NEXT_IMAGE' | 'IMG_NO_LAZY_LOADING' | 'IMG_LARGE_FILE' | 'IMG_MISSING_DIMENSIONS' | 'HSTS_MISSING' | 'CONTENT_TYPE_OPTIONS_MISSING' | 'FRAME_PROTECTION_MISSING' | 'REFERRER_POLICY_MISSING' | 'HTML_SIZE_WARNING' | 'RENDER_BLOCKING_SCRIPT' | 'LARGE_INLINE_STYLE' | 'MISSING_PRECONNECT';
13
13
  export interface AuditFinding {
14
14
  code: IssueCode;
15
15
  severity: IssueSeverity;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vercel-seo-audit",
3
- "version": "2.1.0",
3
+ "version": "2.2.0",
4
4
  "description": "CLI tool that diagnoses SEO and indexing issues for Next.js/Vercel websites",
5
5
  "type": "module",
6
6
  "bin": {