Update site configuration and enhance SEO with structured data
- Changed site URL in configuration from 'https://example.com' to 'https://nicholai.work'. - Updated site title and description for better SEO optimization. - Removed outdated portrait images and replaced them with optimized formats in the hero section. - Enhanced BaseHead component with structured data for improved search engine visibility. - Added reading time calculation to blog posts for better user engagement.
This commit is contained in:
parent
e2d2ada330
commit
673a937db3
@ -12,7 +12,7 @@ import react from '@astrojs/react';
|
|||||||
|
|
||||||
// https://astro.build/config
|
// https://astro.build/config
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
site: 'https://example.com',
|
site: 'https://nicholai.work',
|
||||||
integrations: [mdx(), sitemap(), react()],
|
integrations: [mdx(), sitemap(), react()],
|
||||||
|
|
||||||
adapter: cloudflare({
|
adapter: cloudflare({
|
||||||
|
|||||||
30
dev/blog_template.mdx
Normal file
30
dev/blog_template.mdx
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
---
|
||||||
|
title: 'Your Blog Post Title Here'
|
||||||
|
description: 'A compelling one-sentence description that summarizes the blog post. This appears in meta tags and previews.'
|
||||||
|
pubDate: 'Jan 1 2024'
|
||||||
|
heroImage: '../../assets/blog-placeholder-1.jpg'
|
||||||
|
featured: true
|
||||||
|
category: 'Case Study'
|
||||||
|
tags: ['VFX', 'Houdini', 'Nuke', 'AI/ML', 'Brand Film']
|
||||||
|
---
|
||||||
|
|
||||||
|
<!-- Introduction paragraph: Set the context and hook the reader -->
|
||||||
|
[Write your opening paragraph here. Introduce the project, collaboration, or topic. This should be engaging and provide context for what follows.]
|
||||||
|
|
||||||
|
<!-- Optional: Main hero video or image -->
|
||||||
|
<div class="video-container my-10">
|
||||||
|
<video controls class="w-full border border-white/10">
|
||||||
|
<source src="https://media.nicholai.work/your-video.mp4" type="video/mp4" />
|
||||||
|
Your browser does not support the video tag.
|
||||||
|
</video>
|
||||||
|
<p class="text-slate-500 text-sm mt-3 font-mono">/// FINAL FILM</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Alternative: If using an image instead of video -->
|
||||||
|
<!--
|
||||||
|
<div class="my-10">
|
||||||
|
<img src="path/to/image.jpg" alt="Description" class="w-full border border-white/10" />
|
||||||
|
<p class="text-slate-500 text-sm mt-3 font-mono">/// HERO IMAGE</p>
|
||||||
|
</div>
|
||||||
|
-->
|
||||||
|
|
||||||
5
public/robots.txt
Normal file
5
public/robots.txt
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
User-agent: *
|
||||||
|
Allow: /
|
||||||
|
|
||||||
|
Sitemap: https://nicholai.work/sitemap-index.xml
|
||||||
|
|
||||||
|
Before Width: | Height: | Size: 3.3 MiB After Width: | Height: | Size: 3.3 MiB |
|
Before Width: | Height: | Size: 199 KiB After Width: | Height: | Size: 199 KiB |
@ -3,23 +3,110 @@
|
|||||||
// all pages through the use of the <BaseHead /> component.
|
// all pages through the use of the <BaseHead /> component.
|
||||||
import '../styles/global.css';
|
import '../styles/global.css';
|
||||||
import type { ImageMetadata } from 'astro';
|
import type { ImageMetadata } from 'astro';
|
||||||
import FallbackImage from '../assets/blog-placeholder-1.jpg';
|
import DefaultOGImage from '../assets/nicholai-medium-portrait.jpg';
|
||||||
import { SITE_TITLE } from '../consts';
|
import { SITE_TITLE, SITE_DESCRIPTION, SOCIAL_LINKS } from '../consts';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
title: string;
|
title: string;
|
||||||
description: string;
|
description: string;
|
||||||
image?: ImageMetadata;
|
image?: ImageMetadata;
|
||||||
|
type?: 'website' | 'article';
|
||||||
|
publishedTime?: Date;
|
||||||
|
modifiedTime?: Date;
|
||||||
}
|
}
|
||||||
|
|
||||||
const canonicalURL = new URL(Astro.url.pathname, Astro.site);
|
const canonicalURL = new URL(Astro.url.pathname, Astro.site);
|
||||||
|
|
||||||
const { title, description, image = FallbackImage } = Astro.props;
|
const {
|
||||||
|
title,
|
||||||
|
description,
|
||||||
|
image = DefaultOGImage,
|
||||||
|
type = 'website',
|
||||||
|
publishedTime,
|
||||||
|
modifiedTime,
|
||||||
|
} = Astro.props;
|
||||||
|
|
||||||
|
// Structured Data - Person Schema (optimized for rich results)
|
||||||
|
const personSchema = {
|
||||||
|
"@context": "https://schema.org",
|
||||||
|
"@type": "Person",
|
||||||
|
"@id": "https://nicholai.work/#person",
|
||||||
|
"name": "Nicholai Vogel",
|
||||||
|
"givenName": "Nicholai",
|
||||||
|
"familyName": "Vogel",
|
||||||
|
"url": "https://nicholai.work",
|
||||||
|
"email": SOCIAL_LINKS.email,
|
||||||
|
"image": new URL(DefaultOGImage.src, Astro.site).toString(),
|
||||||
|
"jobTitle": "VFX Supervisor",
|
||||||
|
"description": "VFX Supervisor and Houdini Artist specializing in commercial and music video visual effects",
|
||||||
|
"worksFor": {
|
||||||
|
"@type": "Organization",
|
||||||
|
"name": "Biohazard VFX",
|
||||||
|
"url": "https://biohazardvfx.com"
|
||||||
|
},
|
||||||
|
"knowsAbout": [
|
||||||
|
"Visual Effects",
|
||||||
|
"VFX Supervision",
|
||||||
|
"Compositing",
|
||||||
|
"Houdini",
|
||||||
|
"SideFX Houdini",
|
||||||
|
"Nuke",
|
||||||
|
"The Foundry Nuke",
|
||||||
|
"3D Animation",
|
||||||
|
"AI/ML Integration",
|
||||||
|
"Motion Graphics",
|
||||||
|
"Commercial VFX",
|
||||||
|
"Music Video VFX"
|
||||||
|
],
|
||||||
|
"sameAs": [
|
||||||
|
"https://instagram.com/nicholai.exe/",
|
||||||
|
SOCIAL_LINKS.linkedin,
|
||||||
|
"https://biohazardvfx.com"
|
||||||
|
],
|
||||||
|
"alumniOf": [],
|
||||||
|
"award": []
|
||||||
|
};
|
||||||
|
|
||||||
|
// Structured Data - WebSite Schema with potential search action
|
||||||
|
const websiteSchema = {
|
||||||
|
"@context": "https://schema.org",
|
||||||
|
"@type": "WebSite",
|
||||||
|
"@id": "https://nicholai.work/#website",
|
||||||
|
"name": SITE_TITLE,
|
||||||
|
"description": SITE_DESCRIPTION,
|
||||||
|
"url": "https://nicholai.work",
|
||||||
|
"inLanguage": "en-US",
|
||||||
|
"author": {
|
||||||
|
"@id": "https://nicholai.work/#person"
|
||||||
|
},
|
||||||
|
"publisher": {
|
||||||
|
"@id": "https://nicholai.work/#person"
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Structured Data - Professional Service (helps with local/service searches)
|
||||||
|
const professionalServiceSchema = {
|
||||||
|
"@context": "https://schema.org",
|
||||||
|
"@type": "ProfessionalService",
|
||||||
|
"@id": "https://nicholai.work/#service",
|
||||||
|
"name": "Nicholai Vogel - VFX Services",
|
||||||
|
"description": "Professional visual effects services including VFX supervision, Houdini FX, compositing, and AI integration for commercials and music videos",
|
||||||
|
"url": "https://nicholai.work",
|
||||||
|
"provider": {
|
||||||
|
"@id": "https://nicholai.work/#person"
|
||||||
|
},
|
||||||
|
"areaServed": "Worldwide",
|
||||||
|
"serviceType": ["VFX Supervision", "Visual Effects", "Compositing", "3D Animation", "Motion Graphics"]
|
||||||
|
};
|
||||||
---
|
---
|
||||||
|
|
||||||
<!-- Global Metadata -->
|
<!-- Global Metadata -->
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<meta name="viewport" content="width=device-width,initial-scale=1" />
|
<meta name="viewport" content="width=device-width,initial-scale=1" />
|
||||||
|
<meta name="theme-color" content="#0B0D11" />
|
||||||
|
<meta name="color-scheme" content="dark" />
|
||||||
|
<meta name="robots" content="index, follow" />
|
||||||
|
<meta name="author" content="Nicholai Vogel" />
|
||||||
<link rel="icon" type="image/x-icon" href="/favicon.ico" />
|
<link rel="icon" type="image/x-icon" href="/favicon.ico" />
|
||||||
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32.png" />
|
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32.png" />
|
||||||
<link rel="icon" type="image/png" sizes="192x192" href="/favicon-192.png" />
|
<link rel="icon" type="image/png" sizes="192x192" href="/favicon-192.png" />
|
||||||
@ -33,15 +120,24 @@ const { title, description, image = FallbackImage } = Astro.props;
|
|||||||
/>
|
/>
|
||||||
<meta name="generator" content={Astro.generator} />
|
<meta name="generator" content={Astro.generator} />
|
||||||
|
|
||||||
<!-- Fonts -->
|
<!-- Fonts - Preconnect and load with display=swap -->
|
||||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
||||||
<link
|
<link
|
||||||
href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;600;800&family=Space+Mono:wght@400;700&display=swap"
|
href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;600;800&family=Space+Mono:wght@400;700&display=swap"
|
||||||
rel="stylesheet">
|
rel="stylesheet"
|
||||||
|
media="print"
|
||||||
|
onload="this.media='all'"
|
||||||
|
/>
|
||||||
|
<noscript>
|
||||||
|
<link
|
||||||
|
href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;600;800&family=Space+Mono:wght@400;700&display=swap"
|
||||||
|
rel="stylesheet"
|
||||||
|
/>
|
||||||
|
</noscript>
|
||||||
|
|
||||||
<!-- Icons -->
|
<!-- Icons - Load async to prevent render blocking -->
|
||||||
<script src="https://unpkg.com/lucide@latest"></script>
|
<script src="https://unpkg.com/lucide@latest" defer></script>
|
||||||
|
|
||||||
<!-- Canonical URL -->
|
<!-- Canonical URL -->
|
||||||
<link rel="canonical" href={canonicalURL} />
|
<link rel="canonical" href={canonicalURL} />
|
||||||
@ -52,15 +148,25 @@ const { title, description, image = FallbackImage } = Astro.props;
|
|||||||
<meta name="description" content={description} />
|
<meta name="description" content={description} />
|
||||||
|
|
||||||
<!-- Open Graph / Facebook -->
|
<!-- Open Graph / Facebook -->
|
||||||
<meta property="og:type" content="website" />
|
<meta property="og:type" content={type} />
|
||||||
<meta property="og:url" content={Astro.url} />
|
<meta property="og:url" content={Astro.url} />
|
||||||
<meta property="og:title" content={title} />
|
<meta property="og:title" content={title} />
|
||||||
<meta property="og:description" content={description} />
|
<meta property="og:description" content={description} />
|
||||||
<meta property="og:image" content={new URL(image.src, Astro.url)} />
|
<meta property="og:image" content={new URL(image.src, Astro.url)} />
|
||||||
|
<meta property="og:site_name" content={SITE_TITLE} />
|
||||||
|
<meta property="og:locale" content="en_US" />
|
||||||
|
{publishedTime && <meta property="article:published_time" content={publishedTime.toISOString()} />}
|
||||||
|
{modifiedTime && <meta property="article:modified_time" content={modifiedTime.toISOString()} />}
|
||||||
|
|
||||||
<!-- Twitter -->
|
<!-- Twitter -->
|
||||||
<meta property="twitter:card" content="summary_large_image" />
|
<meta name="twitter:card" content="summary_large_image" />
|
||||||
<meta property="twitter:url" content={Astro.url} />
|
<meta name="twitter:url" content={Astro.url.toString()} />
|
||||||
<meta property="twitter:title" content={title} />
|
<meta name="twitter:title" content={title} />
|
||||||
<meta property="twitter:description" content={description} />
|
<meta name="twitter:description" content={description} />
|
||||||
<meta property="twitter:image" content={new URL(image.src, Astro.url)} />
|
<meta name="twitter:image" content={new URL(image.src, Astro.url).toString()} />
|
||||||
|
<meta name="twitter:creator" content="@nicholai_exe" />
|
||||||
|
|
||||||
|
<!-- Structured Data - JSON-LD -->
|
||||||
|
<script type="application/ld+json" set:html={JSON.stringify(personSchema)} />
|
||||||
|
<script type="application/ld+json" set:html={JSON.stringify(websiteSchema)} />
|
||||||
|
<script type="application/ld+json" set:html={JSON.stringify(professionalServiceSchema)} />
|
||||||
|
|||||||
@ -1,4 +1,7 @@
|
|||||||
---
|
---
|
||||||
|
import { Picture } from 'astro:assets';
|
||||||
|
import heroPortrait from '../../assets/nicholai-closeup-portrait.JPEG';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
headlineLine1: string;
|
headlineLine1: string;
|
||||||
headlineLine2: string;
|
headlineLine2: string;
|
||||||
@ -11,14 +14,19 @@ interface Props {
|
|||||||
const { headlineLine1, headlineLine2, portfolioYear, location, locationLabel, bio } = Astro.props;
|
const { headlineLine1, headlineLine2, portfolioYear, location, locationLabel, bio } = Astro.props;
|
||||||
---
|
---
|
||||||
<section id="hero" class="relative w-full h-[100dvh] overflow-hidden bg-brand-dark">
|
<section id="hero" class="relative w-full h-[100dvh] overflow-hidden bg-brand-dark">
|
||||||
<!-- Background Image (Portrait) -->
|
<!-- Background Image (Portrait) - Optimized with AVIF/WebP -->
|
||||||
<div class="absolute top-0 right-0 w-full md:w-1/2 h-full z-0">
|
<div class="absolute top-0 right-0 w-full md:w-1/2 h-full z-0">
|
||||||
<div class="relative w-full h-full">
|
<div class="relative w-full h-full">
|
||||||
<img
|
<Picture
|
||||||
src="/media/nicholai-closeup-portrait.JPEG"
|
src={heroPortrait}
|
||||||
alt="Nicholai Portrait"
|
formats={['avif', 'webp']}
|
||||||
|
widths={[640, 1024, 1600]}
|
||||||
|
sizes="(max-width: 768px) 100vw, 50vw"
|
||||||
|
alt="Nicholai Vogel portrait"
|
||||||
class="w-full h-full object-cover object-center opacity-0 mix-blend-luminosity md:opacity-0 transition-opacity duration-[2000ms] ease-out delay-500 intro-element"
|
class="w-full h-full object-cover object-center opacity-0 mix-blend-luminosity md:opacity-0 transition-opacity duration-[2000ms] ease-out delay-500 intro-element"
|
||||||
id="hero-portrait"
|
id="hero-portrait"
|
||||||
|
loading="eager"
|
||||||
|
decoding="sync"
|
||||||
/>
|
/>
|
||||||
<div class="absolute inset-0 bg-gradient-to-l from-transparent via-brand-dark/50 to-brand-dark"></div>
|
<div class="absolute inset-0 bg-gradient-to-l from-transparent via-brand-dark/50 to-brand-dark"></div>
|
||||||
<div class="absolute inset-0 bg-gradient-to-t from-brand-dark via-transparent to-transparent"></div>
|
<div class="absolute inset-0 bg-gradient-to-t from-brand-dark via-transparent to-transparent"></div>
|
||||||
|
|||||||
@ -1,10 +1,14 @@
|
|||||||
// Place any global data in this file.
|
// Place any global data in this file.
|
||||||
// You can import this data from anywhere in your site by using the `import` keyword.
|
// You can import this data from anywhere in your site by using the `import` keyword.
|
||||||
|
|
||||||
export const SITE_TITLE = 'Nicholai Vogel | VFX Artist & Technical Generalist';
|
// SEO-optimized title (under 60 characters for full display in search results)
|
||||||
export const SITE_DESCRIPTION = 'VFX Artist & Technical Generalist specializing in Houdini, Nuke, and AI/ML integration. Founder of Biohazard VFX.';
|
export const SITE_TITLE = 'Nicholai Vogel — VFX Supervisor & Technical VFX Artist';
|
||||||
|
|
||||||
|
// SEO-optimized description (under 160 characters, includes keywords and CTA)
|
||||||
|
export const SITE_DESCRIPTION = 'VFX Supervisor specializing in both 2D and 3D VFX, AI and highend technical visualization. Clients: G-Star Raw, Interscope, Ralph Lauren. Founder of Biohazard VFX.';
|
||||||
|
|
||||||
export const SOCIAL_LINKS = {
|
export const SOCIAL_LINKS = {
|
||||||
email: 'nicholai@nicholai.work',
|
email: 'nicholai@nicholai.work',
|
||||||
website: 'https://nicholai.work',
|
website: 'https://nicholai.work',
|
||||||
linkedin: '#' // Update when available
|
linkedin: 'https://www.linkedin.com/in/nicholai-vogel-7a6b85112/'
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
---
|
---
|
||||||
|
import type { ImageMetadata } from 'astro';
|
||||||
import BaseHead from '../components/BaseHead.astro';
|
import BaseHead from '../components/BaseHead.astro';
|
||||||
import Footer from '../components/Footer.astro';
|
import Footer from '../components/Footer.astro';
|
||||||
import GridOverlay from '../components/GridOverlay.astro';
|
import GridOverlay from '../components/GridOverlay.astro';
|
||||||
@ -10,15 +11,35 @@ interface Props {
|
|||||||
title?: string;
|
title?: string;
|
||||||
description?: string;
|
description?: string;
|
||||||
usePadding?: boolean;
|
usePadding?: boolean;
|
||||||
|
image?: ImageMetadata;
|
||||||
|
type?: 'website' | 'article';
|
||||||
|
publishedTime?: Date;
|
||||||
|
modifiedTime?: Date;
|
||||||
}
|
}
|
||||||
|
|
||||||
const { title = SITE_TITLE, description = SITE_DESCRIPTION, usePadding = true } = Astro.props;
|
const {
|
||||||
|
title = SITE_TITLE,
|
||||||
|
description = SITE_DESCRIPTION,
|
||||||
|
usePadding = true,
|
||||||
|
image,
|
||||||
|
type = 'website',
|
||||||
|
publishedTime,
|
||||||
|
modifiedTime,
|
||||||
|
} = Astro.props;
|
||||||
---
|
---
|
||||||
|
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en" class="scroll-smooth">
|
<html lang="en" class="scroll-smooth">
|
||||||
<head>
|
<head>
|
||||||
<BaseHead title={title} description={description} />
|
<BaseHead
|
||||||
|
title={title}
|
||||||
|
description={description}
|
||||||
|
image={image}
|
||||||
|
type={type}
|
||||||
|
publishedTime={publishedTime}
|
||||||
|
modifiedTime={modifiedTime}
|
||||||
|
/>
|
||||||
|
<slot name="head" />
|
||||||
</head>
|
</head>
|
||||||
<body class="antialiased selection:bg-brand-accent selection:text-brand-dark bg-brand-dark text-white">
|
<body class="antialiased selection:bg-brand-accent selection:text-brand-dark bg-brand-dark text-white">
|
||||||
<CustomCursor client:load />
|
<CustomCursor client:load />
|
||||||
|
|||||||
@ -37,6 +37,7 @@ interface Props {
|
|||||||
prevPost?: NavPost;
|
prevPost?: NavPost;
|
||||||
nextPost?: NavPost;
|
nextPost?: NavPost;
|
||||||
relatedPosts?: RelatedPost[];
|
relatedPosts?: RelatedPost[];
|
||||||
|
readTime?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const {
|
const {
|
||||||
@ -51,13 +52,47 @@ const {
|
|||||||
prevPost,
|
prevPost,
|
||||||
nextPost,
|
nextPost,
|
||||||
relatedPosts = [],
|
relatedPosts = [],
|
||||||
|
readTime = '5 min read',
|
||||||
} = Astro.props;
|
} = Astro.props;
|
||||||
|
|
||||||
// Estimated read time (rough calculation)
|
// Article structured data (JSON-LD)
|
||||||
const readTime = '5 min read';
|
const articleSchema = {
|
||||||
|
"@context": "https://schema.org",
|
||||||
|
"@type": "Article",
|
||||||
|
"headline": title,
|
||||||
|
"description": description,
|
||||||
|
"datePublished": pubDate.toISOString(),
|
||||||
|
"dateModified": (updatedDate || pubDate).toISOString(),
|
||||||
|
"author": {
|
||||||
|
"@type": "Person",
|
||||||
|
"name": "Nicholai Vogel",
|
||||||
|
"url": "https://nicholai.work"
|
||||||
|
},
|
||||||
|
"publisher": {
|
||||||
|
"@type": "Person",
|
||||||
|
"name": "Nicholai Vogel",
|
||||||
|
"url": "https://nicholai.work"
|
||||||
|
},
|
||||||
|
"mainEntityOfPage": {
|
||||||
|
"@type": "WebPage",
|
||||||
|
"@id": Astro.url.href
|
||||||
|
},
|
||||||
|
...(heroImage && { "image": new URL(heroImage.src, Astro.url).toString() }),
|
||||||
|
...(category && { "articleSection": category }),
|
||||||
|
...(tags && tags.length > 0 && { "keywords": tags.join(", ") })
|
||||||
|
};
|
||||||
---
|
---
|
||||||
|
|
||||||
<BaseLayout title={title} description={description} image={heroImage}>
|
<BaseLayout
|
||||||
|
title={title}
|
||||||
|
description={description}
|
||||||
|
image={heroImage}
|
||||||
|
type="article"
|
||||||
|
publishedTime={pubDate}
|
||||||
|
modifiedTime={updatedDate}
|
||||||
|
>
|
||||||
|
<!-- Article Structured Data -->
|
||||||
|
<script type="application/ld+json" set:html={JSON.stringify(articleSchema)} slot="head" />
|
||||||
<ReadingProgress />
|
<ReadingProgress />
|
||||||
|
|
||||||
<article class="relative pb-24">
|
<article class="relative pb-24">
|
||||||
|
|||||||
@ -89,6 +89,12 @@ interface Props {
|
|||||||
|
|
||||||
const { post, prevPost, nextPost, relatedPosts } = Astro.props;
|
const { post, prevPost, nextPost, relatedPosts } = Astro.props;
|
||||||
const { Content, headings } = await render(post);
|
const { Content, headings } = await render(post);
|
||||||
|
|
||||||
|
// Calculate reading time (average 200 words per minute)
|
||||||
|
const wordsPerMinute = 200;
|
||||||
|
const wordCount = post.body?.split(/\s+/).length || 0;
|
||||||
|
const readingTime = Math.max(1, Math.ceil(wordCount / wordsPerMinute));
|
||||||
|
const readTimeText = `${readingTime} min read`;
|
||||||
---
|
---
|
||||||
|
|
||||||
<BlogPost
|
<BlogPost
|
||||||
@ -97,6 +103,7 @@ const { Content, headings } = await render(post);
|
|||||||
prevPost={prevPost}
|
prevPost={prevPost}
|
||||||
nextPost={nextPost}
|
nextPost={nextPost}
|
||||||
relatedPosts={relatedPosts}
|
relatedPosts={relatedPosts}
|
||||||
|
readTime={readTimeText}
|
||||||
>
|
>
|
||||||
<Content />
|
<Content />
|
||||||
</BlogPost>
|
</BlogPost>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user