From b4f01d7b53ed5ed0ee9fa6a44eb16666e6ca8e5d Mon Sep 17 00:00:00 2001 From: sanjay-kv Date: Wed, 21 Oct 2026 01:01:01 +1100 Subject: [PATCH] Redesign the Blogs page Editorial layout built from real blog data (new blog-listing plugin): hero with GitHub tile and author strip, Big data spotlight, Latest grid with pagination, Featured picked by front matter, a content changelog strip and a Write for the hive banner. Banners are shown uncropped in 16:9 frames. Adds image, category and featured front matter to the posts and fixes the Sanjay Viswanathan spelling. Co-Authored-By: Claude Sonnet 5.5 --- blog/ETL-pipeline-tutorial/index.md | 2 + blog/authors.yml | 2 +- blog/azure-cost-optimization/index.md | 2 + blog/azure-storage-options/index.md | 2 + blog/azure-synapse-analytics/index.md | 2 + blog/batch-vs-stream-processing/index.md | 2 + blog/data-engineers-vs-mbas/index.md | 3 + blog/deltalake-data-storage/index.md | 2 + blog/fabric-data-engineer/index.md | 2 + blog/git-coding-agent/index.md | 2 + blog/github-cli-agent/index.md | 2 + blog/google-icon-update/index.md | 1 + blog/lakehouse-vs-warehouse/index.md | 2 + blog/medallion-architecture/index.md | 2 + blog/microsoft-data-purview/index.md | 2 + blog/microsoft-fabric-explained/index.md | 2 + blog/n8n-workflow-automation/index.md | 2 + blog/netflix-data-engineering/index.md | 2 + blog/open-ai-agent-builder/index.md | 2 + blog/single-sign-on/index.md | 2 + blog/spark-architecture/index.md | 2 + blog/spark-performance-optimizations/index.md | 2 + blog/ux-ui-design-job/index.md | 2 + community/contributing-guidelines.md | 9 + docs/getting_started.md | 2 +- docusaurus.config.ts | 2 + plugins/blog-listing/index.js | 49 + src/components/blogsPage/Hero.tsx | 102 ++ src/components/blogsPage/PostCard.tsx | 100 ++ src/components/blogsPage/Sections.tsx | 192 +++ src/components/blogsPage/blogData.ts | 85 ++ src/components/blogsPage/blogsPage.module.css | 219 +++ src/data/blogChangelog.ts | 50 + src/pages/blogs/blogs-new.css | 1290 ----------------- src/pages/blogs/blogs.css | 1186 --------------- src/pages/blogs/index.tsx | 458 +----- src/pages/privacy-policy/index.tsx | 2 +- src/utils/authors.ts | 4 +- static/img/blogs/github-cli-agent-cover.png | Bin 0 -> 274331 bytes 39 files changed, 914 insertions(+), 2882 deletions(-) create mode 100644 plugins/blog-listing/index.js create mode 100644 src/components/blogsPage/Hero.tsx create mode 100644 src/components/blogsPage/PostCard.tsx create mode 100644 src/components/blogsPage/Sections.tsx create mode 100644 src/components/blogsPage/blogData.ts create mode 100644 src/components/blogsPage/blogsPage.module.css create mode 100644 src/data/blogChangelog.ts delete mode 100644 src/pages/blogs/blogs-new.css delete mode 100644 src/pages/blogs/blogs.css create mode 100644 static/img/blogs/github-cli-agent-cover.png diff --git a/blog/ETL-pipeline-tutorial/index.md b/blog/ETL-pipeline-tutorial/index.md index e32aa1e8e..2270f992b 100644 --- a/blog/ETL-pipeline-tutorial/index.md +++ b/blog/ETL-pipeline-tutorial/index.md @@ -4,6 +4,8 @@ authors: [Aditya-Singh-Rathore] sidebar_label: "Azure Data Factory — Build Your First ETL" tags: [azure-data-factory, adf, etl, data-pipeline, data-engineering, azure, blob-storage, adls, copy-activity, linked-service, dataset, trigger] date: 2026-05-06 +image: /img/blogs/adf-cover_image.png +category: TUTORIAL description: Azure Data Factory is Microsoft's cloud-native ETL service — a visual, no-code platform for moving and transforming data at scale. This step-by-step guide walks you through building your first real pipeline in under 10 minutes, explaining every concept along the way. diff --git a/blog/authors.yml b/blog/authors.yml index b69d8bcaf..9d904aa1f 100644 --- a/blog/authors.yml +++ b/blog/authors.yml @@ -1,5 +1,5 @@ sanjay-kv: - name: Sanjay Viswanthan + name: Sanjay Viswanathan title: Founder at recode hive url: https://nomadbrains.dev image_url: https://avatars.githubusercontent.com/u/30715153?v=4 diff --git a/blog/azure-cost-optimization/index.md b/blog/azure-cost-optimization/index.md index 7b71bd49d..3a57c4d30 100644 --- a/blog/azure-cost-optimization/index.md +++ b/blog/azure-cost-optimization/index.md @@ -4,6 +4,8 @@ authors: [Aditya-Singh-Rathore] sidebar_label: "Azure Data Pipeline Cost Optimization" tags: [azure, cost-optimization, data-pipeline, adls-gen2, azure-synapse, apache-spark, azure-data-factory, delta-lake, data-engineering, cloud-cost] date: 2026-05-15 +image: /img/blogs/cost_optimzation_cover.png +category: CLOUD COST description: Six costly mistakes in a 2GB Azure data pipeline drove a $4,200 monthly bill. Here's every mistake, root cause, and fix — with before-and-after numbers for each. diff --git a/blog/azure-storage-options/index.md b/blog/azure-storage-options/index.md index 6172ae85a..70be4e643 100644 --- a/blog/azure-storage-options/index.md +++ b/blog/azure-storage-options/index.md @@ -4,6 +4,8 @@ authors: [Aditya-Singh-Rathore] sidebar_label: "Azure Storage & ADLS Gen2: Complete Guide" tags: [azure-storage, blob-storage, adls-gen2, azure-data-lake, queue-storage, table-storage, file-storage, data-engineering, azure, big-data, medallion-architecture] date: 2026-05-06 +image: /img/blogs/azure-storage-cover.png +category: AZURE description: Every Azure data pipeline needs a place to store data. But Azure gives you four different storage types and choosing the wrong one is easier than you think. This guide explains all four, shows how they work together in a real pipeline, and goes deep on ADLS Gen2, the storage layer that powers modern Azure data engineering. diff --git a/blog/azure-synapse-analytics/index.md b/blog/azure-synapse-analytics/index.md index 6f6b31d91..8d98e030f 100644 --- a/blog/azure-synapse-analytics/index.md +++ b/blog/azure-synapse-analytics/index.md @@ -4,6 +4,8 @@ authors: [Aditya-Singh-Rathore] sidebar_label: "Azure Synapse Analytics" tags: [azure-synapse-analytics, data-engineering, sql-pools, apache-spark, microsoft-fabric, data-warehouse, adls-gen2, azure, big-data, etl] date: 2026-05-06 +image: /img/blogs/azure-synapse-cover.png +category: AZURE description: Azure Synapse Analytics is one of the most powerful tools in the Azure data stack. But in 2026, with Microsoft Fabric growing fast, the question isn't just "what is Synapse?" — it's "when should you still use it, and when should you move to Fabric?" Here's the honest answer. diff --git a/blog/batch-vs-stream-processing/index.md b/blog/batch-vs-stream-processing/index.md index bac495823..c42144724 100644 --- a/blog/batch-vs-stream-processing/index.md +++ b/blog/batch-vs-stream-processing/index.md @@ -4,6 +4,8 @@ authors: [Aditya-Singh-Rathore] sidebar_label: "Why We Rolled Back Our Kafka Pipeline to Batch After 6 Monthss" tags: [batch-processing, stream-processing, data-engineering, apache-kafka, apache-flink, apache-spark, data-pipeline, real-time, azure, medallion-architecture, data-architecture] date: 2026-05-06 +image: /img/blogs/batch-vs-stream-cover.png +category: STREAMING description: Everyone talks about the benefits of streaming pipelines — real-time insights, millisecond latency, live dashboards. Nobody talks about what it actually costs you. I rebuilt a working batch pipeline as a streaming system. Here's what I learned the hard way. diff --git a/blog/data-engineers-vs-mbas/index.md b/blog/data-engineers-vs-mbas/index.md index 9e9757946..05d0d8de5 100644 --- a/blog/data-engineers-vs-mbas/index.md +++ b/blog/data-engineers-vs-mbas/index.md @@ -4,6 +4,9 @@ authors: [Aditya-Singh-Rathore] sidebar_label: "Data Engineers vs MBAs as Business Analysts" tags: [data-engineering, career, business-analysis, data-driven, analytics, data-strategy, opinion, leadership] date: 2026-05-19 +image: /img/blogs/ba_de_cover_image.png +category: CAREER +featured: true description: MBAs learn to analyze businesses. Data engineers live inside the data those businesses actually run on. Here's why that difference matters more than any credential — and what both sides should learn from each other. diff --git a/blog/deltalake-data-storage/index.md b/blog/deltalake-data-storage/index.md index 1f0469095..f02a5bb71 100644 --- a/blog/deltalake-data-storage/index.md +++ b/blog/deltalake-data-storage/index.md @@ -4,6 +4,8 @@ authors: [Aditya-Singh-Rathore] sidebar_label: "Delta lake Storage" tags: [deltalake,storage, Big Data, cloud, Data Engineering, fabric] date: 2026-05-01 +image: /img/blogs/delta-lake-logo.png +category: STORAGE description: Delta Lake is an open-source storage framework that enables building a format agnostic Lakehouse architecture with compute engines including Spark, PrestoDB, Flink, Trino, Hive, Snowflake, Google BigQuery, Athena, Redshift, Databricks, Azure Fabric and APIs for Scala, Java, Rust, and Python. With Delta Universal Format aka UniForm, you can read now Delta tables with Iceberg and Hudi clients. diff --git a/blog/fabric-data-engineer/index.md b/blog/fabric-data-engineer/index.md index 63ee6e89a..7e5d9b7a9 100644 --- a/blog/fabric-data-engineer/index.md +++ b/blog/fabric-data-engineer/index.md @@ -4,6 +4,8 @@ authors: [Aditya-Singh-Rathore] sidebar_label: "Fabric Data Engineer" tags: [DP-700,azure, Big Data, cloud,certification,Data Engineering, fabric,experience] date: 2026-05-01 +image: /img/blogs/microsoft-certified-associate-badge.png +category: CERTIFICATION description: "A comprehensive guide to clearing the Microsoft Fabric Data Engineer Associate (DP-700) certification. Learn the preparation strategy, key concepts, hands-on practice tips, and real exam experience from someone who passed it. Discover why Lakehouse, Delta Tables, Dataflows, and DirectLake mode matter, and how to approach scenario-based questions effectively." diff --git a/blog/git-coding-agent/index.md b/blog/git-coding-agent/index.md index 517320d90..8185946e8 100644 --- a/blog/git-coding-agent/index.md +++ b/blog/git-coding-agent/index.md @@ -4,6 +4,8 @@ sidebar_label: GitHub Copilot Coding Agent authors: [sanjay-kv] tags: [GitHub, SEO, Coding agent,Copilot, AI, Automation] date: 2025-07-04 +image: /img/blogs/06-github-agent.png +category: AI TOOLS description: An overview of the GitHub Copilot Coding Agent, an AI-powered tool that automates software engineering tasks by taking GitHub Issues as input to write code, run tests, and create pull requests. draft: false diff --git a/blog/github-cli-agent/index.md b/blog/github-cli-agent/index.md index 312c8873e..3c9af7a57 100644 --- a/blog/github-cli-agent/index.md +++ b/blog/github-cli-agent/index.md @@ -4,6 +4,8 @@ authors: [sanjay-kv] sidebar_label: "GitHub Copilot CLI" tags: [GitHub, CLI, tech, updates, Copilot, Coding, Assistant] date: 2025-09-17 +image: /img/blogs/github-cli-agent-cover.png +category: GITHUB description: GitHub bought power of GitHub Copilot coding agent directly to your terminal, with GitHub Copilot CLI, you can work locally and synchronously with an AI agent. diff --git a/blog/google-icon-update/index.md b/blog/google-icon-update/index.md index d425f10dc..ea9de127d 100644 --- a/blog/google-icon-update/index.md +++ b/blog/google-icon-update/index.md @@ -4,6 +4,7 @@ description: "Google redesigned its Workspace icons in 2026, dropping the four-c authors: [sanjay-kv] tags: [google-workspace, ui-design, ux] date: 2026-05-21 +category: DESIGN image: /img/blogs/cover-google-icon.jpg --- diff --git a/blog/lakehouse-vs-warehouse/index.md b/blog/lakehouse-vs-warehouse/index.md index 6d76f41e4..aa08eb508 100644 --- a/blog/lakehouse-vs-warehouse/index.md +++ b/blog/lakehouse-vs-warehouse/index.md @@ -4,6 +4,8 @@ authors: [Aditya-Singh-Rathore] sidebar_label: "Lakehouse vs Data Warehouse" tags: [lakehouse, data-warehouse, data-engineering, big-data, delta-lake, spark, analytics, snowflake, databricks] date: 2026-05-01 +image: /img/blogs/datalake_vs_warehouse.png +category: ARCHITECTURE description: Lakehouse and Data Warehouse are two of the most debated architectures in modern data engineering. This article breaks down how they differ, where each fits in the data lifecycle, and how to choose between them, without the platform bias. diff --git a/blog/medallion-architecture/index.md b/blog/medallion-architecture/index.md index 736da68d3..158a00706 100644 --- a/blog/medallion-architecture/index.md +++ b/blog/medallion-architecture/index.md @@ -4,6 +4,8 @@ authors: [Aditya-Singh-Rathore] sidebar_label: "Medallion Architecture Explained" tags: [medallion-architecture, data-engineering, bronze-silver-gold, data-pipeline, delta-lake, spark, databricks, microsoft-fabric, data-quality] date: 2026-05-07 +image: /img/blogs/medallion_architecture.png +category: ARCHITECTURE description: Most data pipelines don't fail because of bad technology. They fail because raw data flows directly into reports with no checkpoints, no validation, and no clear ownership. Medallion Architecture fixes exactly this — here's how it works, why it matters, and how to implement it in practice. diff --git a/blog/microsoft-data-purview/index.md b/blog/microsoft-data-purview/index.md index 947015b81..80d65f622 100644 --- a/blog/microsoft-data-purview/index.md +++ b/blog/microsoft-data-purview/index.md @@ -4,6 +4,8 @@ authors: [Aditya-Singh-Rathore] sidebar_label: "Microsoft Purview Data Catalog" tags: [azure, microsoft-purview, data-catalog, data-governance, onboarding, data-lineage, metadata, data-engineering, azure-data-factory, delta-lake] date: 2026-05-19 +image: /img/blogs/purview_cover.png +category: DATA GOVERNANCE description: "Learn how Microsoft Purview Data Catalog improves data discovery, lineage, ownership, and governance. This practical case study shows how we reduced data engineer onboarding from 2 weeks to 3 days — including the configuration that made it work." diff --git a/blog/microsoft-fabric-explained/index.md b/blog/microsoft-fabric-explained/index.md index 8a84d8d1e..ded4425dd 100644 --- a/blog/microsoft-fabric-explained/index.md +++ b/blog/microsoft-fabric-explained/index.md @@ -4,6 +4,8 @@ authors: [Aditya-Singh-Rathore] sidebar_label: "Microsoft Fabric" tags: [microsoft-fabric, onelake, data-engineering, lakehouse, delta-lake, big-data, cloud, power-bi] date: 2026-05-01 +image: /img/blogs/microsoft-farbic-blog-image.png +category: MICROSOFT FABRIC description: Microsoft Fabric is a unified analytics platform that brings together data engineering, data science, real-time analytics, and business intelligence under a single roof — all built on OneLake. Learn how Fabric is architected, how data flows through it, and why it matters for modern data teams. diff --git a/blog/n8n-workflow-automation/index.md b/blog/n8n-workflow-automation/index.md index c14847fb5..c9da57031 100644 --- a/blog/n8n-workflow-automation/index.md +++ b/blog/n8n-workflow-automation/index.md @@ -4,6 +4,8 @@ authors: [Aditya-Singh-Rathore] sidebar_label: "N8N AI Workflows Explained" tags: [N8N, AI Automation, Workflow Automation, No-Code, Integration, Machine Learning, API Integration] date: 2025-09-17 +image: /img/blogs/n8n-logo.png +category: AUTOMATION description: N8N revolutionizes automation by integrating AI capabilities into visual workflows. Learn how to build intelligent automation pipelines that can process data, make decisions, and interact with multiple services seamlessly. diff --git a/blog/netflix-data-engineering/index.md b/blog/netflix-data-engineering/index.md index d253498aa..286712ed6 100644 --- a/blog/netflix-data-engineering/index.md +++ b/blog/netflix-data-engineering/index.md @@ -4,6 +4,8 @@ authors: [Aditya-Singh-Rathore] sidebar_label: "How Netflix Handles 2 Trillion Events Every Day" tags: [netflix, data-engineering, kafka, apache-flink, real-time, event-streaming, data-pipeline, cassandra, avro, iceberg, keystone] date: 2026-05-04 +image: /img/blogs/thumbnail.png +category: CASE STUDY description: Every click, pause, search, and scroll on Netflix generates an event. With 300 million subscribers across 190 countries, Netflix processes 2 trillion events every single day through a pipeline called Keystone. Here's a deep dive into how Kafka, Flink, Cassandra, and Iceberg make it all work in real time. diff --git a/blog/open-ai-agent-builder/index.md b/blog/open-ai-agent-builder/index.md index 4e2455bcb..455708d6c 100644 --- a/blog/open-ai-agent-builder/index.md +++ b/blog/open-ai-agent-builder/index.md @@ -4,6 +4,8 @@ authors: [Aditya-Singh-Rathore] sidebar_label: "OpenAI AgentKit Explained" tags: [OpenAI, AgentKit, AI Agents, Agent Builder, Agentic AI, Developer Tools] date: 2025-10-15 +image: /img/blogs/Agent_Builder.png +category: AI AGENTS description: OpenAI's AgentKit revolutionizes how developers build AI agents with its visual Agent Builder, integrated ChatKit, comprehensive evaluation tools, and seamless third-party integrations. Learn how this complete toolkit takes agents from prototype to production with minimal friction. diff --git a/blog/single-sign-on/index.md b/blog/single-sign-on/index.md index 467b38845..b0723c14c 100644 --- a/blog/single-sign-on/index.md +++ b/blog/single-sign-on/index.md @@ -4,6 +4,8 @@ authors: [Aditya-Singh-Rathore, sanjay-kv] sidebar_label: "How SSO Works - Case Study" tags: [sso, single-sign-on, authentication, identity-provider, oauth, openid-connect, saml, security, web] date: 2026-05-04 +image: /img/blogs/sso_cover.png +category: SECURITY description: SSO lets you log into dozens of apps with a single set of credentials. But how does it actually work under the hood? This beginner-friendly guide walks through the full flow — from clicking "Sign in with Google" to getting access — step by step. diff --git a/blog/spark-architecture/index.md b/blog/spark-architecture/index.md index 119d4d86e..711389633 100644 --- a/blog/spark-architecture/index.md +++ b/blog/spark-architecture/index.md @@ -4,6 +4,8 @@ authors: [Aditya-Singh-Rathore,sanjay-kv] sidebar_label: "Spark Architecture Explained" tags: [Apache Spark, Spark Architecture, Big Data, Distributed Computing, Data Engineering] date: 2025-08-22 +image: /img/blogs/07-spark-blog-banner.png +category: ARCHITECTURE description: Apache Spark is a fast, open-source big data framework that leverages in-memory computing for high performance. Its architecture powers scalable distributed processing across clusters, making it essential for analytics and machine learning. diff --git a/blog/spark-performance-optimizations/index.md b/blog/spark-performance-optimizations/index.md index dde81cb40..5b60c5ce6 100644 --- a/blog/spark-performance-optimizations/index.md +++ b/blog/spark-performance-optimizations/index.md @@ -4,6 +4,8 @@ authors: [Aditya-Singh-Rathore] sidebar_label: "PySpark Optimization Techniques" tags: [pyspark, spark, optimization, data-engineering, delta-lake, performance, partitioning, joins, caching, cluster-config] date: 2026-05-16 +image: /img/blogs/pyspark_optimization_cover.png +category: PERFORMANCE description: Six PySpark mistakes that silently kill pipeline performance and how to fix every one of them. Covering partitioning, shuffle tuning, caching, join strategies, UDFs, predicate pushdown, and cluster config. Explained from scratch. diff --git a/blog/ux-ui-design-job/index.md b/blog/ux-ui-design-job/index.md index 73236ad60..b4d219c7b 100644 --- a/blog/ux-ui-design-job/index.md +++ b/blog/ux-ui-design-job/index.md @@ -7,6 +7,8 @@ tags: - AI date: 2025-06-05 10:32:00 +image: /img/blogs/04-ux-job-design.png +category: CAREER description: Are you passionate about design and dreaming of a career in it? Or maybe you’re already in the design space and looking to pivot into UI/UX? . draft: false # meta: diff --git a/community/contributing-guidelines.md b/community/contributing-guidelines.md index eec55117b..8476f4601 100644 --- a/community/contributing-guidelines.md +++ b/community/contributing-guidelines.md @@ -161,6 +161,15 @@ We welcome contributions! Follow these steps to get started. > Tip: If your branch falls behind main, you can fetch and merge updates from upstream again before pushing. +## Blog banners + +Every blog post needs a banner so it looks right on the Blogs page. + +- Set it in the post's front matter with `image: /img/blogs/your-banner.png`, and add a `category:` (a short label such as ARCHITECTURE or TUTORIAL). +- Banners should be **1600 x 900 pixels (16:9)**, with **one big headline of 3 to 5 words**. The Blogs page shows the whole banner without cropping, so a banner in another shape gets empty bars on its sides. +- Keep important text away from the edges and keep the file small (under 300 KB where you can). +- Add `featured: true` only to the post the editors pick for the Featured spot. + ## Formatting To ensure consistent code style and catch errors before committing, please follow these steps: diff --git a/docs/getting_started.md b/docs/getting_started.md index 18cb18ded..511fabb7e 100644 --- a/docs/getting_started.md +++ b/docs/getting_started.md @@ -91,7 +91,7 @@ Replace my name with your name and respective website links of yours. ```yaml sanjay-kv: - name: Sanjay Viswanthan + name: Sanjay Viswanathan title: Founder at recode hive url: https://nomadbrains.dev image_url: https://avatars.githubusercontent.com/u/30715153?v=4 diff --git a/docusaurus.config.ts b/docusaurus.config.ts index bfafece75..22b9ede45 100644 --- a/docusaurus.config.ts +++ b/docusaurus.config.ts @@ -297,6 +297,8 @@ const config: Config = { "./plugins/learn-words", // Publish dates for the Broadcasts page from YouTube public RSS feeds (no API key) "./plugins/broadcasts-feed", + // Exposes every blog post to the /blogs listing page + "./plugins/blog-listing", // Real GitHub Discussions, fetched at build time (token never reaches the browser) "./plugins/github-discussions", [ diff --git a/plugins/blog-listing/index.js b/plugins/blog-listing/index.js new file mode 100644 index 000000000..16ca1ff0c --- /dev/null +++ b/plugins/blog-listing/index.js @@ -0,0 +1,49 @@ +// Exposes every blog post to the /blogs listing page as global data, so the page never needs a +// hardcoded post list. Reads the blog plugin's content after it has loaded. +const path = require('path'); + +function githubOf(author) { + const gh = author.socials && author.socials.github; + if (gh) return `https://github.com/${gh}`; + if (author.url && /github\.com/i.test(author.url)) return author.url; + return undefined; +} + +module.exports = function blogListingPlugin() { + return { + name: 'blog-listing', + async allContentLoaded({ allContent, actions }) { + const blog = allContent['docusaurus-plugin-content-blog']; + const posts = (blog && blog.default && blog.default.blogPosts) || []; + + const out = posts + .filter((p) => !p.metadata.unlisted) + .map((p) => { + const m = p.metadata; + const fm = m.frontMatter || {}; + return { + id: p.id, + folder: path.basename(path.dirname(m.source.replace(/^@site[\\/]/, ''))), + title: m.title, + permalink: m.permalink, + description: m.description || '', + date: m.date instanceof Date ? m.date.toISOString() : String(m.date), + readingTime: Math.max(1, Math.ceil(m.readingTime || 1)), + image: typeof fm.image === 'string' ? fm.image : undefined, + category: typeof fm.category === 'string' ? fm.category : undefined, + featured: fm.featured === true, + tags: (m.tags || []).map((t) => ({ label: t.label, permalink: t.permalink })), + authors: (m.authors || []).map((a) => ({ + key: a.key || a.name, + name: a.name, + imageURL: a.imageURL, + github: githubOf(a), + })), + }; + }) + .sort((a, b) => new Date(b.date).getTime() - new Date(a.date).getTime()); + + actions.setGlobalData({ posts: out }); + }, + }; +}; diff --git a/src/components/blogsPage/Hero.tsx b/src/components/blogsPage/Hero.tsx new file mode 100644 index 000000000..e6b53f9e8 --- /dev/null +++ b/src/components/blogsPage/Hero.tsx @@ -0,0 +1,102 @@ +import React, { useMemo } from 'react'; +import { Search } from 'lucide-react'; +import { TOPICS, uniqueAuthors, type Post } from './blogData'; +import { AuthorAvatar } from './PostCard'; +import styles from './blogsPage.module.css'; + +const COLS = 32; +const ROWS = 5; + +// Seeded so server and client agree. Levels rise toward the right. +const CELLS = Array.from({ length: COLS * ROWS }, (_, i) => { + const col = Math.floor(i / ROWS); + const row = i % ROWS; + const noise = Math.abs(Math.sin((col + 1) * 12.9898 + (row + 3) * 78.233) * 43758.5453) % 1; + const base = (col / (COLS - 1)) * 3.2; + const level = Math.max(0, Math.min(4, Math.round(base + noise * 1.8 - 0.6))); + return { level, pulse: i % 9 === 0 && level >= 3, delay: (i % 7) * 0.45 }; +}); + +function GithubTile() { + return ( + + +

