diff --git a/app/blog/[slug]/page.js b/app/blog/[slug]/page.js index a02c9f5..bf8fc54 100644 --- a/app/blog/[slug]/page.js +++ b/app/blog/[slug]/page.js @@ -93,6 +93,9 @@ export default async function BlogPostPage({ params }) { // Get related articles with improved algorithm const allPosts = getAllPosts(); + // Create slug order for consistent background cycling + const slugOrder = allPosts.map((post) => post.slug); + // Simple related articles algorithm based on content similarity const getRelatedArticles = (currentPost, allPosts, limit = 3) => { const otherPosts = allPosts.filter((p) => p.slug !== currentPost.slug); @@ -265,6 +268,7 @@ export default async function BlogPostPage({ params }) { {/* Ask Organizer Section */} diff --git a/app/blog/page.js b/app/blog/page.js index 7953ccf..dead414 100644 --- a/app/blog/page.js +++ b/app/blog/page.js @@ -1,5 +1,4 @@ import { getAllBlogPosts } from "../../lib/content"; -import Header from "../components/Header"; import ContentThumbnailTemplate from "../components/ContentThumbnailTemplate"; import ContentContainer from "../components/ContentContainer"; @@ -31,7 +30,6 @@ export default function BlogPage() { return (
-
diff --git a/app/components/ContentThumbnailTemplate.js b/app/components/ContentThumbnailTemplate.js index 09dc3ae..fbed8c1 100644 --- a/app/components/ContentThumbnailTemplate.js +++ b/app/components/ContentThumbnailTemplate.js @@ -13,9 +13,10 @@ const ContentThumbnailTemplate = ({ post, className = "", variant = "vertical", // Internal prop for testing/development + slugOrder = [], // Array of slugs for consistent icon cycling }) => { // Post-specific background selection - different SVG for each post - const getBackgroundImage = (slug, variant) => { + const getBackgroundImage = (slug, variant, slugOrder) => { const verticalImages = [ getAssetPath(ASSETS.VERTICAL_1), getAssetPath(ASSETS.VERTICAL_2), @@ -28,23 +29,20 @@ const ContentThumbnailTemplate = ({ getAssetPath(ASSETS.HORIZONTAL_3), ]; - const images = variant === "vertical" ? verticalImages : horizontalImages; + if (!slug) + return variant === "vertical" ? verticalImages[0] : horizontalImages[0]; - if (!slug) return images[0]; - - // Simple cycling approach to ensure different styles - const slugOrder = [ - "building-community-trust", - "operational-security-mutual-aid", - "making-decisions-without-hierarchy", - "resolving-active-conflicts", - ]; + // Use the passed slugOrder for consistent cycling through background variants const index = slugOrder.indexOf(slug); - const finalIndex = index >= 0 ? index % images.length : 0; - return images[finalIndex]; + const backgroundIndex = index >= 0 ? index % 3 : 0; // Cycle through 3 background variants + + // Return the same background index for both vertical and horizontal variants + return variant === "vertical" + ? verticalImages[backgroundIndex] + : horizontalImages[backgroundIndex]; }; - const backgroundImage = getBackgroundImage(post.slug, variant); + const backgroundImage = getBackgroundImage(post.slug, variant, slugOrder); if (variant === "vertical") { return ( diff --git a/app/components/Header.js b/app/components/Header.js index cf5e0a9..0dd54f8 100644 --- a/app/components/Header.js +++ b/app/components/Header.js @@ -9,7 +9,7 @@ import { getAssetPath, ASSETS } from "../../lib/assetUtils"; // Configuration data for testing export const navigationItems = [ { href: "#", text: "Use cases", extraPadding: true }, - { href: "#", text: "Learn" }, + { href: "/learn", text: "Learn" }, { href: "#", text: "About" }, ]; diff --git a/app/components/HomeHeader.js b/app/components/HomeHeader.js index cac8d03..02b230e 100644 --- a/app/components/HomeHeader.js +++ b/app/components/HomeHeader.js @@ -29,7 +29,7 @@ export default function HomeHeader() { const navigationItems = [ { href: "#", text: "Use cases", extraPadding: true }, - { href: "#", text: "Learn" }, + { href: "/learn", text: "Learn" }, { href: "#", text: "About" }, ]; @@ -79,10 +79,10 @@ export default function HomeHeader() { ? size === "home" || size === "homeMd" ? "homeMd" : size === "large" - ? "large" - : size === "homeXlarge" - ? "homeXlarge" - : "xsmallUseCases" + ? "large" + : size === "homeXlarge" + ? "homeXlarge" + : "xsmallUseCases" : size } variant={ diff --git a/app/components/RelatedArticles.js b/app/components/RelatedArticles.js index 9164d3a..c695b66 100644 --- a/app/components/RelatedArticles.js +++ b/app/components/RelatedArticles.js @@ -3,10 +3,14 @@ import { useState, useEffect } from "react"; import ContentThumbnailTemplate from "./ContentThumbnailTemplate"; -export default function RelatedArticles({ relatedPosts, currentPostSlug }) { +export default function RelatedArticles({ + relatedPosts, + currentPostSlug, + slugOrder = [], +}) { // Filter out the current post from related posts const filteredPosts = relatedPosts.filter( - (post) => post.slug !== currentPostSlug, + (post) => post.slug !== currentPostSlug ); const [currentIndex, setCurrentIndex] = useState(0); @@ -93,7 +97,7 @@ export default function RelatedArticles({ relatedPosts, currentPostSlug }) { const handleMouseUp = () => { document.removeEventListener( "mousemove", - handleMouseMove, + handleMouseMove ); document.removeEventListener("mouseup", handleMouseUp); }; @@ -112,6 +116,7 @@ export default function RelatedArticles({ relatedPosts, currentPostSlug }) {
))} @@ -133,8 +138,8 @@ export default function RelatedArticles({ relatedPosts, currentPostSlug }) { index === currentIndex ? `${progress}%` : index < currentIndex - ? "100%" - : "0%", + ? "100%" + : "0%", }} />
diff --git a/app/learn/page.js b/app/learn/page.js new file mode 100644 index 0000000..39e78fe --- /dev/null +++ b/app/learn/page.js @@ -0,0 +1,116 @@ +import ContentThumbnailTemplate from "../components/ContentThumbnailTemplate"; + +// Mock blog post data for testing +const mockPost1 = { + slug: "resolving-active-conflicts", + frontmatter: { + title: "Resolving Active Conflicts", + description: + "Practical steps for resolving conflicts while maintaining trust, cooperation, and shared goals", + author: "Author name", + date: "2025-04-15", + }, +}; + +const mockPost2 = { + slug: "operational-security-mutual-aid", + frontmatter: { + title: "Operational Security for Mutual Aid", + description: + "Tactics to protect members, secure communication, and prevent Infiltration", + author: "Author name", + date: "2025-04-10", + }, +}; + +const mockPost3 = { + slug: "making-decisions-without-hierarchy", + frontmatter: { + title: "Making decisions without hierarchy", + description: + "A brief guide to collaborative nonhierarchical decision making", + author: "Author name", + date: "2025-04-05", + }, +}; + +export default function LearnPage() { + // Mock slug order for consistent background cycling + const mockSlugOrder = [ + "resolving-active-conflicts", + "operational-security-mutual-aid", + "making-decisions-without-hierarchy", + ]; + + return ( +
+
+

