diff --git a/website/package-lock.json b/website/package-lock.json
index 641b5c5f..65661a8e 100644
--- a/website/package-lock.json
+++ b/website/package-lock.json
@@ -51,6 +51,7 @@
"svelte-check": "^3.8.1",
"tailwindcss": "^3.4.4",
"tslib": "^2.6.3",
+ "tsx": "^4.15.7",
"typescript": "^5.4.5",
"vite": "^5.3.1"
}
@@ -3180,6 +3181,18 @@
"resolved": "https://registry.npmjs.org/geojson-vt/-/geojson-vt-3.2.1.tgz",
"integrity": "sha512-EvGQQi/zPrDA6zr6BnJD/YhwAkBP8nnJ9emh3EnHQKVMfg/MRVtPbMYdgVy/IaEmn4UfagD2a6fafPDL5hbtwg=="
},
+ "node_modules/get-tsconfig": {
+ "version": "4.7.5",
+ "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.7.5.tgz",
+ "integrity": "sha512-ZCuZCnlqNzjb4QprAzXKdpp/gh6KTxSJuw3IBsPnV/7fV4NxC9ckB+vPTt8w7fJA0TaSD7c55BR47JD6MEDyDw==",
+ "dev": true,
+ "dependencies": {
+ "resolve-pkg-maps": "^1.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1"
+ }
+ },
"node_modules/gl-matrix": {
"version": "3.4.3",
"resolved": "https://registry.npmjs.org/gl-matrix/-/gl-matrix-3.4.3.tgz",
@@ -4919,6 +4932,15 @@
"node": ">=4"
}
},
+ "node_modules/resolve-pkg-maps": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz",
+ "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==",
+ "dev": true,
+ "funding": {
+ "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1"
+ }
+ },
"node_modules/resolve-protobuf-schema": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/resolve-protobuf-schema/-/resolve-protobuf-schema-2.1.0.tgz",
@@ -6203,6 +6225,25 @@
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz",
"integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ=="
},
+ "node_modules/tsx": {
+ "version": "4.15.7",
+ "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.15.7.tgz",
+ "integrity": "sha512-u3H0iSFDZM3za+VxkZ1kywdCeHCn+8/qHQS1MNoO2sONDgD95HlWtt8aB23OzeTmFP9IU4/8bZUdg58Uu5J4cg==",
+ "dev": true,
+ "dependencies": {
+ "esbuild": "~0.21.4",
+ "get-tsconfig": "^4.7.5"
+ },
+ "bin": {
+ "tsx": "dist/cli.mjs"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ },
+ "optionalDependencies": {
+ "fsevents": "~2.3.3"
+ }
+ },
"node_modules/tweakpane": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/tweakpane/-/tweakpane-4.0.3.tgz",
diff --git a/website/package.json b/website/package.json
index 8b06b329..115e3e4f 100644
--- a/website/package.json
+++ b/website/package.json
@@ -5,6 +5,7 @@
"scripts": {
"dev": "vite dev",
"build": "vite build",
+ "postbuild": "npx tsx src/lib/sitemap.ts",
"preview": "vite preview",
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
@@ -36,6 +37,7 @@
"svelte-check": "^3.8.1",
"tailwindcss": "^3.4.4",
"tslib": "^2.6.3",
+ "tsx": "^4.15.7",
"typescript": "^5.4.5",
"vite": "^5.3.1"
},
@@ -59,4 +61,4 @@
"tailwind-merge": "^2.3.0",
"tailwind-variants": "^0.2.1"
}
-}
+}
\ No newline at end of file
diff --git a/website/src/lib/sitemap.ts b/website/src/lib/sitemap.ts
new file mode 100644
index 00000000..b58e9b22
--- /dev/null
+++ b/website/src/lib/sitemap.ts
@@ -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 = `
+` +
+
+ Object.keys(languages).map((lang) => `
+
+ ${getURL(lang)}${Object.keys(languages).map((lang2) => `
+ `).join('')}
+ `).join('') +
+
+ Object.keys(languages).map((lang) => `
+
+ ${getURL(lang, '/about')}${Object.keys(languages).map((lang2) => `
+ `).join('')}
+ `).join('') +
+
+ `
+
+`;
+
+ return sitemap;
+}
+
+fs.writeFileSync('build/sitemap.xml', generateSitemap());
\ No newline at end of file
diff --git a/website/src/locales/en.json b/website/src/locales/en.json
index 93af4fac..2316990e 100644
--- a/website/src/locales/en.json
+++ b/website/src/locales/en.json
@@ -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",
diff --git a/website/src/routes/+layout.svelte b/website/src/routes/+layout.svelte
index 7ccef524..7f8c73ec 100644
--- a/website/src/routes/+layout.svelte
+++ b/website/src/routes/+layout.svelte
@@ -1,12 +1,5 @@
-
-
-
-{#if !$isLoading}
-
-{/if}
+
diff --git a/website/src/routes/[...language]/+layout.svelte b/website/src/routes/[...language]/+layout.svelte
new file mode 100644
index 00000000..e90ea297
--- /dev/null
+++ b/website/src/routes/[...language]/+layout.svelte
@@ -0,0 +1,15 @@
+
+
+
+
+{#if !$isLoading}
+
+{/if}
diff --git a/website/src/routes/[...language]/+page.svelte b/website/src/routes/[...language]/+page.svelte
index 2e856d80..ee057b6a 100644
--- a/website/src/routes/[...language]/+page.svelte
+++ b/website/src/routes/[...language]/+page.svelte
@@ -1,12 +1,35 @@
+
+ gpx.studio — {$_('metadata.app_title')}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {#each Object.keys(languages) as lang}
+ {#if lang === 'en'}
+
+ {:else}
+
+ {/if}
+ {/each}
+
+
diff --git a/website/src/routes/[...language]/about/+page.svelte b/website/src/routes/[...language]/about/+page.svelte
index e69de29b..f37393c2 100644
--- a/website/src/routes/[...language]/about/+page.svelte
+++ b/website/src/routes/[...language]/about/+page.svelte
@@ -0,0 +1,32 @@
+
+
+
+ gpx.studio — {$_('metadata.about_title')}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {#each Object.keys(languages) as lang}
+ {#if lang === 'en'}
+
+ {:else}
+
+ {/if}
+ {/each}
+
diff --git a/website/static/og_logo.png b/website/static/og_logo.png
new file mode 100644
index 00000000..63ee1a18
Binary files /dev/null and b/website/static/og_logo.png differ