Some SEO stuff
This commit is contained in:
parent
208b37ce75
commit
41c109416f
11 changed files with 121 additions and 27 deletions
|
|
@ -29,6 +29,15 @@ export default defineConfig({
|
||||||
access: "public",
|
access: "public",
|
||||||
optional: true,
|
optional: true,
|
||||||
default: parsedDoc.marketplace.enabled
|
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
|
||||||
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 9.6 KiB |
|
|
@ -38,6 +38,7 @@
|
||||||
"@types/sequelize": "^4.28.20",
|
"@types/sequelize": "^4.28.20",
|
||||||
"astro": "^4.16.13",
|
"astro": "^4.16.13",
|
||||||
"astro-icon": "^1.1.2",
|
"astro-icon": "^1.1.2",
|
||||||
|
"astro-seo": "^0.8.4",
|
||||||
"chalk": "^5.3.0",
|
"chalk": "^5.3.0",
|
||||||
"concurrently": "^8.2.2",
|
"concurrently": "^8.2.2",
|
||||||
"fastify": "^5.1.0",
|
"fastify": "^5.1.0",
|
||||||
|
|
|
||||||
32
pnpm-lock.yaml
generated
32
pnpm-lock.yaml
generated
|
|
@ -68,6 +68,9 @@ importers:
|
||||||
astro-icon:
|
astro-icon:
|
||||||
specifier: ^1.1.2
|
specifier: ^1.1.2
|
||||||
version: 1.1.2
|
version: 1.1.2
|
||||||
|
astro-seo:
|
||||||
|
specifier: ^0.8.4
|
||||||
|
version: 0.8.4(typescript@5.6.3)
|
||||||
chalk:
|
chalk:
|
||||||
specifier: ^5.3.0
|
specifier: ^5.3.0
|
||||||
version: 5.3.0
|
version: 5.3.0
|
||||||
|
|
@ -155,6 +158,12 @@ packages:
|
||||||
'@antfu/utils@0.7.10':
|
'@antfu/utils@0.7.10':
|
||||||
resolution: {integrity: sha512-+562v9k4aI80m1+VuMHehNJWLOFjBnXn3tdOitzD0il5b7smkSBal4+a3oKiQTbrwMmN/TBUMDvbdoWDehgOww==}
|
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':
|
'@astrojs/check@0.8.3':
|
||||||
resolution: {integrity: sha512-ajcSe+ezX5jCc3dreQlWzbknzXgSGnDETNe3C1mawUOtGpO4t5z2YGaD0y+wzB84lmgPWaWZa0fKSPwLq/wUHw==}
|
resolution: {integrity: sha512-ajcSe+ezX5jCc3dreQlWzbknzXgSGnDETNe3C1mawUOtGpO4t5z2YGaD0y+wzB84lmgPWaWZa0fKSPwLq/wUHw==}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
@ -1307,6 +1316,9 @@ packages:
|
||||||
astro-icon@1.1.2:
|
astro-icon@1.1.2:
|
||||||
resolution: {integrity: sha512-2qAHBtZLYuFEIMP0Ck0edyLi5fQmJjwP2Qbv41f8L4KAJ2sra/dH7q5lCOn4q0DHVtS0w3tPG8UKQRits3UPcg==}
|
resolution: {integrity: sha512-2qAHBtZLYuFEIMP0Ck0edyLi5fQmJjwP2Qbv41f8L4KAJ2sra/dH7q5lCOn4q0DHVtS0w3tPG8UKQRits3UPcg==}
|
||||||
|
|
||||||
|
astro-seo@0.8.4:
|
||||||
|
resolution: {integrity: sha512-Ou1vzQSXAxa0K8rtNtXNvSpYqOGEgMhh0immMxJeXmbVZac3UKCNWAoXWyOQDFYsZvBugCRSg0N1phBqPMVgCw==}
|
||||||
|
|
||||||
astro@4.16.13:
|
astro@4.16.13:
|
||||||
resolution: {integrity: sha512-Mtd76+BC0zLWqoXpf9xc731AhdH4MNh5JFHYdLRvSH0Nqn48hA64dPGh/cWsJvh/DZFmC0NTZusM1Qq2gyNaVg==}
|
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'}
|
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': {}
|
'@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)':
|
'@astrojs/check@0.8.3(typescript@5.6.3)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@astrojs/language-server': 2.15.4(typescript@5.6.3)
|
'@astrojs/language-server': 2.15.4(typescript@5.6.3)
|
||||||
|
|
@ -5377,6 +5401,14 @@ snapshots:
|
||||||
- debug
|
- debug
|
||||||
- supports-color
|
- 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):
|
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:
|
dependencies:
|
||||||
'@astrojs/compiler': 2.10.3
|
'@astrojs/compiler': 2.10.3
|
||||||
|
|
|
||||||
BIN
public/logo.png
Normal file
BIN
public/logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 34 KiB |
|
|
@ -15,6 +15,10 @@ interface TomlData {
|
||||||
logging: boolean;
|
logging: boolean;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
seo: {
|
||||||
|
enabled: boolean;
|
||||||
|
domain: string;
|
||||||
|
};
|
||||||
db: {
|
db: {
|
||||||
name: string;
|
name: string;
|
||||||
username: string;
|
username: string;
|
||||||
|
|
@ -31,6 +35,7 @@ interface Verify {
|
||||||
name: string;
|
name: string;
|
||||||
typeOF: any;
|
typeOF: any;
|
||||||
type: any;
|
type: any;
|
||||||
|
verifyExtras?: () => boolean | Error;
|
||||||
}
|
}
|
||||||
|
|
||||||
let doc = readFileSync(fileURLToPath(new URL("../config.toml", import.meta.url))).toString();
|
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) {
|
if (typeof t[i].typeOF !== t[i].type) {
|
||||||
throw new Error(`Invalid structure: "${t[i].name}" should be a(n) ${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.port", typeOF: parsedDoc.server.server.port, type: "number" },
|
||||||
{ name: "server.server.wisp", typeOF: parsedDoc.server.server.wisp, type: "boolean" },
|
{ name: "server.server.wisp", typeOF: parsedDoc.server.server.wisp, type: "boolean" },
|
||||||
{ name: "server.server.logging", typeOF: parsedDoc.server.server.logging, 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", typeOF: parsedDoc.db, type: "object" },
|
||||||
{ name: "db.name", typeOF: parsedDoc.db.name, type: "string" },
|
{ name: "db.name", typeOF: parsedDoc.db.name, type: "string" },
|
||||||
{ name: "db.username", typeOF: parsedDoc.db.username, type: "string" },
|
{ name: "db.username", typeOF: parsedDoc.db.username, type: "string" },
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,7 @@ async function setupDB(db: ModelStatic<CatalogModel>) {
|
||||||
{
|
{
|
||||||
package_name: "com.nebula.gruvbox",
|
package_name: "com.nebula.gruvbox",
|
||||||
title: "Gruvbox",
|
title: "Gruvbox",
|
||||||
image: "gruvbox.jpeg",
|
image: "gruvbox.jpg",
|
||||||
author: "Nebula Services",
|
author: "Nebula Services",
|
||||||
version: "1.0.0",
|
version: "1.0.0",
|
||||||
description: "The gruvbox theme",
|
description: "The gruvbox theme",
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,8 @@ import { ViewTransitions } from "astro:transitions";
|
||||||
import Header from "@components/Header.astro";
|
import Header from "@components/Header.astro";
|
||||||
import MobileNavigation from "@components/MobileNavigation.astro";
|
import MobileNavigation from "@components/MobileNavigation.astro";
|
||||||
import SettingsLoader from "@components/settings/Loader.astro";
|
import SettingsLoader from "@components/settings/Loader.astro";
|
||||||
|
import { SEO } from "astro-seo";
|
||||||
|
import { SEO as SEOC } from "astro:env/client";
|
||||||
interface Props {
|
interface Props {
|
||||||
title: string;
|
title: string;
|
||||||
noHeader?: string;
|
noHeader?: string;
|
||||||
|
|
@ -11,6 +13,8 @@ interface Props {
|
||||||
}
|
}
|
||||||
|
|
||||||
const { title, noHeader, description, image } = Astro.props;
|
const { title, noHeader, description, image } = Astro.props;
|
||||||
|
const SEOConfig = JSON.parse(SEOC);
|
||||||
|
const Host = Astro.url.host;
|
||||||
---
|
---
|
||||||
|
|
||||||
<!doctype html>
|
<!doctype html>
|
||||||
|
|
@ -18,35 +22,61 @@ const { title, noHeader, description, image } = Astro.props;
|
||||||
<head>
|
<head>
|
||||||
<SettingsLoader transition:persist />
|
<SettingsLoader transition:persist />
|
||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<meta
|
<SEO
|
||||||
name="description"
|
title={title},
|
||||||
content={description ? description : "Astro description"}
|
titleTemplate=`${SEOConfig.enabled && Host === SEOConfig.domain ? 'Nebula | %s': '%s'}`,
|
||||||
/>
|
titleDefault=`${SEOConfig.enabled && Host === SEOConfig.domain ? 'Nebula': ''}`,
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
description=`${SEOConfig.enabled && Host === SEOConfig.domain ? description ? description : 'A stunning and sleek web proxy with support for hundreds of popular sites.' : ''}`,
|
||||||
<meta property="og:image" content={image ? image : ""} />
|
charset="UTF-8",
|
||||||
<link rel="icon" type="image/svg+xml" href="/favicon.svg" id="favicon" />
|
openGraph={{
|
||||||
|
basic: {
|
||||||
|
title: `${SEOConfig.enabled && Host === SEOConfig.domain ? 'Nebula' :''}`,
|
||||||
|
type: 'website',
|
||||||
|
url: `${SEOConfig.enabled && Host === SEOConfig.domain ? 'https://nebulaproxy.io' : ''}`,
|
||||||
|
image: `${SEOConfig.enabled && Host === SEOConfig.domain ? image ? image : '/logo.png': ''}`
|
||||||
|
},
|
||||||
|
optional: {
|
||||||
|
description: `${SEOConfig.enabled && Host === SEOConfig.domain ? description ? description : 'A stunning and sleek web proxy with support for hundreds of popular sites.' : ''}`
|
||||||
|
}
|
||||||
|
}},
|
||||||
|
twitter={{
|
||||||
|
card: "summary_large_image",
|
||||||
|
title: `${SEOConfig.enabled && Host === SEOConfig.domain ? 'Nebula' : ''}`,
|
||||||
|
description: `${SEOConfig.enabled && Host === SEOConfig.domain ? description ? description : 'A stunning and sleek web proxy with support for hundreds of popular sites.' : ''}`,
|
||||||
|
image: `${SEOConfig.enabled && Host === SEOConfig.domain ? image ? image : '/logo.png': ''}`,
|
||||||
|
imageAlt: `${image ? 'Catalog image' : `${SEOConfig.enabled && Host === SEOConfig.domain && "Nebula services's"} logo`}`
|
||||||
|
}},
|
||||||
|
extend={{
|
||||||
|
link: [
|
||||||
|
{ rel: 'icon', type: 'image/svg+xml', href: '/favicon.svg', id: 'favicon' },
|
||||||
|
{
|
||||||
|
rel: 'preload',
|
||||||
|
href: "https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,100;0,300;0,400;0,500;0,700;0,900;1,100;1,300;1,400;1,500;1,700;1,900&display=swap",
|
||||||
|
as: 'style',
|
||||||
|
crossorigin: 'anonymous'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
rel: 'preload',
|
||||||
|
href: "https://fonts.gstatic.com/s/roboto/v32/KFOmCnqEu92Fr1Mu4mxK.woff2",
|
||||||
|
as: 'font',
|
||||||
|
type: 'font/woff2',
|
||||||
|
crossorigin: 'anonymous'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
meta: [
|
||||||
|
{ name: 'viewport', content: 'width=device-width, initial-scale=1.0' },
|
||||||
|
{ name: 'generator', content: `${Astro.generator}` }
|
||||||
|
]
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
{/* I left this out of the SEO component as we need it to persist properly : D */}
|
||||||
<link
|
<link
|
||||||
rel="stylesheet"
|
rel="stylesheet"
|
||||||
href="/nebula.css"
|
href="/nebula.css"
|
||||||
id="stylesheet"
|
id="stylesheet"
|
||||||
transition:persist
|
transition:persist
|
||||||
/>
|
/>
|
||||||
<link
|
<ViewTransitions fallback="animate" />
|
||||||
rel="preload"
|
|
||||||
href="https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,100;0,300;0,400;0,500;0,700;0,900;1,100;1,300;1,400;1,500;1,700;1,900&display=swap"
|
|
||||||
as="style"
|
|
||||||
crossorigin="anonymous"
|
|
||||||
/>
|
|
||||||
<link
|
|
||||||
rel="preload"
|
|
||||||
href="https://fonts.gstatic.com/s/roboto/v32/KFOmCnqEu92Fr1Mu4mxK.woff2"
|
|
||||||
as="font"
|
|
||||||
type="font/woff2"
|
|
||||||
crossorigin="anonymous"
|
|
||||||
/>
|
|
||||||
<meta name="generator" content={Astro.generator} />
|
|
||||||
<title>{title}</title>
|
|
||||||
<ViewTransitions />
|
|
||||||
</head>
|
</head>
|
||||||
<body class="h-full bg-primary">
|
<body class="h-full bg-primary">
|
||||||
{!noHeader && <Header />}
|
{!noHeader && <Header />}
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ const assetsJson = await response.json();
|
||||||
<Layout
|
<Layout
|
||||||
title={`Package: ${assetsJson.title}`}
|
title={`Package: ${assetsJson.title}`}
|
||||||
description=`${assetsJson.title} is a package on Nebula. Start using this package on Nebula today!`
|
description=`${assetsJson.title} is a package on Nebula. Start using this package on Nebula today!`
|
||||||
image={assetsJson.image}
|
image={`/packages/${packageName}/${assetsJson.image}`}
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="flex flex-wrap min-[1032px]:mt-16 mt-8 w-full fixed inset-0 h-full md:h-[calc(100%-4rem)] z-0 bg-primary flex-col items-center content-center justify-center lg:pb-64 font-roboto max-md:p-4"
|
class="flex flex-wrap min-[1032px]:mt-16 mt-8 w-full fixed inset-0 h-full md:h-[calc(100%-4rem)] z-0 bg-primary flex-col items-center content-center justify-center lg:pb-64 font-roboto max-md:p-4"
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ const t = useTranslations(lang);
|
||||||
import { VERSION } from "astro:env/client";
|
import { VERSION } from "astro:env/client";
|
||||||
---
|
---
|
||||||
|
|
||||||
<Layout title="Nebula">
|
<Layout title="Home">
|
||||||
<div
|
<div
|
||||||
class="flex flex-wrap mt-16 justify-center content-center w-full bg-primary fixed inset-0 h-[calc(100%-4rem)] z-0 flex-col items-center"
|
class="flex flex-wrap mt-16 justify-center content-center w-full bg-primary fixed inset-0 h-[calc(100%-4rem)] z-0 flex-col items-center"
|
||||||
>
|
>
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ import Loading from "@components/Loading.astro";
|
||||||
import Layout from "@layouts/Layout.astro";
|
import Layout from "@layouts/Layout.astro";
|
||||||
---
|
---
|
||||||
|
|
||||||
<Layout title="Loading..." noHeader="true">
|
<Layout title="" noHeader="true">
|
||||||
<Loading />
|
<Loading />
|
||||||
</Layout>
|
</Layout>
|
||||||
<script>
|
<script>
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue