From 494ea207bb5963caf28fe9dc61f54e1e46eadf4c Mon Sep 17 00:00:00 2001 From: Jordi Enric Date: Fri, 22 Mar 2024 19:42:11 +0100 Subject: [PATCH] wip --- apps/zendo/src/components/CodeBlock.tsx | 2 +- .../src/components/Editor/ZendoEditor.tsx | 17 ++++++ apps/zendo/src/components/ZendoLogo.tsx | 2 +- apps/zendo/src/components/copy-cell.tsx | 29 +++++++++ .../src/pages/blogs/[blogId]/settings.tsx | 61 ++++++++++++++----- todo/mvp.md | 59 +++++------------- 6 files changed, 111 insertions(+), 59 deletions(-) create mode 100644 apps/zendo/src/components/copy-cell.tsx diff --git a/apps/zendo/src/components/CodeBlock.tsx b/apps/zendo/src/components/CodeBlock.tsx index 4018772..cd752a0 100644 --- a/apps/zendo/src/components/CodeBlock.tsx +++ b/apps/zendo/src/components/CodeBlock.tsx @@ -31,7 +31,7 @@ export const CodeBlock = ({ customStyle={{ padding: "1rem", borderRadius: "0.5rem", - backgroundColor: "#0f172a", + backgroundColor: "rgb(24,24,27)", fontSize: "0.82rem", }} language={language} diff --git a/apps/zendo/src/components/Editor/ZendoEditor.tsx b/apps/zendo/src/components/Editor/ZendoEditor.tsx index f2b73d3..e89723a 100644 --- a/apps/zendo/src/components/Editor/ZendoEditor.tsx +++ b/apps/zendo/src/components/Editor/ZendoEditor.tsx @@ -211,8 +211,25 @@ export const ZendoEditor = (props: Props) => { } }; document.addEventListener("keydown", handleSave); + + // prevent users from leaving if they have unsaved changes + window.onbeforeunload = function (e) { + if (hasChanges) { + const confirm = window.confirm( + "You have unsaved changes, are you sure you want to leave?" + ); + + if (confirm) { + return; + } else { + e.preventDefault(); + } + } + }; + return () => { document.removeEventListener("keydown", handleSave); + window.onbeforeunload = null; }; }); diff --git a/apps/zendo/src/components/ZendoLogo.tsx b/apps/zendo/src/components/ZendoLogo.tsx index fc07c75..0de8b5b 100644 --- a/apps/zendo/src/components/ZendoLogo.tsx +++ b/apps/zendo/src/components/ZendoLogo.tsx @@ -7,5 +7,5 @@ const Logo = () => ( ); export default function ZendoLogo() { - return
zenblog
; + return
zenblog
; } diff --git a/apps/zendo/src/components/copy-cell.tsx b/apps/zendo/src/components/copy-cell.tsx new file mode 100644 index 0000000..b310494 --- /dev/null +++ b/apps/zendo/src/components/copy-cell.tsx @@ -0,0 +1,29 @@ +import { Check, Clipboard } from "lucide-react"; +import React from "react"; +import { Button } from "./ui/button"; + +type Props = { + text: string; +}; + +export const CopyCell = (props: Props) => { + const [isCopied, setIsCopied] = React.useState(false); + + return ( +
+
{props.text}
+ +
+ ); +}; diff --git a/apps/zendo/src/pages/blogs/[blogId]/settings.tsx b/apps/zendo/src/pages/blogs/[blogId]/settings.tsx index 4abbe96..43031b9 100644 --- a/apps/zendo/src/pages/blogs/[blogId]/settings.tsx +++ b/apps/zendo/src/pages/blogs/[blogId]/settings.tsx @@ -12,6 +12,8 @@ import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; import { Button } from "@/components/ui/button"; import { useBlogQuery } from "@/queries/blogs"; +import { CopyCell } from "@/components/copy-cell"; +import { AlertCircle, Info } from "lucide-react"; export default function BlogSettings() { type FormData = { @@ -152,33 +154,64 @@ export default function BlogSettings() { -
+

Integration guide

-

1. Install the zendo API client

+

First, install the zendo client

{`npm install zenblog`} -

2. Create a client

+

Next, store your blog id as an environment variable

- - {` -import { createClient } from "zenblog"; + + {`BLOG_ID=${blog.id}`} + + +

+ + Avoid making your blog id public. You should store it in a secure + way. +

+ +

Now, create a client with your blog id

+ + + {`import { createClient } from "zenblog"; const cms = createClient({ - blogId: "${blog.id}", -}); - `} + blogId: process.env.BLOG_ID, +});`}

- 3. Use the client to fetch posts and render them on your website + Use the client to fetch posts and render them on your website.

+ + {`import { cms } from "../lib/cms"; +import Link from "next/link"; + +const posts = await cms.posts.getAll(); + +return
+ {posts.map((post) => + + {post.title} + + )} +
`} +
+ +

That's it! 👏 Your blog page is ready.

+

Next, you should learn how to render the posts content.

-
-

- 🚨 Danger zone +
+

+ + Danger zone

-

+

This action cannot be undone.
This will permanently delete the blog.
This will also delete all posts in the blog.
diff --git a/todo/mvp.md b/todo/mvp.md index e61a96a..2c36aea 100644 --- a/todo/mvp.md +++ b/todo/mvp.md @@ -2,81 +2,54 @@ ## General -- [x] bug when adding a second tag to a post -- [x] License - [] FAQ on homepage? - [] Update README - [] Homepage use cases examples: personal blog, docs, careers page, product listing pages, help center, changelogs, directory websites, etc. - [] email provider -- [x] supabase spend cap -- [x] Cloudflare ddos protection -- [x] cmd + enter to save post - -## QOL - -- Save posts/create in localstorage so its not lost when you reload the page goddammit - -## Free tier - -- [] limit to 1 blog -- [] 1 user - -## Bugs & Improvements - -- [x] Fix email redirect when navigating to protected routes -- [x] Force email confirmation ## Pricing - [] Add pricing page? -- [x] Sync products between Stripe and Supabase -- [x] Sync subscriptions between Stripe and Supabase ## Blogs - Integration guide - - [] instruct users to keep the blog id private. - [] allow users to rotate the blog id? - [] Recommend users to cache content -- [x] Create blog -- [x] Edit blog -- [x] Delete blog -- [x] View blog -- [x] View all blogs -- [x] Make description optional -- [x] Add emoji picker to Create Blog -- [x] Redirect to blog after creating it - ## Posts - [] When uploading an image, it would be nice if you could rename it before uploading. - [] See "published at" and "updated at" dates in post list - [] change published date in post settings -- [x] View all posts -- [x] Create post -- [x] View post -- [x] Edit post -- [x] Delete post +- [] pagination ## Tags -- [x] Create tag - [] Delete tag - [] Update tag -- [x] View all tags -- [x] Add tags to posts + +## Media + +- [] CRUD media from media tab in blog view ## Docs -- [x] Add documentation for integrating with Zenblog +- [] Add documentation for integrating with Zenblog - [] Copypastable Zenblog Renderer component similar to shadcn ## API Client -- [x] Create API client -- [x] Add method to fetch all posts -- [x] Add method to fetch a single post by slug - [] Pagination - [] Filtering by tag + +## Free tier? + +- [] limit to 1 blog +- [] 1 user + +## QOL + +- Prevent users from leaving the page when they have unsaved changes +- Save posts/create in localstorage so its not lost when you reload the page goddammit