Counter
This guide walks you through building a real-time counter using bigstate.client.javascript.
You will learn how to:
- Create a state object
- Create a delivery channel
- Publish state updates (HTTP)
- Subscribe to updates (WebSocket)
- Render data in the DOM
Overview#
The architecture consists of two parts:
- Publisher (HTTP) → sends state updates
- Subscriber (WebSocket) → receives updates in real time
In this example, both run in the same browser for simplicity.
Prerequisites#
- A BigState API key (
YOUR_API_KEY) - Your owner (
OWNER) - A modern browser
Single HTML File, CDN#
Step 1 - Create HTML structure#
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>BigState — counter</title>
<style>
body {
margin: 0;
}
.container {
width: 100%;
height: 100dvh;
display: flex;
justify-content: center;
align-items: center;
background: #0b1a2a;
}
#counter {
font-size: 100px;
font-weight: bold;
color: #9d50bb;
}
</style>
</head>
<body>
<div class="container">
<div id="counter"></div>
</div>
</body>
</html>
Step 2 - Load the client (UMD)#
<body>
<!-- after the content from the previous steps -->
<script src="https://cdn.jsdelivr.net/npm/bigstate.client.javascript@0.0.7/dist/index.umd.js"></script>
</body>
Do not use type="module" with the UMD build.
Step 3 - Initialize clients#
<body>
<!-- after the content from the previous steps -->
<script>
const { BigStateHttpClient, BigStateWsDeliveryClient } = BigState;
const API_KEY = 'YOUR_API_KEY';
const httpClient = new BigStateHttpClient({
baseUrl: 'https://api.bigstate.dev',
apiKey: API_KEY,
});
const wsClient = new BigStateWsDeliveryClient({
baseUrl: 'https://ws.delivery.bigstate.dev',
apiKey: API_KEY,
});
</script>
</body>
Step 4 - Create a state object#
<body>
<!-- after the content from the previous steps -->
<script>
// script content (Step 3)
const OWNER = 'OWNER';
const COUNTER_OBJECT = `simple:counter@${OWNER}`;
const createObject = async () => {
const data = {
type: 2,
ttl: 100000,
validity: 60,
versionDeep: null,
info: {
name: 'Small counter',
desc: 'Online small counter',
example: { count: 1 },
},
};
const { error } = await httpClient.objectCreate(COUNTER_OBJECT, data);
};
</script>
</body>
Step 5 - Create a delivery#
<body>
<!-- after the content from the previous steps -->
<script>
// script content (Steps 3, 4)
const DELIVERY_WS = `deliveryWsCounter${OWNER}`;
const creatDelivery = async () => {
const data = {
name: 'Counter WS delivery',
objects: [COUNTER_OBJECT],
type: 1,
};
const { error } = await httpClient.deliveryCreate(DELIVERY_WS, data);
console.log(error);
};
</script>
</body>
Step 6 - Publish state updates#
<body>
<!-- after the content from the previous steps -->
<script>
// script content (Steps 3, 4, 5)
const statePublication = async () => {
let count = 0;
setInterval(async () => {
count = count === 1000000000000 ? 0 : count + 1;
const data = {
at: new Date().toISOString(),
value: { count },
};
const { error } = await httpClient.stateSet(COUNTER_OBJECT, data);
if (error) {
console.error('Error set state:', error);
} else {
console.log(`new ${COUNTER_OBJECT} state: `, data.value);
}
}, 400);
};
</script>
</body>
Step 7 - Subscribe to updates#
<body>
<!-- after the content from the previous steps -->
<script>
// script content (Steps 3-6)
const getStates = () => {
const counter = document.querySelector('#counter');
wsClient.subscribeStateUpdate([DELIVERY_WS], (message) => {
console.log(message, 'message');
if (message.type !== 'message') return;
counter.innerText = message.data?.state?.value?.count ?? '';
});
};
</script>
</body>
Step 8 - Start the app#
<body>
<!-- after the content from the previous steps -->
<script>
// script content (Steps 3-7)
const start = async () => {
await createObject();
await creatDelivery();
await statePublication();
getStates();
};
start();
</script>
</body>
Using ESM (Module)#
<script type="module">
import {
BigStateHttpClient,
BigStateWsDeliveryClient,
} from 'https://cdn.jsdelivr.net/npm/bigstate.client.javascript@0.0.7/dist/index.esm.js';
// script content (Steps 3-8)
</script>
Some browsers block module imports over file://. Use a local server if needed.
Using npm#
This package is published as an ES module, so you need a dev server or bundler to use it.
We recommend using one of:
- Vite (recommended)
- Webpack
- Any modern build tool with ESM support
🚀 Quick setup with Vite (recommended)
Create a new project#
npm create vite@latest bs-counter
Choose settings:
Select a framework: -> Vanilla
Select a variant: -> JavaScript
Install with npm and start now: -> No
Install the dependencies and the client:
cd bs-counter
npm install
npm install bigstate.client.javascript
Project structure#
project/
index.html
src/
main.js
style.css
index.html#
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>BigState — counter</title>
</head>
<body>
<div class="container">
<div id="counter"></div>
</div>
<script type="module" src="/src/main.js"></script>
</body>
</html>
main.js#
import {
BigStateHttpClient,
BigStateWsDeliveryClient,
} from 'bigstate.client.javascript';
import './style.css';
// script content (Steps 3-8)
style.css#
body {
margin: 0;
}
.container {
width: 100%;
height: 100dvh;
display: flex;
justify-content: center;
align-items: center;
background: #0b1a2a;
}
#counter {
font-size: 100px;
font-weight: bold;
color: #9d50bb;
}
Run the project#
npm run dev
Next Steps#
- Split publisher and subscriber into separate services
- Add user interaction
- Use multiple objects
- Integrate with React, Vue, Angular
StackBlitz#
The StackBlitz counter starter uses a bundled / multi-file setup; compare paths and behavior with the snippets above.