Logo

Documentation

Blog Rendering

How to use the Quotient SDK to render blogs on your site

Prerequisites

Before you begin, ensure you have:

  • A Quotient account with an API key
  • A React/Next.js project set up
  • Installed the Quotient SDK

Blog Rendering using the Quotient SDK

The easiest way to put a Quotient Blog onto your website is using the Quotient React SDK.

Listing Blogs

On your main blog or news page, you typically want to list blogs based on status, author, tags, etc. so that users can see all your content. You can do this via on the client using react hooks, or on the server using the server client.

Client Side Fetching

useBlogs(): Recommended for client-side fetching

Within client components that are inside a <QuotientProvider>, you can fetch a list of blogs using the useBlogs hook.

// app/blog/blog-list.tsx
import { QuotientProvider, BlogStatus, useBlogs } from "@quotientjs/react";
 
export default function BlogList({
  page,
  limit,
  statuses,
}: {
  page: number;
  limit: number;
  statuses: BlogStatus[];
}) {
  const { data, isLoading } = useBlogs({
    page,
    limit,
    statuses,
  });
 
  const { blogs, pageData } = data
  return {
    {/* Render blog list according to your own specs*/}
  };
}
 
// app/blog/page.tsx
("use client");
import { QuotientProvider } from "@quotientjs/react";
 
const PAGE_SIZE = 50
 
export default function Blogs() {
    const [page, setPage] = useState<number>(1)
    const [statuses, setStatuses] = useState<BlogStatus[]>([])
 
    // Handle setting params however you want
 
    return (
    <QuotientProvider clientOptions={clientOptions}>
      <BlogList page={page} statuses={statuses}/>
    </QuotientProvider>
  );
}
client.blog.list({})

Within client components that are inside a <QuotientProvider>, you can also fetch blogs using the client directly

// app/blog/blog-list.tsx
import { QuotientProvider, BlogStatus, useQuotient } from "@quotientjs/react";
import { useEffect } from "react";
 
export default function BlogList({
  page,
  limit,
  statuses,
}: {
  page: number;
  limit: number;
  statuses: BlogStatus[];
}) {
  const { client } = useQuotient();
  const [page, setPage] = useState(1);
  const [blogs, setBlogs] = useState<any[]>([]);
  const [isLoading, setIsLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);
  const [hasNextPage, setHasNextPage] = useState(false);
 
 
  useEffect(() => {
    async function fetchBlogs() {
      try {
        setIsLoading(true);
        setError(null);
 
        const response = await client.blog.list({
          page,
          limit,
          statuses
        });
 
        setBlogs(response.blogs);
        setHasNextPage(response.pageData.isNextPageAvailable);
      } catch (err) {
        setError(err instanceof Error ? err.message : 'An error occurred');
      } finally {
        setIsLoading(false);
      }
    }
 
    fetchBlogs();
  }, [page, client])
 
  return {
    {/* Render blog list according to your own specs*/}
  };
}
 
// app/blog/page.tsx
("use client");
import { QuotientProvider } from "@quotientjs/react";
 
const PAGE_SIZE = 50
 
export default function Blogs() {
    const [page, setPage] = useState<number>(1)
    const [statuses, setStatuses] = useState<BlogStatus[]>([])
 
    // Handle setting params however you want
 
    return (
    <QuotientProvider clientOptions={clientOptions}>
      <BlogList page={page} statuses={statuses}/>
    </QuotientProvider>
  );
}

Server Side Fetching

client.blog.list({})
// Server Component
//app/page.tsx
export default async function BlogList() {
  const client = QuotientServerClient.init({...});
 
  const data = await client.blog.list({...})
 
  const { blogs, pageData } = data
 
  return (
    {/* Component that use blogs*/}
  )
}

SSR Blog

For a specific blog page, we recommend that if you are using a framework such as Next.JS, Sveltekit, Remix, etc., you fetch your blog and render it on the server. Server-side rendering offers is recommended for SEO purposes.

If using the Quotient React SDK, then you should use the provided <Blog/> component. The <Blog/> component has the following props:

interface BlogProps {
  content: any;
  className?: string;
  elementClassName?: {
    strong?: string;
    em?: string;
    u?: string;
    a?: string;
    p?: string;
    h1?: string;
    h2?: string;
    h3?: string;
    h4?: string;
    h5?: string;
    h6?: string;
    ul?: string;
    ol?: string;
    li?: string;
    image?: string;
    asset?: string;
  };
}

Here is an example implementation Next.JS:

import { Blog } from "@quotientjs/react";
import { QuotientServerClient } from "@quotientjs/client";
 
// app/blog/[slug]/page.tsx
export default async function BlogPost({
  params,
}: {
  params: { slug: string };
}) {
  const client = QuotientServerClient.init({
    apiKey: process.env.NEXT_PUBLIC_QUOTIENT_PUBLIC_API_KEY!,
    baseUrl: getBaseUrlFromAnywhere(),
  });
 
  const data = await client.blog.get({
    slug: params.slug,
  });
 
  return <Blog content={data.blog.content} />;
}

Styling Blog Components

By default, the <Blog/> component has no styling. It takes blog.content and renders it into styleless HTML elements. These elements by default will inherit the default styles provided by your CSS to those elements. If you want to customize the styling of how your Blog content is rendered, there are 3 main ways to style the content:

  1. CSS with Quotient Default Classes

There are CSS class names applied to every HTML element by default. These default class names are as follows:

  • quotient-strong
  • quotient-em
  • quotient-u
  • quotient-a
  • quotient-p
  • quotient-h1
  • quotient-h2
  • quotient-h3
  • quotient-h4
  • quotient-h5
  • quotient-h6
  • quotient-ul
  • quotient-ol
  • quotient-li
  • quotient-image
  • quotient-asset

So, a <p/> rendered by <Blog/> default has the class <p className="quotient-p"/>. If you wish to apply styles to the blog using CSS, in the relevant CSS file you can customize these classes. This is useful if you wish to style without using React or are rendering the rawHtml.

/* globals.css */
 
/* Using default Quotient classes to color <p> green */
.quotient-p {
  color: green;
}
  1. Override Default Classes

On the <Blog> component we provide the elementClassName prop, which allows the developer to define and apply their own class names to the rendered HTML elements. In our CSS file, we define our custom class that we want to apply.

/* globals.css */
 
/* Example 1: The color green is applied to all text with this class */
.green-text {
  color: green;
}
 
/* Example 2: Using a parent class to style elements */
.red-links a {
  color: red;
}
<Blog
  content={blog.content}
  elementClassName={{
    p: "green-text", // Apply green text to all <p>
  }}
  className="red-links" // Make all <a> red
/>
  1. Tailwind Typography Plugin

If you're using Tailwind CSS, the @tailwindcss/typography plugin provides an excellent way to style your blog content with minimal effort. After installing the plugin, you can wrap your <Blog/> component with a prose class to automatically apply well-designed typography defaults to all HTML elements.

<Blog content={blog.content} className="prose prose-lg" />

This approach will automatically style all your blog content including headings, paragraphs, lists, code blocks, and more with sensible defaults. You can also customize the styling using Tailwind's prose modifiers like prose-slate, prose-lg, or prose-dark for dark mode.

To install and set up:

npm install -D @tailwindcss/typography

Then add the plugin to your tailwind.config.js:

module.exports = {
  theme: {
    // ...
  },
  plugins: [
    require("@tailwindcss/typography"),
    // ...
  ],
};