To Keep It Going, Please Show Your Love.Buy Me a Coffee at ko-fi.com

Runes Meta Tags

Runes Meta Tags manages the meta tags for a web page. It allows you to easily configure various meta tags including basic SEO (Search Engine Optimization) information, robots meta tag, and social media specific meta tags for Twitter and Open Graph.

Installation #

Please install runes-meta-tags by using the following command:

pnpm i -D runes-meta-tags

+layout.server.ts #

The +layout.server.ts file is used for serving the default meta tags.

import type { MetaProps } from 'runes-meta-tags';
import { metaTitle, metaDescription, metaImg } from 'runes-meta-tags';
// define __NAME__ in your vite.config.ts
export const load = ({ url }) => {
  const title = metaTitle(url.pathname, __NAME__);
  const basicDesc = 'Meta tags for Runes.';
  const description = metaDescription(url.pathname, basicDesc);
  const image = metaImg(url.pathname, __NAME__);

  const layoutMetaTags: MetaProps = {
    title,
    description,
    keywords: 'runes, meta, tags',
    twitter: {
      card: 'summary_large_image',
      site: '@johndoe',
      handle: '@johndoe',
      title,
      description,
      image,
      imageAlt: title
    },
    og: {
      type: 'website',
      title,
      description,
      url: url.href,
      image,
      imageAlt: title,
      siteName: 'Runes meta',
      imageWidth: '1200',
      imageHeight: '630'
    }
  };
  return {
    layoutMetaTags
  };
};

+layout.svelte #

Import RunesMetaTags and deepMerge from runes-meta-tags. Add data to the $props().

<script>
  import { RunesMetaTags, deepMerge } from 'runes-meta-tags';
  import { page } from '$app/stores';

  let { children, data } = $props();

  let metaTags = $state(
    $page.data.pageMetaTags
      ? deepMerge($page.data.layoutMetaTags, $page.data.pageMetaTags)
      : data.layoutMetaTags
  );
  $effect(() => {
    metaTags = $page.data.pageMetaTags ? deepMerge($page.data.layoutMetaTags, $page.data.pageMetaTags ) : data.layoutMetaTags
  });
</script>

<RunesMetaTags {...metaTags}/>

{@render children()}

about/+page.ts #

You can modify the meta tags if you need. The following is an example for the about page.

import type { MetaProps } from 'runes-meta-tags';
import { metaTitle, metaDescription, metaImg, splitAndCapitalize } from 'runes-meta-tags';
// define __NAME__ in your vite.config.ts
export const load = ({ url }) => {
  const title = metaTitle(url.pathname, __NAME__);
  const basicDesc = splitAndCapitalize(__NAME__);
  const description = metaDescription(url.pathname, basicDesc);
  const image = metaImg(url.pathname, __NAME__);

  const pageMetaTags = {
    title,
    description,
    og: {
      title,
      description
    },
    twitter: {
      title,
      description
    }
  };
  return { pageMetaTags };
};

about/+page.svelte #

about/+page.svelte needs any extra code.

<h1>About</h1>

Playwright test examples #

Index page #

Use the following examples to start your Playwright tests for the index page.

import { expect, test } from '@playwright/test';

test.beforeEach(async ({ page }) => {
  console.log(`Running ${test.info().title}`);
  await page.goto('/');
});

test('index page has expected h1', async ({ page }) => {
  await expect(page.getByRole('heading', { name: 'Runes Meta Tags' })).toBeVisible();
});

test('index page has expected meta title', async ({ page }) => {
  await expect(page).toHaveTitle('Runes Meta Tags');
});

test('index page has expected meta description', async ({ page }) => {
  const metaDescription = page.locator('meta[name="description"]');
  await expect(metaDescription).toHaveAttribute('content', 'Meta tags for Runes.');
});

test('index page has expected meta keywords', async ({ page }) => {
  const metaKeywords = page.locator('meta[name="keywords"]');
  await expect(metaKeywords).toHaveAttribute('content', 'runes, meta, tags');
});

test('index page has expected meta og', async ({ page }) => {
  const metaOgTitle = page.locator('meta[property="og:title"]');
  await expect(metaOgTitle).toHaveAttribute('content', 'Runes Meta Tags');
  const metaOgDescription = page.locator('meta[property="og:description"]');
  await expect(metaOgDescription).toHaveAttribute('content', 'Meta tags for Runes.');
  const metaOgUrl = page.locator('meta[property="og:url"]');
  await expect(metaOgUrl).toHaveAttribute('content', 'http://localhost:4173/');
  const metaOgImage = page.locator('meta[property="og:image"]');
  await expect(metaOgImage).toHaveAttribute(
    'content',
    'https://open-graph-vercel.vercel.app/api/runes-meta-tags'
  );
});

test('index page has expected meta twitter', async ({ page }) => {
  const metaTwitterTitle = page.locator('meta[name="twitter:title"]');
  await expect(metaTwitterTitle).toHaveAttribute('content', 'Runes Meta Tags');
  const metaTwitterDescription = page.locator('meta[name="twitter:description"]');
  await expect(metaTwitterDescription).toHaveAttribute('content', 'Meta tags for Runes.');
  const metaTwitterImage = page.locator('meta[name="twitter:image"]');
  await expect(metaTwitterImage).toHaveAttribute(
    'content',
    'https://open-graph-vercel.vercel.app/api/runes-meta-tags'
  );
});

About page #

Use the following examples to start your Playwright tests for the About page.

import { expect, test } from '@playwright/test';

test.beforeEach(async ({ page }) => {
  console.log(`Running ${test.info().title}`);
  await page.goto('/about');
});

test('about page has expected h1, meta title', async ({ page }) => {
  await expect(page.getByRole('heading', { name: 'About' })).toBeVisible();
});

test('about page has expected meta title', async ({ page }) => {
  await expect(page).toHaveTitle('About - Runes Meta Tags');
});

test('about page has expected meta description', async ({ page }) => {
  const metaDescription = page.locator('meta[name="description"]');
  await expect(metaDescription).toHaveAttribute('content', 'About - Runes Meta Tags');
});

test('about page has expected meta og', async ({ page }) => {
  const metaOgTitle = page.locator('meta[property="og:title"]');
  await expect(metaOgTitle).toHaveAttribute('content', 'About - Runes Meta Tags');
  const metaOgDescription = page.locator('meta[property="og:description"]');
  await expect(metaOgDescription).toHaveAttribute('content', 'About - Runes Meta Tags');
  const metaOgUrl = page.locator('meta[property="og:url"]');
  await expect(metaOgUrl).toHaveAttribute('content', 'http://localhost:4173/about');
  const metaOgImage = page.locator('meta[property="og:image"]');
  await expect(metaOgImage).toHaveAttribute(
    'content',
    'https://open-graph-vercel.vercel.app/api/runes-meta-tags?title=About'
  );
});

test('about page has expected meta twitter', async ({ page }) => {
  const metaTwitterTitle = page.locator('meta[name="twitter:title"]');
  await expect(metaTwitterTitle).toHaveAttribute('content', 'About - Runes Meta Tags');
  const metaTwitterDescription = page.locator('meta[name="twitter:description"]');
  await expect(metaTwitterDescription).toHaveAttribute('content', 'About - Runes Meta Tags');
  const metaTwitterImage = page.locator('meta[name="twitter:image"]');
  await expect(metaTwitterImage).toHaveAttribute(
    'content',
    'https://open-graph-vercel.vercel.app/api/runes-meta-tags?title=About'
  );
});

Technical information about this website