Tutorial

Build a Tutorial Generator with Claude 3.5 Sonnet and React

Build a Tutorial Generator with Claude 3.5 Sonnet and React

Introduction

What is the first thing you follow when you are learning something new—be it cooking or learning how to code? Tutorials, right?

You’re not alone—25.6% of internet users consume tutorials. Also, 57% of the content you see on the internet is generated by AI. Safe to say that you can accomplish tasks faster than ever with AI as an assistant.

In this tutorial, you will learn how to build an application that generates tutorials in Markdown format using DigitalOcean GenAI Platform and the latest Anthropic model support, capable of generating technical guides in Markdown format when you enter a topic. Here’s a demo of what you will be building:

Demo screenshot of the tutorial generator application

Prerequisites

What is the DigitalOcean GenAI Platform?

The GenAI Platform is an all-in-one solution that can help you build AI agents and use the APIs to create all kinds of applications. It supports models from DeepSeek, Anthropic, Meta, and Mistral AI, along with advanced features such as retrieval-augmented generation (RAG), function routing, agent customization, and guardrails to help you create more secure, context-aware applications.

List of Models Supported

The GenAI Platform supports multiple models that you can use to build and deploy AI-driven applications. Here is the complete list of models supported by the GenAI Platform. We recently launched Anthropic Claude 3.5 (Sonnet & Haiku), Claude 3 Opus, and DeepSeek R1-distill-llama-70B, which you can use to create any AI application you want.

List of models supported by GenAI Platform 1

List of models supported by GenAI Platform 2

Building the application

Now that you know about the GenAI Platform, let’s see how you can use it to build a tutorial generator.

The application will follow a simple flow, and you will be using DigitalOcean’s App Platform to deploy the application and the GenAI Platform to add the AI capabilities.

Here’s how the application will look:

The applications's flowchart

Step 1 - Building the frontend

The application consists of two main parts: the history management and the UI.

Let’s start with understanding how you will build the main blocks:

Tutorial history management

First, let’s look at the state management for our tutorials.

You will use React’s useState hook to manage the list of tutorials and the currently selected tutorial:

interface Tutorial {
  topic: string;
  timestamp: string;
  content?: string;
  isLoading?: boolean;
  error?: string;
}

function App() {
  const [tutorials, setTutorials] = useState<Tutorial[]>([]);
  const [selectedTutorial, setSelectedTutorial] = useState<Tutorial | null>(null);
  const [isSidebarOpen, setIsSidebarOpen] = useState(false);
}

This manages:

  • List of tutorials
  • Currently selected tutorial
  • Sidebar open/close state
  • Loading states

Tutorial generation logic

Next, you will understand how tutorial generation logic is handled. The handleSubmit function is used to:

  • Create a new tutorial object.
  • Update the UI to show loading state.
  • Handle success and error cases.
  • Update the tutorial list with the result.
const handleSubmit = async (e: React.FormEvent) => {
  e.preventDefault();
  if (!topic.trim()) return;

  setIsLoading(true);
  const newTutorial: Tutorial = {
    topic,
    timestamp: new Date().toLocaleString(),
    isLoading: true
  };

  setTutorials([newTutorial, ...tutorials]);
  
  try {
    const content = await generateTutorial(topic);
    const completedTutorial = { ...newTutorial, content, isLoading: false };
    setTutorials(prevTutorials => [
      completedTutorial,
      ...prevTutorials.slice(1)
    ]);
    setSelectedTutorial(completedTutorial);
  } catch (error) {
    const failedTutorial = { 
      ...newTutorial, 
      error: (error as Error).message, 
      isLoading: false 
    };
    setTutorials(prevTutorials => [
      failedTutorial,
      ...prevTutorials.slice(1)
    ]);
    setSelectedTutorial(failedTutorial);
  }
};

Slide-out sidebar implementation

You want to be able to access our previously generated articles; for that, you will need to add a sidebar that shows the tutorial history using the code below:

{/* Sidebar Toggle Button */}
<button
  onClick={() => setIsSidebarOpen(true)}
  className="fixed top-4 left-4 p-2 bg-white rounded-lg shadow-md hover:bg-gray-50 z-50"
>
  <Menu className="w-6 h-6 text-gray-700" />
</button>

{/* Sidebar Component */}
<div
  className={`fixed inset-y-0 left-0 w-80 bg-white shadow-2xl transform transition-transform duration-300 ease-in-out z-50 ${
    isSidebarOpen ? 'translate-x-0' : '-translate-x-full'
  }`}
