diff --git a/caster-front/package-lock.json b/caster-front/package-lock.json
index b666e9a5..e0c1d714 100644
--- a/caster-front/package-lock.json
+++ b/caster-front/package-lock.json
@@ -10,6 +10,7 @@
"dependencies": {
"@element-plus/icons-vue": "^2.1.0",
"@sentry/vue": "^7.57.0",
+ "@unhead/vue": "^1.7.4",
"@urql/vue": "^1.0.4",
"element-plus": "^2.3.5",
"graphql": "^16.6.0",
@@ -3422,6 +3423,58 @@
"url": "https://opencollective.com/typescript-eslint"
}
},
+ "node_modules/@unhead/dom": {
+ "version": "1.7.4",
+ "resolved": "https://registry.npmjs.org/@unhead/dom/-/dom-1.7.4.tgz",
+ "integrity": "sha512-xanQMtGmgikqTvDtuyJy6GXgqvUXOdrdnIyqAabpeS8goD8udxo0stzjtbT8ERbMQibzPGSGcN+Ux+MKoWzrjQ==",
+ "dependencies": {
+ "@unhead/schema": "1.7.4",
+ "@unhead/shared": "1.7.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/harlan-zw"
+ }
+ },
+ "node_modules/@unhead/schema": {
+ "version": "1.7.4",
+ "resolved": "https://registry.npmjs.org/@unhead/schema/-/schema-1.7.4.tgz",
+ "integrity": "sha512-wUL4CK0NSEm3KH4kYsiqVYQw5xBk1hpBi5tiNj0BTZgpQVrRufICdK5EHA9Fh7OIAR6tOTWwTvsf5+nK0BgQDA==",
+ "dependencies": {
+ "hookable": "^5.5.3",
+ "zhead": "^2.1.1"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/harlan-zw"
+ }
+ },
+ "node_modules/@unhead/shared": {
+ "version": "1.7.4",
+ "resolved": "https://registry.npmjs.org/@unhead/shared/-/shared-1.7.4.tgz",
+ "integrity": "sha512-YUNA2UxAuDPnDps41BQ8aEIY5hdyvruSB1Vs3AALhRo07MxMivSq5DjNKfYr/JvRN6593RtfI1NHnP9x5M57xA==",
+ "dependencies": {
+ "@unhead/schema": "1.7.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/harlan-zw"
+ }
+ },
+ "node_modules/@unhead/vue": {
+ "version": "1.7.4",
+ "resolved": "https://registry.npmjs.org/@unhead/vue/-/vue-1.7.4.tgz",
+ "integrity": "sha512-ZfgzOhg1Bxo9xwp3upawqerw4134hc9Lhz6t005ixcBwPX+39Wpgc9dC3lf+owFQEVuWkf8F+eAwK2sghVBK4A==",
+ "dependencies": {
+ "@unhead/schema": "1.7.4",
+ "@unhead/shared": "1.7.4",
+ "hookable": "^5.5.3",
+ "unhead": "1.7.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/harlan-zw"
+ },
+ "peerDependencies": {
+ "vue": ">=2.7 || >=3"
+ }
+ },
"node_modules/@urql/core": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/@urql/core/-/core-3.1.1.tgz",
@@ -6641,6 +6694,11 @@
"tslib": "^2.0.3"
}
},
+ "node_modules/hookable": {
+ "version": "5.5.3",
+ "resolved": "https://registry.npmjs.org/hookable/-/hookable-5.5.3.tgz",
+ "integrity": "sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ=="
+ },
"node_modules/hosted-git-info": {
"version": "2.8.9",
"resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz",
@@ -10093,6 +10151,20 @@
"node": ">=14.0"
}
},
+ "node_modules/unhead": {
+ "version": "1.7.4",
+ "resolved": "https://registry.npmjs.org/unhead/-/unhead-1.7.4.tgz",
+ "integrity": "sha512-oOv+9aQS85DQUd0f1uJBtb2uG3SKwCURSTuUWp9WKKzANCb1TjW2dWp5TFmJH5ILF6urXi4uUQfjK+SawzBJAA==",
+ "dependencies": {
+ "@unhead/dom": "1.7.4",
+ "@unhead/schema": "1.7.4",
+ "@unhead/shared": "1.7.4",
+ "hookable": "^5.5.3"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/harlan-zw"
+ }
+ },
"node_modules/unixify": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/unixify/-/unixify-1.0.0.tgz",
@@ -10859,6 +10931,14 @@
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
+ },
+ "node_modules/zhead": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/zhead/-/zhead-2.1.1.tgz",
+ "integrity": "sha512-FRmjAFioi07R+bmL+fqbkXF/pCbC9PwcKQ8RDluC5xTaVbNBgYRQ4eKuS1C8c7Sil//UIxet/AGp7D6royoHhA==",
+ "funding": {
+ "url": "https://github.com/sponsors/harlan-zw"
+ }
}
}
}
diff --git a/caster-front/package.json b/caster-front/package.json
index e1439c88..6627ed3f 100644
--- a/caster-front/package.json
+++ b/caster-front/package.json
@@ -18,6 +18,7 @@
"dependencies": {
"@element-plus/icons-vue": "^2.1.0",
"@sentry/vue": "^7.57.0",
+ "@unhead/vue": "^1.7.4",
"@urql/vue": "^1.0.4",
"element-plus": "^2.3.5",
"graphql": "^16.6.0",
diff --git a/caster-front/src/components/GraphPlayer.vue b/caster-front/src/components/GraphPlayer.vue
index 2cdacbc2..92ec7580 100644
--- a/caster-front/src/components/GraphPlayer.vue
+++ b/caster-front/src/components/GraphPlayer.vue
@@ -1,5 +1,7 @@
diff --git a/caster-front/src/composables/metaHead.ts b/caster-front/src/composables/metaHead.ts
new file mode 100644
index 00000000..fd7f3934
--- /dev/null
+++ b/caster-front/src/composables/metaHead.ts
@@ -0,0 +1,42 @@
+export const metaHead = (
+ metaTitle: string,
+ metaDescription: string,
+ metaImageUrl?: string,
+ siteUrl?: string,
+) => {
+ const meta = {
+ title: metaTitle,
+ meta: [
+ { name: "description", content: metaDescription },
+ { hid: "description", name: "description", content: metaDescription },
+
+ // Twitter Card data
+ { name: "twitter:title", content: metaTitle, hid: "custom" },
+ { name: "twitter:description", content: metaDescription, hid: "custom" },
+
+ // Open Graph
+ { property: "og:title", content: metaTitle, hid: "custom" },
+ {
+ property: "og:description",
+ content: metaDescription,
+ hid: "og:description",
+ },
+ { property: "og:image", content: metaImageUrl, hid: "og:image" },
+ ],
+ };
+
+ if (metaImageUrl) {
+ meta.meta.push({ name: "og:image", content: metaImageUrl });
+ meta.meta.push({
+ name: "twitter:image",
+ content: metaImageUrl,
+ hid: "custom",
+ });
+ }
+
+ if (siteUrl) {
+ meta.meta.push({ property: "og:url", content: siteUrl, hid: "custom" });
+ }
+
+ return meta;
+};
diff --git a/caster-front/src/main.ts b/caster-front/src/main.ts
index abb22a31..38a90383 100644
--- a/caster-front/src/main.ts
+++ b/caster-front/src/main.ts
@@ -1,4 +1,5 @@
import { createApp } from "vue";
+import { createHead } from "@unhead/vue";
import { createPinia } from "pinia";
import urql, { fetchExchange, subscriptionExchange } from "@urql/vue";
import { SubscriptionClient } from "subscriptions-transport-ws";
@@ -13,6 +14,9 @@ import "./assets/main.scss";
const app = createApp(App);
+const head = createHead();
+app.use(head);
+
if (
import.meta.env.VITE_BACKEND_URL &&
import.meta.env.VITE_SENTRY_DSN_CASTER_FRONT
diff --git a/caster-front/tsconfig.app.json b/caster-front/tsconfig.app.json
index cdbea1d7..05b4cfb0 100644
--- a/caster-front/tsconfig.app.json
+++ b/caster-front/tsconfig.app.json
@@ -5,6 +5,7 @@
"compilerOptions": {
"composite": true,
"baseUrl": ".",
+ "allowImportingTsExtensions": true,
"paths": {
"@/*": ["./src/*"]
}