mirror of
https://github.com/AgentDeskAI/browser-tools-mcp.git
synced 2025-06-27 00:41:26 +00:00
added audit and debugger mode
This commit is contained in:
parent
1efe7a8e80
commit
1f33030d0b
@ -577,6 +577,766 @@ server.tool(
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
server.tool("runNextJSAudit", {}, async () => ({
|
||||||
|
content: [
|
||||||
|
{
|
||||||
|
type: "text",
|
||||||
|
text: `
|
||||||
|
You are an expert in SEO and web development with NextJS. Given the following procedures for analyzing my codebase, please perform a comprehensive - page by page analysis of our NextJS application to identify any issues or areas of improvement for SEO.
|
||||||
|
|
||||||
|
After each iteration of changes, reinvoke this tool to re-fetch our SEO audit procedures and then scan our codebase again to identify additional areas of improvement.
|
||||||
|
|
||||||
|
When no more areas of improvement are found, return "No more areas of improvement found, your NextJS application is optimized for SEO!".
|
||||||
|
|
||||||
|
Start by analyzing each of the following aspects of our codebase:
|
||||||
|
1. Meta tags - provides information about your website to search engines and social media platforms.
|
||||||
|
|
||||||
|
Pages should provide the following standard meta tags:
|
||||||
|
|
||||||
|
title
|
||||||
|
description
|
||||||
|
keywords
|
||||||
|
robots
|
||||||
|
viewport
|
||||||
|
charSet
|
||||||
|
Open Graph meta tags:
|
||||||
|
|
||||||
|
og:site_name
|
||||||
|
og:locale
|
||||||
|
og:title
|
||||||
|
og:description
|
||||||
|
og:type
|
||||||
|
og:url
|
||||||
|
og:image
|
||||||
|
og:image:alt
|
||||||
|
og:image:type
|
||||||
|
og:image:width
|
||||||
|
og:image:height
|
||||||
|
Article meta tags (actually it's also OpenGraph):
|
||||||
|
|
||||||
|
article:published_time
|
||||||
|
article:modified_time
|
||||||
|
article:author
|
||||||
|
Twitter meta tags:
|
||||||
|
|
||||||
|
twitter:card
|
||||||
|
twitter:site
|
||||||
|
twitter:creator
|
||||||
|
twitter:title
|
||||||
|
twitter:description
|
||||||
|
twitter:image
|
||||||
|
|
||||||
|
For applications using the pages router, set up metatags like this in pages/[slug].tsx:
|
||||||
|
import Head from "next/head";
|
||||||
|
|
||||||
|
export default function Page() {
|
||||||
|
return (
|
||||||
|
<Head>
|
||||||
|
<title>
|
||||||
|
Next.js SEO: The Complete Checklist to Boost Your Site Ranking
|
||||||
|
</title>
|
||||||
|
<meta
|
||||||
|
name="description"
|
||||||
|
content="Learn how to optimize your Next.js website for SEO by following this complete checklist."
|
||||||
|
/>
|
||||||
|
<meta
|
||||||
|
name="keywords"
|
||||||
|
content="nextjs seo complete checklist, nextjs seo tutorial"
|
||||||
|
/>
|
||||||
|
<meta name="robots" content="index, follow" />
|
||||||
|
<meta name="googlebot" content="index, follow" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<meta charSet="utf-8" />
|
||||||
|
<meta property="og:site_name" content="Blog | Minh Vu" />
|
||||||
|
<meta property="og:locale" content="en_US" />
|
||||||
|
<meta
|
||||||
|
property="og:title"
|
||||||
|
content="Next.js SEO: The Complete Checklist to Boost Your Site Ranking"
|
||||||
|
/>
|
||||||
|
<meta
|
||||||
|
property="og:description"
|
||||||
|
content="Learn how to optimize your Next.js website for SEO by following this complete checklist."
|
||||||
|
/>
|
||||||
|
<meta property="og:type" content="website" />
|
||||||
|
<meta property="og:url" content="https://dminhvu.com/nextjs-seo" />
|
||||||
|
<meta
|
||||||
|
property="og:image"
|
||||||
|
content="https://ik.imagekit.io/dminhvu/assets/nextjs-seo/thumbnail.png?tr=f-png"
|
||||||
|
/>
|
||||||
|
<meta property="og:image:alt" content="Next.js SEO" />
|
||||||
|
<meta property="og:image:type" content="image/png" />
|
||||||
|
<meta property="og:image:width" content="1200" />
|
||||||
|
<meta property="og:image:height" content="630" />
|
||||||
|
<meta
|
||||||
|
property="article:published_time"
|
||||||
|
content="2024-01-11T11:35:00+07:00"
|
||||||
|
/>
|
||||||
|
<meta
|
||||||
|
property="article:modified_time"
|
||||||
|
content="2024-01-11T11:35:00+07:00"
|
||||||
|
/>
|
||||||
|
<meta
|
||||||
|
property="article:author"
|
||||||
|
content="https://www.linkedin.com/in/dminhvu02"
|
||||||
|
/>
|
||||||
|
<meta name="twitter:card" content="summary_large_image" />
|
||||||
|
<meta name="twitter:site" content="@dminhvu02" />
|
||||||
|
<meta name="twitter:creator" content="@dminhvu02" />
|
||||||
|
<meta
|
||||||
|
name="twitter:title"
|
||||||
|
content="Next.js SEO: The Complete Checklist to Boost Your Site Ranking"
|
||||||
|
/>
|
||||||
|
<meta
|
||||||
|
name="twitter:description"
|
||||||
|
content="Learn how to optimize your Next.js website for SEO by following this complete checklist."
|
||||||
|
/>
|
||||||
|
<meta
|
||||||
|
name="twitter:image"
|
||||||
|
content="https://ik.imagekit.io/dminhvu/assets/nextjs-seo/thumbnail.png?tr=f-png"
|
||||||
|
/>
|
||||||
|
</Head>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
For applications using the app router, set up metatags like this in layout.tsx:
|
||||||
|
import type { Viewport, Metadata } from "next";
|
||||||
|
|
||||||
|
export const viewport: Viewport = {
|
||||||
|
width: "device-width",
|
||||||
|
initialScale: 1,
|
||||||
|
themeColor: "#ffffff"
|
||||||
|
};
|
||||||
|
|
||||||
|
export const metadata: Metadata = {
|
||||||
|
metadataBase: new URL("https://dminhvu.com"),
|
||||||
|
openGraph: {
|
||||||
|
siteName: "Blog | Minh Vu",
|
||||||
|
type: "website",
|
||||||
|
locale: "en_US"
|
||||||
|
},
|
||||||
|
robots: {
|
||||||
|
index: true,
|
||||||
|
follow: true,
|
||||||
|
"max-image-preview": "large",
|
||||||
|
"max-snippet": -1,
|
||||||
|
"max-video-preview": -1,
|
||||||
|
googleBot: "index, follow"
|
||||||
|
},
|
||||||
|
alternates: {
|
||||||
|
types: {
|
||||||
|
"application/rss+xml": "https://dminhvu.com/rss.xml"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
applicationName: "Blog | Minh Vu",
|
||||||
|
appleWebApp: {
|
||||||
|
title: "Blog | Minh Vu",
|
||||||
|
statusBarStyle: "default",
|
||||||
|
capable: true
|
||||||
|
},
|
||||||
|
verification: {
|
||||||
|
google: "YOUR_DATA",
|
||||||
|
yandex: ["YOUR_DATA"],
|
||||||
|
other: {
|
||||||
|
"msvalidate.01": ["YOUR_DATA"],
|
||||||
|
"facebook-domain-verification": ["YOUR_DATA"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
icons: {
|
||||||
|
icon: [
|
||||||
|
{
|
||||||
|
url: "/favicon.ico",
|
||||||
|
type: "image/x-icon"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
url: "/favicon-16x16.png",
|
||||||
|
sizes: "16x16",
|
||||||
|
type: "image/png"
|
||||||
|
}
|
||||||
|
// add favicon-32x32.png, favicon-96x96.png, android-chrome-192x192.png
|
||||||
|
],
|
||||||
|
shortcut: [
|
||||||
|
{
|
||||||
|
url: "/favicon.ico",
|
||||||
|
type: "image/x-icon"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
apple: [
|
||||||
|
{
|
||||||
|
url: "/apple-icon-57x57.png",
|
||||||
|
sizes: "57x57",
|
||||||
|
type: "image/png"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
url: "/apple-icon-60x60.png",
|
||||||
|
sizes: "60x60",
|
||||||
|
type: "image/png"
|
||||||
|
}
|
||||||
|
// add apple-icon-72x72.png, apple-icon-76x76.png, apple-icon-114x114.png, apple-icon-120x120.png, apple-icon-144x144.png, apple-icon-152x152.png, apple-icon-180x180.png
|
||||||
|
]
|
||||||
|
}
|
||||||
|
};
|
||||||
|
And like this for any page.tsx file:
|
||||||
|
import { Metadata } from "next";
|
||||||
|
|
||||||
|
export const metadata: Metadata = {
|
||||||
|
title: "Elastic Stack, Next.js, Python, JavaScript Tutorials | dminhvu",
|
||||||
|
description:
|
||||||
|
"dminhvu.com - Programming blog for everyone to learn Elastic Stack, Next.js, Python, JavaScript, React, Machine Learning, Data Science, and more.",
|
||||||
|
keywords: [
|
||||||
|
"elastic",
|
||||||
|
"python",
|
||||||
|
"javascript",
|
||||||
|
"react",
|
||||||
|
"machine learning",
|
||||||
|
"data science"
|
||||||
|
],
|
||||||
|
openGraph: {
|
||||||
|
url: "https://dminhvu.com",
|
||||||
|
type: "website",
|
||||||
|
title: "Elastic Stack, Next.js, Python, JavaScript Tutorials | dminhvu",
|
||||||
|
description:
|
||||||
|
"dminhvu.com - Programming blog for everyone to learn Elastic Stack, Next.js, Python, JavaScript, React, Machine Learning, Data Science, and more.",
|
||||||
|
images: [
|
||||||
|
{
|
||||||
|
url: "https://dminhvu.com/images/home/thumbnail.png",
|
||||||
|
width: 1200,
|
||||||
|
height: 630,
|
||||||
|
alt: "dminhvu"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
twitter: {
|
||||||
|
card: "summary_large_image",
|
||||||
|
title: "Elastic Stack, Next.js, Python, JavaScript Tutorials | dminhvu",
|
||||||
|
description:
|
||||||
|
"dminhvu.com - Programming blog for everyone to learn Elastic Stack, Next.js, Python, JavaScript, React, Machine Learning, Data Science, and more.",
|
||||||
|
creator: "@dminhvu02",
|
||||||
|
site: "@dminhvu02",
|
||||||
|
images: [
|
||||||
|
{
|
||||||
|
url: "https://dminhvu.com/images/home/thumbnail.png",
|
||||||
|
width: 1200,
|
||||||
|
height: 630,
|
||||||
|
alt: "dminhvu"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
alternates: {
|
||||||
|
canonical: "https://dminhvu.com"
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Note that the charSet and viewport are automatically added by Next.js App Router, so you don't need to define them.
|
||||||
|
|
||||||
|
For applications using the app router, dynamic metadata can be defined by using the generateMetadata function, this is useful when you have dynamic pages like [slug]/page.tsx, or [id]/page.tsx:
|
||||||
|
|
||||||
|
import type { Metadata, ResolvingMetadata } from "next";
|
||||||
|
|
||||||
|
type Params = {
|
||||||
|
slug: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
params: Params;
|
||||||
|
searchParams: { [key: string]: string | string[] | undefined };
|
||||||
|
};
|
||||||
|
|
||||||
|
export async function generateMetadata(
|
||||||
|
{ params, searchParams }: Props,
|
||||||
|
parent: ResolvingMetadata
|
||||||
|
): Promise<Metadata> {
|
||||||
|
const { slug } = params;
|
||||||
|
|
||||||
|
const post: Post = await fetch("YOUR_ENDPOINT", {
|
||||||
|
method: "GET",
|
||||||
|
next: {
|
||||||
|
revalidate: 60 * 60 * 24
|
||||||
|
}
|
||||||
|
}).then((res) => res.json());
|
||||||
|
|
||||||
|
return {
|
||||||
|
title: "{post.title} | dminhvu",
|
||||||
|
authors: [
|
||||||
|
{
|
||||||
|
name: post.author || "Minh Vu"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
description: post.description,
|
||||||
|
keywords: post.keywords,
|
||||||
|
openGraph: {
|
||||||
|
title: "{post.title} | dminhvu",
|
||||||
|
description: post.description,
|
||||||
|
type: "article",
|
||||||
|
url: "https://dminhvu.com/{post.slug}",
|
||||||
|
publishedTime: post.created_at,
|
||||||
|
modifiedTime: post.modified_at,
|
||||||
|
authors: ["https://dminhvu.com/about"],
|
||||||
|
tags: post.categories,
|
||||||
|
images: [
|
||||||
|
{
|
||||||
|
url: "https://ik.imagekit.io/dminhvu/assets/{post.slug}/thumbnail.png?tr=f-png",
|
||||||
|
width: 1024,
|
||||||
|
height: 576,
|
||||||
|
alt: post.title,
|
||||||
|
type: "image/png"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
twitter: {
|
||||||
|
card: "summary_large_image",
|
||||||
|
site: "@dminhvu02",
|
||||||
|
creator: "@dminhvu02",
|
||||||
|
title: "{post.title} | dminhvu",
|
||||||
|
description: post.description,
|
||||||
|
images: [
|
||||||
|
{
|
||||||
|
url: "https://ik.imagekit.io/dminhvu/assets/{post.slug}/thumbnail.png?tr=f-png",
|
||||||
|
width: 1024,
|
||||||
|
height: 576,
|
||||||
|
alt: post.title
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
alternates: {
|
||||||
|
canonical: "https://dminhvu.com/{post.slug}"
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
2. JSON-LD Schema
|
||||||
|
|
||||||
|
JSON-LD is a format for structured data that can be used by search engines to understand your content. For example, you can use it to describe a person, an event, an organization, a movie, a book, a recipe, and many other types of entities.
|
||||||
|
|
||||||
|
Our current recommendation for JSON-LD is to render structured data as a <script> tag in your layout.js or page.js components. For example:
|
||||||
|
export default async function Page({ params }) {
|
||||||
|
const { id } = await params
|
||||||
|
const product = await getProduct(id)
|
||||||
|
|
||||||
|
const jsonLd = {
|
||||||
|
'@context': 'https://schema.org',
|
||||||
|
'@type': 'Product',
|
||||||
|
name: product.name,
|
||||||
|
image: product.image,
|
||||||
|
description: product.description,
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<section>
|
||||||
|
{/* Add JSON-LD to your page */}
|
||||||
|
<script
|
||||||
|
type="application/ld+json"
|
||||||
|
dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }}
|
||||||
|
/>
|
||||||
|
{/* ... */}
|
||||||
|
</section>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
You can type your JSON-LD with TypeScript using community packages like schema-dts:
|
||||||
|
|
||||||
|
|
||||||
|
import { Product, WithContext } from 'schema-dts'
|
||||||
|
|
||||||
|
const jsonLd: WithContext<Product> = {
|
||||||
|
'@context': 'https://schema.org',
|
||||||
|
'@type': 'Product',
|
||||||
|
name: 'Next.js Sticker',
|
||||||
|
image: 'https://nextjs.org/imgs/sticker.png',
|
||||||
|
description: 'Dynamic at the speed of static.',
|
||||||
|
}
|
||||||
|
3. Sitemap
|
||||||
|
Your website should provide a sitemap so that search engines can easily crawl and index your pages.
|
||||||
|
|
||||||
|
Generate Sitemap for Next.js Pages Router
|
||||||
|
For Next.js Pages Router, you can use next-sitemap to generate a sitemap for your Next.js website after building.
|
||||||
|
|
||||||
|
For example, running the following command will install next-sitemap and generate a sitemap for this blog:
|
||||||
|
|
||||||
|
|
||||||
|
npm install next-sitemap
|
||||||
|
npx next-sitemap
|
||||||
|
A sitemap will be generated at public/sitemap.xml:
|
||||||
|
|
||||||
|
public/sitemap.xml
|
||||||
|
|
||||||
|
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:news="http://www.google.com/schemas/sitemap-news/0.9" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:mobile="http://www.google.com/schemas/sitemap-mobile/1.0" xmlns:image="http://www.google.com/schemas/sitemap-image/1.1" xmlns:video="http://www.google.com/schemas/sitemap-video/1.1">
|
||||||
|
<url>
|
||||||
|
<loc>https://dminhvu.com</loc>
|
||||||
|
<lastmod>2024-01-11T02:03:09.613Z</lastmod>
|
||||||
|
<changefreq>daily</changefreq>
|
||||||
|
<priority>0.7</priority>
|
||||||
|
</url>
|
||||||
|
<!-- other pages -->
|
||||||
|
</urlset>
|
||||||
|
Please visit the next-sitemap page for more information.
|
||||||
|
|
||||||
|
Generate Sitemap for Next.js App Router
|
||||||
|
For Next.js App Router, you can define the sitemap.ts file at app/sitemap.ts:
|
||||||
|
|
||||||
|
app/sitemap.ts
|
||||||
|
|
||||||
|
import {
|
||||||
|
getAllCategories,
|
||||||
|
getAllPostSlugsWithModifyTime
|
||||||
|
} from "@/utils/getData";
|
||||||
|
import { MetadataRoute } from "next";
|
||||||
|
|
||||||
|
export default async function sitemap(): Promise<MetadataRoute.Sitemap> {
|
||||||
|
const defaultPages = [
|
||||||
|
{
|
||||||
|
url: "https://dminhvu.com",
|
||||||
|
lastModified: new Date(),
|
||||||
|
changeFrequency: "daily",
|
||||||
|
priority: 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
url: "https://dminhvu.com/about",
|
||||||
|
lastModified: new Date(),
|
||||||
|
changeFrequency: "monthly",
|
||||||
|
priority: 0.9
|
||||||
|
},
|
||||||
|
{
|
||||||
|
url: "https://dminhvu.com/contact",
|
||||||
|
lastModified: new Date(),
|
||||||
|
changeFrequency: "monthly",
|
||||||
|
priority: 0.9
|
||||||
|
}
|
||||||
|
// other pages
|
||||||
|
];
|
||||||
|
|
||||||
|
const postSlugs = await getAllPostSlugsWithModifyTime();
|
||||||
|
const categorySlugs = await getAllCategories();
|
||||||
|
|
||||||
|
const sitemap = [
|
||||||
|
...defaultPages,
|
||||||
|
...postSlugs.map((e: any) => ({
|
||||||
|
url: "https://dminhvu.com/{e.slug}",
|
||||||
|
lastModified: e.modified_at,
|
||||||
|
changeFrequency: "daily",
|
||||||
|
priority: 0.8
|
||||||
|
})),
|
||||||
|
...categorySlugs.map((e: any) => ({
|
||||||
|
url: "https://dminhvu.com/category/{e}",
|
||||||
|
lastModified: new Date(),
|
||||||
|
changeFrequency: "daily",
|
||||||
|
priority: 0.7
|
||||||
|
}))
|
||||||
|
];
|
||||||
|
|
||||||
|
return sitemap;
|
||||||
|
}
|
||||||
|
With this sitemap.ts file created, you can access the sitemap at https://dminhvu.com/sitemap.xml.
|
||||||
|
|
||||||
|
|
||||||
|
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
|
||||||
|
<url>
|
||||||
|
<loc>https://dminhvu.com</loc>
|
||||||
|
<lastmod>2024-01-11T02:03:09.613Z</lastmod>
|
||||||
|
<changefreq>daily</changefreq>
|
||||||
|
<priority>0.7</priority>
|
||||||
|
</url>
|
||||||
|
<!-- other pages -->
|
||||||
|
</urlset>
|
||||||
|
4. robots.txt
|
||||||
|
A robots.txt file should be added to tell search engines which pages to crawl and which pages to ignore.
|
||||||
|
|
||||||
|
robots.txt for Next.js Pages Router
|
||||||
|
For Next.js Pages Router, you can create a robots.txt file at public/robots.txt:
|
||||||
|
|
||||||
|
public/robots.txt
|
||||||
|
|
||||||
|
User-agent: *
|
||||||
|
Disallow:
|
||||||
|
Sitemap: https://dminhvu.com/sitemap.xml
|
||||||
|
You can prevent the search engine from crawling a page (usually search result pages, noindex pages, etc.) by adding the following line:
|
||||||
|
|
||||||
|
public/robots.txt
|
||||||
|
|
||||||
|
User-agent: *
|
||||||
|
Disallow: /search?q=
|
||||||
|
Disallow: /admin
|
||||||
|
robots.txt for Next.js App Router
|
||||||
|
For Next.js App Router, you don't need to manually define a robots.txt file. Instead, you can define the robots.ts file at app/robots.ts:
|
||||||
|
|
||||||
|
app/robots.ts
|
||||||
|
|
||||||
|
import { MetadataRoute } from "next";
|
||||||
|
|
||||||
|
export default function robots(): MetadataRoute.Robots {
|
||||||
|
return {
|
||||||
|
rules: {
|
||||||
|
userAgent: "*",
|
||||||
|
allow: ["/"],
|
||||||
|
disallow: ["/search?q=", "/admin/"]
|
||||||
|
},
|
||||||
|
sitemap: ["https://dminhvu.com/sitemap.xml"]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
With this robots.ts file created, you can access the robots.txt file at https://dminhvu.com/robots.txt.
|
||||||
|
|
||||||
|
|
||||||
|
User-agent: *
|
||||||
|
Allow: /
|
||||||
|
Disallow: /search?q=
|
||||||
|
Disallow: /admin
|
||||||
|
|
||||||
|
Sitemap: https://dminhvu.com/sitemap.xml
|
||||||
|
5. Link tags
|
||||||
|
Link Tags for Next.js Pages Router
|
||||||
|
For example, the current page has the following link tags if I use the Pages Router:
|
||||||
|
|
||||||
|
pages/_app.tsx
|
||||||
|
|
||||||
|
import Head from "next/head";
|
||||||
|
|
||||||
|
export default function Page() {
|
||||||
|
return (
|
||||||
|
<Head>
|
||||||
|
{/* other parts */}
|
||||||
|
<link
|
||||||
|
rel="alternate"
|
||||||
|
type="application/rss+xml"
|
||||||
|
href="https://dminhvu.com/rss.xml"
|
||||||
|
/>
|
||||||
|
<link rel="icon" href="/favicon.ico" type="image/x-icon" />
|
||||||
|
<link rel="apple-touch-icon" sizes="57x57" href="/apple-icon-57x57.png" />
|
||||||
|
<link rel="apple-touch-icon" sizes="60x60" href="/apple-icon-60x60.png" />
|
||||||
|
{/* add apple-touch-icon-72x72.png, apple-touch-icon-76x76.png, apple-touch-icon-114x114.png, apple-touch-icon-120x120.png, apple-touch-icon-144x144.png, apple-touch-icon-152x152.png, apple-touch-icon-180x180.png */}
|
||||||
|
<link
|
||||||
|
rel="icon"
|
||||||
|
type="image/png"
|
||||||
|
href="/favicon-16x16.png"
|
||||||
|
sizes="16x16"
|
||||||
|
/>
|
||||||
|
{/* add favicon-32x32.png, favicon-96x96.png, android-chrome-192x192.png */}
|
||||||
|
</Head>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
pages/[slug].tsx
|
||||||
|
|
||||||
|
import Head from "next/head";
|
||||||
|
|
||||||
|
export default function Page() {
|
||||||
|
return (
|
||||||
|
<Head>
|
||||||
|
{/* other parts */}
|
||||||
|
<link rel="canonical" href="https://dminhvu.com/nextjs-seo" />
|
||||||
|
</Head>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Link Tags for Next.js App Router
|
||||||
|
For Next.js App Router, the link tags can be defined using the export const metadata or generateMetadata similar to the meta tags section.
|
||||||
|
|
||||||
|
The code below is exactly the same as the meta tags for Next.js App Router section above.
|
||||||
|
|
||||||
|
app/layout.tsx
|
||||||
|
|
||||||
|
export const metadata: Metadata = {
|
||||||
|
// other parts
|
||||||
|
alternates: {
|
||||||
|
types: {
|
||||||
|
"application/rss+xml": "https://dminhvu.com/rss.xml"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
icons: {
|
||||||
|
icon: [
|
||||||
|
{
|
||||||
|
url: "/favicon.ico",
|
||||||
|
type: "image/x-icon"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
url: "/favicon-16x16.png",
|
||||||
|
sizes: "16x16",
|
||||||
|
type: "image/png"
|
||||||
|
}
|
||||||
|
// add favicon-32x32.png, favicon-96x96.png, android-chrome-192x192.png
|
||||||
|
],
|
||||||
|
shortcut: [
|
||||||
|
{
|
||||||
|
url: "/favicon.ico",
|
||||||
|
type: "image/x-icon"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
apple: [
|
||||||
|
{
|
||||||
|
url: "/apple-icon-57x57.png",
|
||||||
|
sizes: "57x57",
|
||||||
|
type: "image/png"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
url: "/apple-icon-60x60.png",
|
||||||
|
sizes: "60x60",
|
||||||
|
type: "image/png"
|
||||||
|
}
|
||||||
|
// add apple-icon-72x72.png, apple-icon-76x76.png, apple-icon-114x114.png, apple-icon-120x120.png, apple-icon-144x144.png, apple-icon-152x152.png, apple-icon-180x180.png
|
||||||
|
]
|
||||||
|
}
|
||||||
|
};
|
||||||
|
app/page.tsx
|
||||||
|
|
||||||
|
export const metadata: Metadata = {
|
||||||
|
// other parts
|
||||||
|
alternates: {
|
||||||
|
canonical: "https://dminhvu.com"
|
||||||
|
}
|
||||||
|
};
|
||||||
|
6. Script optimization
|
||||||
|
Script Optimization for General Scripts
|
||||||
|
Next.js provides a built-in component called <Script> to add external scripts to your website.
|
||||||
|
|
||||||
|
For example, you can add Google Analytics to your website by adding the following script tag:
|
||||||
|
|
||||||
|
pages/_app.tsx
|
||||||
|
|
||||||
|
import Head from "next/head";
|
||||||
|
import Script from "next/script";
|
||||||
|
|
||||||
|
export default function Page() {
|
||||||
|
return (
|
||||||
|
<Head>
|
||||||
|
{/* other parts */}
|
||||||
|
{process.env.NODE_ENV === "production" && (
|
||||||
|
<>
|
||||||
|
<Script async strategy="afterInteractive" id="analytics">
|
||||||
|
{'
|
||||||
|
window.dataLayer = window.dataLayer || [];
|
||||||
|
function gtag(){dataLayer.push(arguments);}
|
||||||
|
gtag('js', new Date());
|
||||||
|
gtag('config', 'G-XXXXXXXXXX');
|
||||||
|
'}
|
||||||
|
</Script>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</Head>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Script Optimization for Common Third-Party Integrations
|
||||||
|
Next.js App Router introduces a new library called @next/third-parties for:
|
||||||
|
|
||||||
|
Google Tag Manager
|
||||||
|
Google Analytics
|
||||||
|
Google Maps Embed
|
||||||
|
YouTube Embed
|
||||||
|
To use the @next/third-parties library, you need to install it:
|
||||||
|
|
||||||
|
|
||||||
|
npm install @next/third-parties
|
||||||
|
Then, you can add the following code to your app/layout.tsx:
|
||||||
|
|
||||||
|
app/layout.tsx
|
||||||
|
|
||||||
|
import { GoogleTagManager } from "@next/third-parties/google";
|
||||||
|
import { GoogleAnalytics } from "@next/third-parties/google";
|
||||||
|
import Head from "next/head";
|
||||||
|
|
||||||
|
export default function Page() {
|
||||||
|
return (
|
||||||
|
<html lang="en" className="scroll-smooth" suppressHydrationWarning>
|
||||||
|
{process.env.NODE_ENV === "production" && (
|
||||||
|
<>
|
||||||
|
<GoogleAnalytics gaId="G-XXXXXXXXXX" />
|
||||||
|
{/* other scripts */}
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
{/* other parts */}
|
||||||
|
</html>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Please note that you don't need to include both GoogleTagManager and GoogleAnalytics if you only use one of them.
|
||||||
|
7. Image optimization
|
||||||
|
Image Optimization
|
||||||
|
This part can be applied to both Pages Router and App Router.
|
||||||
|
|
||||||
|
Image optimization is also an important part of SEO as it helps your website load faster.
|
||||||
|
|
||||||
|
Faster image rendering speed will contribute to the Google PageSpeed score, which can improve user experience and SEO.
|
||||||
|
|
||||||
|
You can use next/image to optimize images in your Next.js website.
|
||||||
|
|
||||||
|
For example, the following code will optimize this post thumbnail:
|
||||||
|
|
||||||
|
|
||||||
|
import Image from "next/image";
|
||||||
|
|
||||||
|
export default function Page() {
|
||||||
|
return (
|
||||||
|
<Image
|
||||||
|
src="https://ik.imagekit.io/dminhvu/assets/nextjs-seo/thumbnail.png?tr=f-webp"
|
||||||
|
alt="Next.js SEO"
|
||||||
|
width={1200}
|
||||||
|
height={630}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Remember to use a CDN to serve your media (images, videos, etc.) to improve the loading speed.
|
||||||
|
|
||||||
|
For the image format, use WebP if possible because it has a smaller size than PNG and JPEG.
|
||||||
|
`,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}));
|
||||||
|
|
||||||
|
server.tool(
|
||||||
|
"runDebuggerMode",
|
||||||
|
"Run debugger mode to debug an issue in our application",
|
||||||
|
async () => ({
|
||||||
|
content: [
|
||||||
|
{
|
||||||
|
type: "text",
|
||||||
|
text: `
|
||||||
|
Please follow this exact sequence to debug an issue in our application:
|
||||||
|
|
||||||
|
1. Reflect on 5-7 different possible sources of the problem
|
||||||
|
2. Distill those down to 1-2 most likely sources
|
||||||
|
3. Add additional logs to validate your assumptions and track the transformation of data structures throughout the application control flow before we move onto implementing the actual code fix
|
||||||
|
4. Use the "getConsoleLogs", "getConsoleErrors", "getNetworkLogs" & "getNetworkErrors" tools to obtain any newly added web browser logs
|
||||||
|
5. Obtain the server logs as well if accessible - otherwise, ask me to copy/paste them into the chat
|
||||||
|
6. Deeply reflect on what could be wrong + produce a comprehensive analysis of the issue
|
||||||
|
7. Suggest additional logs if the issue persists or if the source is not yet clear
|
||||||
|
8. Once a fix is implemented, ask for approval to remove the previously added logs
|
||||||
|
`,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
server.tool(
|
||||||
|
"runAuditMode",
|
||||||
|
"Run audit mode to optimize our application for SEO, accessibility and performance",
|
||||||
|
async () => ({
|
||||||
|
content: [
|
||||||
|
{
|
||||||
|
type: "text",
|
||||||
|
text: `
|
||||||
|
I want you to enter "Audit Mode". Use the following MCP tools one after the other in this exact sequence:
|
||||||
|
|
||||||
|
1. runAccessibilityAudit
|
||||||
|
2. runPerformanceAudit
|
||||||
|
3. runBestPracticesAudit
|
||||||
|
4. runSEOAudit
|
||||||
|
5. runNextJSAudit (only if our application is ACTUALLY using NextJS)
|
||||||
|
|
||||||
|
After running all of these tools, return back a comprehensive analysis of the audit results.
|
||||||
|
|
||||||
|
Do NOT use runNextJSAudit tool unless you see that our application is ACTUALLY using NextJS.
|
||||||
|
|
||||||
|
DO NOT use the takeScreenshot tool EVER during audit mode. ONLY use it if I specifically ask you to take a screenshot of something.
|
||||||
|
|
||||||
|
DO NOT check console or network logs to get started - your main priority is to run the audits in the sequence defined above.
|
||||||
|
|
||||||
|
After returning an in-depth analysis, scan through my code and identify various files/parts of my codebase that we want to modify/improve based on the results of our audits.
|
||||||
|
|
||||||
|
After identifying what changes may be needed, do NOT make the actual changes. Instead, return back a comprehensive, step-by-step plan to address all of these changes and ask for approval to execute this plan. If feedback is received, make a new plan and ask for approval again. If approved, execute the ENTIRE plan and after all phases/steps are complete, re-run the auditing tools in the same 4 step sequence again before returning back another analysis for additional changes potentially needed.
|
||||||
|
|
||||||
|
Keep repeating / iterating through this process with the four tools until our application is as optimized as possible for SEO, accessibility and performance.
|
||||||
|
|
||||||
|
`,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
// Add tool for Best Practices audits, launches a headless browser instance
|
// Add tool for Best Practices audits, launches a headless browser instance
|
||||||
server.tool(
|
server.tool(
|
||||||
"runBestPracticesAudit",
|
"runBestPracticesAudit",
|
||||||
|
126
browser-tools-mcp/package-lock.json
generated
126
browser-tools-mcp/package-lock.json
generated
@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "@agentdeskai/browser-tools-mcp",
|
"name": "@agentdeskai/browser-tools-mcp",
|
||||||
"version": "1.0.11",
|
"version": "1.1.1",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "@agentdeskai/browser-tools-mcp",
|
"name": "@agentdeskai/browser-tools-mcp",
|
||||||
"version": "1.0.11",
|
"version": "1.1.1",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@modelcontextprotocol/sdk": "^1.4.1",
|
"@modelcontextprotocol/sdk": "^1.4.1",
|
||||||
@ -14,6 +14,7 @@
|
|||||||
"cors": "^2.8.5",
|
"cors": "^2.8.5",
|
||||||
"express": "^4.21.2",
|
"express": "^4.21.2",
|
||||||
"llm-cost": "^1.0.5",
|
"llm-cost": "^1.0.5",
|
||||||
|
"node-fetch": "^2.7.0",
|
||||||
"ws": "^8.18.0"
|
"ws": "^8.18.0"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
@ -24,6 +25,7 @@
|
|||||||
"@types/cors": "^2.8.17",
|
"@types/cors": "^2.8.17",
|
||||||
"@types/express": "^5.0.0",
|
"@types/express": "^5.0.0",
|
||||||
"@types/node": "^22.13.1",
|
"@types/node": "^22.13.1",
|
||||||
|
"@types/node-fetch": "^2.6.11",
|
||||||
"@types/ws": "^8.5.14",
|
"@types/ws": "^8.5.14",
|
||||||
"typescript": "^5.7.3"
|
"typescript": "^5.7.3"
|
||||||
}
|
}
|
||||||
@ -116,6 +118,16 @@
|
|||||||
"undici-types": "~6.20.0"
|
"undici-types": "~6.20.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/node-fetch": {
|
||||||
|
"version": "2.6.12",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.12.tgz",
|
||||||
|
"integrity": "sha512-8nneRWKCg3rMtF69nLQJnOYUcbafYeFSjqkw3jCRLsqkWFlHaoQrr5mXmofFGOx3DKn7UfmBMyov8ySvLRVldA==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@types/node": "*",
|
||||||
|
"form-data": "^4.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@types/qs": {
|
"node_modules/@types/qs": {
|
||||||
"version": "6.9.18",
|
"version": "6.9.18",
|
||||||
"resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.18.tgz",
|
"resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.18.tgz",
|
||||||
@ -175,6 +187,12 @@
|
|||||||
"resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
|
||||||
"integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg=="
|
"integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg=="
|
||||||
},
|
},
|
||||||
|
"node_modules/asynckit": {
|
||||||
|
"version": "0.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
|
||||||
|
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"node_modules/body-parser": {
|
"node_modules/body-parser": {
|
||||||
"version": "1.20.3",
|
"version": "1.20.3",
|
||||||
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz",
|
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz",
|
||||||
@ -247,6 +265,18 @@
|
|||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/combined-stream": {
|
||||||
|
"version": "1.0.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
|
||||||
|
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"delayed-stream": "~1.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.8"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/content-disposition": {
|
"node_modules/content-disposition": {
|
||||||
"version": "0.5.4",
|
"version": "0.5.4",
|
||||||
"resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz",
|
"resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz",
|
||||||
@ -299,6 +329,15 @@
|
|||||||
"ms": "2.0.0"
|
"ms": "2.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/delayed-stream": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
|
||||||
|
"dev": true,
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.4.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/depd": {
|
"node_modules/depd": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
|
||||||
@ -369,6 +408,21 @@
|
|||||||
"node": ">= 0.4"
|
"node": ">= 0.4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/es-set-tostringtag": {
|
||||||
|
"version": "2.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz",
|
||||||
|
"integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"es-errors": "^1.3.0",
|
||||||
|
"get-intrinsic": "^1.2.6",
|
||||||
|
"has-tostringtag": "^1.0.2",
|
||||||
|
"hasown": "^2.0.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/escape-html": {
|
"node_modules/escape-html": {
|
||||||
"version": "1.0.3",
|
"version": "1.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
|
||||||
@ -463,6 +517,21 @@
|
|||||||
"node": ">= 0.8"
|
"node": ">= 0.8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/form-data": {
|
||||||
|
"version": "4.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.2.tgz",
|
||||||
|
"integrity": "sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"asynckit": "^0.4.0",
|
||||||
|
"combined-stream": "^1.0.8",
|
||||||
|
"es-set-tostringtag": "^2.1.0",
|
||||||
|
"mime-types": "^2.1.12"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 6"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/forwarded": {
|
"node_modules/forwarded": {
|
||||||
"version": "0.2.0",
|
"version": "0.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
|
||||||
@ -544,6 +613,21 @@
|
|||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/has-tostringtag": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"has-symbols": "^1.0.3"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/hasown": {
|
"node_modules/hasown": {
|
||||||
"version": "2.0.2",
|
"version": "2.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
|
||||||
@ -677,6 +761,25 @@
|
|||||||
"node": ">= 0.6"
|
"node": ">= 0.6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/node-fetch": {
|
||||||
|
"version": "2.7.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz",
|
||||||
|
"integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==",
|
||||||
|
"dependencies": {
|
||||||
|
"whatwg-url": "^5.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": "4.x || >=6.0.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"encoding": "^0.1.0"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"encoding": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/object-assign": {
|
"node_modules/object-assign": {
|
||||||
"version": "4.1.1",
|
"version": "4.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
|
||||||
@ -947,6 +1050,11 @@
|
|||||||
"node": ">=0.6"
|
"node": ">=0.6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/tr46": {
|
||||||
|
"version": "0.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
|
||||||
|
"integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw=="
|
||||||
|
},
|
||||||
"node_modules/type-is": {
|
"node_modules/type-is": {
|
||||||
"version": "1.6.18",
|
"version": "1.6.18",
|
||||||
"resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
|
"resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
|
||||||
@ -1002,6 +1110,20 @@
|
|||||||
"node": ">= 0.8"
|
"node": ">= 0.8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/webidl-conversions": {
|
||||||
|
"version": "3.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
|
||||||
|
"integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="
|
||||||
|
},
|
||||||
|
"node_modules/whatwg-url": {
|
||||||
|
"version": "5.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
|
||||||
|
"integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==",
|
||||||
|
"dependencies": {
|
||||||
|
"tr46": "~0.0.3",
|
||||||
|
"webidl-conversions": "^3.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/ws": {
|
"node_modules/ws": {
|
||||||
"version": "8.18.0",
|
"version": "8.18.0",
|
||||||
"resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz",
|
"resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user