>
  <div className="p-4">
    <div className="flex justify-between items-center mb-6">
      <h2 className="text-xl font-semibold text-gray-900">Tutorial History</h2>
      <button
        onClick={() => setIsSidebarOpen(false)}
        className="p-2 hover:bg-gray-100 rounded-lg"
      >
        <X className="w-5 h-5 text-gray-600" />
      </button>
    </div>
    {/* Tutorial List */}
    <div className="space-y-3">
      {tutorials.map((tutorial, index) => (
        <button
          key={index}
          onClick={() => {
            setSelectedTutorial(tutorial);
            setIsSidebarOpen(false);
          }}
          className={`w-full text-left p-3 rounded-lg transition-colors ${
            selectedTutorial === tutorial
              ? 'bg-indigo-50 text-indigo-700'
              : 'hover:bg-gray-50'
          }`}
        >
          <h3 className="font-medium truncate">{tutorial.topic}</h3>
          <p className="text-sm text-gray-500">{tutorial.timestamp}</p>
        </button>
      ))}
    </div>
  </div>
</div>

Tutorial content display

For the final part, you want to have a content area that displays the selected tutorial using Markdown rendering.

This is how the code looks like:

{selectedTutorial ? (
  <div className="bg-white rounded-xl shadow-sm border border-gray-100 p-6">
    <div className="flex items-start gap-4">
      <div className="p-2 bg-indigo-100 rounded-lg">
        <BookOpen className="w-6 h-6 text-indigo-600" />
      </div>
      <div className="flex-1">
        <h3 className="text-xl font-semibold text-gray-900 mb-2">
          {selectedTutorial.topic}
        </h3>
        <p className="text-sm text-gray-500">
          Generated on {selectedTutorial.timestamp}
        </p>
        {selectedTutorial.isLoading ? (
          <div className="mt-4 p-4 bg-gray-50 rounded-lg">
            {/* Loading skeleton */}
            <div className="h-4 bg-gray-200 rounded w-3/4 animate-pulse" />
            <div className="h-4 bg-gray-200 rounded w-1/2 mt-2 animate-pulse" />
          </div>
        ) : (
          <div 
            className="mt-4 p-4 bg-gray-50 rounded-lg prose prose-indigo max-w-none"
            dangerouslySetInnerHTML={{ 
              __html: marked(selectedTutorial.content || '') 
            }}
          />
        )}
      </div>
    </div>
  </div>
) : (
  <div className="text-center py-12">
    <div className="text-gray-400 mb-4">
      <BookOpen className="w-12 h-12 mx-auto" />
    </div>
    <h3 className="text-lg font-medium text-gray-900">
      No tutorial selected
    </h3>
    <p className="text-gray-500">
      Generate a new tutorial or select one from the history
    </p>
  </div>
)}

Step 2 - Creating the GenAI agent

Log in to your DigitalOcean account and navigate to the GenAI Platform.

Click on Create agent and give your agent a name.

Agent name

The agent will help you create tutorials, so give it instructions similar to Your task is to generate a nice in-depth tutorial based on the input provided. Use simple language, and provide the article in markdown format. You can choose any model to do the task. You will use Anthropic Claude 3.5 Sonnet for this example.

Configure your agent

Note: To use Anthropic models, you will need an API key that you can generate for free here.

If you want, you can add a knowledge base. For this example, you can skip it and move forward with creating the agent.

Add knowledge base

Once the agent has been deployed, go to Playground to test and see if the agent worked as per your expectations.

Playground

If your agent needs improvement with the type of response, you can try updating the instruction and adjusting the temperature from the Settings tab, as shown below.

Settings tab

Step 3 - Making use of the agent in our application

Now that the agent has been created and works as expected, we must integrate it with the front end. For that, follow the steps below:

Copy the endpoint URL and generate an endpoint access key, as shown in the images below.

Copy endpoint URL

Access endpoint key

Note: Please make sure to save the access key somewhere, as you will need it in the next steps.

Now, go back to the frontend code you wrote and push it to a GitHub repository (similar to what has been done in this Github repository). Then, go to the DigitalOcean App Platform and deploy the application.

This tutorial on Build and Deploy Apps on DigitalOcean App Platform with Custom Domain teaches you how to deploy an application on the app platform.

Once the application has been deployed, go to the Settings tab.

Setting tab

Then scroll down to the App-Level Environment Variables section and click on Edit to add the following variables:

AGENT_BASE_URL: <Your agent endpoint URL>
SECURE_AGENT_KEY: <The endpoint access key that you saved in the first step>

Env variables

