feat: Add post image headers to /assets/header/
- Add SVG icons for external sites - Add polished logo to login - Update front matter in <blog>.md files
43
src/App.jsx
@@ -2,10 +2,10 @@ import React, { useState } from 'react';
|
|||||||
import AppRoutes from './routes/AppRoutes';
|
import AppRoutes from './routes/AppRoutes';
|
||||||
import CampfireAppBar from './components/AppBar';
|
import CampfireAppBar from './components/AppBar';
|
||||||
import CampfirePanelBar from './components/PanelBar';
|
import CampfirePanelBar from './components/PanelBar';
|
||||||
|
import Dashboard from './pages/Dashboard';
|
||||||
import { useNavigate, useLocation } from 'react-router-dom';
|
import { useNavigate, useLocation } from 'react-router-dom';
|
||||||
import { IconsContext } from '@progress/kendo-react-common';
|
import { IconsContext } from '@progress/kendo-react-common';
|
||||||
import Copyright from './components/UI/Copyright';
|
import Copyright from './components/UI/Copyright';
|
||||||
import Dashboard from './pages/Dashboard';
|
|
||||||
|
|
||||||
function App() {
|
function App() {
|
||||||
const [isLoggedIn, setIsLoggedIn] = useState(false);
|
const [isLoggedIn, setIsLoggedIn] = useState(false);
|
||||||
@@ -38,32 +38,35 @@ function App() {
|
|||||||
)}
|
)}
|
||||||
|
|
||||||
{isLoggedIn && location.pathname !== '/login' ? (
|
{isLoggedIn && location.pathname !== '/login' ? (
|
||||||
<CampfirePanelBar
|
<div style={{ display: 'flex', minHeight: '100vh' }}>
|
||||||
isExpanded={isPanelExpanded}
|
{/* Always render the PanelBar on the left */}
|
||||||
onPanelToggle={handlePanelToggle}
|
<CampfirePanelBar
|
||||||
isLoggedIn={isLoggedIn}
|
isExpanded={isPanelExpanded}
|
||||||
>
|
onPanelToggle={handlePanelToggle}
|
||||||
{/* AppRoutes are the main content of the Panel */}
|
isLoggedIn={isLoggedIn}
|
||||||
<AppRoutes isLoggedIn={isLoggedIn} onLogin={handleLogin} />
|
>
|
||||||
</CampfirePanelBar>
|
{/* AppRoutes are the main content of the Panel */}
|
||||||
|
<AppRoutes isLoggedIn={isLoggedIn} onLogin={handleLogin} />
|
||||||
|
</CampfirePanelBar>
|
||||||
|
|
||||||
|
{/* Render Dashboard on the right only when on /dashboard */}
|
||||||
|
{location.pathname === '/dashboard' && (
|
||||||
|
<div style={{ flex: 1, marginLeft: '100px' }}>
|
||||||
|
<Dashboard isLoggedIn={isLoggedIn}>
|
||||||
|
<AppRoutes isLoggedIn={isLoggedIn} onLogin={handleLogin} />
|
||||||
|
</Dashboard>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
) : (
|
) : (
|
||||||
// If not logged in or on the login page, just render the routes
|
// If not logged in or on the login page, just render the routes
|
||||||
<AppRoutes isLoggedIn={isLoggedIn} onLogin={handleLogin} />
|
<AppRoutes isLoggedIn={isLoggedIn} onLogin={handleLogin} />
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{isLoggedIn && location.pathname === '/dashboard' ? (
|
|
||||||
<Dashboard isLoggedIn={isLoggedIn}>
|
|
||||||
<AppRoutes isLoggedIn={isLoggedIn} onLongin={handleLogin} />
|
|
||||||
</Dashboard>
|
|
||||||
) : (
|
|
||||||
<AppRoutes isLoggedIn={isLoggedIn} onLogin={handleLogin} />
|
|
||||||
)}
|
|
||||||
</IconsContext.Provider>
|
</IconsContext.Provider>
|
||||||
</div>
|
</div>
|
||||||
<Copyright />
|
<Copyright />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
|
||||||
};
|
export default App;
|
||||||
|
|
||||||
export default App;
|
|
||||||
|
BIN
src/assets/header/#0-setting-up-camp.jpg
Normal file
After Width: | Height: | Size: 3.6 MiB |
BIN
src/assets/header/#1-the-great-gitea-migration.jpg
Normal file
After Width: | Height: | Size: 1.1 MiB |
BIN
src/assets/header/#2-retrofitting-the-privacy-policy.png
Normal file
After Width: | Height: | Size: 810 KiB |
BIN
src/assets/header/#3-data-privacy-things-to-consider.jpg
Normal file
After Width: | Height: | Size: 3.1 MiB |
BIN
src/assets/header/#4-refactoring-a-false-sense-of-simplicity.png
Normal file
After Width: | Height: | Size: 2.1 MiB |
BIN
src/assets/header/#5-the-power-of-separation-compels-you.webp
Normal file
After Width: | Height: | Size: 130 KiB |
BIN
src/assets/icons/DEV_Community_Badge.svg
Normal file
After Width: | Height: | Size: 1.6 KiB |
BIN
src/assets/icons/Gitea_Logo.svg
Normal file
After Width: | Height: | Size: 4.3 KiB |
BIN
src/assets/icons/Hashnode_icon.svg
Normal file
After Width: | Height: | Size: 1.9 KiB |
BIN
src/assets/icons/Notion-logo.svg
Normal file
After Width: | Height: | Size: 4.0 KiB |
BIN
src/assets/images/campfire_logs_square_logo_bg_match.png
Normal file
After Width: | Height: | Size: 516 KiB |
Before Width: | Height: | Size: 2.0 MiB |
@@ -36,10 +36,10 @@ const LoginComponent = ({ onLogin }) => {
|
|||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<Label htmlFor="password">Password: </Label>
|
<Label htmlFor="password">Password: </Label>
|
||||||
<Input style={{ border: '1px solid #edbd7d' }} type="password" id="password" value={password} onChange={(e) => setPassword(e.target.value)} autoComplete="current-password" />
|
<Input style={{ border: '1px solid #edbd7d', marginBottom: '10px' }} type="password" id="password" value={password} onChange={(e) => setPassword(e.target.value)} autoComplete="current-password" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Button look="flat" type="submit">Login</Button>
|
<Button look="flat" type="submit" style={{ padding: '0 20px' }}>Login</Button>
|
||||||
<div>
|
<div>
|
||||||
<NotificationGroup style={{ textAlign: 'center' }}>
|
<NotificationGroup style={{ textAlign: 'center' }}>
|
||||||
{error && (<Notification type={{ style: 'error', icon: true }} closeable={true} onClose={() => setError('')}>
|
{error && (<Notification type={{ style: 'error', icon: true }} closeable={true} onClose={() => setError('')}>
|
||||||
|
@@ -91,6 +91,7 @@ const CampfirePanelBar = ({ isExpanded = true }) => {
|
|||||||
<span style={{ marginLeft: '8px' }}>{item.title}</span>
|
<span style={{ marginLeft: '8px' }}>{item.title}</span>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
expanded={true}
|
||||||
>
|
>
|
||||||
{item.items.map(renderItem)}
|
{item.items.map(renderItem)}
|
||||||
</PanelBarItem>
|
</PanelBarItem>
|
||||||
|
@@ -10,7 +10,7 @@ export default function Copyright() {
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<p>
|
<p>
|
||||||
© Derek L. Seitz |{" "}
|
© 2025{" | "}Derek L. Seitz{" | "}
|
||||||
<a href="https://dlseitz.dev" target="_blank" rel="noopener noreferrer" class="k-link">
|
<a href="https://dlseitz.dev" target="_blank" rel="noopener noreferrer" class="k-link">
|
||||||
dlseitz.dev
|
dlseitz.dev
|
||||||
</a>
|
</a>
|
||||||
|
@@ -5,7 +5,7 @@ date: 2025-08-24 05:00:00 UTC
|
|||||||
tags: fullstack,developerjourney,BuildInPublic,introduction
|
tags: fullstack,developerjourney,BuildInPublic,introduction
|
||||||
canonical_url: https://campfire.dlseitz.dev/0-setting-up-camp
|
canonical_url: https://campfire.dlseitz.dev/0-setting-up-camp
|
||||||
header:
|
header:
|
||||||
image: /assets/kemal-berkay-dogan-TcUN5sDZPZ8-unsplash.jpg
|
image: /assets/#0-setting-up-camp.jpg
|
||||||
attribution: 'Photo by <a href="https://unsplash.com/@kemaldgn?utm_content=creditCopyText&utm_medium=referral&utm_source=unsplash">Kemal Berkay Dogan</a> on <a href="https://unsplash.com/photos/a-campfire-with-a-cup-of-coffee-sitting-in-front-of-it-TcUN5sDZPZ8?utm_content=creditCopyText&utm_medium=referral&utm_source=unsplash">Unsplash</a>'
|
attribution: 'Photo by <a href="https://unsplash.com/@kemaldgn?utm_content=creditCopyText&utm_medium=referral&utm_source=unsplash">Kemal Berkay Dogan</a> on <a href="https://unsplash.com/photos/a-campfire-with-a-cup-of-coffee-sitting-in-front-of-it-TcUN5sDZPZ8?utm_content=creditCopyText&utm_medium=referral&utm_source=unsplash">Unsplash</a>'
|
||||||
---
|
---
|
||||||
|
|
||||||
|
@@ -5,7 +5,7 @@ date: 2025-08-27 20:19:51 UTC
|
|||||||
tags: CampfireLogs,SelfHosting,Devops,gitea
|
tags: CampfireLogs,SelfHosting,Devops,gitea
|
||||||
canonical_url: https://campfire.dlseitz.dev/1-the-great-gitea-migration
|
canonical_url: https://campfire.dlseitz.dev/1-the-great-gitea-migration
|
||||||
header:
|
header:
|
||||||
image: /assets/leon-contreras-YndHL7gQIJE-unsplash.jpg
|
image: /assets/header/#1-the-great-gitea-migration.jpg
|
||||||
attribution: 'Photo by <a href="https://unsplash.com/@lc_photography?utm_content=creditCopyText&utm_medium=referral&utm_source=unsplash">Leon Contreras</a> on <a href="https://unsplash.com/photos/selective-focus-photography-of-marshmallows-on-fire-pit-YndHL7gQIJE?utm_content=creditCopyText&utm_medium=referral&utm_source=unsplash">Unsplash</a>'
|
attribution: 'Photo by <a href="https://unsplash.com/@lc_photography?utm_content=creditCopyText&utm_medium=referral&utm_source=unsplash">Leon Contreras</a> on <a href="https://unsplash.com/photos/selective-focus-photography-of-marshmallows-on-fire-pit-YndHL7gQIJE?utm_content=creditCopyText&utm_medium=referral&utm_source=unsplash">Unsplash</a>'
|
||||||
---
|
---
|
||||||
|
|
||||||
|
@@ -5,7 +5,7 @@ date: 2025-09-02 20:41:21 UTC
|
|||||||
tags: WebDevelopment,FullStackDevelopment,Nodejs,DevLife
|
tags: WebDevelopment,FullStackDevelopment,Nodejs,DevLife
|
||||||
canonical_url: https://campfire.dlseitz.dev/2-retrofitting-the-privacy-policy
|
canonical_url: https://campfire.dlseitz.dev/2-retrofitting-the-privacy-policy
|
||||||
header:
|
header:
|
||||||
image: /assets/2-privacy-policy-head-img.png
|
image: /assets/header/#2-retrofitting-the-privacy-policy.png
|
||||||
attribution: 'Image generated with Sora. | © 2025 Derek L. Seitz'
|
attribution: 'Image generated with Sora. | © 2025 Derek L. Seitz'
|
||||||
---
|
---
|
||||||
|
|
||||||
|
@@ -5,7 +5,7 @@ date: 2025-09-03 03:49:36 UTC
|
|||||||
tags: dataprivacy,WebDevelopment,Freelancing,PrivacyPolicy
|
tags: dataprivacy,WebDevelopment,Freelancing,PrivacyPolicy
|
||||||
canonical_url: https://campfire.dlseitz.dev/3-data-privacy-things-to-consider
|
canonical_url: https://campfire.dlseitz.dev/3-data-privacy-things-to-consider
|
||||||
header:
|
header:
|
||||||
image: /assets/toa-heftiba-x9I-6yoXrXE-unsplash.jpg
|
image: /assets/header/#3-data-privacy-things-to-consider.jpg
|
||||||
attribution: 'Photo by <a href="https://unsplash.com/@heftiba?utm_content=creditCopyText&utm_medium=referral&utm_source=unsplash">Toa Heftiba</a> on <a href="https://unsplash.com/photos/group-of-people-sitting-on-front-firepit-x9I-6yoXrXE?utm_content=creditCopyText&utm_medium=referral&utm_source=unsplash">Unsplash</a>'
|
attribution: 'Photo by <a href="https://unsplash.com/@heftiba?utm_content=creditCopyText&utm_medium=referral&utm_source=unsplash">Toa Heftiba</a> on <a href="https://unsplash.com/photos/group-of-people-sitting-on-front-firepit-x9I-6yoXrXE?utm_content=creditCopyText&utm_medium=referral&utm_source=unsplash">Unsplash</a>'
|
||||||
|
|
||||||
---
|
---
|
||||||
|
@@ -5,7 +5,7 @@ date: 2025-09-12 01:08:54 UTC
|
|||||||
tags: refactoring,WebDevelopment,FrontendDevelopment,CSS
|
tags: refactoring,WebDevelopment,FrontendDevelopment,CSS
|
||||||
canonical_url: https://campfire.dlseitz.dev/4-refactoring-a-false-sense-of-simplicity
|
canonical_url: https://campfire.dlseitz.dev/4-refactoring-a-false-sense-of-simplicity
|
||||||
header:
|
header:
|
||||||
image: '/assets/20250911_2016_Coding by Campfire_simple_compose_01k4xqta8sfjyrws9ezcwjpg9x.png'
|
image: '/assets/header/#4-refactoring-a-false-sense-of-simplicity.png'
|
||||||
attribution: 'Image generated with Sora. | © 2025 Derek L. Seitz'
|
attribution: 'Image generated with Sora. | © 2025 Derek L. Seitz'
|
||||||
---
|
---
|
||||||
|
|
||||||
|
@@ -5,7 +5,7 @@ date: 2025-09-20 21:51:29 UTC
|
|||||||
tags: WebDevelopment,refactoring,JavaScript,apiintegration
|
tags: WebDevelopment,refactoring,JavaScript,apiintegration
|
||||||
canonical_url: https://campfire.dlseitz.dev/5-the-power-of-separation-compels-you
|
canonical_url: https://campfire.dlseitz.dev/5-the-power-of-separation-compels-you
|
||||||
header:
|
header:
|
||||||
image: /assets/5-separation.webp
|
image: /assets/header/#5-the-power-of-separation-compels-you.webp
|
||||||
attribution: 'Image generated with Sora. | © 2025 Derek L. Seitz'
|
attribution: 'Image generated with Sora. | © 2025 Derek L. Seitz'
|
||||||
contentImagePath: /assets/#5/
|
contentImagePath: /assets/#5/
|
||||||
---
|
---
|
||||||
|
@@ -66,7 +66,7 @@ export const blogPosts = [
|
|||||||
published: true
|
published: true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "#5 - The Power of Separation Compels You!",
|
title: "#5 - The Power of [Separation] Compels You!",
|
||||||
slug: "5-the-power-of-separation-compels-you",
|
slug: "5-the-power-of-separation-compels-you",
|
||||||
filename: "#5-the-power-of-separation-compels-you.md",
|
filename: "#5-the-power-of-separation-compels-you.md",
|
||||||
date: "2025-09-20 21:51:29 UTC",
|
date: "2025-09-20 21:51:29 UTC",
|
||||||
|
@@ -14,10 +14,10 @@ const Dashboard = React.forwardRef((props, ref) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div ref={ref}>
|
<div style={{ textAlign: 'center' }} ref={ref}>
|
||||||
<h1>Dashboard</h1>
|
<h1>Dashboard</h1>
|
||||||
|
|
||||||
<section>
|
<section style={{ textAlign: 'center' }}>
|
||||||
<h2>Published Posts</h2>
|
<h2>Published Posts</h2>
|
||||||
{publishedPosts.length ? (
|
{publishedPosts.length ? (
|
||||||
<ul>
|
<ul>
|
||||||
@@ -26,8 +26,8 @@ const Dashboard = React.forwardRef((props, ref) => {
|
|||||||
<a class="k-link" href={post.canonical_url} target="_blank" rel="noreferrer">
|
<a class="k-link" href={post.canonical_url} target="_blank" rel="noreferrer">
|
||||||
{post.title}
|
{post.title}
|
||||||
</a>{' '}
|
</a>{' '}
|
||||||
<span>{post.date}</span>{' '}
|
<span style={{ marginLeft: '30px', padding: '0 20px' }} >{post.date}</span>{' '}
|
||||||
<Button onClick={() => handleEdit(post.slug)}>Edit</Button>
|
<Button style={{ marginLeft: '30px', padding: '0 20px' }} onClick={() => handleEdit(post.slug)}>Edit</Button>
|
||||||
</li>
|
</li>
|
||||||
))}
|
))}
|
||||||
</ul>
|
</ul>
|
||||||
@@ -36,14 +36,14 @@ const Dashboard = React.forwardRef((props, ref) => {
|
|||||||
)}
|
)}
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section>
|
<section style={{ textAlign: 'center' }}>
|
||||||
<h2>Drafts</h2>
|
<h2>Drafts</h2>
|
||||||
{draftPosts.length ? (
|
{draftPosts.length ? (
|
||||||
<ul>
|
<ul>
|
||||||
{draftPosts.map(post => (
|
{draftPosts.map(post => (
|
||||||
<li key={post.slug}>
|
<li key={post.slug}>
|
||||||
{post.title}{' '}
|
{post.title}{' '}
|
||||||
<Button onClick={() => handleEdit(post.slug)}>Edit</Button>
|
<Button style={{ marginLeft: '30px', padding: '0 20px' }} onClick={() => handleEdit(post.slug)}>Edit</Button>
|
||||||
</li>
|
</li>
|
||||||
))}
|
))}
|
||||||
</ul>
|
</ul>
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import LoginComponent from '../components/LoginComponent';
|
import LoginComponent from '../components/LoginComponent';
|
||||||
import Logo from '../assets/images/campfire_logs_square_logo.png';
|
import Logo from '../assets/images/campfire_logs_square_logo_bg_match.png';
|
||||||
|
|
||||||
const LoginPage = React.forwardRef(({ onLogin }, ref) => {
|
const LoginPage = React.forwardRef(({ onLogin }, ref) => {
|
||||||
return (
|
return (
|
||||||
|