Counter

This guide walks you through building a real-time counter using bigstate.client.javascript.

Real-time counter updates via WebSocket

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.

© 2024 BigState