diff --git a/.gitea/workflows/ci.yaml b/.gitea/workflows/ci.yaml
index 77d2cf1..9d4e29a 100644
--- a/.gitea/workflows/ci.yaml
+++ b/.gitea/workflows/ci.yaml
@@ -316,7 +316,8 @@ jobs:
"$CHROME_PATH" --version
# Run LHCI with arm64 Node + arm64 Chrome
- npx lhci autorun --chrome-path="$CHROME_PATH" --collect.url=http://$HOST:$PORT/
+ # Test homepage and blog pages
+ npx lhci autorun --chrome-path="$CHROME_PATH" --collect.url=http://$HOST:$PORT/ --collect.url=http://$HOST:$PORT/blog --collect.url=http://$HOST:$PORT/blog/resolving-active-conflicts
kill "$SVPID" 2>/dev/null || true
env:
diff --git a/app/blog/page.js b/app/blog/page.js
new file mode 100644
index 0000000..7953ccf
--- /dev/null
+++ b/app/blog/page.js
@@ -0,0 +1,61 @@
+import { getAllBlogPosts } from "../../lib/content";
+import Header from "../components/Header";
+import ContentThumbnailTemplate from "../components/ContentThumbnailTemplate";
+import ContentContainer from "../components/ContentContainer";
+
+export const metadata = {
+ title: "Blog - CommunityRule",
+ description:
+ "Learn about community governance, decision-making, and building successful organizations.",
+ openGraph: {
+ title: "Blog - CommunityRule",
+ description:
+ "Learn about community governance, decision-making, and building successful organizations.",
+ url: "https://communityrule.com/blog",
+ siteName: "CommunityRule",
+ type: "website",
+ },
+ twitter: {
+ card: "summary_large_image",
+ title: "Blog - CommunityRule",
+ description:
+ "Learn about community governance, decision-making, and building successful organizations.",
+ },
+};
+
+export default function BlogPage() {
+ const posts = getAllBlogPosts();
+
+ // Create slug order for consistent icon cycling
+ const slugOrder = posts.map((post) => post.slug);
+
+ return (
+
+
+
+
+
+
+ Blog
+
+
+ Learn about community governance, decision-making, and building
+ successful organizations.
+
+
+
+
+ {posts.map((post, index) => (
+
+ ))}
+
+
+
+
+ );
+}
diff --git a/performance-budgets.json b/performance-budgets.json
index b545e77..6a5df61 100644
--- a/performance-budgets.json
+++ b/performance-budgets.json
@@ -180,6 +180,168 @@
"budget": 5
}
]
+ },
+ {
+ "path": "/blog",
+ "timings": [
+ {
+ "metric": "first-contentful-paint",
+ "budget": 2000
+ },
+ {
+ "metric": "largest-contentful-paint",
+ "budget": 2500
+ },
+ {
+ "metric": "first-meaningful-paint",
+ "budget": 2000
+ },
+ {
+ "metric": "speed-index",
+ "budget": 3000
+ },
+ {
+ "metric": "interactive",
+ "budget": 3000
+ },
+ {
+ "metric": "total-blocking-time",
+ "budget": 300
+ },
+ {
+ "metric": "cumulative-layout-shift",
+ "budget": 0.1
+ },
+ {
+ "metric": "max-potential-fid",
+ "budget": 130
+ }
+ ],
+ "resourceSizes": [
+ {
+ "resourceType": "script",
+ "budget": 300
+ },
+ {
+ "resourceType": "total",
+ "budget": 500
+ },
+ {
+ "resourceType": "image",
+ "budget": 100
+ },
+ {
+ "resourceType": "stylesheet",
+ "budget": 50
+ },
+ {
+ "resourceType": "font",
+ "budget": 50
+ }
+ ],
+ "resourceCounts": [
+ {
+ "resourceType": "script",
+ "budget": 10
+ },
+ {
+ "resourceType": "total",
+ "budget": 50
+ },
+ {
+ "resourceType": "image",
+ "budget": 20
+ },
+ {
+ "resourceType": "stylesheet",
+ "budget": 5
+ },
+ {
+ "resourceType": "font",
+ "budget": 5
+ }
+ ]
+ },
+ {
+ "path": "/blog/*",
+ "timings": [
+ {
+ "metric": "first-contentful-paint",
+ "budget": 2000
+ },
+ {
+ "metric": "largest-contentful-paint",
+ "budget": 2500
+ },
+ {
+ "metric": "first-meaningful-paint",
+ "budget": 2000
+ },
+ {
+ "metric": "speed-index",
+ "budget": 3000
+ },
+ {
+ "metric": "interactive",
+ "budget": 3000
+ },
+ {
+ "metric": "total-blocking-time",
+ "budget": 300
+ },
+ {
+ "metric": "cumulative-layout-shift",
+ "budget": 0.1
+ },
+ {
+ "metric": "max-potential-fid",
+ "budget": 130
+ }
+ ],
+ "resourceSizes": [
+ {
+ "resourceType": "script",
+ "budget": 300
+ },
+ {
+ "resourceType": "total",
+ "budget": 500
+ },
+ {
+ "resourceType": "image",
+ "budget": 100
+ },
+ {
+ "resourceType": "stylesheet",
+ "budget": 50
+ },
+ {
+ "resourceType": "font",
+ "budget": 50
+ }
+ ],
+ "resourceCounts": [
+ {
+ "resourceType": "script",
+ "budget": 10
+ },
+ {
+ "resourceType": "total",
+ "budget": 50
+ },
+ {
+ "resourceType": "image",
+ "budget": 20
+ },
+ {
+ "resourceType": "stylesheet",
+ "budget": 5
+ },
+ {
+ "resourceType": "font",
+ "budget": 5
+ }
+ ]
}
]
}