### Run Production App Source: https://github.com/code-forge-io/seo-tools/blob/main/test-apps/remix-vite/README.md Starts the production-ready Remix application server. This command is used after building the app for deployment. ```shell npm start ``` -------------------------------- ### Install @forge42/seo-tools Source: https://github.com/code-forge-io/seo-tools/blob/main/README.md Install the package using npm. This command adds the SEO tools package to your project dependencies. ```bash npm install @forge42/seo-tools ``` -------------------------------- ### Run Vite Development Server Source: https://github.com/code-forge-io/seo-tools/blob/main/test-apps/remix-vite/README.md Starts the Vite development server for local development. Use this command to see your changes in real-time. ```shell npm run dev ``` -------------------------------- ### Build Production App Source: https://github.com/code-forge-io/seo-tools/blob/main/test-apps/remix-vite/README.md Builds the Remix application for production deployment. This command generates optimized assets and server code. ```shell npm run build ``` -------------------------------- ### Generate Basic Sitemap Source: https://github.com/code-forge-io/seo-tools/blob/main/README.md Generates a sitemap for all Remix routes, ignoring root, sitemap, and robots.txt by default. Ensure the domain is correctly set. ```typescript // routes/sitemap[.]xml.ts import { generateRemixSitemap } from "@forge42/seo-tools/remix/sitemap" export const loader = async() => { const sitemap = await generateRemixSitemap({ domain: "https://example.com", }) return new Response(sitemap, { headers: { "Content-Type": "application/xml", }, }) } ``` -------------------------------- ### Handle Dynamic Routes with Custom Data Source: https://github.com/code-forge-io/seo-tools/blob/main/README.md Generates a sitemap with dynamic entries based on query parameters and custom data. The `handle.sitemap` function allows for custom URL generation and alternate language links. ```typescript // routes/sitemap[.]xml.ts import { generateRemixSitemap } from "@forge42/seo-tools/remix/sitemap" export type SitemapData = { lang: Language } export const loader = async ({ request }) => { const sitemap = await generateRemixSitemap({ // This gets passed to every handler sitemapData: { "lang": request.query.get("lng") as Language } }) return new Response(sitemap, { headers: { "Content-Type": "application/xml", }, }) } // routes/index.tsx import type { SitemapHandle } from "@forge42/seo-tools/remix/sitemap"; import type { SitemapData } from "~/routes/sitemap[.]xml"; // This utility trumps the default url generation so it's important to at least return the current route from here. export const handle: SitemapHandle = { sitemap: async (domain, url, { lang }) => { const alternateLanguages = supportedLanguages.filter((language) => language !== lang) return [ { route: `${domain}${url}?lng=${lang}`, changefreq: "monthly", priority: 1.0, // Create alternate links for each language alternateLinks: alternateLanguages.map((lang) => ({ hreflang: lang, href: `${domain}${url}?lng=${lang}`, })), }, ] }, } ``` -------------------------------- ### Import Canonical Link Generator Source: https://github.com/code-forge-io/seo-tools/blob/main/README.md Import the specific module for generating canonical links. This ensures only the necessary code is included in your bundle. ```javascript import { generateCanonicalLinks } from '@forge42/seo-tools/canonical'; ``` -------------------------------- ### Generate Dynamic Sitemaps and Index Source: https://github.com/code-forge-io/seo-tools/blob/main/README.md Creates language-specific sitemaps and a sitemap index. The `urlTransformer` can modify URLs, and `ignore` can exclude specific routes. The robots.txt generation includes sitemap links and respects deployment environment. ```typescript // routes/sitemap.$lang[.]xml.ts import type { LoaderFunctionArgs } from "@remix-run/node" import { generateRemixSitemap } from "@forge42/seo-tools/remix/sitemap" // Optionally import routes from the remix build to be consumed by the sitemap generator if the default one throws an error import { routes } from "virtual:remix/server-build"; export const loader = async ({ request, params }: LoaderFunctionArgs) => { const domain = `${new URL(request.url).origin}` const sitemap = await generateRemixSitemap({ // Domain to append urls to domain, routes, // Ignores all dashboard routes ignore: ["/status"], // Transforms the url before adding it to the sitemap urlTransformer: (url) => `${url}?lng=${params.lang}`, sitemapData: { lang: params.lang, }, }) return new Response(sitemap, { headers: { "Content-Type": "application/xml; charset=utf-8", }, }) } // routes/sitemap-index[.]xml.ts import type { LoaderFunctionArgs } from "@remix-run/node" import { generateSitemapIndex } from "@forge42/seo-tools/sitemap" export const loader = async ({ request }: LoaderFunctionArgs) => { const domain = new URL(request.url).origin const sitemaps = generateSitemapIndex([ { url: `${domain}/sitemap/en.xml`, lastmod: "2024-07-17", }, { url: `${domain}/sitemap/bs.xml`, lastmod: "2024-07-17", }, ]) return new Response(sitemaps, { headers: { "Content-Type": "application/xml; charset=utf-8", }, }) } // routes/robots[.]txt.ts import type { LoaderFunctionArgs } from "@remix-run/node" import { generateRobotsTxt } from "@forge42/seo-tools/robots" export async function loader({ request }: LoaderFunctionArgs) { const isProductionDeployment = process.env.DEPLOYMENT_ENV === "production" const domain = new URL(request.url).origin const robotsTxt = generateRobotsTxt([ { userAgent: "*", [isProductionDeployment ? "allow": "disallow"]:[ "/"], sitemap: [`${domain}/sitemap-index.xml`], }, ]) return new Response(robotsTxt, { headers: { "Content-Type": "text/plain", }, }) } ``` -------------------------------- ### Generate Sitemap.xml Source: https://github.com/code-forge-io/seo-tools/blob/main/README.md Generates a sitemap.xml file content for a given domain, allowing exclusion of specific routes and defining custom routes with metadata. Useful for helping search engines discover all pages on your site. ```typescript import { generateSitemap } from '@forge42/seo-tools/sitemap'; const sitemap = generateSitemap( { domain: "https://example.com", // Defines the routes you want to exclude from the sitemap (useful if routes are dynamic or auto-generated) ignore: ["/dashboard*"] // Defines the routes you want to include in the sitemap routes: [ { url: "/", lastmod: "2020-02-02", changefreq: "monthly", priority: 0.8 }, { url: "/about", lastmod: "2020-02-02", changefreq: "monthly", priority: 0.8 }, { url: "/contact", lastmod: "2020-02-02", changefreq: "monthly", priority: 0.8 } ], // This is a transformer that allows you to generate the url you need transformer: ({ url, domain }) => `${domain}${url}` } ); console.log(sitemap); ``` -------------------------------- ### Generate Sitemap Index Source: https://github.com/code-forge-io/seo-tools/blob/main/README.md Generates an XML sitemap index file. This is useful for organizing multiple sitemaps on a website. ```typescript import { generateSitemapIndex } from '@forge42/seo-tools/sitemap'; const sitemapIndex = generateSitemapIndex([ { url: 'https://example.com/sitemap1.xml', lastmod: '2022-01-01' }, { url: 'https://example.com/sitemap2.xml', lastmod: '2022-01-01' } ] ); console.log(sitemapIndex); // // // // https://example.com/sitemap1.xml // 2022-01-01 // // // https://example.com/sitemap2.xml // 2022-01-01 // // ``` -------------------------------- ### Generate Robots.txt Source: https://github.com/code-forge-io/seo-tools/blob/main/README.md Generates a robots.txt file content based on specified rules for different user agents. Useful for controlling search engine crawling. ```typescript import { generateRobotsTxt } from '@forge42/seo-tools/robots'; const robotsTxt = generateRobotsTxt([ { userAgent: '*', allow: ['/'], disallow: ['/admin', '/login'], crawlDelay: 1, sitemap: ['https://example.com/sitemap.xml'] }, { userAgent: 'Googlebot', allow: ['/'], disallow: ['/admin', '/login'], crawlDelay: 1, sitemap: ['https://example.com/sitemap.xml'] } ] ); console.log(robotsTxt); ``` -------------------------------- ### Generate Metadata with Structured Data Source: https://github.com/code-forge-io/seo-tools/blob/main/README.md Use the generateMeta utility to create SEO tags for different platforms and include structured data like articles and courses. This utility automatically generates Twitter and Open Graph tags. ```typescript import { generateMeta } from "@forge42/seo-tools/remix/metadata"; import { article } from "@forge42/seo-tools/structured-data/article"; import { course } from "@forge42/seo-tools/structured-data/course"; export const meta: MetaFunction = () => { // This utility will under the hood generate the twitter & og title and description tags for you. const meta = generateMeta({ title: "test", description: "test", url: "test", }, [ { "script:ld+json": article({ "@type": "Article", headline: "Article headline", image: "https://example.com/image.jpg", datePublished: "2021-01-01T00:00:00Z", }) }, { "script:ld+json": course({ "@type": "Course", name: "Course name", description: "Course description", }) } ]) return meta }; ``` -------------------------------- ### Generate Canonical and Alternate Links Source: https://github.com/code-forge-io/seo-tools/blob/main/README.md Use generateCanonicalLinks to create canonical and alternate links for SEO. It accepts transformers for URL and attribute generation, a list of alternatives, the domain, and the current URL. The output can be a string of HTML tags or an array of JSON objects. ```typescript import { generateCanonicalLinks } from '@forge42/seo-tools/canonical'; const canonicalLinks = generateCanonicalLinks({ // Used to generate the final url, it passes your alternatives, url and domain to the function for you to create whatever link you need urlTransformer: ({ url, domain, alternative, canonicalUrl }) => `${domain}/${url}?lng=${alternative}`, // Used to generate the final attributes altAttributesTransformer: ({ url, domain, alternative, canonicalUrl }) => attributes, // This takes a generic type and returns it in your transformers alternatives: ["de", "es"], domain: "https://example.com", url: "current-url", // Used to add additional attributes canonicalAttributes: { // These are included by default but you can add additional attributes rel: 'canonical', // These are included by default but you can add additional attributes href: 'https://example.com' } }, // Second argument tells the function if it should generate the output as string or as an array of json objects false ); console.log(canonicalLinks); // // // // or as an array of json objects // [ // { rel: 'canonical', href: 'https://example.com/current-url' }, // { rel: 'alternate', href: 'https://example.com/current-url?lng=de', hreflang: 'de' }, // { rel: 'alternate', href: 'https://example.com/current-url?lng=es', hreflang: 'es' } // ] ``` -------------------------------- ### Generate Article Structured Data Source: https://github.com/code-forge-io/seo-tools/blob/main/README.md Generates structured data for an article. This can help search engines display richer results for your content. ```typescript import { article } from '@forge42/seo-tools/structured-data/article'; const structuredData = article({ "@type": "Article", "headline": "Article headline", "image": "https://example.com/image.jpg", "datePublished": "2022-01-01", }); // Set it somehow in your html ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.