@sveltejs/adapter-static and Open Graph

How to ensure Open Graph can detect your Meta Tags when using @sveltejs/adapter-static with your SvelteKit project.

SvelteKit logo with the reddish-orange logo on the left of the SvelteKit text. Svelte is in black, Kit in gray coloring.
SvelteKit Logo.

I recently migrated three websites to SvelteKit. Two were formerly Next.js sites, one moving over from WordPress. It is a move that I am glad I made. You will start to see me blog more about my experience with SvelteKit.

Yesterday I was developing a placeholder website, Singapore Node. I wanted to test single-page applications (SPA) on my server. I did not want to rely on Netlify or Vercel for most of my projects. My earlier Jamstack projects ran on my MERN stack server.

Getting SvelteKit set up was an easy process. The extra step was to execute after I finished developing the site.

npm run build

As per website recommendations, I chose the @sveltejs/adapter-static to generate my website's HTML. I made sure to add index.html as the fallback Since I also had Schema.org configured for my site, I made sure to add svelte-preprocess to svelte.config.js. Below are my configurations for this file:

@svelte.config.js

import adapter from '@sveltejs/adapter-static';
import preprocess from 'svelte-preprocess';

/** @type {import('@sveltejs/kit').Config} */
const config = {
	kit: {
		adapter: adapter({
			// default options are shown
			pages: 'build',
			assets: 'build',
			fallback: 'index.html',
			precompress: false
		}),
		prerender: {
			default: true
		},
		trailingSlash: 'always'
	},
	preprocess: [
		preprocess({
			crawl: true,
			enabled: true,
			onError: 'continue',
			entries: ['*'],
			postcss: true,
			preserve: ['ld+json']
		})
	]
};

export default config;

After I built the site, I committed the project to GitHub. I then pulled the project to my server. Setting it up with Nginx was also an easy process. I could see my site live.

Unfortunately, I ran into one issue. While Schema.org could detect my site's schema, all the Open Graph detectors could not detect any of my Meta Tags. It was puzzling because I could see the Meta Tags with DevTools. With Curl, I kept getting a 301 error.

Finally, I realized that only the Meta Tags in app.html file were detected. Since I placed all my meta tags inside the svelte:head tags, I decided to move them to app.html (app.html and index.svelte are below the article) to see what happens.

Open Graph detectors could now fetch my site's Meta Tags. Problem solved. Well at least for single-page applications. Please send me a DM on Twitter if you know another solution to this.

In the future, I will use @sveltejs/adapter-node to build my SvelteKit app to run on a Node.js server. I will write a future post about that experience.

app.html

<!DOCTYPE html>
<html lang="en">
	<head>
		<meta charset="utf-8" />
		<link rel="icon" href="%svelte.assets%/favicon.ico" />
		<meta name="viewport" content="width=device-width, initial-scale=1" />
		<meta
			name="keywords"
			content="keyword 1, keyword 2, etc."
		/>
		<meta
			name="description"
			content="Site Description."
		/>
		<meta name="twitter:card" content="summary_large_image" />
		<meta name="twitter:title" content="Site Title" />
		<meta
			name="twitter:description"
			content="Site Description."
		/>
		<meta
			name="twitter:image"
			content="Socialog image - 1200x630"
		/>
		<meta property="twitter:domain" content="domain" />
		<meta property="twitter:url" content="https://domain" />
		<meta property="og:title" content="Site title" />
		<meta property="og:url" content="https://domain" />
		<meta property="og:type" content="website" />
		<meta
			property="og:image"
			content="Socialog image - 1200x630"
		/>
		<meta
			property="og:image:url"
			content="Socialog image - 1200x630"
		/>
		<meta
			property="og:description"
			content="Site Description."
		/>
		<title>"Site Title"</title>
		<html lang="en-US" />
		%svelte.head%
	</head>
	<body>
		<div>%svelte.body%</div>
	</body>
</html>

index.svelte

<script>
	const schemaOrgWebsite = {
		'@context': 'https://schema.org/',
		'@type': ['Organization', 'Website'],
		name: 'Site Name',
		legalName: 'Site Name',
		url: 'https://domain',
		logo: 'Socialog image - 1200x630',
		foundingDate: '2022',
		founders: [
			{
				'@type': 'Person',
				name: 'Author'
			}
		],
		address: {
			'@type': 'PostalAddress',
			streetAddress: 'Address',
			addressLocality: 'City',
			addressRegion: 'State/Province',
			postalCode: '######',
			addressCountry: 'Country'
		},
		contactPoint: {
			'@type': 'ContactPoint',
			contactType: 'Founder',
			telephone: '[Your Phone]',
			email: 'email'
		},
		sameAs: [
			'https://https://github.com/repository/',
			'https://twitter.com/username',
			'https://instagram.com/username',
			'https://www.facebook.com/username'
		]
	};

	const schemaOrgArray = [schemaOrgWebsite];
	const schemaOrgObject = {
		'@context': 'https://schema.org',
		'@graph': schemaOrgArray
	};
	let jsonLdString = JSON.stringify(schemaOrgObject);
	let jsonLdScript = `
		<script type="application/ld+json">
			${jsonLdString}
		${'<'}/script>
	`;
</script>

<svelte:head>
	{@html jsonLdScript}
</svelte:head>

To learn more about SEO, Schema.org and jsonLD, visit Rodney Lab's Blog.

Subscribe to Kevin Matsunaga

Don’t miss out on the latest issues. Sign up now to get access to the library of members-only issues.
jamie@example.com
Subscribe