mirror of
https://github.com/jordienr/zenblog.git
synced 2026-09-27 09:35:47 -04:00
wip
This commit is contained in:
@@ -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}
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
});
|
||||
|
||||
|
||||
@@ -7,5 +7,5 @@ const Logo = () => (
|
||||
);
|
||||
|
||||
export default function ZendoLogo() {
|
||||
return <div className="text-lg font-bold tracking-tight">zenblog</div>;
|
||||
return <div className="text-lg font-semibold tracking-tight">zenblog</div>;
|
||||
}
|
||||
|
||||
@@ -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 (
|
||||
<div className="flex items-center justify-between rounded-md border bg-zinc-100 px-2 py-1 font-mono text-sm text-zinc-600">
|
||||
<div className="px-2">{props.text}</div>
|
||||
<Button
|
||||
onClick={() => {
|
||||
navigator.clipboard.writeText(props.text);
|
||||
setIsCopied(true);
|
||||
setTimeout(() => setIsCopied(false), 2000);
|
||||
}}
|
||||
size="sm"
|
||||
variant="ghost"
|
||||
>
|
||||
{isCopied ? <Check size={16} /> : <Clipboard size={16} />}
|
||||
{isCopied ? "Copied" : "Copy"}
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -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() {
|
||||
</form>
|
||||
</section>
|
||||
|
||||
<section className="section p-3">
|
||||
<section className="section p-3 [&_h3]:mb-3 [&_h3]:mt-8">
|
||||
<h2 className="text-lg font-medium">Integration guide</h2>
|
||||
<h3 className="mb-4 mt-8">1. Install the zendo API client</h3>
|
||||
<h3>First, install the zendo client</h3>
|
||||
<CodeBlock language="bash">{`npm install zenblog`}</CodeBlock>
|
||||
|
||||
<h3 className="mb-4 mt-8">2. Create a client</h3>
|
||||
<h3>Next, store your blog id as an environment variable</h3>
|
||||
|
||||
<CodeBlock title="/pages/blog.tsx">
|
||||
{`
|
||||
import { createClient } from "zenblog";
|
||||
<CodeBlock language="properties" title=".env">
|
||||
{`BLOG_ID=${blog.id}`}
|
||||
</CodeBlock>
|
||||
|
||||
<p className="mt-2 flex items-center gap-2 rounded-md border border-yellow-300 bg-yellow-100 px-3 py-2 text-yellow-700">
|
||||
<Info size={16} className="" />
|
||||
Avoid making your blog id public. You should store it in a secure
|
||||
way.
|
||||
</p>
|
||||
|
||||
<h3>Now, create a client with your blog id</h3>
|
||||
|
||||
<CodeBlock title="/lib/cms.ts">
|
||||
{`import { createClient } from "zenblog";
|
||||
|
||||
const cms = createClient({
|
||||
blogId: "${blog.id}",
|
||||
});
|
||||
`}
|
||||
blogId: process.env.BLOG_ID,
|
||||
});`}
|
||||
</CodeBlock>
|
||||
|
||||
<h3>
|
||||
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.
|
||||
</h3>
|
||||
<CodeBlock title="/app/blog/page.tsx">
|
||||
{`import { cms } from "../lib/cms";
|
||||
import Link from "next/link";
|
||||
|
||||
const posts = await cms.posts.getAll();
|
||||
|
||||
return <div>
|
||||
{posts.map((post) =>
|
||||
<Link
|
||||
href={"/blog/" + post.slug}
|
||||
key={post.slug}
|
||||
>
|
||||
{post.title}
|
||||
</Link>
|
||||
)}
|
||||
</div>`}
|
||||
</CodeBlock>
|
||||
|
||||
<h3>That's it! 👏 Your blog page is ready.</h3>
|
||||
<p>Next, you should learn how to render the posts content.</p>
|
||||
</section>
|
||||
|
||||
<section className="section border border-red-500 bg-white p-3 ">
|
||||
<h2 className="mb-4 text-lg font-medium text-red-600">
|
||||
🚨 Danger zone
|
||||
<section className="section mt-24 border border-red-500 !bg-red-50/30 p-3">
|
||||
<h2 className="mb-4 flex items-center gap-2 text-lg font-medium text-red-600">
|
||||
<AlertCircle size={24} className="text-red-600" />
|
||||
Danger zone
|
||||
</h2>
|
||||
<p className="space-y-4">
|
||||
<p className="text-red-600">
|
||||
<div>This action cannot be undone.</div>
|
||||
<div>This will permanently delete the blog.</div>
|
||||
<div>This will also delete all posts in the blog.</div>
|
||||
|
||||
+16
-43
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user