diff --git a/astro.config.ts b/astro.config.ts index 8c36981c..8972ea8b 100644 --- a/astro.config.ts +++ b/astro.config.ts @@ -29,6 +29,15 @@ export default defineConfig({ access: "public", optional: true, default: parsedDoc.marketplace.enabled + }), + SEO: envField.string({ + context: "client", + access: "public", + optional: true, + default: JSON.stringify({ + enabled: parsedDoc.seo.enabled, + domain: new URL(parsedDoc.seo.domain).host + }) }) } } diff --git a/database_assets/com.nebula.gruvbox/gruvbox.jpeg b/database_assets/com.nebula.gruvbox/gruvbox.jpeg deleted file mode 100644 index 3d79448f..00000000 Binary files a/database_assets/com.nebula.gruvbox/gruvbox.jpeg and /dev/null differ diff --git a/package.json b/package.json index 12fc24e6..134880c1 100644 --- a/package.json +++ b/package.json @@ -38,6 +38,7 @@ "@types/sequelize": "^4.28.20", "astro": "^4.16.13", "astro-icon": "^1.1.2", + "astro-seo": "^0.8.4", "chalk": "^5.3.0", "concurrently": "^8.2.2", "fastify": "^5.1.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 5e894d22..b2f02e1f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -68,6 +68,9 @@ importers: astro-icon: specifier: ^1.1.2 version: 1.1.2 + astro-seo: + specifier: ^0.8.4 + version: 0.8.4(typescript@5.6.3) chalk: specifier: ^5.3.0 version: 5.3.0 @@ -155,6 +158,12 @@ packages: '@antfu/utils@0.7.10': resolution: {integrity: sha512-+562v9k4aI80m1+VuMHehNJWLOFjBnXn3tdOitzD0il5b7smkSBal4+a3oKiQTbrwMmN/TBUMDvbdoWDehgOww==} + '@astrojs/check@0.5.10': + resolution: {integrity: sha512-vliHXM9cu/viGeKiksUM4mXfO816ohWtawTl2ADPgTsd4nUMjFiyAl7xFZhF34yy4hq4qf7jvK1F2PlR3b5I5w==} + hasBin: true + peerDependencies: + typescript: ^5.0.0 + '@astrojs/check@0.8.3': resolution: {integrity: sha512-ajcSe+ezX5jCc3dreQlWzbknzXgSGnDETNe3C1mawUOtGpO4t5z2YGaD0y+wzB84lmgPWaWZa0fKSPwLq/wUHw==} hasBin: true @@ -1307,6 +1316,9 @@ packages: astro-icon@1.1.2: resolution: {integrity: sha512-2qAHBtZLYuFEIMP0Ck0edyLi5fQmJjwP2Qbv41f8L4KAJ2sra/dH7q5lCOn4q0DHVtS0w3tPG8UKQRits3UPcg==} + astro-seo@0.8.4: + resolution: {integrity: sha512-Ou1vzQSXAxa0K8rtNtXNvSpYqOGEgMhh0immMxJeXmbVZac3UKCNWAoXWyOQDFYsZvBugCRSg0N1phBqPMVgCw==} + astro@4.16.13: resolution: {integrity: sha512-Mtd76+BC0zLWqoXpf9xc731AhdH4MNh5JFHYdLRvSH0Nqn48hA64dPGh/cWsJvh/DZFmC0NTZusM1Qq2gyNaVg==} engines: {node: ^18.17.1 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0'} @@ -4118,6 +4130,18 @@ snapshots: '@antfu/utils@0.7.10': {} + '@astrojs/check@0.5.10(typescript@5.6.3)': + dependencies: + '@astrojs/language-server': 2.15.4(typescript@5.6.3) + chokidar: 3.6.0 + fast-glob: 3.3.2 + kleur: 4.1.5 + typescript: 5.6.3 + yargs: 17.7.2 + transitivePeerDependencies: + - prettier + - prettier-plugin-astro + '@astrojs/check@0.8.3(typescript@5.6.3)': dependencies: '@astrojs/language-server': 2.15.4(typescript@5.6.3) @@ -5377,6 +5401,14 @@ snapshots: - debug - supports-color + astro-seo@0.8.4(typescript@5.6.3): + dependencies: + '@astrojs/check': 0.5.10(typescript@5.6.3) + transitivePeerDependencies: + - prettier + - prettier-plugin-astro + - typescript + astro@4.16.13(@types/node@22.9.0)(lightningcss@1.27.0)(rollup@4.27.2)(terser@5.36.0)(typescript@5.6.3): dependencies: '@astrojs/compiler': 2.10.3 diff --git a/public/logo.png b/public/logo.png new file mode 100644 index 00000000..3afb9bf0 Binary files /dev/null and b/public/logo.png differ diff --git a/server/config.ts b/server/config.ts index 5681d9fb..96b1d11a 100644 --- a/server/config.ts +++ b/server/config.ts @@ -15,6 +15,10 @@ interface TomlData { logging: boolean; }; }; + seo: { + enabled: boolean; + domain: string; + }; db: { name: string; username: string; @@ -31,6 +35,7 @@ interface Verify { name: string; typeOF: any; type: any; + verifyExtras?: () => boolean | Error; } let doc = readFileSync(fileURLToPath(new URL("../config.toml", import.meta.url))).toString(); @@ -41,6 +46,12 @@ function verify(t: Verify[]) { if (typeof t[i].typeOF !== t[i].type) { throw new Error(`Invalid structure: "${t[i].name}" should be a(n) ${t[i].type}`); } + if (t[i].verifyExtras) { + const extra = t[i].verifyExtras(); + if (extra !== true) { + throw extra; + } + } } } @@ -53,6 +64,17 @@ verify([ { name: "server.server.port", typeOF: parsedDoc.server.server.port, type: "number" }, { name: "server.server.wisp", typeOF: parsedDoc.server.server.wisp, type: "boolean" }, { name: "server.server.logging", typeOF: parsedDoc.server.server.logging, type: "boolean" }, + { name: "seo", typeOF: parsedDoc.seo, type: "object" }, + { name: "seo.enabled", typeOF: parsedDoc.seo.enabled, type: "boolean" }, + { name: "seo.domain", typeOF: parsedDoc.seo.domain, type: "string", verifyExtras: () => { + try { + new URL(parsedDoc.seo.domain); + } + catch (e) { + return Error(e); + } + return true; + }}, { name: "db", typeOF: parsedDoc.db, type: "object" }, { name: "db.name", typeOF: parsedDoc.db.name, type: "string" }, { name: "db.username", typeOF: parsedDoc.db.username, type: "string" }, diff --git a/server/dbSetup.ts b/server/dbSetup.ts index b3138ce0..7e63d3db 100644 --- a/server/dbSetup.ts +++ b/server/dbSetup.ts @@ -33,7 +33,7 @@ async function setupDB(db: ModelStatic) { { package_name: "com.nebula.gruvbox", title: "Gruvbox", - image: "gruvbox.jpeg", + image: "gruvbox.jpg", author: "Nebula Services", version: "1.0.0", description: "The gruvbox theme", diff --git a/src/layouts/Layout.astro b/src/layouts/Layout.astro index 4365ce23..a51be1a6 100644 --- a/src/layouts/Layout.astro +++ b/src/layouts/Layout.astro @@ -3,6 +3,8 @@ import { ViewTransitions } from "astro:transitions"; import Header from "@components/Header.astro"; import MobileNavigation from "@components/MobileNavigation.astro"; import SettingsLoader from "@components/settings/Loader.astro"; +import { SEO } from "astro-seo"; +import { SEO as SEOC } from "astro:env/client"; interface Props { title: string; noHeader?: string; @@ -11,6 +13,8 @@ interface Props { } const { title, noHeader, description, image } = Astro.props; +const SEOConfig = JSON.parse(SEOC); +const Host = Astro.url.host; --- @@ -18,35 +22,61 @@ const { title, noHeader, description, image } = Astro.props; - - - - + + {/* I left this out of the SEO component as we need it to persist properly : D */} - - - - {title} - + {!noHeader &&
} diff --git a/src/pages/[lang]/catalog/package/[...packageName].astro b/src/pages/[lang]/catalog/package/[...packageName].astro index e77e8756..050b259e 100644 --- a/src/pages/[lang]/catalog/package/[...packageName].astro +++ b/src/pages/[lang]/catalog/package/[...packageName].astro @@ -10,7 +10,7 @@ const assetsJson = await response.json();
+
diff --git a/src/pages/index.astro b/src/pages/index.astro index 24c50b5a..6939e1ef 100644 --- a/src/pages/index.astro +++ b/src/pages/index.astro @@ -3,7 +3,7 @@ import Loading from "@components/Loading.astro"; import Layout from "@layouts/Layout.astro"; --- - +