mirror of
https://github.com/gpxstudio/gpx.studio.git
synced 2025-09-02 08:42:31 +00:00
seo
This commit is contained in:
31
website/src/lib/sitemap.ts
Normal file
31
website/src/lib/sitemap.ts
Normal file
@@ -0,0 +1,31 @@
|
||||
import fs from 'fs';
|
||||
import { languages } from "./languages";
|
||||
|
||||
function getURL(lang: string, path: string = '/') {
|
||||
return 'https://gpx.studio' + (lang === 'en' ? '' : ('/' + lang)) + path;
|
||||
}
|
||||
|
||||
function generateSitemap() {
|
||||
const sitemap = `<?xml version="1.0" encoding="UTF-8"?>
|
||||
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">` +
|
||||
|
||||
Object.keys(languages).map((lang) => `
|
||||
<url>
|
||||
<loc>${getURL(lang)}</loc>${Object.keys(languages).map((lang2) => `
|
||||
<xhtml:link rel="alternate" hreflang="${lang2}" href="${getURL(lang2)}"/>`).join('')}
|
||||
</url>`).join('') +
|
||||
|
||||
Object.keys(languages).map((lang) => `
|
||||
<url>
|
||||
<loc>${getURL(lang, '/about')}</loc>${Object.keys(languages).map((lang2) => `
|
||||
<xhtml:link rel="alternate" hreflang="${lang2}" href="${getURL(lang2, '/about')}"/>`).join('')}
|
||||
</url>`).join('') +
|
||||
|
||||
`
|
||||
</urlset>
|
||||
`;
|
||||
|
||||
return sitemap;
|
||||
}
|
||||
|
||||
fs.writeFileSync('build/sitemap.xml', generateSitemap());
|
@@ -1,4 +1,9 @@
|
||||
{
|
||||
"metadata": {
|
||||
"app_title": "the online GPX file editor",
|
||||
"about_title": "about",
|
||||
"description": "View, edit and create GPX files online with advanced route planning capabilities, file processing tools and beautiful maps."
|
||||
},
|
||||
"menu": {
|
||||
"new": "New",
|
||||
"new_file": "New file",
|
||||
|
@@ -1,12 +1,5 @@
|
||||
<script>
|
||||
<script lang="ts">
|
||||
import '../app.pcss';
|
||||
|
||||
import { ModeWatcher } from 'mode-watcher';
|
||||
import { isLoading } from 'svelte-i18n';
|
||||
</script>
|
||||
|
||||
<ModeWatcher />
|
||||
|
||||
{#if !$isLoading}
|
||||
<slot />
|
||||
{/if}
|
||||
<slot />
|
||||
|
15
website/src/routes/[...language]/+layout.svelte
Normal file
15
website/src/routes/[...language]/+layout.svelte
Normal file
@@ -0,0 +1,15 @@
|
||||
<script lang="ts">
|
||||
import { ModeWatcher } from 'mode-watcher';
|
||||
import { isLoading, locale, _ } from 'svelte-i18n';
|
||||
import { page } from '$app/stores';
|
||||
|
||||
if ($page.params.language) {
|
||||
locale.set($page.params.language);
|
||||
}
|
||||
</script>
|
||||
|
||||
<ModeWatcher />
|
||||
|
||||
{#if !$isLoading}
|
||||
<slot />
|
||||
{/if}
|
@@ -1,12 +1,35 @@
|
||||
<script lang="ts">
|
||||
import App from '$lib/components/App.svelte';
|
||||
|
||||
import { locale } from 'svelte-i18n';
|
||||
import { page } from '$app/stores';
|
||||
|
||||
if ($page.params.language) {
|
||||
locale.set($page.params.language);
|
||||
}
|
||||
import { base } from '$app/paths';
|
||||
import { languages } from '$lib/languages';
|
||||
import { _ } from 'svelte-i18n';
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<title>gpx.studio — {$_('metadata.app_title')}</title>
|
||||
<meta name="description" content={$_('metadata.description')} />
|
||||
<meta property="og:title" content="gpx.studio — {$_('metadata.app_title')}" />
|
||||
<meta property="og:description" content={$_('metadata.description')} />
|
||||
<meta property="og:image" content="{base}/og_logo.png" />
|
||||
<meta property="og:url" content="{base}/" />
|
||||
<meta property="og:type" content="website" />
|
||||
<meta property="og:site_name" content="gpx.studio" />
|
||||
<meta name="twitter:card" content="summary_large_image" />
|
||||
<meta name="twitter:title" content="gpx.studio — {$_('metadata.app_title')}" />
|
||||
<meta name="twitter:description" content={$_('metadata.description')} />
|
||||
<meta name="twitter:image" content="{base}/og_logo.png" />
|
||||
<meta name="twitter:url" content="{base}/" />
|
||||
<meta name="twitter:site" content="@gpxstudio" />
|
||||
<meta name="twitter:creator" content="@gpxstudio" />
|
||||
|
||||
<link rel="alternate" hreflang="x-default" href="{base}/" />
|
||||
{#each Object.keys(languages) as lang}
|
||||
{#if lang === 'en'}
|
||||
<link rel="alternate" hreflang="en" href="{base}/" />
|
||||
{:else}
|
||||
<link rel="alternate" hreflang={lang} href="{base}/{lang}/" />
|
||||
{/if}
|
||||
{/each}
|
||||
</svelte:head>
|
||||
|
||||
<App />
|
||||
|
@@ -0,0 +1,32 @@
|
||||
<script lang="ts">
|
||||
import { base } from '$app/paths';
|
||||
import { languages } from '$lib/languages';
|
||||
import { _ } from 'svelte-i18n';
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<title>gpx.studio — {$_('metadata.about_title')}</title>
|
||||
<meta name="description" content={$_('metadata.description')} />
|
||||
<meta property="og:title" content="gpx.studio — {$_('metadata.about_title')}" />
|
||||
<meta property="og:description" content={$_('metadata.description')} />
|
||||
<meta property="og:image" content="{base}/og_logo.png" />
|
||||
<meta property="og:url" content="{base}/" />
|
||||
<meta property="og:type" content="website" />
|
||||
<meta property="og:site_name" content="gpx.studio" />
|
||||
<meta name="twitter:card" content="summary_large_image" />
|
||||
<meta name="twitter:title" content="gpx.studio — {$_('metadata.about_title')}" />
|
||||
<meta name="twitter:description" content={$_('metadata.description')} />
|
||||
<meta name="twitter:image" content="{base}/og_logo.png" />
|
||||
<meta name="twitter:url" content="{base}/" />
|
||||
<meta name="twitter:site" content="@gpxstudio" />
|
||||
<meta name="twitter:creator" content="@gpxstudio" />
|
||||
|
||||
<link rel="alternate" hreflang="x-default" href="{base}/" />
|
||||
{#each Object.keys(languages) as lang}
|
||||
{#if lang === 'en'}
|
||||
<link rel="alternate" hreflang="en" href="{base}/" />
|
||||
{:else}
|
||||
<link rel="alternate" hreflang={lang} href="{base}/{lang}/" />
|
||||
{/if}
|
||||
{/each}
|
||||
</svelte:head>
|
||||
|
Reference in New Issue
Block a user