feat: add chat and website updates

This commit is contained in:
Mohamed Boudra
2026-03-29 12:49:05 +07:00
parent 147482d6ed
commit 094864d779
26 changed files with 677 additions and 126 deletions
+40
View File
@@ -0,0 +1,40 @@
import { createFileRoute } from "@tanstack/react-router";
import ReactMarkdown from "react-markdown";
import { getPost, formatDate } from "~/posts";
import { pageMeta } from "~/meta";
export const Route = createFileRoute("/blog/$")({
head: ({ params }) => {
const slug = params._splat ?? "";
const post = getPost(slug);
if (!post) return { meta: pageMeta("Not Found - Paseo", "Post not found.") };
return {
meta: pageMeta(`${post.frontmatter.title} - Paseo`, post.frontmatter.description),
};
},
component: BlogPost,
});
function BlogPost() {
const { _splat } = Route.useParams();
const slug = _splat ?? "";
const post = getPost(slug);
if (!post) {
return <p className="text-muted-foreground">Post not found.</p>;
}
return (
<article>
<div className="mb-8">
<h1 className="text-4xl font-bold mb-2">{post.frontmatter.title}</h1>
<span className="text-lg text-muted-foreground">
{formatDate(new Date(post.frontmatter.date))}
</span>
</div>
<div className="blog-prose">
<ReactMarkdown>{post.content}</ReactMarkdown>
</div>
</article>
);
}
@@ -0,0 +1,53 @@
import { createFileRoute, Link } from "@tanstack/react-router";
import { getPosts, formatDate } from "~/posts";
import { pageMeta } from "~/meta";
export const Route = createFileRoute("/blog/")({
validateSearch: (search: Record<string, unknown>) => ({
drafts: search.drafts !== undefined,
}),
head: () => ({
meta: pageMeta("Blog - Paseo", "Updates, thoughts, and announcements from the Paseo team."),
}),
component: BlogIndex,
});
function BlogIndex() {
const { drafts } = Route.useSearch();
const posts = getPosts(drafts);
return (
<div>
{drafts && (
<div className="mb-6 p-4 bg-primary/10 rounded border-l-4 border-primary">
<p className="text-sm text-foreground/80">Showing draft posts</p>
</div>
)}
<div className="space-y-2">
{posts.map(({ slug, frontmatter }) => (
<div
key={slug}
className="flex flex-col-reverse items-start md:flex-row md:items-center gap-x-4"
>
<span className="text-lg text-muted-foreground tabular-nums">
{formatDate(new Date(frontmatter.date))}
</span>
<Link
to="/blog/$"
params={{ _splat: slug }}
className="text-lg text-foreground hover:text-primary transition-colors"
>
{frontmatter.title}
{frontmatter.draft && (
<span className="ml-2 text-xs px-2 py-1 bg-primary/20 text-primary rounded">
DRAFT
</span>
)}
</Link>
</div>
))}
{posts.length === 0 && <p className="text-muted-foreground">No posts yet.</p>}
</div>
</div>
);
}