Visualising South African Procurement Data by Sector: An Embeddable Bar Chart Widget
The Tenders-SA Sector Trends widget renders an interactive SVG bar chart showing tender volume and value across procurement sectors. No external chart libraries, lazy-loaded, and open source.
Why Visualise Tender Data by Sector?
South African government procurement is distributed across dozens of sectors — construction, information technology, healthcare, transportation, security services, facilities management, and many more. For suppliers deciding where to focus their bidding efforts, understanding which sectors have the highest tender volumes and values is a strategic input. For industry analysts, it reveals where public spending is flowing.
The Sector Trends widget (github.com/Tenders-SA/widget-sector-trends) renders this data as an interactive bar chart that you can embed on any website. It is an open-source, zero-dependency JavaScript widget that draws inline SVG bar charts — no external charting library required. This makes it exceptionally lightweight and fast to render.
What Data Does the Widget Display?
The widget fetches data from the /api/widgets/sector-trends endpoint, which aggregates active tenders by procurement sector. Each sector is represented as a horizontal bar:
| Field | Type | Description |
|---|---|---|
| sector | string | Procurement sector name (e.g. 'Construction', 'IT & Technology') |
| tenderCount | number | Number of active tenders in the sector |
| totalValue | number | Total combined value of tenders in the sector (ZAR) |
The widget shows both a value bar (total contract value) and a count label for each sector. Bars are colour-coded using the Tenders-SA brand palette and scale proportionally to the maximum value in the dataset.
Technical Architecture
The Sector Trends widget is the most technically sophisticated of the four public widgets. It uses several browser APIs that the simpler widgets do not:
Inline SVG Rendering
The chart is rendered entirely with SVG elements — rect for bars, text for labels, line for grid lines. This means there are no dependencies on charting libraries like Chart.js, D3.js, or Recharts. The rendering code in renderer.ts calculates bar dimensions, positions labels, and draws tooltip elements directly using the SVG DOM API.
This approach keeps the bundle size around 7 KB and eliminates the need for canvas or WebGL, which makes the widget suitable for use in environments where heavy DOM manipulation is undesirable.
Lazy Loading with IntersectionObserver
The widget uses the IntersectionObserver API to defer all network requests and rendering until the widget container is visible in the viewport. When a page loads with the widget below the fold, the widget shows a CSS-animated loading skeleton and only makes the API call once the container scrolls into view.
This has two benefits: it avoids unnecessary network requests for off-screen content, and it prevents layout shift by reserving space for the widget skeleton from the moment the script loads.
Responsive Resizing with ResizeObserver
The widget uses ResizeObserver to detect when its container changes size — for example, when a user rotates their phone from portrait to landscape, or when a responsive layout reflows. When a resize is detected, the widget clears the current SVG, recalculates dimensions, and re-renders the chart. This ensures the chart always fills its available space without distortion.
Configuration Options
| Option | Type | Default | Description |
|---|---|---|---|
| province | string | 'all' | Filter by province to show sector breakdown for a specific region |
| category | string | 'all' | Filter by parent category to narrow the sector view |
| limit | number | 8 | Number of sectors to show (max 20) |
| theme | 'light' | 'dark' | 'light' |
| apiBase | string | 'https://tenders-sa.org' | Base URL for the API endpoint |
Embed Methods
Method 1: HTML Data Attribute
1<div 2 data-tendersa-sector-trends 3 data-theme="light" 4 data-limit="8" 5 data-province="all" 6></div> 7 8<script 9 src="https://cdn.jsdelivr.net/npm/@tendersa/widget-sector-trends/dist/widget-sector-trends.iife.js" 10 async 11></script>HTML
Method 2: Programmatic (NPM)
1npm install @tendersa/widget-sector-trendsBASH
1import { SectorTrendsWidget } from '@tendersa/widget-sector-trends' 2 3const container = document.getElementById('chart-container') 4const widget = new SectorTrendsWidget(container, { 5 theme: 'dark', 6 limit: 12, 7 province: 'gauteng', 8}) 9 10widget.render()JAVASCRIPT
The render method is asynchronous and returns a promise that resolves once the data is fetched and the chart is drawn. The widget also supports an init() function for bulk initialisation if you have multiple widget containers on the same page:
1import { init } from '@tendersa/widget-sector-trends' 2 3// Initialise all [data-tendersa-sector-trends] elements on the page 4const widgets = init({ theme: 'dark' }) 5 6// Each widget can be individually destroyed later 7widgets.forEach(w => w.destroy())JAVASCRIPT
Performance and Browser Support
- Bundle size: approximately 7 KB (minified and gzipped)
- All modern browsers with IntersectionObserver and ResizeObserver support (Chrome 61+, Firefox 68+, Safari 12.1+, Edge 79+)
- The chart SVG scales cleanly to 2x and 3x display resolutions because it uses vector graphics, not raster images
- The API endpoint (
/api/widgets/sector-trends) is ISR-cached with 3600-second revalidation, so repeated views of the same sector data are served from the Edge
The Open Source Package
The Sector Trends widget is published as @tendersa/widget-sector-trends on npm and is open source under the MIT license. The source code is available at github.com/Tenders-SA/widget-sector-trends.
The repository includes TypeScript source code with exported type definitions, the full SVG renderer implementation, a tsup build pipeline (ESM, CJS, and IIFE bundles), and utility functions for currency formatting and sector colour mapping.
Use Cases
- Industry publications — Show readers which procurement sectors are most active in a given quarter.
- Business strategy pages — Help readers decide which sectors to target by displaying comparative tender volume and value.
- District and provincial development sites — Display sector breakdowns for a specific province, showing where local procurement spending is concentrated.
- Research and academic projects — Embed live sector data in research portals studying public procurement patterns.
Getting Started
Add the widget to any page with the data-attribute HTML snippet above. The full source code, documentation, and issue tracker are at github.com/Tenders-SA/widget-sector-trends. For direct API access, the endpoint at /api/widgets/sector-trends returns the sector aggregation data in JSON format.
Tags
Based on this article's topics, here are some current tenders that might interest you
Request for Proposals (RFP) The Provision of Underwater Measurement Capabilities and Technical Expertise Related to the Development and Testing of Maritime Technology and Underwater Sensors with the CSIR for a Period of 5 Years.
APPOINTMENT OF A SERVICE PROVIDER TO RENDER THE INFORMATION TECHNOLOGY MANAGEMENT SERVICES FOR A PERIOD OF TWO (2) YEARS.
Want to see all available tenders?
Browse All Tenders →Share this article
Visualising South African Procurement Data by Sector: An Embeddable Bar Chart Widget
The Tenders-SA Sector Trends widget renders an interactive SVG bar chart showing tender volume and value across procurement sectors. No external chart libraries, lazy-loaded, and open source.