JSFiddle - React, Tailwind, and code Playground

HTML

<h1>Widgets: <span id="widget-count">0</span> (<span id="cps">0</span> / s)</h1>

<button id="produce-widget">Produce Widget</button>

<h2>Store:</h2>

<div id="store-container"></div>

<h2>Coding exercises:</h2>

<ul>
    <li>Change the starting costs and see how it affects the game</li>
    <li>Add two more levels of widgeteers</li>
    <li>Add stats near the top showing widgets per second and the number of widgeteers of each type</li>
    <li>Add an upgrades section</li>
    <li>Add save/load buttons that use localStorage.setItem() and localStorage.getItem()</li>
    <li>Check the Bootstrap 3 checkbox in the upper left and change the &lt;button&gt; elements to use &lt;div class="btn btn-primary"&gt; instead</li>
</ul>

JavaScript

// Game is a global object. It is unique and can be called from wherever in the code.
var Game = {
		interval: 10,     // time between each tick (in ms)
		decimals: 2,      // Number of decimals displayed, 0 for just integers
		
		currency: 0,      // currency owned
		
		// DOM elements
		button: undefined,
		count: undefined,
		store: undefined,
		cpsDisplay: undefined,
		
		// This is the handle for the setInterval.
		// It is good practice to keep it stored somewhere, if only to be able
		// to stop it with window.clearInterval(Game.handle)
		handle: undefined,
		
		// The possible buildings will be stored in this array
		buildings: [],
		
		init: function(_buildings) {
			var self = this;
			
			// -- Cache DOM elements
			// (traversing the DOM with jQuery is costly on large pages, so it is recommended
			// to call static elements just once and store them for future use. Also makes for some
			// more readable code)
			this.button = $('#produce-widget');
			this.count = $('#widget-count');
			this.store = $('#store-container');
			this.cpsDisplay = $('#cps');
			
			// bind the click event
			this.button.click(function() {
				self._click(); // Note about 'self' : inside a jQuery click() function, 'this' will contain the element that has been clicked, in this
							   // case the "Produce widget" button. We use 'self' to still have access to our Game object inside the function.
			});
			
			// -- Initialize all buildings and store them in the buildings array
			$.each(_buildings, function(i, _building) {
				var newBuilding = Building(_building).init();
				self.buildings.push(newBuilding);
			});
			
			// Launch the ticker
			this.handle = window.setInterval(function() {
				self._tick();
			}, this.interval);
		},
		
		// called each time you click
		_click: function() {
			this.currency++;
		},
		
		// called at each tick
		_tick: function() {
			// Each building produces his currency, and then we check
			// if we have enough to buy another (ie...