+

+
+ ); +} + +function AuthorsStrip({ posts }: { posts: Post[] }) { + const authors = useMemo(() => uniqueAuthors(posts), [posts]); + if (authors.length === 0) return null; + return ( +
+
    + {authors.map((a) => { + const face = ; + return ( +
  • + {a.github ? ( + {face} + ) : ( + {face} + )} + {a.name} +
  • + ); + })} +
+

+ {authors.length} authors have written {posts.length} posts +

+ + Become one {'→'} (opens in a new tab) + +
+ ); +} + +interface Props { + posts: Post[]; + query: string; + onQuery: (q: string) => void; + topic: string; + onTopic: (label: string) => void; +} + +export default function Hero({ posts, query, onQuery, topic, onTopic }: Props) { + return ( +
+
+ ); +} diff --git a/src/components/blogsPage/PostCard.tsx b/src/components/blogsPage/PostCard.tsx new file mode 100644 index 000000000..e33482342 --- /dev/null +++ b/src/components/blogsPage/PostCard.tsx @@ -0,0 +1,100 @@ +import React from 'react'; +import Link from '@docusaurus/Link'; +import useBaseUrl from '@docusaurus/useBaseUrl'; +import { categoryOf, formatDate, initials, tagText, type Post, type PostAuthor } from './blogData'; +import styles from './blogsPage.module.css'; + +const PILLS = ['pillGreen', 'pillTeal', 'pillOrange', 'pillBlue', 'pillRose'] as const; +const pillClass = (label: string): string => { + let h = 0; + for (let i = 0; i < label.length; i++) h = label.charCodeAt(i) + ((h << 5) - h); + return styles[PILLS[Math.abs(h) % PILLS.length]]; +}; + +export function Pills({ post, max = 3 }: { post: Post; max?: number }) { + if (post.tags.length === 0) return null; + return ( +
    + {post.tags.slice(0, max).map((t) => ( +
  • +