diff --git a/.github/workflows/continuous-deployment.yml b/.github/workflows/continuous-deployment.yml index 6614670..18a80a3 100644 --- a/.github/workflows/continuous-deployment.yml +++ b/.github/workflows/continuous-deployment.yml @@ -55,6 +55,11 @@ jobs: with: node-version: 24 cache: npm + - name: Setup Ruby + uses: ruby/setup-ruby@v1 + with: + ruby-version: 3.3 + bundler-cache: true - name: Restore cache uses: actions/cache@v4 with: @@ -70,6 +75,7 @@ jobs: - name: Build with Next.js env: NEXT_BASE_PATH: ${{ github.event.repository.name }} + JEKYLL_BASE_PATH: /${{ github.event.repository.name }}/blogs run: npm run build - name: Download DocumentDB packages from latest release run: .github/scripts/download_packages.sh diff --git a/.github/workflows/continuous-integration.yml b/.github/workflows/continuous-integration.yml index ee09c25..72ef7b5 100644 --- a/.github/workflows/continuous-integration.yml +++ b/.github/workflows/continuous-integration.yml @@ -41,6 +41,12 @@ jobs: with: node-version: 24 cache: npm + - name: Setup Ruby + # The full site build now includes the Jekyll-powered blogs section. + uses: ruby/setup-ruby@v1 + with: + ruby-version: 3.3 + bundler-cache: true - name: Install dependencies run: npm ci - name: Build Next.js site diff --git a/.gitignore b/.gitignore index 1dc4d7d..b245cd3 100644 --- a/.gitignore +++ b/.gitignore @@ -27,6 +27,12 @@ articles/**/*.yml /.next/ /out/ +# jekyll +/.bundle/ +/.jekyll-cache/ +/.sass-cache/ +/vendor/bundle/ + # production /build @@ -49,5 +55,4 @@ yarn-error.log* # typescript *.tsbuildinfo next-env.d.ts - -.claude/ \ No newline at end of file +.claude/ diff --git a/Gemfile b/Gemfile new file mode 100644 index 0000000..3009d5d --- /dev/null +++ b/Gemfile @@ -0,0 +1,5 @@ +source "https://rubygems.org" + +gem "ffi", "~> 1.15.5" +gem "jekyll", "~> 4.3.4" +gem "webrick", "~> 1.8" diff --git a/Gemfile.lock b/Gemfile.lock new file mode 100644 index 0000000..acc265d --- /dev/null +++ b/Gemfile.lock @@ -0,0 +1,76 @@ +GEM + remote: https://rubygems.org/ + specs: + addressable (2.8.9) + public_suffix (>= 2.0.2, < 8.0) + colorator (1.1.0) + concurrent-ruby (1.3.6) + em-websocket (0.5.3) + eventmachine (>= 0.12.9) + http_parser.rb (~> 0) + eventmachine (1.2.7) + ffi (1.15.5) + forwardable-extended (2.6.0) + google-protobuf (3.23.4) + http_parser.rb (0.8.1) + i18n (1.14.8) + concurrent-ruby (~> 1.0) + jekyll (4.3.4) + addressable (~> 2.4) + colorator (~> 1.0) + em-websocket (~> 0.5) + i18n (~> 1.0) + jekyll-sass-converter (>= 2.0, < 4.0) + jekyll-watch (~> 2.0) + kramdown (~> 2.3, >= 2.3.1) + kramdown-parser-gfm (~> 1.0) + liquid (~> 4.0) + mercenary (>= 0.3.6, < 0.5) + pathutil (~> 0.9) + rouge (>= 3.0, < 5.0) + safe_yaml (~> 1.0) + terminal-table (>= 1.8, < 4.0) + webrick (~> 1.7) + jekyll-sass-converter (3.0.0) + sass-embedded (~> 1.54) + jekyll-watch (2.2.1) + listen (~> 3.0) + kramdown (2.5.2) + rexml (>= 3.4.4) + kramdown-parser-gfm (1.1.0) + kramdown (~> 2.0) + liquid (4.0.4) + listen (3.10.0) + logger + rb-fsevent (~> 0.10, >= 0.10.3) + rb-inotify (~> 0.9, >= 0.9.10) + logger (1.7.0) + mercenary (0.4.0) + pathutil (0.16.2) + forwardable-extended (~> 2.6) + public_suffix (5.1.1) + rake (13.3.1) + rb-fsevent (0.11.2) + rb-inotify (0.11.1) + ffi (~> 1.0) + rexml (3.4.4) + rouge (3.30.0) + safe_yaml (1.0.5) + sass-embedded (1.58.3) + google-protobuf (~> 3.21) + rake (>= 10.0.0) + terminal-table (3.0.2) + unicode-display_width (>= 1.1.1, < 3) + unicode-display_width (2.6.0) + webrick (1.9.2) + +PLATFORMS + ruby + +DEPENDENCIES + ffi (~> 1.15.5) + jekyll (~> 4.3.4) + webrick (~> 1.8) + +BUNDLED WITH + 2.4.22 diff --git a/app/blogs/page.tsx b/app/blogs/page.tsx deleted file mode 100644 index a42308b..0000000 --- a/app/blogs/page.tsx +++ /dev/null @@ -1,74 +0,0 @@ -import { getAllPosts } from '../services/blogService'; -import { Card } from '../components/Card'; -import { Post } from '../types/Post'; - -export default function Blogs() { - const posts: Post[] = getAllPosts(); - const featuredPosts = posts.filter(post => post.featured); - const regularPosts = posts.filter(post => !post.featured); - - return ( -
- {/* Artistic background elements */} -
-
-
-
-
-
-
- - {/* Floating particles */} -
-
-
-
-
- -
- {/* Header */} -
-

