6月にNotion blogのAwesome(https://github.com/steelydylan/Awesome)を使いはじめました。
mosyaのコミュニティでちょっと図々しい投稿をしてみたのがキッカケ。
ずっとエラーで
手も足も出せなかったリポジトリを無事に公開できたときの感動は格別🎉
このAwesomeブログを使って2ヶ月経ちました。
いつものことながら使えば使うほど愛着が湧いてきて、Notion blogの面白さを堪能できるようになってきました。
この記事ではその面白さをコードに乗せてお伝えできればと思います 🥳
Awesomeブログを立ち上げるために必要な設定や、
実際に私のブログ(https://like.herohoro.com/)で使っているカスタマイズ方法について紹介します☆
ブログを使う際に、最低限必要なカスタマイズはblog.config.tsに集約されています。
blog.config.tsの全コード:https://github.com/steelydylan/Awesome/blob/master/blog.config.ts
私のブログでカスタマイズした項目をピックアップすると….
コード:https://github.com/steelydylan/Awesome/blob/master/blog.config.ts
この他に、ブログのタイトルを変更する場合は…
public>Images>logo.svg
をいじります
https://github.com/steelydylan/Awesome/blob/master/public/images/logo.svg?short_path=1632d17
<svg xmlns="http://www.w3.org/2000/svg" width="201" height="39" viewBox="0 0 201 39">
<text id="AWESOME." transform="translate(0 31)" fill="#2c2c2c" font-size="30" font-family="Futura-Bold, Futura" font-weight="700" letter-spacing="0.1em"><tspan x="0" y="0">AWESOME.</tspan></text>
</svg>
解説記事の方で詳しく手順が書かれています。
https://mosya.dev/blog/awesome#cloudflareの設定
途中、クレジットカードの登録があるのでドキドキしますが、
今のところ特に請求されてない….ぽいです👀
ここまで設定ができると基本的なことは満足して使えるようになります(*๓´╰╯`๓)♡
https://64dcfa1e3a3410009ac66c9f--tranquil-kulfi-a42dcf.netlify.app/horomi
ただ、easy-notion-blog….いや、astro-notion-blogで対応しているNotionブロックはまだサポートされていません。
https://like.herohoro.com/sample/block-check
でも、AwesomeはAwesomeの良さがあるなと思っています。
デザインもそうですし、
blog.config.txで大体のことが済んでしまうのも嬉しいですし、
subNavigation
をblog.config.txで設定してしまえば固定ページのように扱えることにも驚きました。
subNavigation: [
{
name: "terms",
url: "/about/terms",
},
{
name: "privacy",
url: "/about/privacy",
},
{
name: "GitHub",
url: "https://github.com/steelydylan/Awesome",
},
],
↓
使い始めて1ヶ月を経過したあたりで….
複製したNotionDBにあるプロパティの中でAwesomeに反映されていないプロパティをどうしてもつなげたくなってきました。(改造魂っ!!!
Awesomeで表示されているディレクトリから
NotionAPIのあるファイルまでどういう経路を辿っているのかを調べてみました。
Next.js13のpagesタイプなので….
pages>index.tsxがトップページの記事一覧になります。
pages>index.tsxの全コード:https://github.com/steelydylan/Awesome/blob/master/pages/index.tsx
propsのarticlesでgetFilteredArticles
が代入されています。
export const getStaticProps = async () => {
const articles = await getArticles();
return {
revalidate: 60,
props: {
current: 0,
max: Math.ceil(articles.length / blogConfig.article.articlesPerPage),
articles: await getFilteredArticles({
current: 0,
}),
},
};
};
getStaticPropsについて:
In thepages
directory, thegetStaticProps
function is used to pre-render a page at build time. This function can be used to fetch data from an external API or directly from a database, and pass this data down to the entire page as it's being generated during the build.
utiles>get-articles.tsxの全コード:https://github.com/steelydylan/Awesome/blob/master/utils/get-articles.ts
articles変数でgetArticles
が代入されています👀
export const getFilteredArticles = async ({
current,
categoryId,
tagId,
}: {
current: number;
categoryId?: string;
tagId?: string;
}) => {
const articles = await getArticles();
const results = articles
.filter(({ data }) => {
if (!categoryId) {
return true;
}
return data.category === categoryId;
})
同じファイル内にgetArticles関数があります。
blog.config.tsのuseをnotionとした場合に、getDatabase
関数を動かすようです👀
export const getArticles = async (): Promise<Article[]> => {
if (blogConfig.use === "notion") {
return getDatabase(process.env.NOTION_DATABASE_ID as string, {
sorts: [
{
property: "rEYP",
direction: "descending",
},
],
});
}
return getArticlesFromFile();
};
utils>notion.tsxの全コード:https://github.com/steelydylan/Awesome/blob/master/utils/notion.tsx
素敵な眺めです 😍
export const getDatabase = async (
databaseId: string,
args: Omit<QueryDatabaseParameters, "database_id"> = {}
) => {
const response = await notion.databases.query({
database_id: databaseId,
...args,
});
const { results } = response;
const posts = await Promise.all(
results.map(async (result: PageObjectResponse) => {
const d = result.properties;
const item = {
thumbnail: "",
authors: "",
slug: "",
published: "no",
date: "",
description: "",
page: "",
id: result.id,
category: "",
};
await Promise.all(
Object.keys(d).map(async (key) => {
const property = d[key];
if (property.type === "people") {
item[key.toLowerCase()] = property.people
.map((p) => (p as any).name)
.join(",");
} else if (property.type === "rich_text") {
item[key.toLowerCase()] = property.rich_text[0]?.plain_text;
} else if (property.type === "files") {
if (property.files[0]?.type === "external") {
item[key.toLowerCase()] = property.files[0].name;
} else {
let src = property.files[0]?.file?.url;
if (src && process.env.CLOUD_FLARE_ACCOUNT_ID) {
const fileName =
result.id +
"_" +
result.last_edited_time +
"_" +
src.split("/").pop().replace(/\?.*$/, "");
try {
src = await uploadToR2(src, fileName);
} catch (e) {
console.log(e);
}
}
item[key.toLowerCase()] = src;
}
} else if (property.type === "title") {
item[key.toLowerCase()] = property.title[0]?.plain_text;
} else if (property.type === "checkbox") {
item[key.toLowerCase()] = property.checkbox;
} else if (property.type === "multi_select") {
item[key.toLowerCase()] = property.multi_select?.[0]?.name;
} else if (property.type === "select") {
item[key.toLowerCase()] = property.select?.name;
} else if (property.type === "date") {
item[key.toLowerCase()] = property.date?.start;
}
})
);
// console.log(item)
return {
content: "",
data: {
tags: [],
title: item.page,
date: item.date,
category: item.category,
writtenBy: item.authors,
thumbnail: item.thumbnail,
id: item.id,
description: item.description,
status: item.published ? "open" : "draft",
},
permalink: `${blogConfig.siteUrl}/${item.category}/${item.slug}`,
slug: item.slug,
id: item.id,
excerpt: "",
related: [],
} as Article;
})
);
return posts;
};
Awesomeで表示されているpagesディレクトリからnotionAPIのコードがある場所まで辿れました🌝
いよいよdescriptionとpeopleをAwesomeに表示させる改造に入ります🔥(準備はいいか!?w
これは結構簡単です✌
Awesomeの表示させているpages>index.tsxをもう一度見てみてください 💁♀️
returnの前にconsole.log(articles)
を追加して確認します👀
articlesを1つずつ取り出してdata.descriptionと記述すれば
NotionDBのdescriptionプロパティを表示させることができます 🌈
実際に記事を表示させるコンポネントは<ArticleCard />
コンポネントにまとまっています。
return (
<Layout>
<Hero
title={blogConfig.hero.title}
description={blogConfig.hero.description}
/>
<Wrapper>
<main className="main">
<ArticleList>
<Title>{blogConfig.topPage.title}</Title>
<LatestArticle>
{articles.map((article) => (
<AritcleColumn key={article.slug} column={3}>
<ArticleCard
article={article.data}
href={`/${article.data.category}/${article.slug}`}
/>
ArticleCard
コンポネントは components<articles<card.tsxにあります。
components>articles>card.tsxの全コード:https://github.com/steelydylan/Awesome/blob/master/components/articles/card.tsx
日付の下に<p>{article.description}</p>
を入れてみました\(^o^)/
export function ArticleCard({ article, className, href }: Props) {
// console.log({article})
return (
<div className={className}>
<div className="article-img-wrap">
<Link href={href}>
<img
src={article.thumbnail ?? blogConfig.article.defaultThumbnail}
className="article-img"
alt=""
loading="lazy"
/>
</Link>
</div>
<div className="article-content">
<TagList
tags={getTagList(article.tags)}
category={getCategory(article.category)}
/>
<h2 className="article-title">
<Link href={href}>{article.title}</Link>
</h2>
<PublishdAt date={article.date} />
<p>{article.description}</p> 👉これ
</div>
表示されました\(^o^)/♥\(^o^)/
….これはかなり苦戦しました 🥺(4時間格闘
descriptionで確認したやり方でやってもauthorsの値は空。
そこで、NotionAPIの記述のあるutils>notion.tsxから調査 🔎
utils>notion.tsxの全コード:https://github.com/steelydylan/Awesome/blob/master/utils/notion.tsx
Authorsという名前のプロパティはNotionAPIでいうとpeopleプロパティを使っています。
https://developers.notion.com/reference/property-object#people
peopleの中身はYoomを使って確認してみました 🤫
PR:
mapで取り出す前に1つだけ取って内容を確認してみます🔎
const posts = await Promise.all(
results.map(async (result: PageObjectResponse) => {
const d = result.properties;
const item = {
thumbnail: "",
authors: "",
slug: "",
published: "no",
date: "",
description: "",
page: "",
id: result.id,
category: "",
};
await Promise.all(
Object.keys(d).map(async (key) => {
const property = d[key];
if (property.type === "people") {
item[key.toLowerCase()] = property.people[0]🚩
// .map((p) => (p as any).name)🚩
// .join(",");🚩
} else if (property.type === "rich_text") {
item[key.toLowerCase()] = property.rich_text[0]?.plain_text;
} else if (property.type === "files") {
😱😱😱😱😱
name以降が取れていません😱😱😱😱😱
blog.config.tsで設定するidにはこのidを入れてつなげる準備をすることにします✌
writers: [
{
id: "148bfa26-a10a-4673-86c7-539868890a5c", 👉これ
name: "horomi",
description:
"Notionサポーターで活動してるけど、独学が生きがいな引きこもりさん",
image: "/images/profile_500x500.PNG",
blog.config(writer)とutils>notion.tsx(writtenBy)ををつなげるために
ulits内に別途get-author.tsというファイルを作りました。
import blogConfig from "@/blog.config";
export const getAuthor = (writtenBy: string) => {
const author = blogConfig.writers.find((c) => c.id === writtenBy);
if (!author) {
return null;
}
return author;
};
descriptionを表示させたときと同様にして
components>articles>card.tsxに追記!!
<div className="article-content">
<TagList
tags={getTagList(article.tags)}
category={getCategory(article.category)}
/>
<p>🐈‍⬛:{getAuthor(article.writtenBy)?.name}</p> 👉追記
<h2 className="article-title">
<Link href={href}>{article.title}</Link>
</h2>
<PublishdAt date={article.date} />
<p>{article.description}</p>
</div>
できました〜〜〜\(^o^)/♥\(^o^)/♥\(^o^)/
記事のAuthorごとにAuthorカードを切り替えるのも楽しかったです 🥳
久しぶりに興奮しましたwww
同じNotion blogでも開発者によって全然違う内容なのが面白いなと思いました。
同じTypeScriptなのに…
同じNotionAPIなのに….
同じブログなのに….
Notion blogに対して期待する内容は人それぞれかと思いますが
私はずっと変わりません。
mosyaを始めて4ヶ月目が終わろうとしています。
ただ「おもしろそうだから…」という理由ではじめたmosyaですが、
Awesomeのコードにも通じるものを感じるようになり、
久しぶりに改造を試みたところ
コンポネント同士のつながりを紐解けたり
配列の関数の理解が進んだりと
回り回ってブログの改造力(読解力)が上がったような気がしました。
特に今までなかなか理解できず何度も勉強してきたJavaScriptをmosyaでしっかり整理することができるなんて思ってもいなかったので、本当にやってよかったなという思いでいっぱいです 🥰
まだまだできるようになりたいことがたくさんあるので
少しずつレッスンを進めていこうと思います(*๓´╰╯`๓)♡(*๓´╰╯`๓)♡(*๓´╰╯`๓)♡
PR:
mosyaのコミュニティに最近できた【宣伝部屋】
作った作品になるかは分かりませんが、記事を投稿してみました✌
Awesomeが急に分かってきたのは、mosyaのおかげなのは気づいていましたが、
ごだいさんのよく使うコードが詰まっているレッスンだったからという発見があり
わくわくしてきました。
mosyaをもっとやればごだいさんの作った数々のプログラムを解読できるようになるのかな…. 🤔
もっと知りたいな〜〜〜〜
▼ この記事に興味があったら同じタグから関連記事をのぞいてみてね
RSSリーダーにatomのリンクを登録すると通知が行くよ🐌
https://herohoro.com/atom
やってみてね(*´ω`*)(*´ω`*)
フォロー大歓迎\(^o^)/
フォロー大歓迎\(^o^)/