mirror of
https://github.com/versia-pub/blog.git
synced 2025-12-06 00:48:18 +01:00
feat: ✨ Improve image rendering, add more branding and SEO
This commit is contained in:
parent
3a0d5822fd
commit
d05288ae68
13
app.vue
13
app.vue
|
|
@ -3,3 +3,16 @@
|
||||||
<NuxtPage />
|
<NuxtPage />
|
||||||
</NuxtLayout>
|
</NuxtLayout>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { useSchemaOrg, useServerSeoMeta } from "#imports";
|
||||||
|
import { logo, org } from "./types/schemas.ts";
|
||||||
|
|
||||||
|
useServerSeoMeta({
|
||||||
|
titleTemplate: (titleChunk) => {
|
||||||
|
return titleChunk ? `${titleChunk} · Versia Blog` : "Versia Blog";
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
useSchemaOrg([org, logo]);
|
||||||
|
</script>
|
||||||
|
|
@ -6,8 +6,6 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { defineProps } from "vue";
|
|
||||||
|
|
||||||
defineProps<{
|
defineProps<{
|
||||||
body: string;
|
body: string;
|
||||||
}>();
|
}>();
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,12 @@
|
||||||
<template>
|
<template>
|
||||||
<nuxt-img :src="image" width="800" format="webp" alt=""
|
<nuxt-img :src="image" :width="width" :height="height" format="webp" alt="" :preload="true"
|
||||||
class="drop-shadow-2xl w-full rounded bg-zinc-900 ring-1 ring-white/10" />
|
class="drop-shadow-2xl w-full rounded bg-zinc-900 ring-1 ring-white/10" />
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { defineProps } from "vue";
|
|
||||||
|
|
||||||
defineProps<{
|
defineProps<{
|
||||||
image: string;
|
image: string;
|
||||||
|
width?: number;
|
||||||
|
height?: number;
|
||||||
}>();
|
}>();
|
||||||
</script>
|
</script>
|
||||||
|
|
@ -12,8 +12,6 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { defineProps } from "vue";
|
|
||||||
|
|
||||||
defineProps<{
|
defineProps<{
|
||||||
title: string;
|
title: string;
|
||||||
created_at: string;
|
created_at: string;
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,13 @@ export const getPost = async (path: string): Promise<Post | null> => {
|
||||||
content: renderedBody,
|
content: renderedBody,
|
||||||
created_at: new Date(Number(header.created_at || 0)).toISOString(),
|
created_at: new Date(Number(header.created_at || 0)).toISOString(),
|
||||||
description: header.description,
|
description: header.description,
|
||||||
image: header.image,
|
image: {
|
||||||
|
url: header.image,
|
||||||
|
width: header.image_width ? Number(header.image_width) : undefined,
|
||||||
|
height: header.image_height
|
||||||
|
? Number(header.image_height)
|
||||||
|
: undefined,
|
||||||
|
},
|
||||||
title: header.title,
|
title: header.title,
|
||||||
path,
|
path,
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,8 @@ title: A test post for the Versia Blog
|
||||||
created_at: 1700020246000
|
created_at: 1700020246000
|
||||||
description: This is a test post for the Versia Blog. I write this post to test the blog system.
|
description: This is a test post for the Versia Blog. I write this post to test the blog system.
|
||||||
image: https://images.pexels.com/photos/2646237/pexels-photo-2646237.jpeg
|
image: https://images.pexels.com/photos/2646237/pexels-photo-2646237.jpeg
|
||||||
|
image_width: 6000
|
||||||
|
image_height: 4000
|
||||||
author: CPlusPatch
|
author: CPlusPatch
|
||||||
author_image: https://mk-cdn.cpluspatch.com/uploads/5cd850d3-6b6b-4543-97ca-9854b9dbf9f3.webp
|
author_image: https://mk-cdn.cpluspatch.com/uploads/5cd850d3-6b6b-4543-97ca-9854b9dbf9f3.webp
|
||||||
author_handle: @jessewh
|
author_handle: @jessewh
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
import { readdirSync } from "node:fs";
|
import { readdirSync } from "node:fs";
|
||||||
import { join } from "node:path";
|
import { join } from "node:path";
|
||||||
import { defineNuxtConfig } from "nuxt/config";
|
import { defineNuxtConfig } from "nuxt/config";
|
||||||
|
import { org } from "./types/schemas.ts";
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Reads the content directory and returns an array of all the files in the directory and subdirectories.
|
* Reads the content directory and returns an array of all the files in the directory and subdirectories.
|
||||||
|
|
@ -110,4 +111,26 @@ export default defineNuxtConfig({
|
||||||
failOnError: true,
|
failOnError: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
app: {
|
||||||
|
head: {
|
||||||
|
link: [
|
||||||
|
{
|
||||||
|
rel: "icon",
|
||||||
|
href: "/favicon.png",
|
||||||
|
type: "image/png",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
htmlAttrs: {
|
||||||
|
lang: "en-us",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
schemaOrg: {
|
||||||
|
identity: {
|
||||||
|
name: "Versia",
|
||||||
|
logo: "https://versia.pub/#logo",
|
||||||
|
url: "https://versia.pub",
|
||||||
|
sameAs: [],
|
||||||
|
},
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
<template>
|
<template>
|
||||||
<div v-if="post" class="mx-auto max-w-3xl py-24 sm:py-32 px-6 lg:px-8 flex flex-col items-center gap-10">
|
<div v-if="post" class="mx-auto max-w-3xl py-24 sm:py-32 px-6 lg:px-8 flex flex-col items-center gap-10">
|
||||||
<Title v-if="post.title" :created_at="post.created_at" :title="post.title" />
|
<Title v-if="post.title" :created_at="post.created_at" :title="post.title" />
|
||||||
<Image v-if="post.image" :image="post.image" />
|
<Image v-if="post.image" :image="post.image.url" :width="post.image.width" :height="post.image.height" />
|
||||||
<Content :body="body" />
|
<Content :body="body" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
@ -36,12 +36,19 @@ if (!post.value) {
|
||||||
|
|
||||||
useSchemaOrg([
|
useSchemaOrg([
|
||||||
defineArticle({
|
defineArticle({
|
||||||
// author: post.value.author.name,
|
author: {
|
||||||
|
name: post.value.author.name,
|
||||||
|
image: post.value.author.image,
|
||||||
|
},
|
||||||
datePublished: post.value.created_at,
|
datePublished: post.value.created_at,
|
||||||
image: post.value.image,
|
image: {
|
||||||
|
url: post.value.image.url,
|
||||||
|
width: post.value.image.width,
|
||||||
|
height: post.value.image.height,
|
||||||
|
},
|
||||||
description: post.value.description,
|
description: post.value.description,
|
||||||
inLanguage: "en-US",
|
inLanguage: "en-US",
|
||||||
thumbnailUrl: post.value.image,
|
thumbnailUrl: post.value.image.url,
|
||||||
}),
|
}),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
|
@ -51,8 +58,11 @@ useServerSeoMeta({
|
||||||
author: post.value.author.name,
|
author: post.value.author.name,
|
||||||
description: post.value.description,
|
description: post.value.description,
|
||||||
ogDescription: post.value.description,
|
ogDescription: post.value.description,
|
||||||
ogImage: post.value.image,
|
ogImage: post.value.image.url,
|
||||||
|
ogImageHeight: post.value.image.height,
|
||||||
|
ogImageWidth: post.value.image.width,
|
||||||
twitterCard: "summary_large_image",
|
twitterCard: "summary_large_image",
|
||||||
|
twitterImage: post.value.image.url,
|
||||||
});
|
});
|
||||||
|
|
||||||
let body = post.value.content;
|
let body = post.value.content;
|
||||||
|
|
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 4.2 KiB |
BIN
public/favicon.png
Normal file
BIN
public/favicon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.8 KiB |
|
|
@ -1,4 +1,3 @@
|
||||||
import { join } from "node:path";
|
|
||||||
import { getPost } from "~/composables/server/Post";
|
import { getPost } from "~/composables/server/Post";
|
||||||
import { createError, defineEventHandler } from "#imports";
|
import { createError, defineEventHandler } from "#imports";
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,7 @@
|
||||||
{
|
{
|
||||||
// https://nuxt.com/docs/guide/concepts/typescript
|
// https://nuxt.com/docs/guide/concepts/typescript
|
||||||
"extends": "./.nuxt/tsconfig.json"
|
"extends": "./.nuxt/tsconfig.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"allowImportingTsExtensions": true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,8 @@ export interface FrontMatter {
|
||||||
title: string;
|
title: string;
|
||||||
description: string;
|
description: string;
|
||||||
image: string;
|
image: string;
|
||||||
|
image_width?: number;
|
||||||
|
image_height?: number;
|
||||||
created_at: string;
|
created_at: string;
|
||||||
private?: string;
|
private?: string;
|
||||||
author: string;
|
author: string;
|
||||||
|
|
@ -12,7 +14,11 @@ export interface FrontMatter {
|
||||||
export interface Post {
|
export interface Post {
|
||||||
title: string;
|
title: string;
|
||||||
description: string;
|
description: string;
|
||||||
image: string;
|
image: {
|
||||||
|
url: string;
|
||||||
|
width?: number;
|
||||||
|
height?: number;
|
||||||
|
};
|
||||||
banner?: string;
|
banner?: string;
|
||||||
author: Author;
|
author: Author;
|
||||||
private: boolean;
|
private: boolean;
|
||||||
|
|
|
||||||
16
types/schemas.ts
Normal file
16
types/schemas.ts
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
import { defineImage, defineOrganization } from "#imports";
|
||||||
|
|
||||||
|
export const logo = defineImage({
|
||||||
|
"@id": "https://versia.pub/#logo",
|
||||||
|
url: "https://cdn.versia.pub/branding/png/icon.png",
|
||||||
|
width: 1024,
|
||||||
|
height: 1024,
|
||||||
|
caption: "A couple of white stars on a pink rounded square.",
|
||||||
|
});
|
||||||
|
|
||||||
|
export const org = defineOrganization({
|
||||||
|
name: "Versia",
|
||||||
|
logo: logo["@id"],
|
||||||
|
url: "https://versia.pub",
|
||||||
|
sameAs: [],
|
||||||
|
});
|
||||||
Loading…
Reference in a new issue