Step 4 - Integrating OpenAI SDK within the application

For the final step, you will integrate the OpenAI SDK into the application, we will use the code below:

import OpenAI from "openai";
const SECURE_AGENT_KEY = import.meta.env.VITE_SECURE_AGENT_KEY;
const AGENT_BASE_URL = import.meta.env.VITE_AGENT_BASE_URL;
const AGENT_ENDPOINT = `${AGENT_BASE_URL}/api/v1/`;

if (!SECURE_AGENT_KEY || !AGENT_BASE_URL) {
  throw new Error("Missing agent access key or base URL! Ensure VITE_SECURE_AGENT_KEY and VITE_AGENT_BASE_URL are set in .env");
}
const client = new OpenAI({
  apiKey: SECURE_AGENT_KEY,
  baseURL: AGENT_ENDPOINT, 
  dangerouslyAllowBrowser: true
});
export async function generateTutorial(topic: string): Promise<string> {
  try {
    console.log("Starting tutorial generation for topic:", topic);

    const prompt = `Your task is to generate a nice in-depth tutorial based on the input provided. Use simple language and provide the article in markdown format.\n\nTopic: ${topic}\n\nPlease create a comprehensive tutorial that includes:\n1. Introduction\n2. Prerequisites (if any)\n3. Step-by-step instructions\n4. Code examples (if applicable)\n5. Best practices\n6. Common pitfalls\n7. Conclusion`;

    const response = await client.chat.completions.create({
      model: "Anthropic Claude 3.5 Sonnet",
      messages: [
        { role: "system", content: "You are an expert technical writer who creates clear, concise, and comprehensive tutorials." },
        { role: "user", content: prompt }
      ],
      temperature: 0.7,
      max_tokens: 2000
    });

    console.log("OpenAI response received:", response);    
    const content = response.choices[0]?.message?.content || "No response from AI";
    
    return content;
    
  } catch (error) {
    console.error("Error generating tutorial:", error);
  
    let errorMessage = "Unknown error occurred.";
  
  if (error instanceof OpenAI.RateLimitError) {
      errorMessage = "Rate limit exceeded. Please try again later.";
    } else if (error instanceof Error) {
      errorMessage = error.message; 
    }  
    throw new Error(`OpenAI SDK Error: ${errorMessage}`);
  }
} 

And that’s a wrap! You can now use this application to ideate or write your tutorials.

After you have followed all the steps, this is how your application will look like:

You can also try the deployed tutorial generator live app.

Live tutorial generator app

Conclusion

In this tutorial, you learned how to use the GenAI Platform to build AI-driven applications based on your use case and how to integrate it with third-party APIs.

In the meantime, if you want to learn more about the GenAI Platform, here are some helpful resources:

  1. GitHub repository with the application code.
  2. Integrating GenAI Agents into Your Website: A Step-by-Step Guide.
  3. Building a Custom Real-time Chat Experience with DigitalOcean’s GenAI Platform
  4. 12 Days of DigitalOcean (Day 9) - Automating Receipt Parsing with DigitalOcean’s GenAI Agent

If you have any questions, you can contact us on Discord.

Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.

Learn more about our products

About the authors
Default avatar

Engineer & Writer

A Developer Advocate by profession. I like to build with Cloud, GenAI and can build beautiful websites using JavaScript.


Default avatar

Sr Technical Writer

Senior Technical Writer @ DigitalOcean | 2x Medium Top Writers | 2 Million+ monthly views & 34K Subscribers | Ex Cloud Consultant @ AMEX | Ex SRE(DevOps) @ NUTANIX


Still looking for an answer?

Ask a questionSearch for more help

Was this helpful?
 
Leave a comment


This textbox defaults to using Markdown to format your answer.

You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!

Try DigitalOcean for free

Click below to sign up and get $200 of credit to try our products over 60 days!

Sign up

Join the Tech Talk
Success! Thank you! Please check your email for further details.

Please complete your information!

Become a contributor for community

Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation.

DigitalOcean Documentation

Full documentation for every DigitalOcean product.

Resources for startups and SMBs

The Wave has everything you need to know about building a business, from raising funding to marketing your product.

Get our newsletter

Stay up to date by signing up for DigitalOcean’s Infrastructure as a Newsletter.

New accounts only. By submitting your email you agree to our Privacy Policy

The developer cloud

Scale up as you grow — whether you're running one virtual machine or ten thousand.

Get started for free

Sign up and get $200 in credit for your first 60 days with DigitalOcean.*

*This promotional offer applies to new accounts only.