Skip to main content

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.


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:

  1. Register/Login to get a session token
  2. Store the token securely (httpOnly cookies recommended)
  3. 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?

ResourceDescription
Starter TemplatesProduction-ready Next.js, Angular, and Mobile templates
Block DocumentationDeep dive into each block's features and API
API ReferenceComplete API documentation with examples
Frontend SDKFull SDK documentation and source code

Starter Templates

Want to skip the setup? Use our production-ready templates:

TemplateFrameworkGet Started
Next.jsNext.js 15 + React 19Use Template
AngularAngular 19Use Template
MobileReact Native (Expo 52)Use Template

Need Help?