Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/web/docs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
"@radix-ui/react-icons": "1.3.2",
"@radix-ui/react-tabs": "1.1.2",
"@radix-ui/react-tooltip": "1.1.6",
"@theguild/components": "9.3.4",
"@theguild/components": "9.5.0",
"date-fns": "4.1.0",
"next": "15.2.4",
"react": "19.0.0",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: Hive Platform Achieves SOC-2 Type II Certification
tags: [security, cloud, hive, platform, compliance]
tags: [security, cloud, graphql-hive, platform, compliance]
authors: dotan
date: 2025-03-25
description:
Expand Down
9 changes: 6 additions & 3 deletions packages/web/docs/src/app/blog/(posts)/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { cn, HiveLayoutConfig } from '@theguild/components';
import { cn, GetYourAPIGameRightSection, HiveLayoutConfig } from '@theguild/components';
import { LandingPageContainer } from '../../../components/landing-page-container';
import '../../hive-prose-styles.css';
import { BlogPostHeader } from '../components/blog-post-layout/blog-post-header';
import { SimilarPosts } from '../components/blog-post-layout/similar-posts';
import '../../hive-prose-styles.css';

const MAIN_CONTENT = 'main-content';

Expand All @@ -13,11 +14,13 @@ export default function BlogPostLayout({ children }: { children: React.ReactNode
<div
className={cn(
MAIN_CONTENT,
'mx-auto flex *:!pl-2 sm:*:!ml-auto sm:*:!pl-0 [&>div>:first-child]:hidden [&_main>p:first-of-type]:text-2xl/8',
'mx-auto flex *:!pl-2 sm:*:!ml-auto sm:*:!pl-0 [&>div>:first-child]:hidden [&_main>p:first-of-type]:text-xl/8 md:[&_main>p:first-of-type]:text-2xl/8',
)}
>
{children}
</div>
<SimilarPosts className="mx-4 md:mx-6" />
<GetYourAPIGameRightSection className="mx-4 sm:mb-6 md:mx-6" />
</LandingPageContainer>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export function BlogPostHeader({ className }: { className?: string }) {
{image && <BlogPostPicture image={image} />}
<header
className={cn(
'flex flex-col items-center rounded-3xl bg-[rgb(var(--nextra-bg))] px-1 pb-6 pt-4 md:px-12 md:pb-12 md:pt-6 xl:w-[888px]',
'flex flex-col rounded-3xl bg-[rgb(var(--nextra-bg))] px-1 pb-6 pt-4 sm:items-center md:px-12 md:pb-12 md:pt-6 xl:w-[888px]',
image && '-mt-20 max-sm:mx-6',
className,
)}
Expand All @@ -38,7 +38,7 @@ export function BlogPostHeader({ className }: { className?: string }) {
<Heading
as="h1"
size="md"
className="mb-0 mt-4 w-[--article-max-width] text-pretty text-center"
className="mb-0 mt-4 w-[--article-max-width] text-pretty sm:text-center"
>
{title}
</Heading>
Expand All @@ -47,7 +47,7 @@ export function BlogPostHeader({ className }: { className?: string }) {
authors: Array.isArray(authors) ? authors : [authors],
date,
}}
className="mt-4"
className="mt-4 max-sm:justify-start"
/>
</header>
</>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
'use client';

import { useFrontmatter } from '#components/use-frontmatter';
import { BlogFrontmatter, BlogPostFile } from '../../../blog-types';
import { BlogCard } from '../../blog-card';

export function SimilarPostsClient({ sortedPosts }: { sortedPosts: BlogPostFile[] }) {
const { frontmatter } = useFrontmatter<BlogFrontmatter>();
const tags = Array.isArray(frontmatter.tags) ? frontmatter.tags : [frontmatter.tags];

const postsToShow = [];
const intersectedTags: string[] = [];

for (let i = 0; i < sortedPosts.length && postsToShow.length < 2; i++) {
const post = sortedPosts[i];
if (post.frontMatter.title !== frontmatter.title) {
const postTags = Array.isArray(post.frontMatter.tags)
? post.frontMatter.tags
: [post.frontMatter.tags];

const tagsInCommon = postTags.filter(tag => tags.includes(tag));
if (tagsInCommon.length > 0) {
postsToShow.push(post);
intersectedTags.push(tagsInCommon[0]);
}
}
}

if (postsToShow.length === 0) {
// We need the CSS in the server component to know we didn't find any similar posts.
return <del />;
}

return postsToShow.map((post, i) => (
<BlogCard key={i} post={post} className="h-full" tag={intersectedTags[i]} />
));
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { ArrowIcon, cn, Heading } from '@theguild/components';
import { getPageMap } from '@theguild/components/server';
import { isBlogPost } from '../../../blog-types';
import { SimilarPostsClient } from './client';

export async function SimilarPosts({ className }: { className?: string }) {
// We're overfetching all posts here, because Nextra doesn't allow us
// to get the current post frontmatter on the server, and we need it to
// filter the similar posts. This could be worked around by moving the
// code to a remark/rehype plugin layer, but it seems like an overkill.
// We can optimize this later.
const [_meta, _indexPage, ...pageMap] = await getPageMap('/blog');
const sortedPosts = pageMap
.filter(isBlogPost)
.sort((a, b) => new Date(b.frontMatter.date).getTime() - new Date(a.frontMatter.date).getTime())
.slice(
0,
// This is an assumption that 100 posts is enough to find similar ones.
// Worst case we'll not render the section if there's no similar post.
100,
);

return (
<section
className={cn(
'flex items-stretch gap-4 py-6 *:flex-1 max-md:flex-col sm:gap-6 lg:p-24',
'has-[del]:hidden',
className,
)}
>
<div className="text-green-1000 md:max-w-[36%] dark:text-neutral-100">
<header className="flex items-center justify-between max-md:justify-center">
<Heading size="md" as="h3">
Explore
</Heading>
<ArrowIcon className="ml-2 size-12 shrink-0 max-md:hidden" />
</header>
<p className="mt-4 max-md:text-center">Dive deeper into related topics.</p>
</div>
<SimilarPostsClient sortedPosts={sortedPosts} />
</section>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ export function LetsGetAdvancedSection({ className, ...rest }: React.HTMLAttribu
<div className="nextra-scrollbar overflow-auto max-sm:-m-4 max-sm:p-4">
<ul className="mt-6 flex gap-6 *:flex *:flex-col *:rounded-3xl max-sm:*:w-80 max-sm:*:shrink-0 sm:grid sm:grid-cols-2 md:mt-8 md:*:p-8 lg:mt-12 xl:mt-16 xl:grid-cols-4 [&>*>:last-child]:contents [&>*>h3]:mb-4">
<InfoCard
as="li"
icon={<ArrowRightWallIcon />}
heading="GraphQL Subscriptions"
// moved to the last place, because it's the shortest
Expand All @@ -33,7 +34,7 @@ export function LetsGetAdvancedSection({ className, ...rest }: React.HTMLAttribu
Documentation
</CallToAction>
</InfoCard>
<InfoCard icon={<CogIcon />} heading="@defer and @stream Support">
<InfoCard as="li" icon={<CogIcon />} heading="@defer and @stream Support">
Allows more efficient data loading patterns, improving user interface responsiveness and
system performance.
<div className="grow" />
Expand All @@ -45,7 +46,7 @@ export function LetsGetAdvancedSection({ className, ...rest }: React.HTMLAttribu
Documentation
</CallToAction>
</InfoCard>
<InfoCard icon={<StackIcon />} heading="Request Batching">
<InfoCard as="li" icon={<StackIcon />} heading="Request Batching">
Reduces network overhead by enabling multiple GraphQL operations in a single HTTP
request, enhancing data retrieval efficiency.
<div className="grow" />
Expand All @@ -57,7 +58,7 @@ export function LetsGetAdvancedSection({ className, ...rest }: React.HTMLAttribu
Documentation
</CallToAction>
</InfoCard>
<InfoCard icon={<TargetIcon />} heading="Demand Control">
<InfoCard as="li" icon={<TargetIcon />} heading="Demand Control">
Facilitates efficient management of API resources by setting limits on query complexity
and execution depth, tailored for high-demand cloud environments.
<div className="grow" />
Expand Down
6 changes: 1 addition & 5 deletions packages/web/docs/src/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -97,11 +97,7 @@ export default async function HiveDocsLayout({ children }: { children: ReactNode
icon: <AccountBox />,
children: 'Case Studies',
},
{
href: 'https://the-guild.dev/graphql/hive/blog',
icon: <PencilIcon />,
children: 'Blog',
},
{ href: '/blog', icon: <PencilIcon />, children: 'Blog' },
{
href: 'https://github.com/graphql-hive/console',
icon: <GitHubIcon />,
Expand Down
2 changes: 1 addition & 1 deletion packages/web/docs/src/components/lede.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@ import { cn } from '@theguild/components';
export interface LedeProps extends React.HTMLAttributes<HTMLParagraphElement> {}

export function Lede(props: LedeProps) {
return <div {...props} className={cn('sm:*:text-xl/6 md:*:text-2xl/8', props.className)} />;
return <div {...props} className={cn('sm:*:text-xl/8 md:*:text-2xl/8', props.className)} />;
}
11 changes: 6 additions & 5 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.