<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Pounce Engineering]]></title><description><![CDATA[Pounce Engineering]]></description><link>https://pounceza.hashnode.dev</link><generator>RSS for Node</generator><lastBuildDate>Tue, 03 Nov 2026 02:35:03 GMT</lastBuildDate><atom:link href="https://pounceza.hashnode.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[A map explorer that still works when WebGL fails: fallback, keyboard and accessibility checks]]></title><description><![CDATA[A map explorer depends on WebGL for its 3D view. Browsers, devices and graphics drivers do not always provide it. This post describes how Pounce Atlas…]]></description><link>https://pounceza.hashnode.dev/a-map-explorer-that-still-works-when-webgl-fails-fallback-keyboard-and-accessibility-checks</link><guid isPermaLink="true">https://pounceza.hashnode.dev/a-map-explorer-that-still-works-when-webgl-fails-fallback-keyboard-and-accessibility-checks</guid><category><![CDATA[Open Source]]></category><category><![CDATA[webdev]]></category><category><![CDATA[Accessibility]]></category><dc:creator><![CDATA[Pounce Za]]></dc:creator><pubDate>Sun, 01 Nov 2026 10:02:32 GMT</pubDate><content:encoded><![CDATA[<p>A map explorer depends on WebGL for its 3D view. Browsers, devices and graphics drivers do not always provide it. This post describes how Pounce Atlas keeps its records usable when that happens, and which browser tests check the behaviour.</p>
<p>Disclosure: AI assisted with drafting this post. Pounce reviewed it against the public browser test file. The examples are fictional.</p>
<h2>The problem</h2>
<p>If the WebGL canvas cannot start, a map-only interface shows nothing useful. Records should still be reachable as a list, and the controls should still work with a keyboard.</p>
<h2>What the browser tests check</h2>
<p>The browser tests use Playwright Test. Among them, these checks cover the fallback and related behaviour:</p>
<ul>
<li>A WebGL failure leaves a working, accessible list of records.</li>
<li>A failed dataset load recovers with another local fixture, so the page does not stay empty.</li>
<li>A phone-sized layout does not overflow, and the detail sheet can be closed.</li>
<li>Menus are opaque, and keyboard selection works.</li>
<li>Changing datasets stops playback and resets selections, so an old selection does not stay on screen.</li>
<li>The main view and the import dialog are checked with automated accessibility tests using axe-core.</li>
</ul>
<h2>Why a list matters</h2>
<p>A list gives people a second way to read the same records. It also makes the data easier to check: names, categories and locations can be read as text without a 3D scene.</p>
<h2>What these tests cannot prove</h2>
<p>They show that the checked paths behave as the tests expect, on the configurations that were run. They do not prove that every device, browser or assistive technology works. Some browser tests also need a private dataset that is not distributed, so they are skipped unless an environment flag is set.</p>
<p>Browser test source: <a href="https://github.com/zaiqltd/pounce-atlas/blob/main/tests/browser/atlas.spec.ts">https://github.com/zaiqltd/pounce-atlas/blob/main/tests/browser/atlas.spec.ts</a>
Repository: <a href="https://github.com/zaiqltd/pounce-atlas">https://github.com/zaiqltd/pounce-atlas</a>
Demo with fictional data: <a href="https://pounce.co.za/atlas/">https://pounce.co.za/atlas/</a></p>
]]></content:encoded></item><item><title><![CDATA[Imported files stay on your device: how Pounce Atlas handles CSV and JSON]]></title><description><![CDATA[Pounce Atlas is an open-source explorer for geographic datasets. It can load your own CSV or JSON file in the browser. This post explains what the app does…]]></description><link>https://pounceza.hashnode.dev/imported-files-stay-on-your-device-how-pounce-atlas-handles-csv-and-json</link><guid isPermaLink="true">https://pounceza.hashnode.dev/imported-files-stay-on-your-device-how-pounce-atlas-handles-csv-and-json</guid><category><![CDATA[Open Source]]></category><category><![CDATA[datascience]]></category><category><![CDATA[JavaScript]]></category><dc:creator><![CDATA[Pounce Za]]></dc:creator><pubDate>Sun, 01 Nov 2026 09:58:40 GMT</pubDate><content:encoded><![CDATA[<p>Pounce Atlas is an open-source explorer for geographic datasets. It can load your own CSV or JSON file in the browser. This post explains what the app does with that file, what it does not do, and what remains your responsibility.</p>
<p>Disclosure: AI assisted with drafting this post. Pounce reviewed it against the public README, data contract and tests.</p>
<h2>What happens to an imported file</h2>
<p>According to the README, the Import feature loads a compatible CSV or JSON file in the browser. The imported contents stay on that device in the current page, and no server import service is part of the application.</p>
<h2>Share links</h2>
<p>A share link preserves a view of a built-in dataset. A share link never uploads a locally imported file.</p>
<h2>Events and CSV</h2>
<p>CSV imports do not create activity events. If you need dated events, use JSON with correctly dated events.</p>
<h2>Rules that still apply to your data</h2>
<ul>
<li>Use precision labels honestly: exact, town, province or unknown. A town label means an approximate town centre.</li>
<li>Do not invent coordinates for a missing location. Leave both coordinate cells empty when the location is unknown.</li>
<li>A town or exact record needs both latitude and longitude. Numeric strings from CSV are accepted, and boolean coordinates are rejected.</li>
</ul>
<p>The data contract has the full rules: <a href="https://github.com/zaiqltd/pounce-atlas/blob/main/docs/DATA-CONTRACT.md">https://github.com/zaiqltd/pounce-atlas/blob/main/docs/DATA-CONTRACT.md</a></p>
<h2>What the parser is tested for</h2>
<p>The CSV parser handles quoted commas, escaped quotes and newlines. It flags an unterminated quote, a duplicate header and a ragged row. Imported file content is treated as text, not as code.</p>
<h2>What this does not cover</h2>
<p>The app does not verify that you have the right to use a dataset, and it does not check that addresses are correct. Check licences and consent for your own data before you import it.</p>
<p>Repository and README: <a href="https://github.com/zaiqltd/pounce-atlas">https://github.com/zaiqltd/pounce-atlas</a>
Demo with fictional data: <a href="https://pounce.co.za/atlas/">https://pounce.co.za/atlas/</a></p>
]]></content:encoded></item><item><title><![CDATA[An announcement isn’t an opening: separating event, observation and snapshot dates]]></title><description><![CDATA[Disclosure: AI assisted the drafting of this article; Pounce reviewed it against the public Atlas source. Pounce builds Pounce Atlas, an open-source…]]></description><link>https://pounceza.hashnode.dev/an-announcement-isn-t-an-opening-separating-event-observation-and-snapshot-dates</link><guid isPermaLink="true">https://pounceza.hashnode.dev/an-announcement-isn-t-an-opening-separating-event-observation-and-snapshot-dates</guid><category><![CDATA[Open Source]]></category><category><![CDATA[datascience]]></category><dc:creator><![CDATA[Pounce Za]]></dc:creator><pubDate>Sun, 01 Nov 2026 09:45:34 GMT</pubDate><content:encoded><![CDATA[<p><strong>Disclosure:</strong> AI assisted the drafting of this article; Pounce reviewed it against the public Atlas source. Pounce builds <a href="https://pounce.co.za/atlas/">Pounce Atlas</a>, an open-source explorer for geographic datasets. Its examples are fictional, and its activity view describes only events recorded in the selected dataset.</p>
<p>A map can make a date look more certain than the evidence behind it. A marker appears, a timeline gains an entry, and a reader may infer that a business opened or expanded on that day. But a dataset often carries several different clocks: when an event happened or is planned, when a record was checked, when a snapshot was generated, and the cutoff through which a source was considered. Collapsing those into one date turns evidence about the data into a claim about the world.</p>
<p>Atlas keeps these meanings separate in its <a href="https://github.com/zaiqltd/pounce-atlas/blob/main/docs/DATA-CONTRACT.md">public data contract</a>.</p>
<h2>Four dates, four questions</h2>
<p><strong>Event date (events[].date) asks: when is the described event dated?</strong> It is an ISO calendar date for the event itself. The accompanying status says whether that event is occurred or announced. An announced opening scheduled for a future day is still an announcement, not a completed opening. Preserve that status instead of converting a plan into a fact.</p>
<p><strong>Record check date (checkedAt) asks: when was this record checked?</strong> It is a record-level observation about review, not proof that every field was independently reverified. A recent check date does not move an older event forward in time.</p>
<p><strong>Snapshot generation time (generatedAt) asks: when was this dataset file generated?</strong> It describes the build of a particular snapshot. Regenerating a file can update this timestamp even when a record was not checked that day and no event occurred then.</p>
<p><strong>Source cutoff (sourceAsOf) asks: what source period does the dataset claim to cover?</strong> It is a declared source cutoff, not a blanket assertion that all records were checked at the cutoff. The contract explicitly warns against that inference.</p>
<p>There can be other dates too. A source page’s publication date, the first time a collector fetched it, and the first time a team noticed an event are not interchangeable with those four fields. If they matter, keep them distinct and define them. Do not silently substitute one for another.</p>
<h2>A fictional example</h2>
<p>Imagine a clearly fictional business called <strong>Harbour Lantern Works</strong>. A source note dated 18 October says it has announced a second workshop for 1 February next year. A researcher checks the record on 20 October. The dataset’s source cutoff is 25 October, and the file is generated on 26 October.</p>
<p>A careful record could retain the planned event date as 1 February and set its status to announced; it could record checkedAt as 20 October, sourceAsOf as 25 October, and generatedAt as the actual snapshot-build timestamp on 26 October. The source note’s 18 October publication date remains separate if the dataset stores it. The company and dates here are invented to illustrate the schema, not claims about a real business.</p>
<p>A reader should be able to tell that the item is a future plan reported in a snapshot, not evidence that the workshop is already open. If the source only says “early next year,” do not invent a precise day. The Atlas contract says to leave an uncertain event out of a precise dated timeline until it has been checked.</p>
<h2>Keep geography and absence honest too</h2>
<p>An event has no coordinates in this schema. Its optional locationLabel is text for context; it does not locate the event at a company’s headquarters. The dataset may locate a record at town precision, but that is not an event coordinate or a verified street address. Don’t copy the record’s map point onto an event as if the event happened there.</p>
<p>Likewise, an empty activity view has a narrow meaning. Atlas filters Activity to records with a matching event in the chosen range and filters. If no event matches, the result is “no matching event recorded in this selected snapshot and range.” It is not proof that nothing happened. The methodology notes that a quiet area can reflect incomplete collection, and that Map or Industries may still show records absent from Activity.</p>
<h2>Make the distinction executable</h2>
<p>The public validateDataset implementation checks event dates and statuses, and rejects a future event marked occurred. The model tests exercise invalid calendar dates, require a future event to be announced, and check that Activity date filters include matching dates while records without events do not enter Activity counts. I ran npm test in the public source checkout for this article: <strong>21 tests passed, 0 failed</strong>. That is evidence about the checked code paths, not proof that any external dataset is complete or that an announced event later occurred.</p>
<p>The lesson is simple: event time describes the event; check time describes observation; generation time describes the file; and source cutoff describes the declared coverage boundary. Keep those clocks visible, carry announced through the interface, and treat no match as a limit of the selected data rather than a claim about reality.</p>
<p>Explore the <a href="https://pounce.co.za/atlas/">live Pounce Atlas demo</a> using its fictional examples, or inspect the <a href="https://github.com/zaiqltd/pounce-atlas">MIT-licensed application source</a>, <a href="https://github.com/zaiqltd/pounce-atlas/blob/main/docs/DATA-CONTRACT.md">data contract</a>, <a href="https://github.com/zaiqltd/pounce-atlas/blob/main/docs/METHODOLOGY.md">methodology</a>, and <a href="https://github.com/zaiqltd/pounce-atlas/blob/main/tests/model.test.ts">model tests</a>. Application code is MIT licensed; data and map/font assets have separate notices.</p>
]]></content:encoded></item><item><title><![CDATA[Import a CSV without turning missing locations into false map pins]]></title><description><![CDATA[Import a fictional CSV into Pounce Atlas while preserving unknown locations, town-level precision and the limits of locally shared data.]]></description><link>https://pounceza.hashnode.dev/import-a-csv-without-turning-missing-locations-into-false-map-pins</link><guid isPermaLink="true">https://pounceza.hashnode.dev/import-a-csv-without-turning-missing-locations-into-false-map-pins</guid><category><![CDATA[data visualization]]></category><dc:creator><![CDATA[Pounce Za]]></dc:creator><pubDate>Mon, 26 Oct 2026 07:35:51 GMT</pubDate><content:encoded><![CDATA[<p>A map pin can look more certain than the row behind it. A town-level coordinate is not a street address, and a missing coordinate should not silently become <code>(0, 0)</code>.</p>
<p>This walkthrough uses <a href="https://pounce.co.za/atlas/">Pounce Atlas</a>, an open-source geographic dataset explorer from Pounce. The example below is entirely fictional. It demonstrates two records located only to a town and a third with no location, rather than presenting a real business directory.</p>
<h2>1. Make location precision explicit</h2>
<p>Save this UTF-8 text as <code>atlas-fictional-import-example.csv</code>:</p>
<pre><code class="language-csv">name,sector,trade,town,province,lat,lon,precision,website
Example Workshop,Manufacturing,Metal fabrication,Johannesburg,Gauteng,-26.20227,28.04363,town,https://example.com
Example Studio,Creative services,Design,Johannesburg,Gauteng,-26.20227,28.04363,town,
Example Remote Team,Professional services,Consulting,,,,,unknown,
</code></pre>
<p>The two Johannesburg rows deliberately share an approximate town-centre coordinate. That does not imply they share a building or have a business relationship. The town reference follows the GeoNames-attributed example in Atlas's data contract.</p>
<p>The remote team's town, province and coordinate cells are empty. Its <code>precision</code> is <code>unknown</code>. There is no fabricated location to make the map look complete.</p>
<p>Use the exact header names. Quote cells containing commas or newlines, and double any literal quotes inside a quoted cell. <code>website</code> is optional; the example.com address is a placeholder, not a real organization website. Avoid spreadsheet formulas as field values.</p>
<h2>2. Import and check the list before the map</h2>
<p>Open the demo, choose <strong>Import data</strong>, then <strong>Choose a CSV or JSON file</strong> and select the file.</p>
<p>For this sample, the expected result is:</p>
<ul>
<li><strong>3 listings</strong> in the list.</li>
<li><strong>2 located listings</strong> on the map.</li>
<li><strong>1 unlocated</strong> record retained in the dataset.</li>
<li>Three industry categories, each containing one record.</li>
<li>A <strong>Local file</strong> label and <strong>Snapshot date not supplied</strong> notice.</li>
</ul>
<p>This three-row file was checked against the live demo with those results. Keeping the unlocated record in the list matters: missing geography should not silently remove an entity from the dataset.</p>
<h2>3. Treat precision as a constraint</h2>
<p>Atlas's contract supports four precision values:</p>
<ul>
<li><code>exact</code>: the relevant premises have actually been established and are suitable for the intended use.</li>
<li><code>town</code>: an approximate town centre, not a verified address.</li>
<li><code>province</code>: only the province is known.</li>
<li><code>unknown</code>: geographic precision is unavailable.</li>
</ul>
<p>The importer normalizes <code>province</code> and <code>unknown</code> coordinates to <code>null</code>. A <code>town</code> or <code>exact</code> record needs both latitude and longitude. Numeric strings in CSV are accepted, but passing validation does not verify an address. The current South African base map also means globally valid coordinates are not automatically useful for this particular interface.</p>
<h2>4. Use JSON when dates and provenance matter</h2>
<p>The CSV format has no event or snapshot-license columns. Use the documented JSON envelope when you need stable record IDs, dataset versions, attribution, reuse terms or dated events.</p>
<p>In particular, an event's date is not the day a row was imported or first discovered. An announced opening is not a completed opening. If the date is uncertain, do not manufacture a precise timeline entry.</p>
<p>The importer currently limits files to 10 MB and datasets to 50,000 records. Those are validation limits, not a performance benchmark or a recommendation to start with the largest possible file.</p>
<h2>5. Understand what sharing does not do</h2>
<p>Imported files are processed in the browser. Atlas has no import endpoint or remote geocoding service. A view URL does not carry an imported file's rows to another person; they need the file themselves. Built-in demonstration datasets have a separate shareable-view workflow.</p>
<p>Before publishing a dataset elsewhere, verify its actual redistribution rights, field allowlist and privacy implications. Successful parsing is not publication permission.</p>
<p>The <a href="https://github.com/zaiqltd/pounce-atlas">source repository and data-contract documentation</a> are available for reuse and inspection. Application code is MIT-licensed; map references, place data and fonts retain their separate notices. The released business and venue examples are fictional, not production Pounce data.</p>
<p><em>Written with AI assistance and checked against the v0.1.0 data contract and a live three-row import.</em></p>
]]></content:encoded></item></channel></rss>