feat: initial setup, frontend, backend, postgresql

This commit is contained in:
2025-05-30 17:47:50 -04:00
parent 970c83d62b
commit 3ee136d52d
35 changed files with 6612 additions and 0 deletions
+120
View File
@@ -0,0 +1,120 @@
import {
BrowserRouter as Router,
Routes,
Route,
Link,
useParams,
} from "react-router-dom";
import { useState, useEffect } from "react";
import ReactMarkdown from "react-markdown";
import { BlogViewer } from "./utils/BlogViewer";
import { BlogList } from "./utils/BlogList";
function App() {
const [darkMode, setDarkMode] = useState(true);
return (
<div className={darkMode ? "dark" : ""}>
<Router>
<div className="min-h-screen bg-gray-100 dark:bg-gray-900 text-gray-900 dark:text-gray-100">
<AppBar toggleDarkMode={() => setDarkMode(!darkMode)} />
<div className="p-4">
<Routes>
<Route path="/" element={<LandingPage />} />
<Route path="/blog" element={<BlogList />} />
<Route path="/blog/:slug" element={<BlogViewer />} />
<Route path="/about" element={<About />} />
<Route path="/contact" element={<Contact />} />
</Routes>
</div>
</div>
</Router>
</div>
);
}
function AppBar({ toggleDarkMode }: { toggleDarkMode: () => void }) {
return (
<nav className="bg-white dark:bg-gray-800 shadow p-4 flex space-x-4 items-center">
<Link to="/" className="font-bold text-blue-600 dark:text-blue-400">
Home
</Link>
<Link
to="/blog"
className="text-gray-800 dark:text-gray-200 hover:text-blue-600 dark:hover:text-blue-400"
>
Blog
</Link>
<Link
to="/about"
className="text-gray-800 dark:text-gray-200 hover:text-blue-600 dark:hover:text-blue-400"
>
About Me
</Link>
<Link
to="/contact"
className="text-gray-800 dark:text-gray-200 hover:text-blue-600 dark:hover:text-blue-400"
>
Contact
</Link>
<button
onClick={toggleDarkMode}
className="ml-auto text-sm bg-gray-200 dark:bg-gray-700 px-2 py-1 rounded"
>
Toggle Dark Mode
</button>
</nav>
);
}
function LandingPage() {
return (
<div className="text-center py-10">
<h1 className="text-4xl font-bold mb-4">Welcome to My Site</h1>
<p className="text-lg text-gray-700 dark:text-gray-300">
Explore my blog, learn about me, or get in touch.
</p>
</div>
);
}
export const BlogPost = () => {
const { slug } = useParams<{ slug: string }>();
const [content, setContent] = useState<string>("");
useEffect(() => {
if (!slug) return;
fetch(`../public/blogs/${slug}.md`)
.then((res) => res.text())
.then((text) => setContent(text));
}, [slug]);
if (!content) return <div>Loading...</div>;
return (
<article className="prose dark:prose-invert max-w-none p-4">
<ReactMarkdown>{content}</ReactMarkdown>
</article>
);
};
function About() {
return (
<div>
<h2 className="text-2xl font-bold mb-4">About Me</h2>
<p>This is a placeholder for information about me.</p>
</div>
);
}
function Contact() {
return (
<div>
<h2 className="text-2xl font-bold mb-4">Contact</h2>
<p>This is a placeholder for contact information or a form.</p>
</div>
);
}
export default App;