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 { create23BlocksClient } from '@23blocks/sdk';

const client = create23BlocksClient({
urls: { authentication: 'https://auth.api.us.23blocks.com' }, // Use service-specific URLs
apiKey: 'your-api-key', // From Dashboard → API Keys (your live API key, pk_live_*)
});
Environment Variables

Never hardcode API keys. Use environment variables:

const client = create23BlocksClient({
urls: { authentication: 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 URLs​

Each service has its own URL:

https://{service}.api.us.23blocks.com

For example: https://auth.api.us.23blocks.com, https://files.api.us.23blocks.com

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://auth.api.us.23blocks.com/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://files.api.us.23blocks.com/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://university.api.us.23blocks.com/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 { create23BlocksClient } from '@23blocks/sdk';

const client = create23BlocksClient({
urls: { university: 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 { create23BlocksClient } from '@23blocks/sdk';
import { environment } from '../environments/environment';

@Injectable({ providedIn: 'root' })
export class BlocksService {
private client = create23BlocksClient({
urls: { authentication: environment.blocksApiUrl, university: 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 { create23BlocksClient } from '@23blocks/sdk';

const client = create23BlocksClient({
urls: { university: 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 { create23BlocksClient } from '@23blocks/sdk';
import Constants from 'expo-constants';

const client = create23BlocksClient({
urls: { authentication: 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 = create23BlocksClient({
urls: { authentication: process.env.BLOCKS_API_URL, university: 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
Block DocumentationComplete 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?​