summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoão Augusto Costa Branco Marado Torres <torres.dev@disroot.org>2025-07-06 22:27:04 -0300
committerJoão Augusto Costa Branco Marado Torres <torres.dev@disroot.org>2025-07-06 22:27:04 -0300
commit449f71511e539878af4c65f073cdc373b469c45e (patch)
tree6c264a77426284d97d1c9b9d7a27a6015c3077a8
parent4ae2b810b68538ba4c287b0c80d6c2e002fe9ddd (diff)
feat: more structured data
Signed-off-by: João Augusto Costa Branco Marado Torres <torres.dev@disroot.org>
-rw-r--r--src/components/BaseHead.astro15
-rw-r--r--src/components/Footer.astro25
-rw-r--r--src/components/Header.astro3
-rw-r--r--src/components/organisms/Date.astro3
-rw-r--r--src/components/organisms/KeywordsList.astro2
-rw-r--r--src/components/templates/MicroBlog.astro27
-rw-r--r--src/components/templates/Search.astro15
-rw-r--r--src/components/templates/SimplePostList.astro33
-rw-r--r--src/layouts/Base.astro6
-rw-r--r--src/pages/blog/read/[...slug].astro420
-rw-r--r--src/pages/index.astro15
11 files changed, 371 insertions, 193 deletions
diff --git a/src/components/BaseHead.astro b/src/components/BaseHead.astro
index 885447c..b57127a 100644
--- a/src/components/BaseHead.astro
+++ b/src/components/BaseHead.astro
@@ -58,13 +58,22 @@ const {
type="text/html"
title={`${isOnion ? "Clearnet" : "Tor"} version`}
>
+<link
+ rel="license"
+ href="https://www.gnu.org/licenses/agpl-3.0.html"
+ itemprop="license"
+/>
<!-- Primary Meta Tags -->
<title>{title}</title>
-<meta name="title" content={title} />
-<meta name="description" content={description} />
+<meta name="title" content={title} itemprop="name" />
+<meta name="description" content={description} itemprop="description" />
<meta name="author" content={PUBLIC_SITE_AUTHOR} />
-{keywords.length > 0 && <meta name="keywords" content={keywords.join(",")} />}
+{
+ keywords.length > 0 && (
+ <meta name="keywords" content={keywords.join(",")} itemprop="keywords" />
+ )
+}
<meta name="theme-color" content="oklch(0.4564 0.1835 20.81)" />
<meta
name="theme-color"
diff --git a/src/components/Footer.astro b/src/components/Footer.astro
index 3238c50..f69ba8a 100644
--- a/src/components/Footer.astro
+++ b/src/components/Footer.astro
@@ -22,10 +22,20 @@ const git = isOnion ? PUBLIC_GIT_TOR_URL ?? PUBLIC_GIT_URL : PUBLIC_GIT_URL;
</p>
)
}
- <address>
+ <address
+ itemprop="maintainer author"
+ itemscope
+ itemtype="https://schema.org/Person"
+ >
+ <link href={site} rel="author" itemprop="url" />
<p>
- Sítio web de <a href={site} target="_blank" rel="author"
- >João Augusto Costa Branco Marado Torres</a>
+ Sítio web de <a href={site} target="_blank" rel="author" itemprop="name"
+ >João Augusto Costa Branco Marado Torres</a> &lt;<a
+ href="mailto:torres.dev@disroot.pt"
+ target="_blank"
+ rel="author"
+ itemprop="email"
+ >torres.dev@disroot.pt</a>&gt;
</p>
{
PUBLIC_SIMPLE_X_ADDRESS && (
@@ -42,10 +52,15 @@ const git = isOnion ? PUBLIC_GIT_TOR_URL ?? PUBLIC_GIT_URL : PUBLIC_GIT_URL;
</p>
<section id="copying" class="mute">
<h2 class="sr-only">Licença de <span lang="en">Software</span></h2>
- <div lang="en">
+ <div lang="en" itemprop="copyrightNotice">
<p>
&lt;<a href="/" hreflang="pt-PT">cravodeabril.pt</a>&gt; Copyright
- &copy; 2025 João Augusto Costa Branco Marado Torres
+ &copy; <time datetime="2025" itemprop="copyrightYear">2025</time> <span
+ itemprop="copyrightHolder"
+ itemscope
+ itemtype="Person"
+ ><span itemprop="name"
+ >João Augusto Costa Branco Marado Torres</span></span>
</p>
<p>
This program is free software: you can redistribute it and/or modify it
diff --git a/src/components/Header.astro b/src/components/Header.astro
index 496337f..39fe35f 100644
--- a/src/components/Header.astro
+++ b/src/components/Header.astro
@@ -5,7 +5,8 @@ import Search from "./templates/Search.astro";
<header>
<h1>
- <span class="bracket">&lt;</span><a href="/">cravodeabril.pt</a><span
+ <span class="bracket">&lt;</span><a itemprop="url" href="/"
+ >cravodeabril.pt</a><span
class="bracket"
>&gt;</span>
</h1>
diff --git a/src/components/organisms/Date.astro b/src/components/organisms/Date.astro
index c1ec7e5..960cfb7 100644
--- a/src/components/organisms/Date.astro
+++ b/src/components/organisms/Date.astro
@@ -1,8 +1,11 @@
---
+import type { HTMLAttributes } from "astro/types";
+
interface Props {
date: Date;
locales: Intl.LocalesArgument;
options: Intl.DateTimeFormatOptions;
+ itemprop: HTMLAttributes<"time">["itemprop"];
}
const { date, locales, options } = Astro.props;
diff --git a/src/components/organisms/KeywordsList.astro b/src/components/organisms/KeywordsList.astro
index 4d4b140..d3b9e7f 100644
--- a/src/components/organisms/KeywordsList.astro
+++ b/src/components/organisms/KeywordsList.astro
@@ -7,7 +7,7 @@ const { keywords } = Astro.props;
---
<p>
- {keywords.map((x) => <span>#<b>{x}</b></span>)}
+ {keywords.map((x) => <span>#<b itemprop="keywords">{x}</b></span>)}
</p>
<style>
diff --git a/src/components/templates/MicroBlog.astro b/src/components/templates/MicroBlog.astro
index c16155e..88321dc 100644
--- a/src/components/templates/MicroBlog.astro
+++ b/src/components/templates/MicroBlog.astro
@@ -2,12 +2,9 @@
import Date from "@components/organisms/Date.astro";
import KeywordsList from "@components/organisms/KeywordsList.astro";
import { getFirstUserID, getLastUpdate } from "@lib/collection/helpers";
-import { Micro } from "@lib/collection/schemas";
-import type { CollectionEntry, z } from "astro:content";
+import type { Micro, MicroEntry } from "@lib/collection/schemas";
-interface Props extends CollectionEntry<"blog"> {
- data: z.infer<typeof Micro>;
-}
+interface Props extends MicroEntry {}
const micro = Astro.props;
const { id, data, rendered } = micro;
@@ -19,10 +16,14 @@ const [first, ...names] = display.split(/\s/);
const last = names.length > 0 ? names[names.length - 1] : "";
const little = ((first?.[0] ?? "") + (last?.[0] ?? "")).slice(0, 2);
---
-<article>
+<article
+ itemprop="blogPost"
+ itemscope
+ itemtype="https://schema.org/BlogPosting"
+>
<header>
<h3 class="title">
- <a href={`/blog/read/${id}`}>{title}</a>
+ <a href={`/blog/read/${id}`} itemprop="headline name">{title}</a>
</h3>
<span class="profile_picture">{
user?.website ? <a href={user.website}>{little}</a> : (
@@ -30,15 +31,21 @@ const little = ((first?.[0] ?? "") + (last?.[0] ?? "")).slice(0, 2);
)
}</span>
<div>
- {first} {last} <small>· <Date
+ <span
+ itemprop="author"
+ itemscope
+ itemtype="https://schema.org/Person"
+ ><span itemprop="alternateName">{first} {last}</span></span>
+ <span class="small">· <Date
{date}
locales={lang}
options={{ month: "short", day: "numeric" }}
- /></small>
+ itemprop="dateModified"
+ /></span>
</div>
</header>
<div class="content small">
- <div {lang}>
+ <div {lang} itemprop="articleBody text">
<Fragment set:html={rendered?.html} />
</div>
<footer>
diff --git a/src/components/templates/Search.astro b/src/components/templates/Search.astro
index 5245643..ae80d32 100644
--- a/src/components/templates/Search.astro
+++ b/src/components/templates/Search.astro
@@ -2,8 +2,16 @@
const { site } = Astro;
---
-<search>
- <link rel="dns-prefetch" href="https://www.google.com/search">
+<search
+ itemprop="potentialAction"
+ itemscope
+ itemtype="https://schema.org/SearchAction"
+>
+ <link
+ rel="dns-prefetch"
+ href="https://www.google.com/search"
+ itemprop="target"
+ >
<form
action="https://www.google.com/search"
target="_blank"
@@ -13,7 +21,7 @@ const { site } = Astro;
name="search"
>
<details>
- <summary>Pesquisar no website</summary>
+ <summary itemprop="description">Pesquisar no website</summary>
<div class="details">
<p>
<label>Barra de pesquisa <input
@@ -25,6 +33,7 @@ const { site } = Astro;
title={`"site:${site} " é usado para que os resultados da pesquisa fiquem restritos a este website`}
pattern={`site:${site} .+`}
size={`site:${site} .+`.length}
+ itemprop="query"
/></label>
</p>
<p class="mute">
diff --git a/src/components/templates/SimplePostList.astro b/src/components/templates/SimplePostList.astro
index c2c002b..164b32b 100644
--- a/src/components/templates/SimplePostList.astro
+++ b/src/components/templates/SimplePostList.astro
@@ -21,14 +21,22 @@ const { posts } = Astro.props;
const display = name ?? email ?? entity;
return (
<li>
- <article>
- <h3><a href={`/blog/read/${id}`}>{title}</a></h3>
- {
- description &&
- description.split("\n\n").map((paragraph) => (
- <p class="small">{paragraph}</p>
- ))
- }
+ <article
+ itemprop="blogPost"
+ itemscope
+ itemtype="https://schema.org/BlogPosting"
+ >
+ <h3>
+ <a href={`/blog/read/${id}`} itemprop="headline name">{title}</a>
+ </h3>
+ <div itemprop="abstract">
+ {
+ description &&
+ description.split("\n\n").map((paragraph) => (
+ <p class="small">{paragraph}</p>
+ ))
+ }
+ </div>
<footer class="small">
<Date
@@ -39,7 +47,12 @@ const { posts } = Astro.props;
month: "long",
day: "numeric",
}}
- />{display}
+ itemprop="dateModified"
+ /><span
+ itemprop="author"
+ itemscope
+ itemtype="https://schema.org/Person"
+ ><span itemprop="alternateName">{display}</span></span>
<KeywordsList {keywords} />
</footer>
</article>
@@ -58,7 +71,7 @@ const { posts } = Astro.props;
& > article {
padding-inline-end: calc(var(--size-9) * 1em);
- & > p:not(:first-of-type) {
+ & > [itemprop="abstract"] > p:not(:first-of-type) {
margin-block-start: 1.5em;
}
diff --git a/src/layouts/Base.astro b/src/layouts/Base.astro
index afee012..f03252e 100644
--- a/src/layouts/Base.astro
+++ b/src/layouts/Base.astro
@@ -27,13 +27,15 @@ interface Props extends ComponentProps<typeof BaseHead> {
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
-->
-<html dir="ltr" lang="pt-PT">
+<html dir="ltr" lang="pt-PT" itemscope itemtype="https://schema.org/WebSite">
<head>
<BaseHead {...Astro.props} />
</head>
<body>
<Header />
- <slot />
+ <div itemscope itemtype="https://schema.org/WebPage">
+ <slot />
+ </div>
<Footer />
<noscript>I see, a man of culture :)</noscript>
</body>
diff --git a/src/pages/blog/read/[...slug].astro b/src/pages/blog/read/[...slug].astro
index 5b42e86..71d0929 100644
--- a/src/pages/blog/read/[...slug].astro
+++ b/src/pages/blog/read/[...slug].astro
@@ -1,7 +1,6 @@
---
import { type CollectionEntry, getCollection } from "astro:content";
import { render } from "astro:content";
-import BaseHead from "@components/BaseHead.astro";
import Translations from "@components/Translations.astro";
import { toIso8601Full } from "@utils/datetime";
import ReadingTime from "@components/ReadingTime.astro";
@@ -10,10 +9,17 @@ import Citations from "@components/Citations.astro";
import Signature from "@components/signature/Signature.astro";
import CopyrightNotice from "@components/CopyrightNotice.astro";
import { verifier as verifierPrototype } from "@lib/pgp/verify";
-import { getSigners } from "@lib/collection/helpers";
+import { getSigners, isTranslation } from "@lib/collection/helpers";
import { get } from "@utils/anonymous";
import Authors from "@components/signature/Authors.astro";
import { getEntry } from "astro:content";
+import Base from "@layouts/Base.astro";
+import readingTime from "reading-time";
+import type {
+ Entry,
+ MicroEntry,
+ OriginalEntry,
+} from "@lib/collection/schemas";
export async function getStaticPaths() {
const posts = await getCollection("blog");
@@ -27,11 +33,11 @@ type Props = CollectionEntry<"blog">;
const post = Astro.props;
-let original: CollectionEntry<"blog">;
-if (post.data.kind === "translation") {
- original = await getEntry(
- post.data.translationOf as CollectionEntry<"blog">,
- );
+let original: OriginalEntry | MicroEntry;
+if (isTranslation(post)) {
+ original = await getEntry(post.data.translationOf) as
+ | OriginalEntry
+ | MicroEntry;
if (!original) {
throw new Error(`Original post not found for ${post.id}`);
@@ -126,174 +132,278 @@ const { Content } = await render(post);
const { lang } = post.data;
const commit = await verification?.commit;
+
+const reading = post.body ? readingTime(post.body, {}) : undefined;
+const minutes = reading === undefined
+ ? undefined
+ : Math.ceil(reading.minutes);
+const estimative = reading === undefined
+ ? undefined
+ : new Intl.DurationFormat(lang, {
+ style: "long",
+ }).format({ minutes });
+const duration = minutes === undefined
+ ? undefined
+ : `PT${Math.floor(minutes / 60) > 0 ? Math.floor(minutes / 60) + "H" : ""}${
+ minutes % 60 > 0 ? minutes % 60 + "M" : ""
+ }`;
+
+const getOrUndefined = (k: string) =>
+ k in post.data ? post.data[k as keyof typeof post.data] : undefined;
+const author = {
+ "@type": "Person",
+} as const;
+const contributor = post.data.signers.filter(({ role }) =>
+ role === "co-author"
+).map(() => {
+ return {
+ "@type": "Person",
+ } as const;
+});
+const translator = post.data.signers.filter(({ role }) =>
+ role === "translator"
+).map(() => {
+ return {
+ "@type": "Person",
+ } as const;
+});
+const JSONLD = {
+ "@context": "https://schema.org",
+ "@type": "BlogPosting",
+ "@id": Astro.url.href,
+ articleBody: post.rendered?.html ?? post.body,
+ abstract: getOrUndefined("description"),
+ alternativeHeadline: getOrUndefined("subtitle"),
+ author,
+ citation: [].map(() => {
+ return {
+ "@type": "CreativeWork",
+ };
+ }),
+ contributor,
+ copyrightHolder: [author, ...contributor, ...translator],
+ // copyrightNotice: post.data.license, // WORKAROUND
+ copyrightYear: post.data.dateCreated.getFullYear(),
+ creativeWorkStatus: "Published",
+ dateCreated: post.data.dateCreated.toISOString(),
+ dateModified: "dateUpdated" in post.data
+ ? post.data.dateUpdated?.toISOString()
+ : undefined,
+ // datePublished: undefined, // from git commit commit date
+ encodingFormat: "text/html",
+ headline: post.data.title,
+ inLanguage: post.data.lang,
+ isAccessibleForFree: true,
+ isBasedOn: isTranslation(post)
+ ? {
+ "@type": "BlogPosting",
+ "@id": new URL(`blog/read/${post.data.translationOf}`, Astro.site).href,
+ }
+ : undefined,
+ keywords: original.data.keywords,
+ license: post.data.license, // WORKAROUND
+ locationCreated: {
+ "@type": "Place",
+ // XXX: getOrUndefined("locationCreated"),
+ },
+ mentions: [].map(() => {
+ return {
+ "@type": "Thing",
+ };
+ }),
+ // publication: {
+ // "@type": "PublicationEvent",
+ // }, // from git commit
+ // publisher: {
+ // "@type": "Person",
+ // }, // from git commit
+ text: post.rendered?.html ?? post.body,
+ timeRequired: post.body !== undefined ? duration : undefined,
+ translationOf: isTranslation(post)
+ ? {
+ "@type": "BlogPosting",
+ "@id": new URL(`blog/read/${post.data.translationOf}`, Astro.site).href,
+ }
+ : undefined,
+ translator,
+ // version: undefined // TODO
+ wordCount: reading?.words,
+ workTranslations: translations.filter(({ id }) => id !== post.id).map((
+ { id },
+ ) => ({
+ "@type": "BlogPosting",
+ "@id": new URL(`blog/read/${id}`, Astro.site).href,
+ })),
+ description: getOrUndefined("description"),
+ name: post.data.title,
+ url: Astro.url.href,
+} as const;
---
-<html lang="pt-PT">
- <head>
- <BaseHead
- title={post.data.title}
- description={"description" in post.data
- ? post.data.description
- : post.data.title}
- />
- </head>
-
- <body>
- <main>
- <article
- itemscope
- itemtype="http://schema.org/BlogPosting"
- itemid={Astro.url.href}
- >
- <Translations {translations} {lang} />
- <hgroup>
- <h1 itemprop="headline">{post.data.title}</h1>
- {
- "subtitle" in post.data && (
- <p itemprop="alternativeHeadline" class="subtitle">
- {post.data.subtitle}
- </p>
- )
- }
- </hgroup>
+<Base
+ title={post.data.title}
+ description={"description" in post.data ? post.data.description : post.data.title}
+>
+ <main>
+ <article
+ itemscope
+ itemtype="http://schema.org/BlogPosting"
+ itemid={Astro.url.href}
+ >
+ <Translations {translations} {lang} />
+ <hgroup>
+ <h1 itemprop="headline">{post.data.title}</h1>
{
- "description" in post.data && post.data.description &&
- (
- <section itemprop="abstract">
- <h2>Resumo</h2>
- {
- post.data.description.split(new RegExp("\\s{2,}"))
- .map((
- x,
- ) => <p>{x}</p>)
- }
- </section>
+ "subtitle" in post.data && (
+ <p itemprop="alternativeHeadline" class="subtitle">
+ {post.data.subtitle}
+ </p>
)
}
- {verification && <Signature {lang} {verification} />}
- <footer>
- {
- verification?.verifications &&
+ </hgroup>
+ {
+ "description" in post.data && post.data.description &&
(
- <Authors
- verifications={verification.verifications}
- expectedSigners={signers}
- commitSignerKey={commit?.signature?.signer}
- />
- )
- }
- <dl>
- <dt>Data de criação</dt>
- <dd>
- <time
- itemprop="dateCreated"
- datetime={toIso8601Full(post.data.dateCreated)}
- >{
- new Intl.DateTimeFormat([lang], {}).format(
- post.data.dateCreated,
- )
- }</time>
- </dd>
+ <section itemprop="abstract">
+ <h2>Resumo</h2>
{
- post.data.dateUpdated && (
- <dt>Última atualização</dt><dd>
- <time
- itemprop="dateModified"
- datetime={toIso8601Full(post.data.dateUpdated)}
- >{
- new Intl.DateTimeFormat([lang], {}).format(
- post.data.dateUpdated,
- )
- }</time>
- </dd>
- )
- }
- {
- "locationCreated" in post.data &&
- post.data.locationCreated && (
- <dt
- itemprop="locationCreated"
- itemscope
- itemtype="https://schema.org/Place"
- >
- Local de criação
- </dt><dd>
- <span itemprop="name">{post.data.locationCreated}</span>
- </dd>
- )
+ post.data.description.split(new RegExp("\\s{2,}"))
+ .map((
+ x,
+ ) => <p>{x}</p>)
}
- </dl>
- <ReadingTime body={post.body} {lang} />
- </footer>
- <hr />
- <div itemprop="articleBody text"><Content /></div>
- <hr />
- {
- "keywords" in original.data && (
- <Keywords keywords={original.data.keywords} />
- )
- }
+ </section>
+ )
+ }
+ {verification && <Signature {lang} {verification} />}
+ <footer>
{
- "relatedPosts" in original.data && (
- <Citations citations={original.data.relatedPosts} />
+ verification?.verifications &&
+ (
+ <Authors
+ verifications={verification.verifications}
+ expectedSigners={signers}
+ commitSignerKey={commit?.signature?.signer}
+ />
)
}
- <CopyrightNotice
- author={signers[0]?.entity.data.websites?.[0] ?? "Anonymous"}
- website={signers[0]?.entity.data.websites?.[0]}
- email={signers[0]?.entity.data.websites?.[0]}
- title={post.data.title}
- dateCreated={post.data.dateCreated}
- license={post.data.license}
- />
- </article>
- </main>
- </body>
-</html>
+ <dl>
+ <dt>Data de criação</dt>
+ <dd>
+ <time
+ itemprop="dateCreated"
+ datetime={toIso8601Full(post.data.dateCreated)}
+ >{
+ new Intl.DateTimeFormat([lang], {}).format(
+ post.data.dateCreated,
+ )
+ }</time>
+ </dd>
+ {
+ post.data.dateUpdated && (
+ <dt>Última atualização</dt><dd>
+ <time
+ itemprop="dateModified"
+ datetime={toIso8601Full(post.data.dateUpdated)}
+ >{
+ new Intl.DateTimeFormat([lang], {}).format(
+ post.data.dateUpdated,
+ )
+ }</time>
+ </dd>
+ )
+ }
+ {
+ "locationCreated" in post.data &&
+ post.data.locationCreated && (
+ <dt
+ itemprop="locationCreated"
+ itemscope
+ itemtype="https://schema.org/Place"
+ >
+ Local de criação
+ </dt><dd>
+ <span itemprop="name">{post.data.locationCreated}</span>
+ </dd>
+ )
+ }
+ </dl>
+ <ReadingTime body={post.body} {lang} />
+ </footer>
+ <hr />
+ <div itemprop="articleBody text"><Content /></div>
+ <hr />
+ {
+ "keywords" in original.data && (
+ <Keywords keywords={original.data.keywords} />
+ )
+ }
+ {
+ "relatedPosts" in original.data && (
+ <Citations citations={original.data.relatedPosts} />
+ )
+ }
+ <CopyrightNotice
+ author={signers[0]?.entity.data.websites?.[0] ?? "Anonymous"}
+ website={signers[0]?.entity.data.websites?.[0]}
+ email={signers[0]?.entity.data.websites?.[0]}
+ title={post.data.title}
+ dateCreated={post.data.dateCreated}
+ license={post.data.license}
+ />
+ </article>
+ </main>
+</Base>
+
+<script
+ type="application/ld+json"
+ is:inline
+ set:html={JSON.stringify(JSONLD)}
+/>
<script type="module" is:inline>
hashchange();
- window.addEventListener("hashchange", hashchange);
-
- document.addEventListener(
- "click",
- function (event) {
- if (
- event.target &&
- event.target instanceof HTMLAnchorElement &&
- event.target.href === location.href &&
- location.hash.length > 1
- ) {
- requestIdleCallback(function () {
- if (!event.defaultPrevented) {
- hashchange();
- }
- });
- }
- },
- false,
- );
+ window.addEventListener("hashchange", hashchange);
+
+ document.addEventListener(
+ "click",
+ function (event) {
+ if (
+ event.target &&
+ event.target instanceof HTMLAnchorElement &&
+ event.target.href === location.href &&
+ location.hash.length > 1
+ ) {
+ requestIdleCallback(function () {
+ if (!event.defaultPrevented) {
+ hashchange();
+ }
+ });
+ }
+ },
+ false,
+ );
- function hashchange() {
- let hash;
+ function hashchange() {
+ let hash;
- try {
- hash = decodeURIComponent(location.hash.slice(1)).toLowerCase();
- } catch (e) {
- return;
- }
+ try {
+ hash = decodeURIComponent(location.hash.slice(1)).toLowerCase();
+ } catch (e) {
+ return;
+ }
- const name = "user-content-" + hash;
- const target = document.getElementById(name) ||
- document.getElementsByName(name)[0];
+ const name = "user-content-" + hash;
+ const target = document.getElementById(name) ||
+ document.getElementsByName(name)[0];
- if (target) {
- requestIdleCallback(function () {
- target.scrollIntoView();
- });
- }
+ if (target) {
+ requestIdleCallback(function () {
+ target.scrollIntoView();
+ });
}
+ }
</script>
<style is:inline>
diff --git a/src/pages/index.astro b/src/pages/index.astro
index 1c80a76..5908e66 100644
--- a/src/pages/index.astro
+++ b/src/pages/index.astro
@@ -23,7 +23,11 @@ const micro = await fromPosts(
---
<Base title={PUBLIC_SITE_TITLE}>
- <main>
+ <main
+ itemprop="mainContentOfPage"
+ itemscope
+ itemtype="https://schema.org/WebPageElement"
+ >
<article>
<h2>Viva abril!</h2>
<figure>
@@ -44,8 +48,13 @@ const micro = await fromPosts(
</article>
{
(originals.length > 0 || micro) && (
- <section id="posts">
- <h2>Últimas aplicações atualizadas</h2>
+ <section
+ id="posts"
+ itemprop="citation"
+ itemscope
+ itemtype="http://schema.org/Blog"
+ >
+ <h2 itemprop="name description">Últimas aplicações atualizadas</h2>
{micro && <div id="last-micro"><MicroBlog {...micro} /></div>}
<div id="last-originals"><SimplePostList posts={originals} /></div>
</section>