In today's digital landscape, a thriving community is more than just a feature—it's a moat. It drives user retention, provides invaluable feedback, and transforms customers into advocates. But building community functionality from scratch? That's a complex, time-consuming endeavor involving backend services, database management, moderation tools, and scalability planning.
What if you could treat community as code?
Introducing forum.services.do, an AI-powered API that handles the heavy lifting of community management. With our "Community as a Service" platform, you can integrate robust forum features directly into your existing application using simple API calls.
This guide will walk you through building a basic but functional community forum feature inside a React application. You'll learn how to fetch and display threads, and how to enable users to create new posts—all powered by the forum.services.do API.
Before we start, make sure you have the following:
First, let's bootstrap a new React application using Create React App. Open your terminal and run:
npx create-react-app community-app
cd community-app
This creates a new directory named community-app and sets up a standard React project structure.
To communicate with the forum.services.do API, we'll use the official JavaScript SDK. It provides a clean, promise-based interface for all API endpoints.
Install it via npm:
npm install @do/sdk
It's best practice to keep your API keys out of your source code. Create a new file in the root of your project called .env and add your API key.
.env
REACT_APP_FORUM_API_KEY=YOUR_API_KEY
Replace YOUR_API_KEY with the key you obtained from the forum.services.do dashboard.
Next, let's create a centralized client instance that we can import anywhere in our app. Create a new folder src/services and a file inside it named forumApi.js.
src/services/forumApi.js
import { Forum } from '@do/sdk';
// The Forum client will automatically look for the API key in your environment variables.
const forum = new Forum({
apiKey: process.env.REACT_APP_FORUM_API_KEY
});
export default forum;
Now for the fun part. Let's create a component to display a list of threads from a specific board in your forum. You can create boards and get their IDs from your forum.services.do dashboard.
Create a new component file: src/components/ForumFeed.js.
src/components/ForumFeed.js
import React, { useState, useEffect } from 'react';
import forumApi from '../services/forumApi';
const ForumFeed = () => {
const [threads, setThreads] = useState([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
const fetchThreads = async () => {
try {
setLoading(true);
// Replace 'b-123-announcements' with your actual Board ID
const response = await forumApi.threads.list({ boardId: 'b-123-announcements' });
setThreads(response.data);
setError(null);
} catch (err) {
setError('Failed to fetch threads. Please try again later.');
console.error(err);
} finally {
setLoading(false);
}
};
fetchThreads();
}, []); // The empty dependency array ensures this runs once on mount
if (loading) return <div>Loading threads...</div>;
if (error) return <div style={{ color: 'red' }}>{error}</div>;
return (
<div className="forum-feed">
<h1>Announcements</h1>
{threads.length > 0 ? (
<ul>
{threads.map((thread) => (
<li key={thread.id}>
<h2>{thread.title}</h2>
<p>{thread.content.substring(0, 150)}...</p>
<small>Posted by User {thread.authorId}</small>
</li>
))}
</ul>
) : (
<p>No threads found. Be the first to post!</p>
)}
</div>
);
};
export default ForumFeed;
Now, let's add this feed to our main App.js file.
src/App.js
import React from 'react';
import ForumFeed from './components/ForumFeed';
import './App.css'; // Basic styling
function App() {
return (
<div className="App">
<header className="App-header">
<h1>My App's Community Forum</h1>
</header>
<main>
<ForumFeed />
</main>
</div>
);
}
export default App;
Start your app with npm start, and you should see a list of threads pulled directly from your community!
Viewing threads is great, but communities thrive on interaction. Let's add a form to allow users to create new threads. We'll use the exact code from our API documentation to show how simple it is.
Create a new component: src/components/NewThreadForm.js.
src/components/NewThreadForm.js
import React, { useState } from 'react';
import forumApi from '../services/forumApi';
const NewThreadForm = ({ onThreadCreated }) => {
const [title, setTitle] = useState('');
const [content, setContent] = useState('');
const [isSubmitting, setIsSubmitting] = useState(false);
const handleSubmit = async (e) => {
e.preventDefault();
if (!title || !content) {
alert('Please fill out both title and content.');
return;
}
setIsSubmitting(true);
try {
const newThread = await forumApi.threads.create({
boardId: 'b-123-announcements', // The same board ID as our feed
title: title,
content: content,
authorId: 'u-456-test-user' // In a real app, this would be the logged-in user's ID
});
console.log('Created new thread with ID:', newThread.id);
setTitle('');
setContent('');
if(onThreadCreated) {
onThreadCreated(); // Callback to refresh the feed
}
} catch (error) {
console.error('Failed to create thread:', error);
alert('Could not post your thread. Please try again.');
} finally {
setIsSubmitting(false);
}
};
return (
<form onSubmit={handleSubmit} className="new-thread-form">
<h3>Create a New Post</h3>
<input
type="text"
value={title}
onChange={(e) => setTitle(e.target.value)}
placeholder="Thread Title"
disabled={isSubmitting}
/>
<textarea
value={content}
onChange={(e) => setContent(e.target.value)}
placeholder="What's on your mind?"
rows="5"
disabled={isSubmitting}
/>
<button type="submit" disabled={isSubmitting}>
{isSubmitting ? 'Posting...' : 'Post Thread'}
</button>
</form>
);
};
export default NewThreadForm;
Finally, update App.js to include the form and a method to refresh the feed after a new post is created. We'll use a simple key-swapping trick to force the ForumFeed to re-mount and fetch new data.
src/App.js (Updated)
import React, { useState } from 'react';
import ForumFeed from './components/ForumFeed';
import NewThreadForm from './components/NewThreadForm';
import './App.css';
function App() {
const [refreshKey, setRefreshKey] = useState(0);
const handleThreadCreated = () => {
setRefreshKey(oldKey => oldKey + 1);
};
return (
<div className="App">
<header className="App-header">
<h1>My App's Community Forum</h1>
</header>
<main>
<NewThreadForm onThreadCreated={handleThreadCreated}/>
<hr />
<ForumFeed key={refreshKey} />
</main>
</div>
);
}
export default App;
Now you have a fully interactive (though basic) forum! Users can view existing posts and contribute their own.
We just built the frontend, but the real power of forum.services.do is happening behind the scenes. When a user submits a thread, our API doesn't just store it in a database. Our AI agents can instantly scan it for:
This automated moderation is the core of our community management API. It keeps your community safe and reduces the manual workload on your team, allowing your platform to scale without drowning in moderation queues. All of this is configurable in your dashboard—no extra code required.
You've successfully integrated a community feature into your React app. From here, the possibilities are endless:
By handling the complex backend logic, forum.services.do empowers you to focus on what you do best: building an amazing user experience.
Ready to turn your application into a community hub? Sign up at forum.services.do to get your free API key and start building today.