@buildcores/render-client
v1.7.1
Published
React component for interactive 360-degree video rendering
Readme
@buildcores/render-client
Documentation | Technical API Docs
A React component library for interactive 360-degree PC build rendering with drag-to-scrub functionality. Create immersive 3D visualizations of computer builds that users can rotate and explore.
Interactive 3D PC build that users can rotate by dragging
🚀 Installation
npm install @buildcores/render-client📖 Quick Start
import React from "react";
import { BuildRender, getAvailableParts } from "@buildcores/render-client";
function App() {
const parts = {
parts: {
CPU: ["7xjqsomhr"], // AMD Ryzen 7 9800X3D
GPU: ["z7pyphm9k"], // ASUS GeForce RTX 5080 ASTRAL
RAM: ["dpl1iyvb5"], // PNY DDR5
Motherboard: ["iwin2u9vx"], // Asus ROG STRIX X870E-E GAMING WIFI
PSU: ["m4kilv190"], // LIAN LI 1300W
Storage: ["0bkvs17po"], // SAMSUNG 990 EVO
PCCase: ["qq9jamk7c"], // MONTECH KING 95 PRO
CPUCooler: ["62d8zelr5"], // ARCTIC LIQUID FREEZER 360
},
};
return (
<div>
<BuildRender
parts={parts}
size={500}
mouseSensitivity={0.2}
touchSensitivity={0.2}
/>
</div>
);
}🔐 Authentication Modes
@buildcores/render-client supports two auth modes:
legacy(backward-compatible): sends a long-lived API key fromapiConfig.authToken.session(recommended): fetches short-lived delegated tokens from your backend viaapiConfig.getRenderSessionToken.
const apiConfig = {
environment: "prod",
authMode: "session",
getRenderSessionToken: async () => {
// Your backend endpoint should broker BuildCores /auth/render-session
const res = await fetch("/buildcores/session", { method: "POST" });
if (!res.ok) throw new Error("Failed to mint BuildCores session");
const data = await res.json();
return {
token: data.session_token,
expiresAt: data.expires_at,
};
},
};Legacy browser API key flow is deprecated and should only be used for temporary compatibility.
/render-build-experimental behavior is unchanged.
🔧 API Reference
BuildRender Component
The main React component for rendering interactive 3D PC builds.
Props
| Prop | Type | Required | Default | Description |
| ------------------ | -------------------- | -------- | ------- | ---------------------------------------- |
| parts | RenderBuildRequest | ✅ | - | PC parts configuration object |
| size | number | ✅ | - | Video size in pixels (square dimensions) |
| mouseSensitivity | number | ❌ | 0.2 | Mouse drag sensitivity (0.001-1) |
| touchSensitivity | number | ❌ | 0.2 | Touch drag sensitivity (0.001-1) |
| modelQuality | "low" \| "medium" \| "high" | ❌ | API default | 3D model asset quality for server renders |
| showInteractiveConfigButton | boolean | ❌ | false | Show the embedded fan/radiator configuration menu for parts-based async renders |
| interactiveConfigPanelPosition | "top-left" \| "top-right" \| "bottom-left" \| "bottom-right" | ❌ | "top-left" | Corner where the embedded configuration menu opens |
| interactiveConfigPanelHeight | "compact" \| "max" \| number \| string | ❌ | "max" | Height for the embedded configuration menu |
Parts Configuration
The parts prop uses the RenderBuildRequest interface:
interface RenderBuildRequest {
parts: {
[K in PartCategory]?: string[];
};
format?: "video" | "sprite";
width?: number; // Optional: Canvas pixel width (256-2000)
height?: number; // Optional: Canvas pixel height (256-2000)
scene?: "sunset" | "dawn" | "night" | "warehouse" | "forest" | "apartment" | "studio" | "studio_v2" | "city" | "park" | "lobby";
showBackground?: boolean;
showGrid?: boolean;
winterMode?: boolean; // mutually exclusive with springMode
springMode?: boolean; // mutually exclusive with winterMode
}
// Available part categories
enum PartCategory {
CPU = "CPU",
GPU = "GPU",
RAM = "RAM",
Motherboard = "Motherboard",
PSU = "PSU",
Storage = "Storage",
PCCase = "PCCase",
CPUCooler = "CPUCooler",
}Current Limitation: Each category array must contain exactly one part ID. Multiple parts per category will be supported in future versions.
Resolution Control: You can specify custom width and height (both must be provided together, 256-2000 pixels) for higher or lower quality renders. If not specified, the default resolution is used.
Environment Controls: You can configure scene, showBackground, showGrid, and seasonal toggles (winterMode / springMode) for async render endpoints.
Examples
Complete Build (All Components)
const completeBuild = {
parts: {
CPU: ["7xjqsomhr"], // AMD Ryzen 7 9800X3D
GPU: ["z7pyphm9k"], // ASUS GeForce RTX 5080 ASTRAL
RAM: ["dpl1iyvb5"], // PNY DDR5
Motherboard: ["iwin2u9vx"], // Asus ROG STRIX X870E-E GAMING WIFI
PSU: ["m4kilv190"], // LIAN LI 1300W
Storage: ["0bkvs17po"], // SAMSUNG 990 EVO
PCCase: ["qq9jamk7c"], // MONTECH KING 95 PRO
CPUCooler: ["62d8zelr5"], // ARCTIC LIQUID FREEZER 360
},
};
<BuildRender parts={completeBuild} size={500} />;Case Only (Minimal)
const caseOnly = {
parts: {
PCCase: ["qq9jamk7c"], // MONTECH KING 95 PRO
},
};
<BuildRender parts={caseOnly} size={500} />;Custom Resolution (High Quality)
const highResBuild = {
parts: {
CPU: ["7xjqsomhr"],
GPU: ["z7pyphm9k"],
RAM: ["dpl1iyvb5"],
Motherboard: ["iwin2u9vx"],
PSU: ["m4kilv190"],
Storage: ["0bkvs17po"],
PCCase: ["qq9jamk7c"],
CPUCooler: ["62d8zelr5"],
},
width: 1920, // Custom resolution width
height: 1080, // Custom resolution height
};
<BuildRender parts={highResBuild} size={500} />;getAvailableParts() Function
Fetches all available PC parts from the BuildCores API.
function getAvailableParts(): Promise<AvailablePartsResponse>;Return Type
interface PartDetails {
id: string; // Unique part identifier
name: string; // Human-readable part name
image: string; // URL to part image
}
type AvailablePartsResponse = {
[K in PartCategory]: PartDetails[];
};Example Response
{
"CPU": [
{
"id": "7xjqsomhr",
"name": "AMD Ryzen 7 9800X3D",
"image": "https://example.com/cpu1.jpg"
},
{
"id": "x2thvstj3",
"name": "AMD Ryzen 7 9700X",
"image": "https://example.com/cpu2.jpg"
}
],
"GPU": [
{
"id": "z7pyphm9k",
"name": "ASUS GeForce RTX 5080 ASTRAL",
"image": "https://example.com/gpu1.jpg"
},
{
"id": "4a0mjb360",
"name": "PNY GeForce RTX 5060 Ti 16GB",
"image": "https://example.com/gpu2.jpg"
}
],
"RAM": [
{
"id": "dpl1iyvb5",
"name": "PNY DDR5",
"image": "https://example.com/ram1.jpg"
}
],
"Motherboard": [
{
"id": "iwin2u9vx",
"name": "Asus ROG STRIX X870E-E GAMING WIFI",
"image": "https://example.com/mb1.jpg"
}
],
"PSU": [
{
"id": "m4kilv190",
"name": "LIAN LI 1300W",
"image": "https://example.com/psu1.jpg"
}
],
"Storage": [
{
"id": "0bkvs17po",
"name": "SAMSUNG 990 EVO",
"image": "https://example.com/storage1.jpg"
}
],
"PCCase": [
{
"id": "qq9jamk7c",
"name": "MONTECH KING 95 PRO",
"image": "https://example.com/case1.jpg"
}
],
"CPUCooler": [
{
"id": "62d8zelr5",
"name": "ARCTIC LIQUID FREEZER 360",
"image": "https://example.com/cooler1.jpg"
}
]
}Usage Example
import { useState, useEffect } from "react";
import {
BuildRender,
getAvailableParts,
type AvailablePartsResponse,
} from "@buildcores/render-client";
function PCBuildConfigurator() {
const [availableParts, setAvailableParts] = useState<AvailablePartsResponse>(
{} as AvailablePartsResponse
);
const [selectedParts, setSelectedParts] = useState<Record<string, string>>(
{}
);
const [isLoading, setIsLoading] = useState(true);
useEffect(() => {
const fetchParts = async () => {
try {
const parts = await getAvailableParts();
setAvailableParts(parts);
// Set default selections (first part of each category)
const defaults: Record<string, string> = {};
Object.entries(parts).forEach(([category, partList]) => {
if (partList.length > 0) {
defaults[category] = partList[0].id;
}
});
setSelectedParts(defaults);
} catch (error) {
console.error("Failed to fetch available parts:", error);
} finally {
setIsLoading(false);
}
};
fetchParts();
}, []);
if (isLoading) return <div>Loading parts...</div>;
// Build the parts object for BuildRender
const buildParts = {
parts: Object.fromEntries(
Object.entries(selectedParts).map(([category, partId]) => [
category,
[partId], // Wrap in array as required
])
),
};
return (
<div>
<BuildRender parts={buildParts} size={500} />
{/* Part selection UI */}
{Object.entries(availableParts).map(([category, parts]) => (
<div key={category}>
<h3>{category}</h3>
<select
value={selectedParts[category] || ""}
onChange={(e) =>
setSelectedParts((prev) => ({
...prev,
[category]: e.target.value,
}))
}
>
{parts.map((part) => (
<option key={part.id} value={part.id}>
{part.name}
</option>
))}
</select>
</div>
))}
</div>
);
}✨ Features
- 🎮 Interactive Controls: Drag with mouse or touch to rotate the 3D model
- 📱 Mobile Support: Optimized touch controls for mobile devices
- ⚡ Real-time Rendering: Dynamic video generation based on part selection
- 💡 User Guidance: Animated hints showing users they can interact
- 📏 Responsive: Adapts to any size you specify
- 🔒 TypeScript: Full TypeScript support with comprehensive types
🔧 Configuration
Sensitivity Settings
Fine-tune the drag sensitivity for different use cases:
<BuildRender parts={parts} size={500} mouseSensitivity={0.003} />
<BuildRender parts={parts} size={500} mouseSensitivity={0.01} />
<BuildRender parts={parts} size={500} mouseSensitivity={0.02} />Size Configuration
Set the display size based on your layout needs:
<BuildRender parts={parts} size={500} />📝 License
ISC
⚠️ YOU MUST HAVE A LICENSE TO THE BUILDCORES API TO USE THIS
To contact us, visit: www.buildcores.com/api
🤝 Contributing
Issues and pull requests are welcome! Please ensure TypeScript types are properly maintained.
Built with ❤️ for the PC building community