- Latest from our Blog -

-

- Insights, updates, and deep dives into the world of document databases and open-source innovation -

-
-
- - - {/* Blog Grid */} -
- {/* Featured Posts */} - {featuredPosts.map((post, index) => ( - - ))} - - {/* Regular Posts */} - {regularPosts.map((post, index) => ( - - ))} -
-
-
- ); -} \ No newline at end of file diff --git a/app/components/Card.tsx b/app/components/Card.tsx deleted file mode 100644 index 2fe678d..0000000 --- a/app/components/Card.tsx +++ /dev/null @@ -1,154 +0,0 @@ -import { JSX } from 'react'; -import { Post } from '../types/Post'; - -export function Card({ post, featured = false }: { post: Post; featured?: boolean }) { - const icons: Record = { - 'microsoft-open-source-blog': ( - - ), - 'aws-blog': ( - - ), - 'azure-cosmos-db-blog': ( - - ), - 'yugabytedb-blog': ( - - ), - }; - - const icon = icons[post.category as keyof typeof icons]; - - const styles = { - 'microsoft-open-source-blog': { - label: 'Microsoft Open Source Blog', - timestamp: 'August 25, 2025', - gradientFrom: 'from-blue-500', - gradientTo: 'to-blue-600', - textColor: 'blue-400', - hoverColor: 'blue-300', - bgGradient: 'from-blue-500/10 to-purple-500/10', - borderHover: 'border-blue-500/50', - tagColors: [ - 'bg-blue-500/20 text-blue-400', - 'bg-purple-500/20 text-purple-400', - 'bg-green-500/20 text-green-400', - 'bg-orange-500/20 text-orange-400', - ], - }, - 'aws-blog': { - label: 'AWS Blogs', - timestamp: 'Recent', - gradientFrom: 'from-orange-500', - gradientTo: 'to-orange-600', - textColor: 'orange-400', - hoverColor: 'orange-300', - bgGradient: 'from-orange-500/10 to-amber-500/10', - borderHover: 'border-orange-500/50', - tagColors: [ - 'bg-orange-500/20 text-orange-400', - 'bg-amber-500/20 text-amber-400', - 'bg-yellow-500/20 text-yellow-400', - 'bg-blue-500/20 text-blue-400', - ], - }, - 'azure-cosmos-db-blog': { - label: 'Azure Cosmos DB Blog', - timestamp: 'Recent', - gradientFrom: 'from-purple-500', - gradientTo: 'to-purple-600', - textColor: 'purple-400', - hoverColor: 'purple-300', - bgGradient: 'from-purple-500/10 to-pink-500/10', - borderHover: 'border-purple-500/50', - tagColors: [ - 'bg-purple-500/20 text-purple-400', - 'bg-blue-500/20 text-blue-400', - 'bg-green-500/20 text-green-400', - 'bg-orange-500/20 text-orange-400', - ], - }, - 'yugabytedb-blog': { - label: 'YugabyteDB Blog', - timestamp: 'Partner Content', - gradientFrom: 'from-green-500', - gradientTo: 'to-green-600', - textColor: 'green-400', - hoverColor: 'green-300', - bgGradient: 'from-green-500/10 to-emerald-500/10', - borderHover: 'border-green-500/50', - tagColors: [ - 'bg-green-500/20 text-green-400', - 'bg-blue-500/20 text-blue-400', - 'bg-orange-500/20 text-orange-400', - 'bg-yellow-500/20 text-yellow-400', - ], - }, - }; - - const style = styles[post.category as keyof typeof styles]; - - return ( - - ); -} diff --git a/app/components/Navbar.tsx b/app/components/Navbar.tsx index 78c5188..728b676 100644 --- a/app/components/Navbar.tsx +++ b/app/components/Navbar.tsx @@ -1,100 +1,158 @@ +"use client"; + +import { useState } from "react"; import Image from "next/image"; import Link from "next/link"; import { withBasePath } from "../services/sitePath"; + +type NavItem = { + label: string; + href: string; + kind: "link" | "anchor"; + newTab?: boolean; + icon?: "github" | "discord"; +}; + +const navItems: NavItem[] = [ + { label: "Home", href: "/", kind: "link" }, + { + label: "GitHub", + href: "https://github.com/documentdb/documentdb", + kind: "anchor", + newTab: true, + icon: "github", + }, + { + label: "Discord", + href: "https://discord.gg/vH7bYu524D", + kind: "anchor", + newTab: true, + icon: "discord", + }, + { label: "Docs", href: "/docs", kind: "link" }, + { label: "Download", href: "/packages", kind: "link" }, + { label: "K8s Operator", href: "/kubernetes-operator", kind: "link" }, + { label: "Blogs", href: withBasePath("/blogs/"), kind: "anchor" }, + { label: "Samples", href: "/samples", kind: "link" }, +]; + +function NavIcon({ name }: { name: NonNullable }) { + if (name === "github") { + return ( + + + + ); + } + + return ( + + + + ); +} + +function renderNavItem( + item: NavItem, + className: string, + onClick?: () => void, +) { + const content = ( + <> + {item.icon ? : null} + {item.label} + + ); + + if (item.kind === "link") { + return ( + + {content} + + ); + } + + return ( + + {content} + + ); +} + export default function Navbar() { + const [isMenuOpen, setIsMenuOpen] = useState(false); + + const closeMenu = () => setIsMenuOpen(false); + return ( -