Skip to content

Commit c050fb2

Browse files
finalized and published to NPM
1 parent e4a620b commit c050fb2

File tree

12 files changed

+398
-275
lines changed

12 files changed

+398
-275
lines changed

src/lib/components/BlogPost.svelte

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
<script lang="ts">
2+
import { JsonLd, MetaTags } from "svelte-meta-tags";
3+
import ErrorPage from "./ErrorPage.svelte";
4+
import Post from "./Post.svelte";
5+
import type { TableOfContentItems } from "$lib/types";
6+
import type { PageData } from "../../routes/blog/[slug]/$types";
7+
8+
export let data: PageData;
9+
10+
let tableOfContent: (TableOfContentItems | undefined)[] | undefined;
11+
12+
$: tableOfContent = data?.blocks?.map((block)=>{
13+
if(block.type==="heading_1"){
14+
return {
15+
type: block.type,
16+
text: block.heading_1?.rich_text?.[0]?.plain_text,
17+
id: block.id
18+
}
19+
}else if(block.type==="heading_2"){
20+
return {
21+
type: block.type,
22+
text: block.heading_2?.rich_text?.[0]?.plain_text,
23+
id: block.id
24+
}
25+
}else if(block.type==="heading_3"){
26+
return {
27+
type: block.type,
28+
text: block.heading_3?.rich_text?.[0]?.plain_text,
29+
id: block.id
30+
}
31+
}else{
32+
return undefined;
33+
}
34+
});
35+
</script>
36+
37+
<MetaTags
38+
title= {data.title}
39+
titleTemplate="%s | StoreBud- Launch ecommerce website in india and the world"
40+
description= {data.description}
41+
openGraph={{
42+
url: "https://mystorebud.com/blog/" + data.slug,
43+
title:data.title,
44+
description: data.description,
45+
images: [
46+
{ url: data.cover ?? "" }
47+
],
48+
site_name: 'StoreBud'
49+
}}
50+
twitter={{
51+
handle: '@mystorebud',
52+
site: '@mystorebud',
53+
cardType: 'summary_large_image',
54+
title: data.title,
55+
description: data.description,
56+
image: data.cover ,
57+
imageAlt: data.title
58+
}}
59+
facebook={{
60+
appId: '1234567890'
61+
}}
62+
/>
63+
64+
<JsonLd
65+
schema={{
66+
"@context": "https://schema.org",
67+
"@type": "BlogPosting",
68+
"headline": data.title,
69+
"image": data.cover,
70+
"author": data.author?.name ?? "Team StoreBud",
71+
"publisher": {
72+
"@type": "Organization",
73+
"name": "StoreBud",
74+
"logo": {
75+
"@type": "ImageObject",
76+
"url": "https://www.mystorebud.com/android-chrome-192x192.png"
77+
}
78+
},
79+
"url": "http://www.mystorebud.com",
80+
"mainEntityOfPage": {
81+
"@type": "WebPage",
82+
"@id": "https://mystorebud.com/blog"
83+
},
84+
"description": data.description,
85+
"articleBody": data.description,
86+
"dateCreated": data?.published ? new Date(data?.published).toISOString() : new Date().toISOString(),
87+
"datePublished": data?.published ? new Date(data.published).toISOString() : new Date().toISOString(),
88+
}}
89+
/>
90+
91+
<ErrorPage {data} />
92+
93+
<div class="min-h-screen bg-white py-8 flex flex-col justify-center relative overflow-hidden lg:py-12">
94+
<div class="relative w-full px-6 py-12 md:max-w-3xl md:mx-auto lg:max-w-4xl lg:pt-16 lg:pb-28">
95+
<Post blocks={data.blocks} {tableOfContent} title={data.title} cover={data.cover} faqs={data.faqs} author={data.author} published={data.published} />
96+
</div>
97+
</div>
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<script lang="ts">
2+
export let data: any;
3+
</script>
4+
5+
{#if data?.error}
6+
<div class="flex min-h-screen min-w-full justify-center items-center">
7+
<div class="bg-slate-200 p-10 rounded-md text-gray-700 flex flex-col gap-4">
8+
<h3 class="font-bold text-2xl text-gray-700">Error code: {data.error.code}</h3>
9+
<p class="text-lg text-gray-600">{data.error.message}</p>
10+
</div>
11+
</div>
12+
{/if}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<script lang="ts">
2+
import PostItem from "./PostItem.svelte";
3+
import type { PageData } from "../../routes/$types";
4+
import ErrorPage from "./ErrorPage.svelte";
5+
export let data: PageData;
6+
</script>
7+
8+
{#if data.pages}
9+
<div class="min-h-screen bg-white py-8 flex flex-col gap-20 relative overflow-hidden lg:py-8">
10+
<div class="relative w-full px-6 py-12 md:max-w-3xl md:mx-auto lg:max-w-4xl lg:pt-12 lg:pb-28">
11+
<div class="flex flex-col gap-12 mb-8">
12+
<h1 class="font-bold text-4xl">Welcome to StoreBud blog - Platform for growing D2C brands!</h1>
13+
14+
<p class="text-lg">
15+
StoreBud blogs cover variuos topics related to setting up your own ecommerce website in India and
16+
other parts of the world, including tips and tricks, best practices and success stroies of the
17+
growing D2C brands.
18+
</p>
19+
</div>
20+
21+
{#each data.pages as page}
22+
<PostItem properties = { page.properties } cover = { page.cover } />
23+
{/each}
24+
</div>
25+
</div>
26+
{/if}
27+
28+
<ErrorPage {data} />

src/lib/index.js

Lines changed: 0 additions & 1 deletion
This file was deleted.

src/lib/index.ts

Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
import { Client, isFullUser } from "@notionhq/client";
2+
import { getBlocks, getDatabaseById, getFAQs, getPageBySlug } from "./notion/api";
3+
import { PUBLIC_NOTION_TOKEN } from "$env/static/public";
4+
import type { ServerLoadEvent } from "@sveltejs/kit";
5+
import BlogPost from "$lib/components/BlogPost.svelte";
6+
import PostsList from "$lib/components/PostsList.svelte";
7+
8+
type Tokens = { notionToken: string, databaseId: string, vercelByPassToken?: string };
9+
export type BlogClient = {client: Client, config: Tokens};
10+
11+
let notionCLient: BlogClient;
12+
13+
export const initNotion = ( config: Tokens ): BlogClient | null => {
14+
if(config?.notionToken && config?.notionToken){
15+
const client = new Client({
16+
auth: config.notionToken,
17+
});
18+
notionCLient = { client, config};
19+
return notionCLient;
20+
}else{
21+
return null;
22+
}
23+
}
24+
25+
export const getAllPosts = async () => {
26+
try {
27+
28+
if(!notionCLient){
29+
return {
30+
error: {
31+
code: 400,
32+
message: "Notion client is not initialized"
33+
}
34+
}
35+
}
36+
37+
const res = await getDatabaseById(notionCLient);
38+
39+
if(res.isOk()){
40+
if(res.value?.length > 0){
41+
return {
42+
pages: res.value
43+
}
44+
}else{
45+
return {
46+
error: {
47+
code: 400,
48+
message: "Please add rows in the database"
49+
}
50+
}
51+
}
52+
}
53+
54+
if(res.isErr()){
55+
return {
56+
error: {
57+
code: res.error.code,
58+
message: res.error.message
59+
}
60+
}
61+
}
62+
} catch (error) {
63+
return {
64+
error: {
65+
code: 500,
66+
message: "Some error ocurred"
67+
}
68+
}
69+
}
70+
}
71+
72+
73+
export const getBlogPageBySlug = async (event: ServerLoadEvent) => {
74+
const { slug } = event.params;
75+
76+
if(!notionCLient){
77+
return {
78+
error: {
79+
code: 400,
80+
message: "Notion client is not initialized"
81+
}
82+
}
83+
}
84+
85+
if(!slug){
86+
return {
87+
error: {
88+
code: 400,
89+
message: "Invalid or missing blog slug"
90+
}
91+
}
92+
}
93+
94+
const response = await getPageBySlug(notionCLient , slug);
95+
96+
if(response.isOk() && response.value?.length>0){
97+
const page = response.value?.[0];
98+
const title = page.properties["Title"].type=="title" && page.properties["Title"]?.title?.[0]?.type=="text" ? page.properties["Title"]?.title?.[0]?.text?.content : undefined;
99+
const description = page.properties["Short Description"]?.type=="rich_text"? page.properties["Short Description"]?.rich_text?.[0]?.plain_text : undefined;
100+
const cover = page?.cover?.type=="external" ? page?.cover?.external?.url : undefined;
101+
const published = page.properties["Publish Date"]?.type == "date" ? page.properties["Publish Date"].date?.start: undefined;
102+
const author = page.properties["Authors"]?.type=="people" && page.properties["Authors"]?.people?.[0] ? isFullUser(page.properties["Authors"]?.people?.[0])? page.properties["Authors"]?.people?.[0] : undefined: undefined;
103+
104+
if(!page?.id){
105+
return {
106+
error: {
107+
code: 500,
108+
message: "Invalid or missing page!"
109+
}
110+
}
111+
}
112+
113+
const blockResponse = await getBlocks(notionCLient , page.id);
114+
115+
if(blockResponse.isOk()){
116+
//console.log("result", JSON.stringify(blockResponse.value));
117+
const blocks = blockResponse.value;
118+
const faqsTableId = blocks?.filter((f) => f.type=="table")?.[0]?.id;
119+
let faqs = null;
120+
121+
if(faqsTableId){
122+
const faqsResponse = await getFAQs(notionCLient , faqsTableId);
123+
124+
if(faqsResponse.isOk()){
125+
faqs = faqsResponse.value;
126+
}
127+
}
128+
129+
return {
130+
blocks,
131+
title,
132+
description,
133+
cover,
134+
slug,
135+
published,
136+
author,
137+
faqs
138+
}
139+
}
140+
141+
if(blockResponse.isErr()){
142+
return {
143+
error: {
144+
code: blockResponse.error.code,
145+
message: blockResponse.error.message
146+
}
147+
}
148+
}
149+
}else{
150+
return {
151+
error: {
152+
code: 500,
153+
message: "Some error ocurred"
154+
}
155+
}
156+
}
157+
158+
if(response.isErr()){
159+
return {
160+
error: {
161+
code: response.error.code,
162+
message: response.error.message
163+
}
164+
}
165+
}
166+
}
167+
168+
export { BlogPost, PostsList }

0 commit comments

Comments
 (0)