diff --git a/src/assets/images/campfire_logs_square_logo.png b/src/assets/images/campfire_logs_square_logo.png
deleted file mode 100644
index 179f5bd..0000000
Binary files a/src/assets/images/campfire_logs_square_logo.png and /dev/null differ
diff --git a/src/components/Editor/MarkdownEditor.jsx b/src/components/Editor/MarkdownEditor.jsx
new file mode 100644
index 0000000..3c236d2
--- /dev/null
+++ b/src/components/Editor/MarkdownEditor.jsx
@@ -0,0 +1,68 @@
+// MarkdownEditor.jsx
+// KendoReact Splitter implementation for dual-pane markdown editing with live preview
+// Demonstrates advanced layout components and real-time markdown processing
+import React, { useState } from 'react';
+import { Splitter, SplitterPane } from '@progress/kendo-react-layout';
+import { marked } from 'marked';
+
+function MarkdownEditor({ markdownContent, onMarkdownChange, onSplitterChange, panes }) {
+ return (
+ // KendoReact Splitter for dual-pane markdown editing with live preview
+
+
+
+
Markdown Editor
+
+
+
+
+
+
+
+ );
+}
+
+export default MarkdownEditor;
diff --git a/src/components/Editor/MetadataEditor.jsx b/src/components/Editor/MetadataEditor.jsx
new file mode 100644
index 0000000..42b8ce2
--- /dev/null
+++ b/src/components/Editor/MetadataEditor.jsx
@@ -0,0 +1,71 @@
+// MetadataEditor.jsx
+import React, { useState } from 'react';
+import { Input } from '@progress/kendo-react-inputs';
+import { Label } from '@progress/kendo-react-labels';
+import { Button } from '@progress/kendo-react-buttons';
+
+function MetadataEditor({ postData }) {
+ const [title, setTitle] = useState(postData?.title || '');
+ const [tags, setTags] = useState(postData?.tags?.join(', ') || '');
+ const [headerImage, setHeaderImage] = useState(postData?.header?.image || '');
+
+ const handleTitleChange = (e) => {
+ setTitle(e.target.value);
+ };
+
+ const handleTagsChange = (e) => {
+ setTags(e.target.value);
+ };
+
+ const handleHeaderImageChange = (e) => {
+ const file = e.target.files[0];
+ if (file) {
+ console.log('Header image uploaded:', file);
+ }
+ };
+
+
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+}
+
+export default MetadataEditor;
\ No newline at end of file
diff --git a/src/components/Editor/custom/EditorModeToggle.jsx b/src/components/Editor/custom/EditorModeToggle.jsx
new file mode 100644
index 0000000..f9ba9b9
--- /dev/null
+++ b/src/components/Editor/custom/EditorModeToggle.jsx
@@ -0,0 +1,26 @@
+// EditorModeToggle.jsx
+// Custom KendoReact component for switching between HTML and Markdown editing modes
+// Demonstrates reusable UI components and state management patterns
+import React from 'react';
+import { Button } from '@progress/kendo-react-buttons';
+
+function EditorModeToggle({ editMode, onToggle }) {
+ return (
+ // Toggle button positioned above the editor with consistent styling
+
+
+
+ );
+}
+
+export default EditorModeToggle;
diff --git a/src/components/Editor/custom/InlineCodeTool.jsx b/src/components/Editor/custom/InlineCodeTool.jsx
new file mode 100644
index 0000000..6259bd7
--- /dev/null
+++ b/src/components/Editor/custom/InlineCodeTool.jsx
@@ -0,0 +1,49 @@
+// InlineCodeTool.jsx
+// Custom KendoReact Editor tool for inline code formatting
+import React from 'react';
+import { Button } from '@progress/kendo-react-buttons';
+import { SvgIcon } from '@progress/kendo-react-common';
+import { codeSnippetIcon } from '@progress/kendo-svg-icons';
+
+const InlineCodeTool = (props) => {
+ const { view } = props;
+
+ const handleClick = () => {
+ if (view) {
+ // Access ProseMirror editor state and dispatch
+ const { state, dispatch } = view;
+ const markType = state.schema.marks.code;
+ const { from, to } = state.selection;
+
+ if (markType) {
+ const tr = state.tr;
+ // Check if selected text already has code mark
+ const hasMark = state.doc.rangeHasMark(from, to, markType);
+
+ if (hasMark) {
+ // Remove code mark if already present
+ tr.removeMark(from, to, markType);
+ } else {
+ // Add code mark to selected text
+ tr.addMark(from, to, markType.create());
+ }
+
+ // Dispatch transaction to apply changes
+ dispatch(tr);
+ }
+ }
+ };
+
+ return (
+ // KendoReact Button with SVG icon
+
+ );
+};
+
+export default InlineCodeTool;
\ No newline at end of file
diff --git a/src/components/UI/Breadcrumb.jsx b/src/components/UI/Breadcrumb.jsx
new file mode 100644
index 0000000..d72ee93
--- /dev/null
+++ b/src/components/UI/Breadcrumb.jsx
@@ -0,0 +1,75 @@
+// Breadcrumb.jsx
+import React from 'react';
+import { Breadcrumb } from '@progress/kendo-react-layout';
+import { useLocation } from 'react-router-dom';
+
+const CampfireBreadcrumb = () => {
+ const location = useLocation();
+
+ const getBreadcrumbs = () => {
+ const path = location.pathname;
+ const pathSegments = path.split('/').filter(segment => segment);
+
+ if (path === '/dashboard' || path === '/') {
+ return [{ id: 'dashboard', text: 'Dashboard' }];
+ }
+
+ if (path === '/posts') {
+ return [
+ { id: 'dashboard', text: 'Dashboard' },
+ { id: 'posts', text: 'Published Posts' }
+ ];
+ }
+
+ if (path === '/drafts') {
+ return [
+ { id: 'dashboard', text: 'Dashboard' },
+ { id: 'drafts', text: 'Drafts' }
+ ];
+ }
+
+ if (path === '/editor') {
+ return [
+ { id: 'editor', text: 'Editor' },
+ { id: 'new-post', text: 'New Post' }
+ ];
+ }
+
+ if (path.startsWith('/editor/')) {
+ const slug = pathSegments[1];
+ return [
+ { id: 'editor', text: 'Editor' },
+ { id: 'edit-post', text: 'Edit Post' } // Placeholder for actual title
+ ];
+ }
+
+ return [{ id: 'dashboard', text: 'Dashboard' }];
+ };
+
+ const breadcrumbData = getBreadcrumbs();
+ console.log('Breadcrumb data:', breadcrumbData);
+
+ return (
+
+
+
+
+ );
+};
+
+export default CampfireBreadcrumb;
\ No newline at end of file
diff --git a/src/data/postsCache.js b/src/data/postsCache.js
new file mode 100644
index 0000000..eb3c957
--- /dev/null
+++ b/src/data/postsCache.js
@@ -0,0 +1,50 @@
+// postsCache.js
+// Caching layer for blog post data
+// Prevents multiple simultaneous API calls and provides efficient data access
+import { loadPosts } from './blog-post-data';
+
+// Cache state management
+let postsCache = null;
+let isLoading = false;
+let loadPromise = null;
+
+// Singleton pattern with promise deduplication for efficient data loading
+export const getPosts = async () => {
+ // Return cached data immediately if available
+ if (postsCache) {
+ return postsCache;
+ }
+
+ // Prevent duplicate loading - wait for existing promise
+ if (isLoading && loadPromise) {
+ return loadPromise;
+ }
+
+ // Start loading process with promise caching
+ isLoading = true;
+ loadPromise = loadPosts().then(posts => {
+ postsCache = posts;
+ isLoading = false;
+ return posts;
+ });
+
+ return loadPromise;
+};
+
+// Filter published posts for dashboard display
+export const getPublishedPosts = async () => {
+ const posts = await getPosts();
+ return posts.filter(post => post.published);
+};
+
+// Filter draft posts for editor management
+export const getDraftPosts = async () => {
+ const posts = await getPosts();
+ return posts.filter(post => !post.published);
+};
+
+// Find specific post by slug for editor functionality
+export const getPostBySlug = async (slug) => {
+ const posts = await getPosts();
+ return posts.find(post => post.slug === slug);
+};