Step 4: Connect Your Frontend
Your backend is ready. Now let's connect it to your frontend application. You have two options: use our SDK or call the REST API directly.
Option 1: Using the SDK (Recommended)
Our Frontend SDK provides a type-safe, developer-friendly way to interact with all blocks.
Install the SDK
npm install @23blocks/sdk
Initialize the Client
import { BlocksClient } from '@23blocks/sdk';
const client = new BlocksClient({
baseUrl: 'https://api.23blocks.com/v1',
appId: 'your-app-id', // From Dashboard → API Keys
apiKey: 'your-api-key' // From Dashboard → API Keys
});
Environment Variables
Never hardcode API keys. Use environment variables:
const client = new BlocksClient({
baseUrl: process.env.BLOCKS_API_URL,
appId: process.env.BLOCKS_APP_ID,
apiKey: process.env.BLOCKS_API_KEY
});
Use the Blocks
Each block is available as a property on the client:
// Auth Block
const user = await client.auth.register({
email: 'user@example.com',
password: 'SecurePass123!'
});
const session = await client.auth.login({
email: 'user@example.com',
password: 'SecurePass123!'
});
// Files Block
const file = await client.files.upload({
file: fileBlob,
folder: 'avatars',
public: true
});
// Content Block
const articles = await client.content.list('articles', {
limit: 10,
status: 'published'
});
// University Block
const courses = await client.university.courses.list();
const progress = await client.university.progress.get(userId, courseId);
// Rewards Block
const badges = await client.rewards.badges.listEarned(userId);
await client.rewards.points.award(userId, 100, 'Completed lesson');
Option 2: REST API (Direct Calls)
Prefer to call the API directly? Every block exposes RESTful endpoints.
Base URL
https://api.23blocks.com/v1/{app-id}
Authentication
Include your API key in the Authorization header:
Authorization: Bearer your-api-key
Example Requests
Register a User (Auth Block):
curl -X POST https://api.23blocks.com/v1/your-app-id/auth/register \
-H "Authorization: Bearer your-api-key" \
-H "Content-Type: application/json" \
-d '{
"email": "user@example.com",
"password": "SecurePass123!"
}'
Upload a File (Files Block):
curl -X POST https://api.23blocks.com/v1/your-app-id/files/upload \
-H "Authorization: Bearer your-api-key" \
-F "file=@/path/to/document.pdf" \
-F "folder=documents" \
-F "public=false"
List Courses (University Block):
curl https://api.23blocks.com/v1/your-app-id/university/courses \
-H "Authorization: Bearer your-api-key"
Response Format
All API responses follow this structure:
{
"success": true,
"data": { ... },
"meta": {
"page": 1,
"limit": 20,
"total": 150
}
}
Error responses:
{
"success": false,
"error": {
"code": "AUTH_INVALID_CREDENTIALS",
"message": "Invalid email or password"
}
}
Framework Examples
React
import { useEffect, useState } from 'react';
import { BlocksClient } from '@23blocks/sdk';
const client = new BlocksClient({
baseUrl: process.env.REACT_APP_BLOCKS_URL,
appId: process.env.REACT_APP_BLOCKS_APP_ID,
apiKey: process.env.REACT_APP_BLOCKS_API_KEY
});
function CourseList() {
const [courses, setCourses] = useState([]);
useEffect(() => {
client.university.courses.list()
.then(response => setCourses(response.data))
.catch(console.error);
}, []);
return (
<ul>
{courses.map(course => (
<li key={course.id}>{course.title}</li>
))}
</ul>
);
}
Angular
import { Injectable } from '@angular/core';
import { BlocksClient } from '@23blocks/sdk';
import { environment } from '../environments/environment';
@Injectable({ providedIn: 'root' })
export class BlocksService {
private client = new BlocksClient({
baseUrl: environment.blocksApiUrl,
appId: environment.blocksAppId,
apiKey: environment.blocksApiKey
});
getCourses() {
return this.client.university.courses.list();
}
registerUser(email: string, password: string) {
return this.client.auth.register({ email, password });
}
}
Vue 3
<script setup>
import { ref, onMounted } from 'vue';
import { BlocksClient } from '@23blocks/sdk';
const client = new BlocksClient({
baseUrl: import.meta.env.VITE_BLOCKS_URL,
appId: import.meta.env.VITE_BLOCKS_APP_ID,
apiKey: import.meta.env.VITE_BLOCKS_API_KEY
});
const courses = ref([]);
onMounted(async () => {
const response = await client.university.courses.list();
courses.value = response.data;
});
</script>
<template>
<ul>
<li v-for="course in courses" :key="course.id">
{{ course.title }}
</li>
</ul>
</template>
React Native / Expo
import { BlocksClient } from '@23blocks/sdk';
import Constants from 'expo-constants';
const client = new BlocksClient({
baseUrl: Constants.expoConfig.extra.blocksUrl,
appId: Constants.expoConfig.extra.blocksAppId,
apiKey: Constants.expoConfig.extra.blocksApiKey
});
// Use exactly like React
Handling Authentication
For user-facing apps, you'll typically:
- Register/Login to get a session token
- Store the token securely (httpOnly cookies recommended)
- Include the token in subsequent requests
// Login and get session
const session = await client.auth.login({
email: 'user@example.com',
password: 'SecurePass123!'
});
// Store the token
localStorage.setItem('session_token', session.token);
// Use authenticated requests
const client = new BlocksClient({
baseUrl: process.env.BLOCKS_API_URL,
appId: process.env.BLOCKS_APP_ID,
sessionToken: localStorage.getItem('session_token')
});
// Now requests are authenticated as the user
const myProfile = await client.auth.me();
const myCourses = await client.university.enrollments.mine();
You're Ready!
Congratulations! You now have:
- ✅ A 23blocks account
- ✅ An app with your backend blocks
- ✅ Your frontend connected
What's Next?
| Resource | Description |
|---|---|
| Starter Templates | Production-ready Next.js, Angular, and Mobile templates |
| Block Documentation | Deep dive into each block's features and API |
| API Reference | Complete API documentation with examples |
| Frontend SDK | Full SDK documentation and source code |
Starter Templates
Want to skip the setup? Use our production-ready templates:
| Template | Framework | Get Started |
|---|---|---|
| Next.js | Next.js 15 + React 19 | Use Template |
| Angular | Angular 19 | Use Template |
| Mobile | React Native (Expo 52) | Use Template |
Need Help?
- Slack Community - Get help from the community
- GitHub Issues - Report bugs or request features
- Email Support - Contact our team directly