+ Learn +

+ +
+ {/* Featured Articles */} +
+

+ Featured Articles +

+
+ + + +
+
+ + {/* More Articles */} +
+

+ More Articles +

+
+ + + +
+
+ + {/* Coming Soon */} +
+

+ More Content Coming Soon +

+

+ We're working on adding more educational content to help you build + better communities. Check back soon for new articles and + resources. +

+
+
+
+
+ ); +} diff --git a/app/test-thumbnail/page.js b/app/test-thumbnail/page.js deleted file mode 100644 index 18ab2f1..0000000 --- a/app/test-thumbnail/page.js +++ /dev/null @@ -1,116 +0,0 @@ -import ContentThumbnailTemplate from "../components/ContentThumbnailTemplate"; - -// Mock blog post data for testing -const mockPost1 = { - slug: "resolving-active-conflicts", - frontmatter: { - title: "Resolving Active Conflicts", - description: - "Practical steps for resolving conflicts while maintaining trust, cooperation, and shared goals", - author: "Author name", - date: "2025-04-15", - }, -}; - -const mockPost2 = { - slug: "operational-security-mutual-aid", - frontmatter: { - title: "Operational Security for Mutual Aid", - description: - "Tactics to protect members, secure communication, and prevent Infiltration", - author: "Author name", - date: "2025-04-10", - }, -}; - -const mockPost3 = { - slug: "making-decisions-without-hierarchy", - frontmatter: { - title: "Making decisions without hierarchy", - description: - "A brief guide to collaborative nonhierarchical decision making", - author: "Author name", - date: "2025-04-05", - }, -}; - -export default function TestThumbnailPage() { - return ( -
-
-

- ContentThumbnailTemplate Test -

- -
- {/* Vertical Variant */} -
-

- Vertical Variant -

-
- - - -
-
- - {/* Horizontal Variant */} -
-

- Horizontal Variant -

-
- - - -
-
- - {/* Component Props */} -
-

- Component Props -

-
-
-

- Required Props: -

-
    -
  • - post - Blog post object with frontmatter -
  • -
-
-
-

- Optional Props: -

-
    -
  • - className - Additional CSS classes -
  • -
  • - variant - "vertical" (default) or - "horizontal" (for development/testing) -
  • -
-
-
-
- - {/* Mock Data */} -
-

- Mock Data Structure -

-
-              {JSON.stringify(mockPost1, null, 2)}
-            
-
-
-
-
- ); -} diff --git a/docs/CONTENT_CREATION_GUIDE.md b/docs/CONTENT_CREATION_GUIDE.md index c7c06ed..a560143 100644 --- a/docs/CONTENT_CREATION_GUIDE.md +++ b/docs/CONTENT_CREATION_GUIDE.md @@ -2,6 +2,31 @@ A simple guide for creating blog content for Community Rule. +## How to Upload an Article + +Here's how to contribute a new article: + +1. **Fork the repository** (if you haven't already) +2. **Create a new branch** for your article: `git checkout -b add-my-article-title` +3. **Create your article file** in the `content/blog/` directory +4. **Test locally** (optional but recommended): + - Run `npm install` to install dependencies + - Run `npm run dev` to start the development server + - Visit `http://localhost:3000/blog/your-article-slug` to preview +5. **Commit your changes**: + ```bash + git add content/blog/your-article.md + git commit -m "Add article: Your Article Title" + ``` +6. **Push to your fork**: + ```bash + git push origin add-my-article-title + ``` +7. **Create a pull request** in Gitea with: + - Clear title describing your article + - Brief description of what the article covers + - Any relevant context or notes for reviewers + ## Quick Start 1. **Copy the template**: Use `content/blog/_template.md` as your starting point