{
	"version": "https://jsonfeed.org/version/1.1",
	"title": "Tech for Personal Growth",
	"language": "en",
	"home_page_url": "https://hominidsoftware.com/tech-personal-growth/",
	"feed_url": "https://hominidsoftware.com/feed/feed.json",
	"description": "Essays on using digital technology to become a better person",
	"author": {
		"name": "Doug Reeder",
		"url": "https://hominidsoftware.com/about/"
	},
	"favicon": "https://hominidsoftware.com/favicon.ico",
	"items": [
		{
			"id": "https://hominidsoftware.com/tech-personal-growth/gemini-android-xr/",
			"url": "https://hominidsoftware.com/tech-personal-growth/gemini-android-xr/",
			"title": "Gemini will determine the success of Android XR",
			"summary": "Android XR will struggle to establish an ecosystem; practical real-world uses for Gemini in the headset form-factor will be key.",
			"content_html": "<h2 id=\"the-new-entrant\" tabindex=\"-1\">The new entrant <a class=\"header-anchor\" href=\"https://hominidsoftware.com/tech-personal-growth/gemini-android-xr/#the-new-entrant\">#</a></h2>\n<p>Android XR appears to be a professionally-executed implementation of mixed reality.\nSamsung and Google put out competitive hardware;\nI will assume for this post that they will have table stakes.</p>\n<div class=\"center-horizontal\">\n<picture><source type=\"image/avif\" srcset=\"https://hominidsoftware.com/img/Project-Moohan-3-4-750w.avif 750w, https://hominidsoftware.com/img/Project-Moohan-3-4-909w.avif 909w\" sizes=\"100vw\"><source type=\"image/webp\" srcset=\"https://hominidsoftware.com/img/Project-Moohan-3-4-750w.webp 750w, https://hominidsoftware.com/img/Project-Moohan-3-4-909w.webp 909w\" sizes=\"100vw\"><img alt=\"Project Moohan [Infinity], courtesy of Samsung\" loading=\"lazy\" decoding=\"async\" src=\"https://hominidsoftware.com/img/Project-Moohan-3-4-750w.png\" width=\"909\" height=\"583\" srcset=\"https://hominidsoftware.com/img/Project-Moohan-3-4-750w.png 750w, https://hominidsoftware.com/img/Project-Moohan-3-4-909w.png 909w\" sizes=\"100vw\"></picture>\n</div>\n<p><em>Project Moohan [&quot;Infinity&quot;], courtesy of Samsung; not shown: external power brick</em></p>\n<h2 id=\"the-legacy\" tabindex=\"-1\">The legacy <a class=\"header-anchor\" href=\"https://hominidsoftware.com/tech-personal-growth/gemini-android-xr/#the-legacy\">#</a></h2>\n<p>Google launched Daydream nearly a decade ago and dropped it less than three years later.\nThey launched Glass OS and dropped it about four years later.\nCareer rewards at Google follow the Launch, Promote, Abandon cycle (that's the terminology used by employees).\nSamsung launched and dropped Gear VR.</p>\n<p>You can argue that phone VR was a technological dead-end — but Oculus developed the OS for Gear VR, and its descendant now powers all Meta headsets (that greatly outnumber other headsets).\nAny developer who lived through that will think carefully before betting significant resources on Android XR.</p>\n<h2 id=\"the-established-competition\" tabindex=\"-1\">The established competition <a class=\"header-anchor\" href=\"https://hominidsoftware.com/tech-personal-growth/gemini-android-xr/#the-established-competition\">#</a></h2>\n<p>Meta has a commanding lead in VR games.\nIf Google can convince enough of the largest social VR networks to port their apps, they could achieve near-parity there, but no more.\nXR productivity and lifestyle apps are not drawing many users yet.\n[My contribution there is <a href=\"https://hominidsoftware.com/model-presenter/\">Model Presenter</a>.]</p>\n<p>Meta's Horizon OS can run Android apps.\nAndroid app developers can spatialize their apps using Meta's API, and get access to tens of millions of headsets now, or Google's and get access to however many (or few) Project Moohan headsets sell next year.\nI know where I'd put my effort, especially give that that's still less than one percent of Android devices.</p>\n<p>Teardown of Vision Pro hardware shows that it's not technologically ahead of other headsets, it's just better, more expensive hardware.\nSo, if Android XR headsets are cheaper, they will struggle to match the flowing experience of Vision Pro.\nWithout the grace of Vision OS and its hardware, using flat apps in a headset is of marginal value, even for users invested in Android apps, or rubbed the wrong way by Apple paternalism.\nGoogle is hit-and-miss on user experience while Apple has nailed the UX for Vision OS.</p>\n<h2 id=\"the-value-proposition\" tabindex=\"-1\">The value proposition <a class=\"header-anchor\" href=\"https://hominidsoftware.com/tech-personal-growth/gemini-android-xr/#the-value-proposition\">#</a></h2>\n<p>Most households and organizations still don't have a VR headset, so Google and Samsung don't have to pry users away from an existing ecosystem.\nBut they still have to woo users.</p>\n<p>What's left to draw users to Android XR? Machine learning.\nGemini will be the main draw for years.</p>\n<p>Given time, Android XR could grow its ecosystem beyond that, but Google tends to kill products\nafter three-to-five years, if they don't achieve Internet scale.\nApple has made it clear Vision OS is a long-term project, that is not expected to be profitable for years.\nThe Quest is, at the very least, a successful gaming and social VR console, even if Zuckerberg can't convince his shareholders to underwrite his vision of the future.\nPico is ready to take the center of VR gaming, if Meta falters.</p>\n<p>The most impressive demos of Gemini have the user walking up to something they are unfamiliar with, and Gemini telling them what is is, what's important about it, and/or how to use it.\nYou do that sporadically, not all day long.  A phone is fine for that.</p>\n<p>What can Gemini do in the headset form factor, that it can’t do in a phone, that is actually useful to ordinary people (as opposed to a an impressive tech demo)?\nMost people are already carrying around an Android phone with an excellent camera and a solid microphone.\nYou need to pull it out to access Gemini, but that's a modest hurdle.\nMore importantly, it's obvious when someone is using the camera on their phone.\nIt doesn't have the vibe of someone surreptitiously spying on you.\nThe reaction to XR headsets in public will be less virulent than that Google Glass evoked,\nand eventually, it will be accepted that anyone around you could be recording you.\nBut that won't change in the next five years.</p>\n<p>So hands-free functionality is where Gemini has to shine.\nHeads-up walking directions in unfamiliar places, when you're loaded with luggage, will be valuable.\nContinuous translation in real life will be valuable when you're in a foreign country.\nSo, frequent travellers will be a core market.\nThey will also appreciate viewing flat-screen entertainment on a virtual large screen.\nSome of them will pack a mouse and keyboard and use a headset instead of a personal computer.\n(But you can do the latter two with other headsets.)</p>\n<p>It's possible a voice assistant is what XR productivity and lifestyle apps need to take off.\nI look forward to seeing what emerges.</p>\n<p>Whenever you hear of some neat thing someone is doing with Google XR, ask yourself if it's better than something people already have — better enough to buy and carry around a new device.</p>\n<h2 id=\"the-conclusion\" tabindex=\"-1\">The Conclusion <a class=\"header-anchor\" href=\"https://hominidsoftware.com/tech-personal-growth/gemini-android-xr/#the-conclusion\">#</a></h2>\n<p>I don't see enough value in Google XR, that enough people will buy it, that will sustain Google's interest, long enough to build a competitive ecosystem.\nThere are many clever and dedicated people in- and outside of Google and Samsung —\nI hope they can produce products that succeed at these difficult challenges, and prove me wrong.\nBut there are safer bets for those interested in XR.</p>\n<p>XR needs more competition, to reduce lock-in, so it serves people, rather than corporations.</p>\n",
			"date_published": "2024-12-14T00:00:00Z",
			"date_modified": "2026-03-27T02:56:35Z"
		}
		,
		{
			"id": "https://hominidsoftware.com/tech-personal-growth/Hubs-Managed-Databse/Hubs-Managed-Database/",
			"url": "https://hominidsoftware.com/tech-personal-growth/Hubs-Managed-Databse/Hubs-Managed-Database/",
			"title": "A Managed Database for Hubs",
			"summary": "Reworking the script and input values to less-than-obvious settings are required",
			"content_html": "<p><em>Content warning: extremely technical — may induce trance, fugue or psychedelic states, out-of-body experiences, lucid dreaming or technical breakthroughs.</em></p>\n<h2 id=\"motivation\" tabindex=\"-1\">Motivation <a class=\"header-anchor\" href=\"https://hominidsoftware.com/tech-personal-growth/Hubs-Managed-Databse/Hubs-Managed-Database/#motivation\">#</a></h2>\n<p>I continue my quest to make my Hubs Community Edition instance observable and production-ready.\nIt's difficult to access PostgresQL running in a container in Kubernetes for development or monitoring.\nBacking up the PostgresQL database as a volume (of files) allows restoring to the same version of PostrgresQL,\nbut not necessarily a newer version, which you might be obliged to use if you change provider\nor your current version reaches end-of-life.\nSo, the next step is moving the PostgresQL database outside the Kubernetes cluster.</p>\n<h2 id=\"managed-databases\" tabindex=\"-1\">Managed Databases <a class=\"header-anchor\" href=\"https://hominidsoftware.com/tech-personal-growth/Hubs-Managed-Databse/Hubs-Managed-Database/#managed-databases\">#</a></h2>\n<p>Operating databases is a specialty all its own — tuning the number of connections and amount of memory,\nsetting up backups and restores, updating to newer versions — preferably with no down time.\nI, as an application programmer, would prefer to leave that to experts.\nFortunately, hosting providers are even more likely to offer managed databases than managed Kubernetes.\nDigitalOcean is no exception, offering managed PostgresQL v13–16.\nIt's automatically backed-up daily, and restores, updates and scaling can all happen without down time.</p>\n<p>Hubs still encodes passwords using MD5, and PostgresQL v13 is the last version that uses MD5 by default.\n(MD5 is no longer considered secure.)\nFortunately, DigitalOcean still offers v13.\n(Hubs needs to update its password encoding before v13 reaches end-of-life on 2025-11-13.)</p>\n<p>Another advantage of managed databases is monitoring.\nDigitalOcean provides the most important metrics automatically:</p>\n<div class=\"center-horizontal\">\n<picture><source type=\"image/avif\" srcset=\"https://hominidsoftware.com/img/managed-database-metrics-DigitalOcean-739w.avif 739w\" sizes=\"100vw\"><source type=\"image/webp\" srcset=\"https://hominidsoftware.com/img/managed-database-metrics-DigitalOcean-739w.webp 739w\" sizes=\"100vw\"><img alt=\"Managed database metrics on DigitalOcean\" loading=\"lazy\" decoding=\"async\" src=\"https://hominidsoftware.com/img/managed-database-metrics-DigitalOcean-739w.png\" width=\"739\" height=\"1763\"></picture>\n</div>\nI only need to understand these enough to know when my database is overloaded.\n<p>A downside of moving the database outside the Kubernetes cluster is that the database and cluster need to\nbe scaled up (and paid for) separately. Kubernetes can autoscale, but the database cannot.\nMy database costs $15.00/month, raising my costs 63%.\nAlso, the database configuration is no longer part of the Kubernetes template files, so I have to\nkeep track of it separately.</p>\n<h2 id=\"configuration\" tabindex=\"-1\">Configuration <a class=\"header-anchor\" href=\"https://hominidsoftware.com/tech-personal-growth/Hubs-Managed-Databse/Hubs-Managed-Database/#configuration\">#</a></h2>\n<p>Once the database was up, I had to figure out how to configure Hubs to use it.\nThere are several strategies, depending on whether you continue to use the <code>pgbouncer</code> and <code>pgbouncer-t</code>\ndeployments for database connection pooling.\nPgbouncer (the software itself) is normally a transparent proxy, so you just need to change the connection parameters on the client.</p>\n<h3 id=\"change-database-only\" tabindex=\"-1\">Change Database Only <a class=\"header-anchor\" href=\"https://hominidsoftware.com/tech-personal-growth/Hubs-Managed-Databse/Hubs-Managed-Database/#change-database-only\">#</a></h3>\n<p>Mike Morran from Mozilla gave a demonstration on <a href=\"https://www.youtube.com/watch?v=ShQqXGjB0qo\">Persistent Volumes and External Database - Community Edition Setup Session</a> (the database info isn't until the last 20 minutes).\nThere, he shows how to edit <code>hcce.yaml</code> to direct <code>pgbouncer</code> and <code>pgbouncer-t</code> to an external database.\nIt was hard to extract exactly what you do, but my notes say it's something like:</p>\n<p>point pgbouncer to external SQL DB in hcce.yaml (change password in multiple places)</p>\n<ol>\n<li>change password:\n<ol>\n<li>change stringData.PGRST_DB_URI</li>\n<li>change stringData.DB_USER ?</li>\n<li>change stringData.DB_PASS; ensure URI encoded properly.\npostgresql://username:password@host:port/database?application_name=myapp</li>\n<li>change stringData.PSQL</li>\n</ol>\n</li>\n<li>in pgbouncer &amp; pgbouncer-t change value of &quot;DB_HOST&quot; from &quot;pgsql&quot; to private IP addr of PostgresQL</li>\n<li>? delete pgsql deployment &amp; service?</li>\n<li>? comment out pgsql deployment &amp; service?</li>\n<li>apply hcce.yaml</li>\n<li>check logs of pgbouncer</li>\n</ol>\n<p>He also assumes PostgresQL is using its usual port, 5432, and you can use the <code>postgres</code> superuser account\nin PostgresQL.  (On DigitalOcean managed PostgresQL the <code>postgres</code> superuser is used only for management.)</p>\n<p>This is the approach to take if your provider does not offer managed connection pooling. Google Cloud is one such.</p>\n<h3 id=\"change-database-and-connection-pools\" tabindex=\"-1\">Change Database &amp; Connection Pools <a class=\"header-anchor\" href=\"https://hominidsoftware.com/tech-personal-growth/Hubs-Managed-Databse/Hubs-Managed-Database/#change-database-and-connection-pools\">#</a></h3>\n<p>DigitalOcean offers connection pooling for free with a managed database.\nThat sounded more observable, and possibly higher performance.\nThey use pgbouncer also, so I dove into <code>hcce.yaml</code> to extract the parameters.\nLargely, they use the default values, so the connection pools each will use up to 20 database connections\nand support up to 10,000 client connections. They are not configured to use TLS (aka SSL).\n<code>pgbouncer</code> uses the default session mode and <code>pgbouncer-t</code> uses transaction mode, hence the names\n(and the reason there are two connection pools).</p>\n<p>The cheapest managed PostgresQL has 22 connections available for apps.\nThe Reticulum configuration that uses <code>pgbouncer-t</code> has a parameter <code>pool_size</code> of 10\n(it's not clear what this refers to).\nI created two connection pools using the Digital Ocean UI.\nThe one using transaction mode I named <code>retpooltransaction</code> and set to use 10 connections.\nThe one using session mode I named <code>retpoolsession</code> and set to use the other 12 available connections.\nBoth are reached on port 25061, and require TLS (aka SSL),\nso I needed to set the hostname, port and database name (the name of the pool) separately.\n<code>input-values.yaml</code> only has parameters for <code>DB_HOST</code> and <code>DB_HOST_T</code>, and <code>PGRST_DB_URI</code>\nand <code>PSQL</code> didn't use all the parameters needed,\nso I edited <code>input-values.yaml</code> and\n<code>generate_script/hcce.yam</code> to have all these parameters:</p>\n<pre class=\"language-yaml\" tabindex=\"0\"><code class=\"language-yaml\"><span class=\"token key atrule\">DB_HOST</span><span class=\"token punctuation\">:</span> <span class=\"token string\">\"private-hominid-do-user-99999999-0.m.db.ondigitalocean.com\"</span>\n<span class=\"token key atrule\">DB_PORT</span><span class=\"token punctuation\">:</span> <span class=\"token string\">\"25061\"</span>\n<span class=\"token key atrule\">DB_NAME</span><span class=\"token punctuation\">:</span> <span class=\"token string\">\"retpoolsession\"</span>\n<span class=\"token key atrule\">DB_SSL</span><span class=\"token punctuation\">:</span> <span class=\"token string\">\"true\"</span>\n<span class=\"token key atrule\">DB_SSLMODE</span><span class=\"token punctuation\">:</span> <span class=\"token string\">\"require\"</span>\n<span class=\"token key atrule\">PGRST_DB_URI</span><span class=\"token punctuation\">:</span> <span class=\"token string\">\"postgres://$DB_USER:$DB_PASS@$DB_HOST:$DB_PORT/$DB_NAME?sslmode=$DB_SSLMODE\"</span>\n<span class=\"token key atrule\">PSQL</span><span class=\"token punctuation\">:</span>         <span class=\"token string\">\"postgres://$DB_USER:$DB_PASS@$DB_HOST:$DB_PORT/$DB_NAME?sslmode=$DB_SSLMODE\"</span>\n<span class=\"token key atrule\">DB_HOST_T</span><span class=\"token punctuation\">:</span> <span class=\"token string\">\"private-hominid-do-user-99999999-0.m.db.ondigitalocean.com\"</span>\n<span class=\"token key atrule\">DB_PORT_T</span><span class=\"token punctuation\">:</span> <span class=\"token string\">\"25061\"</span>\n<span class=\"token key atrule\">DB_NAME_T</span><span class=\"token punctuation\">:</span> <span class=\"token string\">\"retpooltransaction\"</span></code></pre>\n<p>Unfortunately, <code>DB_SSL</code> is needed to furnish a boolean value, and <code>DB_SSLMODE</code> to furnish\nan enumerated value. I've submitted a <a href=\"https://github.com/Hubs-Foundation/hubs-cloud/pull/364\">pull request to add the new parameters</a>.</p>\n<p>There should also be values, analogous to <code>GENERATE_PERSISTENT_VOLUMES</code>, to enable/disable\ncreating the database deployment and service, and the connection pool deployments and services.\nThat would require editing <code>generate_script/index.js</code>, which I've been trying to avoid.</p>\n<p>I had some difficulty getting this configuration to work, so I tried a configuration\nwithout connection pools — Reticulum talking directly to the database — to validate that\nit was possible to connect.  Logs were very useful here; I repeatedly used</p>\n<pre><code>kubectl delete deploy --all\nkubectl delete pvc --all\nkubectl delete pv --all\n# delete the block storage volume and the `retdb` database\n# using the DigitalOcean UI\nkubectl apply -f hcce.yaml\nkubectl get deployments\nkubectl get pods\nkubectl logs reticulum-7798f5dbb6-9bcrw -f\nkubectl logs reticulum-7798f5dbb6-9bcrw -c postgrest -f\n</code></pre>\n<p>I didn't use <code>kubectl delete -f hcce.yaml</code>, because it deletes the load balancer, requiring\nDNS to be updated with the new IP address.\n(Despite the similar suffix, the <code>postgrest</code> container uses <code>pgbouncer</code>, not <code>pgbouncer-t</code>.)</p>\n<p>Once I had all the parameters being properly set in <code>hcce.yaml</code>, Reticulum connected to <code>retpoolsession</code>\nproperly.  However, for the other pool, even with correct parameters, I always got</p>\n<pre><code>(Postgrex.Error) ERROR 3D000 (invalid_catalog_name) database &quot;retpooltransaction&quot; does not exist\n</code></pre>\n<p>Eventually, after much thrashing, I tried renaming the transaction-mode connection pool from <code>retpooltransaction</code> to <code>retdb</code>,\nand <em>then</em> Reticulum connected properly to the transaction-mode connection pool. (The database and the connection pool are on different ports, so you can re-use the name.)\nI have no idea why this tweak is necessary.</p>\n<h2 id=\"conclusion\" tabindex=\"-1\">Conclusion <a class=\"header-anchor\" href=\"https://hominidsoftware.com/tech-personal-growth/Hubs-Managed-Databse/Hubs-Managed-Database/#conclusion\">#</a></h2>\n<p>I now have automatic daily backups for my database.\nI can now use <code>psql</code> to connect directly to the database, and run queries like</p>\n<pre><code>select hub_sid, name from hubs where entry_mode = 'allow';\n</code></pre>\n<p>or</p>\n<pre><code>select avatar_id, name from avatars where allow_remixing = 't';\n</code></pre>\n<p>to understand what's going on inside my Hubs instance.</p>\n<p>With the persistent volume separate from the node(s) (<a href=\"https://hominidsoftware.com/tech-personal-growth/Hubs-on-DigitalOcean/\">see my previous post</a>),\nI can set my Kubernetes cluster to scale up the number of nodes to handle heavier loads,\nand if the connection pools or database is then the limiting resource, I can scale that up, too.\nI can backup and archive my Hubs instance, and restore it on another provider.</p>\n<p>I have a production-ready instance of Hubs!</p>\n",
			"date_published": "2024-11-17T00:00:00Z",
			"date_modified": "2024-11-28T02:11:18Z"
		}
		,
		{
			"id": "https://hominidsoftware.com/tech-personal-growth/Hubs-on-DigitalOcean/",
			"url": "https://hominidsoftware.com/tech-personal-growth/Hubs-on-DigitalOcean/",
			"title": "Persistent Storage for Hubs on DigitalOcean",
			"summary": "Days of sifting through details produced a simple solution.",
			"content_html": "<p><a href=\"https://hominidsoftware.com/tech-personal-growth/Hubs-on-DigitalOcean/#my-final-configuration-but-see-my-next-post\">skip to solution</a></p>\n<p><em>Content warning: extremely technical — may cause drowsiness — do not read while operating heavy machinery</em></p>\n<h2 id=\"setting-up-hubs-cloud-community-edition\" tabindex=\"-1\">Setting up Hubs Cloud Community Edition <a class=\"header-anchor\" href=\"https://hominidsoftware.com/tech-personal-growth/Hubs-on-DigitalOcean/#setting-up-hubs-cloud-community-edition\">#</a></h2>\n<p>The free Hubs service from Mozilla has been shut down, along with Hubs Cloud.\nFortunately, the Community Edition of Hubs Cloud is now straightforward to set up.\nThe number of steps is large, but that’s hard to avoid with a freestanding consumer-ready service.</p>\n<p>I followed the <a href=\"https://docs.hubsfoundation.org/beginners-guide-to-CE.html\">Beginner’s Guide to CE</a>, with the changes noted below.\nIt wasn’t clear that Kubernetes commands haven’t necessarily taken effect when the command exits (which is not obvious if you’re new to Kubernetes).</p>\n<p>It’s not documented in the Beginner’s Guide, but Hubs works fine with a subdomain like <code>hubs.hominidsoftware.com</code>, so I could use my existing domain.\nI was also able to configure my existing Postfix mail server to handle the new subdomain, keeping down my total infrastructure and accounts.</p>\n<p>The other trouble I ran into into trouble was getting Let’s Encrypt certificates set up.\nI had to apply <code>hcce.yaml</code> once as generated, then run the script <code>gen-ssl</code>, then edit <code>hcce.yaml</code> to comment out the flag <code>--default-ssl-certificate=hcce/cert-hcce</code> for haproxy and finally apply <code>hcce.yaml</code> again.  :-(\nThat turns out to be a known issue, in the long list of tasks for the Hubs maintainers.</p>\n<h2 id=\"operational-trouble\" tabindex=\"-1\">Operational trouble <a class=\"header-anchor\" href=\"https://hominidsoftware.com/tech-personal-growth/Hubs-on-DigitalOcean/#operational-trouble\">#</a></h2>\n<p>Originally, I set up my Kubernetes cluster to Autoscale.\n(I overlooked the step in the Beginner’s Guide which said to set Fixed scaling and only one node.)\nAll was well, until a heavy load triggered a second node to spin up.\nThe configuration for Community Edition stores avatars, resources and scenes using <code>hostPath</code> volumes — that is, files are stored on the node’s filesystem.\nTwo different nodes won’t share a filesystem, so avatars, resources and scenes were unavailable on the new node and storage became scrambled.</p>\n<p>A workaround was to change the cluster scaling type to Fixed, and only configure one node (as the Beginner’s Guide instructs).</p>\n<p>That’s the Achilles’ Heel of Community Edition: it’s not configured for production use.</p>\n<h2 id=\"persistent-storage\" tabindex=\"-1\">Persistent storage <a class=\"header-anchor\" href=\"https://hominidsoftware.com/tech-personal-growth/Hubs-on-DigitalOcean/#persistent-storage\">#</a></h2>\n<p>Unfortunately, there isn’t yet any proper documentation on persistent storage for Hubs.\nThe <a href=\"https://docs.hubsfoundation.org/system-overview.html#postgres-db\">System Overview</a> just notes there’s &quot;a postgresql database behind reticulum and a file store&quot;.\nThere is a YouTube video: <a href=\"https://www.youtube.com/watch?v=ShQqXGjB0qo\">Persistent Volumes and External Database - Community Edition Setup Session - April 24, 2024</a>.\nAfter an hour of unrelated stuff, you find out the file storage can be Google Cloud Persistent Volumes exposed as NFS.\nIt was not immediately clear to me why a StorageClass of <code>nfs</code> was chosen over <code>standard-rwo</code></p>\n<p>Digital Ocean doesn’t offer NFS for either its Volumes Block Storage or Spaces Object Storage (S3-compatible blob storage).\nSince a Kubernetes Volume is essentially a directory, I set up a bucket in Spaces Object Storage, and started reading the Kubernetes docs to find the parameters to connect.\nIt turns out, the most popular container orchestration system doesn’t natively talk the most popular mass storage protocol.\nNot what I expected.\nThere <em>are</em> <a href=\"https://github.com/awslabs/mountpoint-s3-csi-driver?tab=readme-ov-file\">Container Storage Interface (CSI) Drivers for S3</a> that you can install, but I prefer to start with a simple solution.</p>\n<p>So (as I should have done earlier), I finally searched the WWW for &quot;DigitalOcean&quot; &quot;PersistentVolume&quot;.\nDigitalOcean supports <code>csi-digitalocean</code>, a CSI for their Volumes Block Storage, which they install on all their managed clusters.\n(You can’t directly check if a CSI is installed; you have to check if its StorageClasses are available.)\nDocumentation on configuring it could be improved, but basically, in a <code>PersistentVolumeClaim</code>, you just change <code>storageClassName</code> from <code>manual</code> to <code>do-block-storage</code>.\nIf you don’t explicitly configure a matching <code>PersistentVolume</code>, one will be dynamically created.\nI commented out the <code>PersistentVolume</code> in <code>hcce.yaml</code> for <code>ret-pv</code>, the Reticulum file storage.\nThat worked, albeit the <code>PersistentVolume</code> had a Reclaim Policy of Delete, which you obviously don’t want for your permanent storage.\nI went back to the list of available StorageClasses: <code>do-block-storage</code>, <code>do-block-storage-retain</code>, <code>do-block-storage-xfs</code> and <code>do-block-storage-xfs-retain</code>, which are not really documented. <code>-retain</code> sounds like a Reclaim Policy and indeed, using <code>do-block-storage-retain</code> dynamically created a <code>PersistentVolume</code> with a Reclaim Policy of Retain.</p>\n<p>Hubs needs a PostgresQL database.\nDigitalOcean offers managed PostresQL databases.\nThe video notes that Hubs requires MD5 password encryption, which is not the default for v14 and later.\nYou can, however configure that in later versions.</p>\n<p>I was ready to spin up a manged PostgresQL database, when I remembered that Community Edition has a <code>postgresql</code> container which writes and reads to a <code>PersistenVolumeClaim</code> of its own.\nCould you just change that use DigitalOcean Block Storage?\nI had trouble getting it working, but fortunately Kubernetes is easy to debug :-)</p>\n<div class=\"center-horizontal\">\n<picture><source type=\"image/avif\" srcset=\"https://hominidsoftware.com/img/kubernetes-debug-flowchart-750w.avif 750w, https://hominidsoftware.com/img/kubernetes-debug-flowchart-1785w.avif 1785w\" sizes=\"100vw\"><source type=\"image/webp\" srcset=\"https://hominidsoftware.com/img/kubernetes-debug-flowchart-750w.webp 750w, https://hominidsoftware.com/img/kubernetes-debug-flowchart-1785w.webp 1785w\" sizes=\"100vw\"><img alt=\"A visual guide on troubleshooting Kubernetes deployments\" loading=\"lazy\" decoding=\"async\" src=\"https://hominidsoftware.com/img/kubernetes-debug-flowchart-750w.png\" width=\"1785\" height=\"2526\" srcset=\"https://hominidsoftware.com/img/kubernetes-debug-flowchart-750w.png 750w, https://hominidsoftware.com/img/kubernetes-debug-flowchart-1785w.png 1785w\" sizes=\"100vw\"></picture>\n</div>\n<p><em>Thanks to Daniele Polencic</em></p>\n<p>Setting the <code>pgsql-pvc</code> <code>PersistenVolumeClaim</code> to use the <code>do-block-storage-retain</code> StorageClass resulted in the pgsql deployment failing.\nThe pod log contained</p>\n<pre><code>initdb: error: directory &quot;/var/lib/postgresql/data&quot; exists but is not empty\nIt contains a lost+found directory, perhaps due to it being a mount point.\n</code></pre>\n<p>That check should be disabled for this case, but I had another option: using the <code>do-block-storage-xfs-retain</code> StorageClass.\n<code>-xfs</code> sounds like the XFS file system.\nWould PostgresQL be happier XFS rather than ext4?\nThe answer is yes, so both <code>PersistentVolumesClaims</code> are now <code>do-block-storage-xfs-retain</code> (for consistency), and my Hubs instance has persistent storage that’s not tied to a node!  Next, I’ll need to set up regular backups for my shiny new volumes.</p>\n<p>Unfortunately, PostgresQL is still a black box.\nFor a truly production-ready system, PostgresQL should be separate from the cluster, for easy administration and maintenance.</p>\n<h2 id=\"access-from-multiple-nodes\" tabindex=\"-1\">Access from multiple nodes? <a class=\"header-anchor\" href=\"https://hominidsoftware.com/tech-personal-growth/Hubs-on-DigitalOcean/#access-from-multiple-nodes\">#</a></h2>\n<p>Now storage can be accessed from any node — but <code>accessModes</code> <code>ReadWriteOnce</code> only allows one node at a time.\nWhen I set the mode to <code>ReadWriteMany</code>, the PersistentVolumes weren’t created.</p>\n<p>To have a cluster that can handle large meetings, I installed DO’s <a href=\"https://docs.digitalocean.com/products/marketplace/catalog/csi-for-s3/\">CSI for S3</a> and, for <code>ret-pvc</code> set</p>\n<pre><code>spec:\n  storageClassName: csi-s3\n  accessModes:\n    - ReadWriteMany\n</code></pre>\n<p>That dynamically created an S3 bucket in DigitalOcean Spaces which can be accessed from multiple nodes.\nThe Reclaim Policy was <code>Delete</code>.  It might require creating a new StorageClass manually to get a Reclaim Policy of <code>Retain</code>.</p>\n<p>It’s highly unlikely that PostgresQL would be happy with multiple instances writing to the same set of files, so I didn’t try this for <code>pgsql-pvc</code>.</p>\n<h2 id=\"increasing-storage-capacity\" tabindex=\"-1\">Increasing Storage Capacity <a class=\"header-anchor\" href=\"https://hominidsoftware.com/tech-personal-growth/Hubs-on-DigitalOcean/#increasing-storage-capacity\">#</a></h2>\n<p>DigitalOcean notes that you can increase <code>capacity.storage</code> and re-apply at any time, and the <code>PersistentVolume</code> will be re-sized.\nUnfortunately, the <em>filesystem</em> on the volume isn’t necessarily re-sized, so it might make sense to set a larger capacity from the start.\nMore research will be required. :-S</p>\n<h2 id=\"my-final-configuration-but-see-my-next-post\" tabindex=\"-1\">My Final Configuration [but see my next post!] <a class=\"header-anchor\" href=\"https://hominidsoftware.com/tech-personal-growth/Hubs-on-DigitalOcean/#my-final-configuration-but-see-my-next-post\">#</a></h2>\n<p>As I haven’t yet set up an external PostgresQL database, for simplicity and cost savings, I went back to the StorageClass of <code>do-block-storage-xfs-retain</code> for now:</p>\n<pre><code>#################################################################################\n################################# persistent volume ##################################\n######################################################################################\n#apiVersion: v1\n#kind: PersistentVolume\n#metadata:\n#  name: pgsql-pv\n#  labels:\n#    type: local\n#spec:\n#  storageClassName: manual\n#  capacity:\n#    storage: 10Gi\n#  accessModes:\n#    - ReadWriteOnce\n#  persistentVolumeReclaimPolicy: Retain\n#  claimRef:\n#    name: pgsql-pvc\n#    namespace: hcce\n#  hostPath:\n#    path: &quot;/mnt/pgsql_data&quot;\n#    type: DirectoryOrCreate\n---\n#apiVersion: v1\n#kind: PersistentVolume\n#metadata:\n#  name: ret-pv\n#  labels:\n#    type: local\n#spec:\n#  storageClassName: manual\n#  capacity:\n#    storage: 10Gi\n#  accessModes:\n#    - ReadWriteOnce\n#  persistentVolumeReclaimPolicy: Retain\n#  claimRef:\n#    name: ret-pvc\n#    namespace: hcce\n#  hostPath:\n#    path: &quot;/mnt/ret_storage_data&quot;\n#    type: DirectoryOrCreate\n---\n######################################################################################\n############################## persistent volume claim ###############################\n######################################################################################\napiVersion: v1\nkind: PersistentVolumeClaim\nmetadata:\n  name: pgsql-pvc\n  namespace: hcce\nspec:\n  storageClassName: do-block-storage-xfs-retain\n  accessModes:\n    - ReadWriteOnce\n  resources:\n    requests:\n      storage: 10Gi\n---\napiVersion: v1\nkind: PersistentVolumeClaim\nmetadata:\n  name: ret-pvc\n  namespace: hcce\nspec:\n  storageClassName: do-block-storage-xfs-retain\n  accessModes:\n    - ReadWriteOnce\n  resources:\n    requests:\n      storage: 10Gi\n---\n</code></pre>\n<h2 id=\"changing-the-hubs-default-configuration\" tabindex=\"-1\">Changing the Hubs default configuration <a class=\"header-anchor\" href=\"https://hominidsoftware.com/tech-personal-growth/Hubs-on-DigitalOcean/#changing-the-hubs-default-configuration\">#</a></h2>\n<p>StorageClasses <code>do-block-storage</code>, <code>do-block-storage-retain</code>, <code>do-block-storage-xfs</code> and <code>do-block-storage-xfs-retain</code> are unique to DigitalOcean and <code>csi-s3</code> requires installation of <code>k8s-csi-s3</code>, so you couldn’t use them in the default Community Edition configuration.\nHowever, if you don’t set the StorageClass at all, you’ll get the cluster’s default StorageClass.\nFor DigitalOcean, that’s <code>do-block-storage</code> which has a Reclaim Policy of Delete, but is more durable than <code>hostPath</code> volumes and can be backed-up and then restored to a Retained volume.\nThe default StorageClass for Google and Amazon’s managed Kubernetes is similar.</p>\n<p>If PostgresQL can be configured to not care about the <code>lost+found</code> directory, the <code>pgsql-pvc</code> <code>PersistentVolumeClaim</code> could also use the default <code>StorageClass</code>.\nOn every cloud provider I checked, the default <code>StorageClass</code> is external to nodes.\nThat would make persistent storage the default. As the Hubs configuration doesn’t constrain the number of nodes, this would avoid non-experts losing data, as I did.</p>\n<h2 id=\"addendum-10-november-2024\" tabindex=\"-1\">Addendum (10 November 2024) <a class=\"header-anchor\" href=\"https://hominidsoftware.com/tech-personal-growth/Hubs-on-DigitalOcean/#addendum-10-november-2024\">#</a></h2>\n<p>Changing the PostgresQL volume to mount higher in the filesystem hierarchy (that is, changing <code>deployment.spec.template.spec.containers[0].volumeMounts[0].mountPath</code> from <code>/var/lib/postgresql/data</code> to just <code>/var/lib/postgresql</code>) puts <code>lost+found</code> (if it exists) where PostgresQL doesn’t care.</p>\n<p>So, I submitted <a href=\"https://github.com/Hubs-Foundation/hubs-cloud/pull/363\">a pull request</a> which creates\nthe volumes using the default StorageClass, so the right thing happens automagically on any provider.\nIt also creates the <code>pgsql</code> volume with accessMode <code>ReadWriteOncePod</code>, so if someone mistakenly creates another replica of <code>pgsql</code>, the database files won’t be mangled.</p>\n",
			"date_published": "2024-10-28T00:00:00Z",
			"date_modified": "2025-05-29T19:19:23Z"
		}
		,
		{
			"id": "https://hominidsoftware.com/tech-personal-growth/webapp-install-mess/",
			"url": "https://hominidsoftware.com/tech-personal-growth/webapp-install-mess/",
			"title": "The Mess That Is Installing a WebApp",
			"summary": "Almost all platforms support installing a PWA, but prompting the user is still fragmented.",
			"content_html": "<h2 id=\"progressive-web-apps-pwas\" tabindex=\"-1\">Progressive Web Apps (PWAs) <a class=\"header-anchor\" href=\"https://hominidsoftware.com/tech-personal-growth/webapp-install-mess/#progressive-web-apps-pwas\">#</a></h2>\n<p>A persistent argument for native apps over webapps has been that webapps didn't behave like native apps.\nThey couldn't access device APIs,\nwere slow to start up and couldn't run offline,\nalways appeared in a browser window with navigation UI,\nand did not appear in the lists of running or recent apps.</p>\n<p>Now, almost all of the APIs that most apps need (such as geolocation, push messaging and Bluetooth)\nare available to webapps, often under the banner of <a href=\"https://developer.mozilla.org/en-US/docs/Web/API\">HTML5</a>.\n<a href=\"https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API/Using_Service_Workers\">Service Workers</a>,\nthe <a href=\"https://developer.mozilla.org/en-US/docs/Web/API/Cache\">Cache API</a>,\n<a href=\"https://developer.mozilla.org/en-US/docs/Web/API/Web_Storage_API\">Web Storage</a> and <a href=\"https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API\">IndexedDB</a> allow webapps to start instantly\nand run offline.\nA <a href=\"https://developer.mozilla.org/en-US/docs/Web/Progressive_web_apps/Manifest\">Web App Manifest</a> provides the OS with the info\nit needs to &quot;install&quot; the webapp, so it can appear in its own window, be listed with native apps, have a full\nset of icons, be a destination for sharing, etc.</p>\n<p>The new APIs enjoy broad support from the browser makers (with Safari trailing three to four years behind),\nalbeit not all features are implemented on all platforms.</p>\n<p>What's more, these technologies are independent, allowing webapps to implement the app-like features\nonly where they need them.  Websites that users already interact with can instantly start and run offline,\nregardless of whether they are installed, or even can be installed on a given platform.\nThat's the &quot;Progressive&quot; part.</p>\n<h2 id=\"installation\" tabindex=\"-1\">Installation <a class=\"header-anchor\" href=\"https://hominidsoftware.com/tech-personal-growth/webapp-install-mess/#installation\">#</a></h2>\n<p>While all the browser makers are positive about allowing apps to be installed in some sense, they differ\nin the user experience.</p>\n<p>Apple doesn't want webapps to compete with its App Store and their 30% cut on all content,\nso Safari makes the user illogically search in the &quot;Share&quot; menu to find &quot;Add to Home Screen&quot; on mobile\nand &quot;Add to Dock&quot; on Macs.</p>\n<p>Mozilla has also decided that installation should initiated by the user, as bookmarks always have been.\nThat is reasonable (though any website can be bookmarked, but only some can be installed) and they do little to educate users about this feature.\nThey also only implement it on Android. When Mozilla was pushing its Firefox OS, they asked developers to\nuse non-standard APIs and repackage their webapps, but now they show little interest in standards to make it easy\nto install webapps. That comes across as &quot;Not Invented Here&quot;.</p>\n<p>Google has proposed and implemented the <code>beforeinstallprompt</code> event allowing webapps to trigger a standard browser\ndialog prompting the user to install (or decline to install) the webapp.\nThis <code>beforeinstallprompt</code> event is also sanity-gated.\nThat is, the dialog is not displayed on the first visit to the webapp. Other criteria also apply, such as\n&quot;don't allow until the user has interacted with the webapp&quot; and &quot;don't prompt the user too often&quot;</p>\n<p>Given that Chromium browsers have implemented <code>beforeinstallprompt</code>\nand Firefox and Safari have definitely decided not to implement it (see https://github.com/w3c/manifest/issues/835),\nan installable webapp must implement something along the lines of:</p>\n<pre class=\"language-JavaScript\" tabindex=\"0\"><code class=\"language-JavaScript\">if (appSpecificUserEngagementDetected) {\n\tif (installPromptDeferred) { // BeforeInstallPromptEvent saying system install prompt is available\n\t\tenqueueSnackbar(`Install this webapp for easy access and a separate window.`,\n\t\t\t{callback: async () => {await installPromptDeferred.prompt(); /* ... */}});\n\t} else if (/\\b(iPad|iPhone|iPod)\\b/.test(navigator.userAgent) &&\n\t\t\t/WebKit/.test(navigator.userAgent) &&\n\t\t\t!/Edge/.test(navigator.userAgent) &&\n\t\t\t!window.MSStream) {\n\t\tenqueueSnackbar(`For easy access and a separate window, tap the share button then \"Add to Home Screen\"`);\n\t} else if (/\\b(Macintosh)\\b/.test(navigator.userAgent) &&\n\t\t\t/Safari/.test(navigator.userAgent) &&\n\t\t\t! /\\b(Chrom\\w{1,3}\\/[\\d.]+)\\b/.test(navigator.userAgent)) {\n\t\tenqueueSnackbar(`For easy access and a separate window, click the share button then \"Add to Dock\"`);\n\t} else if (/\\bMobile\\b/.test(navigator.userAgent) &&\n\t\t\t/\\b(Firefox\\/[\\d.]+)\\b/.test(navigator.userAgent) &&\n\t\t\t! /\\b(Seamonkey\\/[\\d.]+)\\b/.test(navigator.userAgent)) {\n\t\tenqueueSnackbar(`For easy access and a separate window, from the Firefox menu select \"Install\"`);\n\t}\n}</code></pre>\n<p>That is, each webapp must detect, not a feature, but the user interface for installation\n(that is, if the browser is Safari Mobile, Safari Mac, or Firefox Android), and educate the user about it.\nBrowser sniffing is notoriously unreliable, but is the only way to customize for browser UI.\nAlso, each installable webapp must write its own user education text, and preferably localize it.\nAfter all this work, the code is fragile against changes to the user interface of Safari and Firefox.</p>\n<p>A better solution would be for Safari and Firefox to provide standardized and localized user education UI.\nInstallation is unfamiliar to most users, and doesn't apply to most websites, so when better to educate users\nthan when they've engaged with an installable webapp?</p>\n<p>I have therefore proposed that Mozilla implement standardized and localized user education (a dialog)\nin Firefox Android, triggered by an API with different semantics than Google's <code>beforeinstallprompt</code>,\nbut the same signature.\nThus, almost all installable web apps would immediately take advantage of it.</p>\n<p>Please comment on <a href=\"https://connect.mozilla.org/t5/ideas/standardize-amp-localize-user-education-re-install-pwa-command/idi-p/46661\">my proposal on Mozilla Connect</a>,\nto help it gain critical mass, so Mozilla will take it seriously.\nAlas, it's not vetted yet :-( so please check again next week.</p>\n",
			"date_published": "2023-12-06T00:00:00Z",
			"date_modified": "2025-05-28T03:27:04Z"
		}
		,
		{
			"id": "https://hominidsoftware.com/tech-personal-growth/notes-in-tasks-to-tasks-in-notes/",
			"url": "https://hominidsoftware.com/tech-personal-growth/notes-in-tasks-to-tasks-in-notes/",
			"title": "From Notes-in-tasks to Tasks-in-notes",
			"summary": "",
			"content_html": "<h2 id=\"outline-tracker\" tabindex=\"-1\">Outline Tracker <a class=\"header-anchor\" href=\"https://hominidsoftware.com/tech-personal-growth/notes-in-tasks-to-tasks-in-notes/#outline-tracker\">#</a></h2>\n<p>I learned Palm webOS programming to write <a href=\"https://hominidsoftware.com/outlinetracker/index.html\"><em>Outline Tracker</em></a>, a To-Do List app.\nThe main feature was filtering to display only the tasks you could work on at the current time,\nat your current &quot;Place&quot;, and not blocked by other tasks.\nTasks could also repeat on either a strict or lax schedule, and were visible in the webOS Calendar app.\nThey also had a person responsible for them.</p>\n<p>However, items in local Projects could be toggled between Tasks with a checkbox, and Notes without.\nIn addition, each item could also have <em>content text</em>, which was only displayed when the item was expanded.</p>\n<div class=\"center-horizontal\">\n<p><img src=\"https://hominidsoftware.com/outlinetracker/visuals/content_text.png\" alt=\"screen shot showing content text\"></p>\n</div>\n<p>It could act as an outliner, importing from <a href=\"https://microformats.org/wiki/xoxo\"><em>XOXO</em></a> files.\nA Project could be all text, with no Tasks.</p>\n<p>The data model was very general, essentially a superset of all the To-Do apps I studied.\nUnfortunately, this did not lend itself to a low-friction user interface.\nCreating multiple tasks required switching between the hardware keyboard and on-screen buttons.\nNew Places could only be created in a separate screen.\nThe UI was fine for creating a few complex items, but was clunky for making a shopping list.\nIt pushed the user toward a few large Projects, instead of many small ones, which doesn't match much outside a job.\nIt also lacked an &quot;inbox&quot; where the user could quickly create a task, and later fill in the details.</p>\n<p>It also had Basecamp (now Basecamp Classic) Projects, which could be synchronized between devices.\nThese were restricted to Basecamp's more rigid data model, where lists could have context text,\nbut tasks could not. Tasks, however, could have multiple text Comments.\nIt also has text-only Messages at the top level.</p>\n<p>Other To-Do apps likewise allow text that isn't explicitly a task, in various places.</p>\n<h2 id=\"notes-together\" tabindex=\"-1\">Notes Together <a class=\"header-anchor\" href=\"https://hominidsoftware.com/tech-personal-growth/notes-in-tasks-to-tasks-in-notes/#notes-together\">#</a></h2>\n<p>After the demise of webOS, I started a line of research that eventually led to <a href=\"https://hominidsoftware.com/notes-together/\"><em>Notes Together</em></a>, a note-taking app.\nIt's marquee feature is full-text search (using Indexed DB under the hood),\neliminating the need to curate notes with categories or explicit tags.\nUsers are encouraged to toss in snippets of text or pictures and get back to whatever they were doing.\nSemantic formatting such as headings, lists, tables, block quotes and monospaced code blocks\nis retained. Styling is discarded, so pasted and user-typed text harmonize.\nSyncing with <a href=\"https://remotestorage.io/\"><em>remoteStorage</em></a> avoids compromising the data model to work with third-party software.</p>\n<p>I found myself keeping notes with lists of groceries to buy and which episodes I had seen in a TV series.\nShopping lists are entered very naturally, by typing return after every item (like all word processing apps).\nThe Unicode checkmark ✔️ was useful here, but clunky to insert.\nSo I added code for unordered and ordered checklists (<em>Task Lists</em> and <em>Sequences</em>, respectively).\nA very few clicks can paste in anything that resembles a list and transform it to a checklist.\n(Completed Tasks are moved to the bottom of the list instead of being hidden,\nso it's easy to recover from a fat-fingered tap.)\nThus, a note-taking app became a lower-friction place than a To-Do app to keep simple to-do lists.</p>\n<div class=\"center-horizontal\">\n<picture><source type=\"image/avif\" srcset=\"https://hominidsoftware.com/img/Notes-Together-Task-List-750w.avif 750w\" sizes=\"100vw\"><source type=\"image/webp\" srcset=\"https://hominidsoftware.com/img/Notes-Together-Task-List-750w.webp 750w\" sizes=\"100vw\"><img alt=\"a Task List in Notes Together\" loading=\"lazy\" decoding=\"async\" src=\"https://hominidsoftware.com/img/Notes-Together-Task-List-750w.jpeg\" width=\"750\" height=\"1334\"></picture>\n</div>\n<p>Text associated with a task is not confined to certain fields —\nyou write a document and place the checklist anywhere you like, even in a table cell.\nYou don't have to move the cursor between fields; it's all one document.</p>\n<p>Notes Together will never be able to show you <em>only</em> the tasks you can work on here-and-now,\nor <em>just</em> the tasks you're waiting on others to do.\nNor will you be able to see work errands and household errands in the same list\n(unless you keep everything in one giant list ☹).\nNor does it help you with repeating chores\n(though you can lock a note against edits, and repeatedly check and uncheck the items).\nHowever, every note has an associated Date,\nso it's possible to have a Task List for each day on which something is due\n(though then you can't see all the tasks in one list).\nLists can contain sub-lists, so Tasks can contain sub-Tasks.\n(I haven't yet written code to check an item when the last item on a sub-list is checked.)\nEvery word is indexed, so there's not a separate list of tags that the user must curate, unlike Outline Tracker.</p>\n<p>So Notes Together can't slice and dice tasks like Outline Tracker, but everything you <em>can</em> do is low-friction.\nI find it more pleasant to use to track my To-Dos.</p>\n<h2 id=\"conclusion\" tabindex=\"-1\">Conclusion <a class=\"header-anchor\" href=\"https://hominidsoftware.com/tech-personal-growth/notes-in-tasks-to-tasks-in-notes/#conclusion\">#</a></h2>\n<p>Despite starting from different places, my two apps ended up having surprisingly similar capabilities.\nEase of use turned out to be more important than the &quot;correct&quot; data model.</p>\n<p>It's said that every Unix application expands until it can read email.  Here's hoping I never reach that point. ☺︎</p>\n",
			"date_published": "2023-06-08T00:00:00Z",
			"date_modified": "2024-08-21T23:57:12Z"
		}
		,
		{
			"id": "https://hominidsoftware.com/tech-personal-growth/good-day-to-dance/",
			"url": "https://hominidsoftware.com/tech-personal-growth/good-day-to-dance/",
			"title": "Today is a Good Day to ... Dance",
			"summary": "Klaang the Klingon shows how ballet is done right",
			"content_html": "<h2 id=\"1st-position\" tabindex=\"-1\">1st Position <a class=\"header-anchor\" href=\"https://hominidsoftware.com/tech-personal-growth/good-day-to-dance/#1st-position\">#</a></h2>\n<p><picture><source type=\"image/avif\" srcset=\"https://hominidsoftware.com/img/Klaang-1st-Position-750w.avif 750w, https://hominidsoftware.com/img/Klaang-1st-Position-1500w.avif 1500w, https://hominidsoftware.com/img/Klaang-1st-Position-3024w.avif 3024w\" sizes=\"100vw\"><source type=\"undefined\" srcset=\"https://hominidsoftware.com/img/Klaang-1st-Position-750w.tiff 750w, https://hominidsoftware.com/img/Klaang-1st-Position-1500w.tiff 1500w, https://hominidsoftware.com/img/Klaang-1st-Position-3024w.tiff 3024w\" sizes=\"100vw\"><img alt=\"1st Position\" loading=\"lazy\" decoding=\"async\" src=\"https://hominidsoftware.com/img/Klaang-1st-Position-750w.webp\" width=\"3024\" height=\"4032\" srcset=\"https://hominidsoftware.com/img/Klaang-1st-Position-750w.webp 750w, https://hominidsoftware.com/img/Klaang-1st-Position-1500w.webp 1500w, https://hominidsoftware.com/img/Klaang-1st-Position-3024w.webp 3024w\" sizes=\"100vw\"></picture></p>\n<h2 id=\"2nd-position\" tabindex=\"-1\">2nd Position <a class=\"header-anchor\" href=\"https://hominidsoftware.com/tech-personal-growth/good-day-to-dance/#2nd-position\">#</a></h2>\n<p><picture><source type=\"image/avif\" srcset=\"https://hominidsoftware.com/img/Klaang-2nd-Position-750w.avif 750w, https://hominidsoftware.com/img/Klaang-2nd-Position-1500w.avif 1500w, https://hominidsoftware.com/img/Klaang-2nd-Position-3024w.avif 3024w\" sizes=\"100vw\"><source type=\"undefined\" srcset=\"https://hominidsoftware.com/img/Klaang-2nd-Position-750w.tiff 750w, https://hominidsoftware.com/img/Klaang-2nd-Position-1500w.tiff 1500w, https://hominidsoftware.com/img/Klaang-2nd-Position-3024w.tiff 3024w\" sizes=\"100vw\"><img alt=\"2nd Position\" loading=\"lazy\" decoding=\"async\" src=\"https://hominidsoftware.com/img/Klaang-2nd-Position-750w.webp\" width=\"3024\" height=\"4032\" srcset=\"https://hominidsoftware.com/img/Klaang-2nd-Position-750w.webp 750w, https://hominidsoftware.com/img/Klaang-2nd-Position-1500w.webp 1500w, https://hominidsoftware.com/img/Klaang-2nd-Position-3024w.webp 3024w\" sizes=\"100vw\"></picture></p>\n<h2 id=\"3rd-position\" tabindex=\"-1\">3rd Position <a class=\"header-anchor\" href=\"https://hominidsoftware.com/tech-personal-growth/good-day-to-dance/#3rd-position\">#</a></h2>\n<p><picture><source type=\"image/avif\" srcset=\"https://hominidsoftware.com/img/Klaang-3rd-Position-750w.avif 750w, https://hominidsoftware.com/img/Klaang-3rd-Position-1500w.avif 1500w, https://hominidsoftware.com/img/Klaang-3rd-Position-3024w.avif 3024w\" sizes=\"100vw\"><source type=\"undefined\" srcset=\"https://hominidsoftware.com/img/Klaang-3rd-Position-750w.tiff 750w, https://hominidsoftware.com/img/Klaang-3rd-Position-1500w.tiff 1500w, https://hominidsoftware.com/img/Klaang-3rd-Position-3024w.tiff 3024w\" sizes=\"100vw\"><img alt=\"3rd Position\" loading=\"lazy\" decoding=\"async\" src=\"https://hominidsoftware.com/img/Klaang-3rd-Position-750w.webp\" width=\"3024\" height=\"4032\" srcset=\"https://hominidsoftware.com/img/Klaang-3rd-Position-750w.webp 750w, https://hominidsoftware.com/img/Klaang-3rd-Position-1500w.webp 1500w, https://hominidsoftware.com/img/Klaang-3rd-Position-3024w.webp 3024w\" sizes=\"100vw\"></picture></p>\n<h2 id=\"4th-position\" tabindex=\"-1\">4th Position <a class=\"header-anchor\" href=\"https://hominidsoftware.com/tech-personal-growth/good-day-to-dance/#4th-position\">#</a></h2>\n<p><picture><source type=\"image/avif\" srcset=\"https://hominidsoftware.com/img/Klaang-4th-Position-750w.avif 750w, https://hominidsoftware.com/img/Klaang-4th-Position-1500w.avif 1500w, https://hominidsoftware.com/img/Klaang-4th-Position-3024w.avif 3024w\" sizes=\"100vw\"><source type=\"undefined\" srcset=\"https://hominidsoftware.com/img/Klaang-4th-Position-750w.tiff 750w, https://hominidsoftware.com/img/Klaang-4th-Position-1500w.tiff 1500w, https://hominidsoftware.com/img/Klaang-4th-Position-3024w.tiff 3024w\" sizes=\"100vw\"><img alt=\"4th Position\" loading=\"lazy\" decoding=\"async\" src=\"https://hominidsoftware.com/img/Klaang-4th-Position-750w.webp\" width=\"3024\" height=\"4032\" srcset=\"https://hominidsoftware.com/img/Klaang-4th-Position-750w.webp 750w, https://hominidsoftware.com/img/Klaang-4th-Position-1500w.webp 1500w, https://hominidsoftware.com/img/Klaang-4th-Position-3024w.webp 3024w\" sizes=\"100vw\"></picture></p>\n<h2 id=\"5th-position\" tabindex=\"-1\">5th Position <a class=\"header-anchor\" href=\"https://hominidsoftware.com/tech-personal-growth/good-day-to-dance/#5th-position\">#</a></h2>\n<p><picture><source type=\"image/avif\" srcset=\"https://hominidsoftware.com/img/Klaang-5th-Position-750w.avif 750w, https://hominidsoftware.com/img/Klaang-5th-Position-1500w.avif 1500w, https://hominidsoftware.com/img/Klaang-5th-Position-3024w.avif 3024w\" sizes=\"100vw\"><source type=\"undefined\" srcset=\"https://hominidsoftware.com/img/Klaang-5th-Position-750w.tiff 750w, https://hominidsoftware.com/img/Klaang-5th-Position-1500w.tiff 1500w, https://hominidsoftware.com/img/Klaang-5th-Position-3024w.tiff 3024w\" sizes=\"100vw\"><img alt=\"5th Position\" loading=\"lazy\" decoding=\"async\" src=\"https://hominidsoftware.com/img/Klaang-5th-Position-750w.webp\" width=\"3024\" height=\"4032\" srcset=\"https://hominidsoftware.com/img/Klaang-5th-Position-750w.webp 750w, https://hominidsoftware.com/img/Klaang-5th-Position-1500w.webp 1500w, https://hominidsoftware.com/img/Klaang-5th-Position-3024w.webp 3024w\" sizes=\"100vw\"></picture></p>\n<h2 id=\"demi-plie\" tabindex=\"-1\">Demi-plie <a class=\"header-anchor\" href=\"https://hominidsoftware.com/tech-personal-growth/good-day-to-dance/#demi-plie\">#</a></h2>\n<p><picture><source type=\"image/avif\" srcset=\"https://hominidsoftware.com/img/Klaang-Demi-plie-A-750w.avif 750w, https://hominidsoftware.com/img/Klaang-Demi-plie-A-1500w.avif 1500w, https://hominidsoftware.com/img/Klaang-Demi-plie-A-3024w.avif 3024w\" sizes=\"100vw\"><source type=\"undefined\" srcset=\"https://hominidsoftware.com/img/Klaang-Demi-plie-A-750w.tiff 750w, https://hominidsoftware.com/img/Klaang-Demi-plie-A-1500w.tiff 1500w, https://hominidsoftware.com/img/Klaang-Demi-plie-A-3024w.tiff 3024w\" sizes=\"100vw\"><img alt=\"Demi-plie A\" loading=\"lazy\" decoding=\"async\" src=\"https://hominidsoftware.com/img/Klaang-Demi-plie-A-750w.webp\" width=\"3024\" height=\"4032\" srcset=\"https://hominidsoftware.com/img/Klaang-Demi-plie-A-750w.webp 750w, https://hominidsoftware.com/img/Klaang-Demi-plie-A-1500w.webp 1500w, https://hominidsoftware.com/img/Klaang-Demi-plie-A-3024w.webp 3024w\" sizes=\"100vw\"></picture></p>\n<p><picture><source type=\"image/avif\" srcset=\"https://hominidsoftware.com/img/Klaang-Demi-plie-B-750w.avif 750w, https://hominidsoftware.com/img/Klaang-Demi-plie-B-1500w.avif 1500w, https://hominidsoftware.com/img/Klaang-Demi-plie-B-3024w.avif 3024w\" sizes=\"100vw\"><source type=\"undefined\" srcset=\"https://hominidsoftware.com/img/Klaang-Demi-plie-B-750w.tiff 750w, https://hominidsoftware.com/img/Klaang-Demi-plie-B-1500w.tiff 1500w, https://hominidsoftware.com/img/Klaang-Demi-plie-B-3024w.tiff 3024w\" sizes=\"100vw\"><img alt=\"Demi-plie B\" loading=\"lazy\" decoding=\"async\" src=\"https://hominidsoftware.com/img/Klaang-Demi-plie-B-750w.webp\" width=\"3024\" height=\"4032\" srcset=\"https://hominidsoftware.com/img/Klaang-Demi-plie-B-750w.webp 750w, https://hominidsoftware.com/img/Klaang-Demi-plie-B-1500w.webp 1500w, https://hominidsoftware.com/img/Klaang-Demi-plie-B-3024w.webp 3024w\" sizes=\"100vw\"></picture></p>\n<p><picture><source type=\"image/avif\" srcset=\"https://hominidsoftware.com/img/Klaang-Demi-plie-A-750w.avif 750w, https://hominidsoftware.com/img/Klaang-Demi-plie-A-1500w.avif 1500w, https://hominidsoftware.com/img/Klaang-Demi-plie-A-3024w.avif 3024w\" sizes=\"100vw\"><source type=\"undefined\" srcset=\"https://hominidsoftware.com/img/Klaang-Demi-plie-A-750w.tiff 750w, https://hominidsoftware.com/img/Klaang-Demi-plie-A-1500w.tiff 1500w, https://hominidsoftware.com/img/Klaang-Demi-plie-A-3024w.tiff 3024w\" sizes=\"100vw\"><img alt=\"Demi-plie C\" loading=\"lazy\" decoding=\"async\" src=\"https://hominidsoftware.com/img/Klaang-Demi-plie-A-750w.webp\" width=\"3024\" height=\"4032\" srcset=\"https://hominidsoftware.com/img/Klaang-Demi-plie-A-750w.webp 750w, https://hominidsoftware.com/img/Klaang-Demi-plie-A-1500w.webp 1500w, https://hominidsoftware.com/img/Klaang-Demi-plie-A-3024w.webp 3024w\" sizes=\"100vw\"></picture></p>\n<h2 id=\"battement-tendu\" tabindex=\"-1\">Battement Tendu <a class=\"header-anchor\" href=\"https://hominidsoftware.com/tech-personal-growth/good-day-to-dance/#battement-tendu\">#</a></h2>\n<p><picture><source type=\"image/avif\" srcset=\"https://hominidsoftware.com/img/Klaang-Battement-Tendu-A-750w.avif 750w, https://hominidsoftware.com/img/Klaang-Battement-Tendu-A-1500w.avif 1500w, https://hominidsoftware.com/img/Klaang-Battement-Tendu-A-3024w.avif 3024w\" sizes=\"100vw\"><source type=\"undefined\" srcset=\"https://hominidsoftware.com/img/Klaang-Battement-Tendu-A-750w.tiff 750w, https://hominidsoftware.com/img/Klaang-Battement-Tendu-A-1500w.tiff 1500w, https://hominidsoftware.com/img/Klaang-Battement-Tendu-A-3024w.tiff 3024w\" sizes=\"100vw\"><img alt=\"Battement Tendu A\" loading=\"lazy\" decoding=\"async\" src=\"https://hominidsoftware.com/img/Klaang-Battement-Tendu-A-750w.webp\" width=\"3024\" height=\"4032\" srcset=\"https://hominidsoftware.com/img/Klaang-Battement-Tendu-A-750w.webp 750w, https://hominidsoftware.com/img/Klaang-Battement-Tendu-A-1500w.webp 1500w, https://hominidsoftware.com/img/Klaang-Battement-Tendu-A-3024w.webp 3024w\" sizes=\"100vw\"></picture></p>\n<p><picture><source type=\"image/avif\" srcset=\"https://hominidsoftware.com/img/Klaang-Battement-Tendu-B-750w.avif 750w, https://hominidsoftware.com/img/Klaang-Battement-Tendu-B-1500w.avif 1500w, https://hominidsoftware.com/img/Klaang-Battement-Tendu-B-3024w.avif 3024w\" sizes=\"100vw\"><source type=\"undefined\" srcset=\"https://hominidsoftware.com/img/Klaang-Battement-Tendu-B-750w.tiff 750w, https://hominidsoftware.com/img/Klaang-Battement-Tendu-B-1500w.tiff 1500w, https://hominidsoftware.com/img/Klaang-Battement-Tendu-B-3024w.tiff 3024w\" sizes=\"100vw\"><img alt=\"Battement Tendu B\" loading=\"lazy\" decoding=\"async\" src=\"https://hominidsoftware.com/img/Klaang-Battement-Tendu-B-750w.webp\" width=\"3024\" height=\"4032\" srcset=\"https://hominidsoftware.com/img/Klaang-Battement-Tendu-B-750w.webp 750w, https://hominidsoftware.com/img/Klaang-Battement-Tendu-B-1500w.webp 1500w, https://hominidsoftware.com/img/Klaang-Battement-Tendu-B-3024w.webp 3024w\" sizes=\"100vw\"></picture></p>\n<h2 id=\"pirouette\" tabindex=\"-1\">Pirouette <a class=\"header-anchor\" href=\"https://hominidsoftware.com/tech-personal-growth/good-day-to-dance/#pirouette\">#</a></h2>\n<p><picture><source type=\"image/avif\" srcset=\"https://hominidsoftware.com/img/Klaang-Pirouette-A-750w.avif 750w, https://hominidsoftware.com/img/Klaang-Pirouette-A-1500w.avif 1500w, https://hominidsoftware.com/img/Klaang-Pirouette-A-3024w.avif 3024w\" sizes=\"100vw\"><source type=\"undefined\" srcset=\"https://hominidsoftware.com/img/Klaang-Pirouette-A-750w.tiff 750w, https://hominidsoftware.com/img/Klaang-Pirouette-A-1500w.tiff 1500w, https://hominidsoftware.com/img/Klaang-Pirouette-A-3024w.tiff 3024w\" sizes=\"100vw\"><img alt=\"Pirouette A\" loading=\"lazy\" decoding=\"async\" src=\"https://hominidsoftware.com/img/Klaang-Pirouette-A-750w.webp\" width=\"3024\" height=\"4032\" srcset=\"https://hominidsoftware.com/img/Klaang-Pirouette-A-750w.webp 750w, https://hominidsoftware.com/img/Klaang-Pirouette-A-1500w.webp 1500w, https://hominidsoftware.com/img/Klaang-Pirouette-A-3024w.webp 3024w\" sizes=\"100vw\"></picture></p>\n<p><picture><source type=\"image/avif\" srcset=\"https://hominidsoftware.com/img/Klaang-Pirouette-B-750w.avif 750w, https://hominidsoftware.com/img/Klaang-Pirouette-B-1500w.avif 1500w, https://hominidsoftware.com/img/Klaang-Pirouette-B-3024w.avif 3024w\" sizes=\"100vw\"><source type=\"undefined\" srcset=\"https://hominidsoftware.com/img/Klaang-Pirouette-B-750w.tiff 750w, https://hominidsoftware.com/img/Klaang-Pirouette-B-1500w.tiff 1500w, https://hominidsoftware.com/img/Klaang-Pirouette-B-3024w.tiff 3024w\" sizes=\"100vw\"><img alt=\"Pirouette B\" loading=\"lazy\" decoding=\"async\" src=\"https://hominidsoftware.com/img/Klaang-Pirouette-B-750w.webp\" width=\"3024\" height=\"4032\" srcset=\"https://hominidsoftware.com/img/Klaang-Pirouette-B-750w.webp 750w, https://hominidsoftware.com/img/Klaang-Pirouette-B-1500w.webp 1500w, https://hominidsoftware.com/img/Klaang-Pirouette-B-3024w.webp 3024w\" sizes=\"100vw\"></picture></p>\n<p><picture><source type=\"image/avif\" srcset=\"https://hominidsoftware.com/img/Klaang-Pirouette-C-750w.avif 750w, https://hominidsoftware.com/img/Klaang-Pirouette-C-1500w.avif 1500w, https://hominidsoftware.com/img/Klaang-Pirouette-C-3024w.avif 3024w\" sizes=\"100vw\"><source type=\"undefined\" srcset=\"https://hominidsoftware.com/img/Klaang-Pirouette-C-750w.tiff 750w, https://hominidsoftware.com/img/Klaang-Pirouette-C-1500w.tiff 1500w, https://hominidsoftware.com/img/Klaang-Pirouette-C-3024w.tiff 3024w\" sizes=\"100vw\"><img alt=\"Pirouette C\" loading=\"lazy\" decoding=\"async\" src=\"https://hominidsoftware.com/img/Klaang-Pirouette-C-750w.webp\" width=\"3024\" height=\"4032\" srcset=\"https://hominidsoftware.com/img/Klaang-Pirouette-C-750w.webp 750w, https://hominidsoftware.com/img/Klaang-Pirouette-C-1500w.webp 1500w, https://hominidsoftware.com/img/Klaang-Pirouette-C-3024w.webp 3024w\" sizes=\"100vw\"></picture></p>\n<p><picture><source type=\"image/avif\" srcset=\"https://hominidsoftware.com/img/Klaang-Pirouette-D-750w.avif 750w, https://hominidsoftware.com/img/Klaang-Pirouette-D-1500w.avif 1500w, https://hominidsoftware.com/img/Klaang-Pirouette-D-3024w.avif 3024w\" sizes=\"100vw\"><source type=\"undefined\" srcset=\"https://hominidsoftware.com/img/Klaang-Pirouette-D-750w.tiff 750w, https://hominidsoftware.com/img/Klaang-Pirouette-D-1500w.tiff 1500w, https://hominidsoftware.com/img/Klaang-Pirouette-D-3024w.tiff 3024w\" sizes=\"100vw\"><img alt=\"Pirouette D\" loading=\"lazy\" decoding=\"async\" src=\"https://hominidsoftware.com/img/Klaang-Pirouette-D-750w.webp\" width=\"3024\" height=\"4032\" srcset=\"https://hominidsoftware.com/img/Klaang-Pirouette-D-750w.webp 750w, https://hominidsoftware.com/img/Klaang-Pirouette-D-1500w.webp 1500w, https://hominidsoftware.com/img/Klaang-Pirouette-D-3024w.webp 3024w\" sizes=\"100vw\"></picture></p>\n",
			"date_published": "2023-06-02T00:00:00Z",
			"date_modified": "2024-08-21T23:57:12Z"
		}
		,
		{
			"id": "https://hominidsoftware.com/tech-personal-growth/croquet-os-and-aframe/",
			"url": "https://hominidsoftware.com/tech-personal-growth/croquet-os-and-aframe/",
			"title": "Multiuser WebXR using Croquet OS &amp; A-Frame",
			"summary": "There&#39;s a new network option for A-Frame",
			"content_html": "<p><em>Croquet OS</em> (then <a href=\"https://multisynq.io/\"><em>Multisynq</em></a>, now <a href=\"https://forerunnerprotocol.xyz/\"><em>Forerunner</em></a>) is real-time synchronization-as-a-service (and not restricted to WebXR). You don't run your own synchronization server; large traffic volumes require payment.\n[Update: <a href=\"https://github.com/croquet/croquet#croquet-\">The original Croquet is now open-source</a>, and you can choose to run your own reflector, to be independent of the Forerunner network.]</p>\n<p>Croquet does <em>not</em> handle voice nor text chat, though you <em>could</em> write a text chat feature using it.\nThus, Croquet is good for writing tools which augment other multiuser experiences.\nFor a full, standalone immersive multi-user experience, it may be less effort to extend some other technology, such as writing a <a href=\"https://docs.hubsfoundation.org/dev-client-basics\">custom Hubs client</a>.</p>\n<p>Croquet is designed around keeping state in its own Model objects, which have a number of restrictions so each client maintains a bit-identical simulation.\nWeb apps which keep all state and modeling in Croquet Models avoid the who-grabbed-it-first problem.</p>\n<p>Croquet has Views to handle display and user input, which can differ between users. They mediate between Models and the rest of your code.</p>\n<p>Croquet keeps snapshots on the network, so sessions can be resumed, even if no clients are still online. (Unlike networked-aframe, if I understand it correctly.)\nCroquet has its <em>Worldcore</em> library to handle scene graph, position, rotation, etc. Worldcore can render using their <em>webgl</em> package or Three.js. Croquet packages cover most, but not all, of what Three.js does. There is no directory of third-party components available for use.</p>\n<p><a href=\"https://aframe.io/\">A-Frame</a> maintains a scene graph using Three.js, so you won't use Worldcore with A-Frame. You can the <a href=\"https://github.com/NikolaySuslov/aframe-croquet-component\">A-Frame Croquet Component</a> to synchronize the attributes of A-Frame entities</p>\n<p>Off-the-shelf A-Frame components maintain state internally. When user input or world modeling (such as collision detection) happens in A-Frame, a synthetic DOM event must be emitted for a View to receive. Typically, the View will need to publish a message to one or more Models. The message must be sent over the network to every client. The Model(s) (on each client) would typically publish a message to other Models or their Views, and the View(s) (on each client) will set attributes on A-Frame objects. This can make debugging tedious, but delay comes mainly from the network.</p>\n<p>You could rewrite A-Frame components to keep state in Croquet Models, but at that point it may make more sense to switch to Worldcore.</p>\n<p>The <a href=\"https://www.npmjs.com/package/aframe-state-component\">A-Frame State Component</a> provides a centralized store for state data. An analogous component with similar syntax could be written for Croquet, but that hasn't happened yet.</p>\n<p>The <a href=\"https://github.com/NikolaySuslov/aframe-croquet-component\">A-Frame Croquet Component</a> allows a world to define an <a href=\"https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/template\">HTML Template</a> for user avatars. A different <code>color</code> attribute is applied to each user's avatar.\nMost primitives (including <a href=\"https://aframe.io/docs/1.7.0/components/gltf-model.html\">gltf-model</a>) don't use <code>color</code>, so the A-Frame Croquet Component will attempt to tint their materials, using the <code>color</code> attribute.</p>\n<p><a href=\"https://xalot.surge.sh/\" title=\"Xalot world\"><picture><source type=\"image/avif\" srcset=\"https://hominidsoftware.com/img/xalot-world-747w.avif 747w\" sizes=\"100vw\"><source type=\"image/webp\" srcset=\"https://hominidsoftware.com/img/xalot-world-747w.webp 747w\" sizes=\"100vw\"><img alt=\"Xalot world\" loading=\"lazy\" decoding=\"async\" src=\"https://hominidsoftware.com/img/xalot-world-747w.png\" width=\"747\" height=\"513\"></picture></a></p>\n<p>For other users to join the <em>same</em> session, a current user must share the URL, including the query string.</p>\n<p>Croquet Models are typically synced 20 times per second, not coupled to A-Frame <code>tick()</code>. That's fine for low-speed syncing, for example, seeing which way another player's avatar is facing. That's also fine for detecting whether a moving object collides with a stationary object. A-Frame collision detection will not be coupled to Croquet syncing, so high-speed simulation will have issues. For example, calculating if one player's fireball collides with the other player's dodging avatar will depend on which client the calculation is done. Likewise, one client might calculate that one player had grabbed some object first, while another client might calculate that another player had grabbed it first.</p>\n<p>A number of edge cases have to be dealt with</p>\n<ul>\n<li>Some attribute types could be serialized, but code still needs to be added to aframe-croquet-component.</li>\n<li>A-Frame components may have non-serializable attributes. HTMLElements are not serializable, so their ID is saved instead. Other non-serializable attributes will cause errors.</li>\n<li>Procedural generation of a world requires waiting until random seeds can be obtained from a model (as only Croquet Models can generate the same random number sequence on every client).</li>\n</ul>\n<p>It's easy to <a href=\"https://github.com/NikolaySuslov/aframe-croquet-component#how-to-share-an-entity-in-an-a-frame-scene-with-other-users\">throw together a multi-user experience</a> using existing A-Frame components and your A-Frame expertise. However, as an immature library, you might have to code and submit a PR to get advanced capabilities. And it may not be the best choice for an action game or polished experience.</p>\n<p>See also this <a href=\"https://aframe.wiki/en/#!pages/multiuser.md#Comparison_Table\">Comparison of Croquet with Networked A-Frame and Mozilla Hubs</a>.</p>\n",
			"date_published": "2023-04-25T00:00:00Z",
			"date_modified": "2026-05-12T14:42:49Z"
		}
		,
		{
			"id": "https://hominidsoftware.com/tech-personal-growth/civil-cold-war/",
			"url": "https://hominidsoftware.com/tech-personal-growth/civil-cold-war/",
			"title": "Civil Cold War",
			"summary": "Political polarization will continue for a long time",
			"content_html": "<p>If a post on politics is not what you’re up for, feel free to ignore this.</p>\n<p>I write assuming Biden will win and be able to take office.</p>\n<p>Despite this, the plain fact remains that a very large minority of American are okay with supporting a candidate who openly attacks democracy, the rule of law, and civil rights. 2016 was not an aberration. The evidence is there, but it does not shift their votes. More people have voted for Trump than in 2016. America is not the country we thought it was. Nor is there much motivation for Republican leadership to change much. Why change what very nearly worked?</p>\n<p>Thus, we face the very high likelihood of continued political polarization, leaving the Federal government unable to act effectively against danger from without and within and degrading what professionalism there is.</p>\n<p>What do you call that situation? I call it a Civil Cold War.</p>\n<p>Of course, there are many differences between the world in the second half of the 20th century and America today. Not least is that the world was never united in one society and government beforehand.</p>\n<p>I do not take the Cold War as a blueprint for what will happen to America, but I do look to it for patterns that may recur.</p>\n<p>One pattern to recall is that most people in “Communist” countries were basically decent people who valued the services provided them by their government without endorsing all of its activities. Government propaganda was able to drown out Western messages, without the help of Facebook’s individual profiles.</p>\n<p>Another pattern is the use of disinformation and rigged elections over naked force.  “Communist” leaders knew the danger of open warfare.</p>\n",
			"date_published": "2020-11-04T00:00:00Z",
			"date_modified": "2023-04-20T20:31:14Z"
		}
		,
		{
			"id": "https://hominidsoftware.com/tech-personal-growth/architecture-webvr-discovery/",
			"url": "https://hominidsoftware.com/tech-personal-growth/architecture-webvr-discovery/",
			"title": "A User-Empowering Architecture for WebVR Discovery",
			"summary": "A better way to find VR &amp; AR content on the Web is needed.",
			"content_html": "<p>Currently, it’s hard to browse the VR web. Sites are available over HTTP but hard to find. If you know the URL, you can laboriously type it in on a virtual keyboard, but that’s not something most users are willing to do.</p>\n<p>Search using existing web crawlers is possible, but typing fewer characters than a URL is only less annoying, not really low friction. Voice search is possible in low-noise environments, but presents privacy issues, even if speech recognition is done on-device. Current web crawlers also lack a filter for VR and/or 360 content.</p>\n<p>Another possibility is presenting the user with multiple feeds of content. This is the approach taken by Oculus. However, given Facebook’s history, a substantial number of users will not trust Oculus to work in their best interest, or treat content outside the Facebook ecosystem equally.</p>\n<p>The feed approach could satisfy users concerned about privacy and control if the user could control what sources were used to generate the feeds. RSS feeds would be ideal. <a href=\"https://vrsites.com/\">WebXR experiences\n(Meta Quest tested)</a> <a href=\"https://webvr.directory/\">WebVR Directory by Supermedium</a> <a href=\"https://experiments.withgoogle.com/collection/webvr\">Experiments with Google</a> and <a href=\"https://acerwebvr.github.io/\">Acer WebVR Start Page</a> are websites that curate WebVR experiences. <a href=\"https://aframe.io/blog/\">A-Frame Blog</a> is a blog collecting projects, tools, and events related to the A-Frame framework.</p>\n<p>Scraping summaries from web pages that reference WebVR content is possible, but fragile. Feed items could be generated from site metadata, including Open Graph Protocol and oEmbed. Something along the lines of Slack’s Unfurl Cascade is probably best.</p>\n<p>Identifying links to WebVR sites is a bit tricky - there is no Open Graph type for WebVR. For the general case you’d need to run enough JavaScript to detect usage of WebVR APIs. Some shortcuts are possible, such as looking for script tags for WebVR frameworks. Distinguishing 360 photo or video content from full VR may not be generally possible. Identifying other content of interest is even trickier to do on the fly.</p>\n<p>There should be straightforward UI to add and remove sources. It might or might not make sense to take a user’s Favorites as sources.</p>\n<p>The UI should present at least two composite feeds - one of liked content the user can return to, and another of new items.</p>\n<p>Finally, the system should order items using an estimation of how well the user will like the content. Framerate, number of page crashes and time-on-page could be tracked. Some tweaking should be possible - perhaps giving a simple thumb-up or thumb-down on each item of content. A headset that can run VR ought to be able to crunch a fair amount of data, to predict what a user most wants.</p>\n",
			"date_published": "2019-03-29T00:00:00Z",
			"date_modified": "2023-04-26T12:50:58Z"
		}
		,
		{
			"id": "https://hominidsoftware.com/tech-personal-growth/buying-lion-online/",
			"url": "https://hominidsoftware.com/tech-personal-growth/buying-lion-online/",
			"title": "Buying OS X Lion Online",
			"summary": "Apple&#39;s much-touted concern with user experience was not in evidence",
			"content_html": "<p>Steps:</p>\n<ol>\n<li>&quot;buy&quot; from Apple store</li>\n<li>receive &quot;order is being processed&quot; email the next day</li>\n<li>receive &quot;shipment notification&quot; email, the day after that</li>\n<li>receive &quot;order is being processed&quot; email, the day after that</li>\n<li>receive email with password for a PDF file allegedly attached to another email [do not receive any PDF]</li>\n<li>call phone number in email</li>\n<li>phone system repeatedly fails to understand my request to &quot;re-send license PDF&quot;</li>\n<li>phone system refuses to proceed withou &quot;web order number&quot; [not present in email]</li>\n<li>Dig up Apple ID password</li>\n<li>Go through dozens of screens on store to find the only order I've placed in years, with its order number</li>\n<li>call phone number again</li>\n<li>enter order number</li>\n<li>eventually get redirected to human, who gives me the actual license code</li>\n<li>open Mac App Store</li>\n<li>attempt to find &quot;Redeem&quot; link or &quot;Quick Links&quot; section it's allegedly in; fail to find it in tool bar or menus</li>\n<li>click through all toolbar items</li>\n<li>try &quot;view my account&quot; menu item</li>\n<li>be required to approve new 17-page terms of service</li>\n<li>eventually fine &quot;redeem&quot; link in the &quot;Featured&quot; section (because when redeeming a purchase, you want to be dunned to buy more)</li>\n<li>enter license code</li>\n<li>App Store tells me it's downloading, but provides no further feedback</li>\n<li>select &quot;Check for unfinished downloads&quot; under Store menu</li>\n<li>re-enter Apple ID password entered a few minutes ago</li>\n<li>App Store displays progress bar indicating download will take 35 minutes more</li>\n</ol>\n<p>How is this supposed to be more convenient than them mailing me a DVD?</p>\n",
			"date_published": "2014-08-24T00:00:00Z",
			"date_modified": "2024-08-10T22:18:11Z"
		}
		,
		{
			"id": "https://hominidsoftware.com/tech-personal-growth/designing-webapps-multiple-devices/",
			"url": "https://hominidsoftware.com/tech-personal-growth/designing-webapps-multiple-devices/",
			"title": "Designing Web Apps For Multiple Devices",
			"summary": "A guest post on the Mozilla Hacks blog, in Apps and Mobile",
			"content_html": "<p><em>Originally appeared on the <a href=\"https://hacks.mozilla.org/2013/11/designing-web-apps-for-multiple-devices/\">Mozilla Hacks blog</a></em></p>\n<p>Before 2010, there were few devices on the Web other than smartphones and desktop/laptop computers. Developers could assume phone users had a small screen, low bandwidth and used a webapp for brief moments. Desktop users were assumed to have a large screen, high bandwidth and spend large amounts of time within an application.</p>\n<p>Designing a webapp now means designing for 2014 and beyond, where users buy giant phones, phablets and tablets in many sizes. 4G connections may be faster than DSL or the throttled Wi-Fi at a coffee-shop. A number of laptop and “all-in-one” computers have touchscreens. Users may spend an evening hour on the couch with a tablet. And it was never true that all desktop users wanted apps to take up their whole screen – writing an e-mail or report often requires consulting another app, which ought to be content with half the screen.</p>\n<p>Segmenting users by device today typically leads to bad assumptions for large minorities. Users use multiple devices throughout the day and dislike learning different interaction patterns for different devices. Apple’s “Back to the Mac” initiative sought to bring smartphone features to OS X, and Windows 8 and Ubuntu Unity strive to have a single experience from phones to desktops.</p>\n<h2 id=\"app-examples\" tabindex=\"-1\">App examples <a class=\"header-anchor\" href=\"https://hominidsoftware.com/tech-personal-growth/designing-webapps-multiple-devices/#app-examples\">#</a></h2>\n<p>It is difficult to achieve a good user experience for all devices and screen sizes, as seen by the criticism of Windows 8 and Apple's “Back to the Mac” initiative. It <em>can</em> be done for a range of devices, especially by new apps unburdened by legacy expectations. I present here two web apps optimized for smartphones through desktops (but not “smart” TVs, feature phones nor smartwatches): a photo gallery and a memo app.</p>\n<h3 id=\"photo-gallery\" tabindex=\"-1\">Photo gallery <a class=\"header-anchor\" href=\"https://hominidsoftware.com/tech-personal-growth/designing-webapps-multiple-devices/#photo-gallery\">#</a></h3>\n<p>The photo gallery is half of a photo sharing app. <s><a href=\"http://hominidsoftware.com:1234/\">A sample album of the gallery</a> can be seen online.</s> (<a href=\"https://hominidsoftware.com/zapphotoshare/index.html\">The application described as a whole</a> is worth seeing.)</p>\n<p><picture><source type=\"image/avif\" srcset=\"https://hominidsoftware.com/img/ss_tablet_en_3_1.1.9-750w.avif 750w, https://hominidsoftware.com/img/ss_tablet_en_3_1.1.9-1024w.avif 1024w\" sizes=\"100vw\"><source type=\"image/webp\" srcset=\"https://hominidsoftware.com/img/ss_tablet_en_3_1.1.9-750w.webp 750w, https://hominidsoftware.com/img/ss_tablet_en_3_1.1.9-1024w.webp 1024w\" sizes=\"100vw\"><img alt=\"photo gallery: thumbnail grid\" loading=\"lazy\" decoding=\"async\" src=\"https://hominidsoftware.com/img/ss_tablet_en_3_1.1.9-750w.png\" width=\"1024\" height=\"768\" srcset=\"https://hominidsoftware.com/img/ss_tablet_en_3_1.1.9-750w.png 750w, https://hominidsoftware.com/img/ss_tablet_en_3_1.1.9-1024w.png 1024w\" sizes=\"100vw\"></picture></p>\n<p>The photo gallery follows the paradigm used by a number of prior photo browsing apps. Thumbnails are presented in a grid which scrolls vertically. The number and width of columns depends on the screen width. Grid cells could be small or large; I chose the minimum cell size to be the smallest common screen width for smartphones: 320 CSS pixels. Thus, the number of columns is <code>floor(windowWidth / 320)</code> and the cell size is <code>windowWidth / number of columns</code>. Columns normally are from 320 to 639 pixels wide.</p>\n<table>\n<thead>\n<tr>\n<th>Window Width</th>\n<th style=\"text-align:center\"># Columns</th>\n<th>Typical Device</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>320-639</td>\n<td style=\"text-align:center\">1</td>\n<td>phone/phablet (portrait)</td>\n</tr>\n<tr>\n<td>640-959</td>\n<td style=\"text-align:center\">2</td>\n<td>phablet (landscape), tablet (portrait)</td>\n</tr>\n<tr>\n<td>960-1279</td>\n<td style=\"text-align:center\">3</td>\n<td>tablet (landscape)</td>\n</tr>\n<tr>\n<td>1280-</td>\n<td style=\"text-align:center\">4</td>\n<td>laptop, desktop</td>\n</tr>\n</tbody>\n</table>\n<p>The number of columns is capped at four, so scrolling doesn’t outpace data transfer.</p>\n<p>One approach would use fixed size thumbnails of 300×300 and increase the padding as cells get larger. However, the image library available (libjpeg) only supports half-, quarter- and eighth-size reductions, so padding is fixed and images are resized to fill. The web app requests a photo of appropriate size and the server (written in node.js, and normally running on a phone) returns the smallest version of the photo that fills the requested size cell.</p>\n<p><picture><source type=\"image/avif\" srcset=\"https://hominidsoftware.com/img/ss_tablet_en_4_1.1.9-750w.avif 750w, https://hominidsoftware.com/img/ss_tablet_en_4_1.1.9-1024w.avif 1024w\" sizes=\"100vw\"><source type=\"image/webp\" srcset=\"https://hominidsoftware.com/img/ss_tablet_en_4_1.1.9-750w.webp 750w, https://hominidsoftware.com/img/ss_tablet_en_4_1.1.9-1024w.webp 1024w\" sizes=\"100vw\"><img alt=\"photo gallery: carousel\" loading=\"lazy\" decoding=\"async\" src=\"https://hominidsoftware.com/img/ss_tablet_en_4_1.1.9-750w.png\" width=\"1024\" height=\"768\" srcset=\"https://hominidsoftware.com/img/ss_tablet_en_4_1.1.9-750w.png 750w, https://hominidsoftware.com/img/ss_tablet_en_4_1.1.9-1024w.png 1024w\" sizes=\"100vw\"></picture></p>\n<p>Tapping on a thumbnail switches to a carousel which fills the window. The user can zoom in further by double-tapping the image or using the mousewheel. Originally, full-screen mode was engaged when the carousel was displayed; however, changing to full-screen takes several seconds on many devices, so now full-screen mode must be manually set. Touchscreen users can swipe to navigate forward and backward, while desktop users can use the keyboard. A weakness is that a mouse user can click on a picture to navigate forward, but must swipe (or use the keyboard) to navigate backward. Mouse users could benefit from visible navigation buttons, but mice aren’t easy for a web app to detect.</p>\n<p>Switching modes from the thumbnail gallery to the carousel and back is easy on any device. This supports the typical scenario of: user skims thumbnails to photo of interest, taps to enlarge, uses carousel to go through related photos, and returns to thumbnails. Users can navigate a substantial number of photos the same way on any device. A larger screen is shows more thumbnails at once and more detail on individual photos, but interaction is the same.</p>\n<p>Development was eased by creative use of the List widget of Enyo 2 (though any list widget could have been used). Application code sizes the cells and fills each row with 1-4 thumbnails, while the List widget handles creating and re-using DOM elements. The carousel is Enyo’s ImageCarousel, which is designed from the ground up to run well on multiple types of devices.</p>\n<h3 id=\"memo-app-serene-notes\" tabindex=\"-1\">Memo app (Serene Notes) <a class=\"header-anchor\" href=\"https://hominidsoftware.com/tech-personal-growth/designing-webapps-multiple-devices/#memo-app-serene-notes\">#</a></h3>\n<p>The second example is a deceptively simple memo app, which can be <a href=\"https://serenenotes.hominidsoftware.com/\">used on-line</a> <s>or installed on Firefox OS from the Marketplace</s>.</p>\n<p><picture><source type=\"image/avif\" srcset=\"https://hominidsoftware.com/img/Memos_ss_phab_land_2col-750w.avif 750w, https://hominidsoftware.com/img/Memos_ss_phab_land_2col-960w.avif 960w\" sizes=\"100vw\"><source type=\"image/webp\" srcset=\"https://hominidsoftware.com/img/Memos_ss_phab_land_2col-750w.webp 750w, https://hominidsoftware.com/img/Memos_ss_phab_land_2col-960w.webp 960w\" sizes=\"100vw\"><img alt=\"Serene Notes: phablet landscape (two columns)\" loading=\"lazy\" decoding=\"async\" src=\"https://hominidsoftware.com/img/Memos_ss_phab_land_2col-750w.png\" width=\"960\" height=\"540\" srcset=\"https://hominidsoftware.com/img/Memos_ss_phab_land_2col-750w.png 750w, https://hominidsoftware.com/img/Memos_ss_phab_land_2col-960w.png 960w\" sizes=\"100vw\"></picture></p>\n<p>The fundamental layout is two panels side-by-side. In windows narrower than 640 CSS pixels, the second panel slides in on top of the first. Collapse is based solely on window width, not device class, so phablet users will have one column in portrait mode and two columns in landscape mode.</p>\n<div class=\"flex-center-center\">\n<picture><source type=\"image/avif\" srcset=\"https://hominidsoftware.com/img/Memos_ss_phab_port_1col-540w.avif 540w\" sizes=\"100vw\"><source type=\"image/webp\" srcset=\"https://hominidsoftware.com/img/Memos_ss_phab_port_1col-540w.webp 540w\" sizes=\"100vw\"><img alt=\"Serene Notes: phablet portrait (one column)\" loading=\"lazy\" decoding=\"async\" src=\"https://hominidsoftware.com/img/Memos_ss_phab_port_1col-540w.png\" width=\"540\" height=\"960\"></picture>\n</div>\n<p>Tablet and desktop users don’t need to muck with dialogs or layers, while phone users have fast transitions. Most importantly, the shift in mental models is easy when going from a phone to a larger device. While this app does not currently sync user data between devices, adding that would give a seamless experience across devices. [The successor app <a href=\"https://notestogether.hominidsoftware.com/#\">Notes Together</a> does sync between devices.]</p>\n<p>Presently, the Help pane displaces the Details pane. In windows wider than 960px, Help should really be a third panel.</p>\n<p>The collapsing panels use the Enyo Panels widget. Another instance of Panels is used to swap the Details and Help panes in the second panel. Using a JavaScript framework designed to support multiple devices really speeds development.</p>\n<p>To maximize display of user data the list foregoes controls on items in favor of direct manipulation: items can be swiped (or double-clicked) for operations such as Delete. Reordering is done by hold-then-drag. Discoverability was traded off for power – many apps will need to strike a different balance. A possible future enhancement on larger screens would be to add visible controls or at least tool tips.</p>\n<div class=\"flex-center-center\">\n<picture><source type=\"image/avif\" srcset=\"https://hominidsoftware.com/img/Memos_ss_phab_port_1col_search-540w.avif 540w\" sizes=\"100vw\"><source type=\"image/webp\" srcset=\"https://hominidsoftware.com/img/Memos_ss_phab_port_1col_search-540w.webp 540w\" sizes=\"100vw\"><img alt=\"Serene Notes: live search (phone)\" loading=\"lazy\" decoding=\"async\" src=\"https://hominidsoftware.com/img/Memos_ss_phab_port_1col_search-540w.png\" width=\"540\" height=\"960\"></picture>\n</div>\n<p>Fixed groupings such as folders or notebooks would require the user to navigate an extra level to access data. Search allows a memo to be in multiple groupings, and requires less UI. (However, it is not appropriate for users who rely on spatial memory.)</p>\n<p>While typing on a touchscreen is laborious, the app minimizes typing by using prefix searches. Searching for “s fra” will find all memos that contain “San Francisco” and few false positives among hundreds of memos. The on-screen keyboard on most phones obscures all but a few list items, but live search and the counter of hits tells the user when she has narrowed the search to a handful of memos. Skimming the list then allows the user to select the desired record. Live full-text search is implemented using IndexedDB.</p>\n<p>Typing is also minimized by localizing the search to the preferred language of the browser or OS. In Spanish ñ is a different letter than n (and Spanish keyboards have a key devoted to it), just as w is a different letter than u in English. For Spanish users, peña never matches pena, reducing false matches. However, users are not required to know languages other than their own, so for a Spanish user “cote” matches the French cote, coté, côte and côté.</p>\n<p>Hardware keyboards allow users to type more quickly and accurately, larger screens minimize scrolling, and faster processors and disks make complicated searches nearly instantaneous, but the interface works the same for all devices.</p>\n<h2 id=\"mobile-first\" tabindex=\"-1\">Mobile first <a class=\"header-anchor\" href=\"https://hominidsoftware.com/tech-personal-growth/designing-webapps-multiple-devices/#mobile-first\">#</a></h2>\n<p>Both apps were designed “mobile-first”, which tends to result in lean apps, with fewer features than standard desktop apps. Given that most features in desktop apps are rarely used, that’s not necessarily a problem for desktop users. Carefully-chosen defaults eliminate the need for preference settings.</p>\n<p>Working out a user interface design that works well across a range of devices often requires more effort initially, but can result in a more user-friendly experience with the added benefit of being easier to maintain. A few powerful user-interface elements can eliminate the need for many panes, dialogs, dropdowns and buttons.</p>\n",
			"date_published": "2013-11-05T00:00:00Z",
			"date_modified": "2024-08-21T23:57:12Z"
		}
		,
		{
			"id": "https://hominidsoftware.com/tech-personal-growth/webos-desk-accessories/",
			"url": "https://hominidsoftware.com/tech-personal-growth/webos-desk-accessories/",
			"title": "webOS “Desk Accessories”",
			"summary": "This post originally appeared on the webOS Developer Relations blog",
			"content_html": "<p><em><strong>Editor’s note:</strong> This week we are featuring a guest challenge from rockstar webOS developer Doug Reeder. He has pioneered an app interface that he calls Desk Accessories. Your challenge this week is to create an app that uses this kind of interface. Take it away, Doug!</em></p>\n<h2 id=\"background\" tabindex=\"-1\">Background <a class=\"header-anchor\" href=\"https://hominidsoftware.com/tech-personal-growth/webos-desk-accessories/#background\">#</a></h2>\n<p><a href=\"https://arstechnica.com/uncategorized/2007/03/study-says-leave-the-multitasking-to-your-computer/\">Psychological research</a> shows that humans cannot efficiently concentrate on more than one activity at a time. However, there are single activities that require two apps on the screen at once. For example, one might want to compose an e-mail while reading figures from a spreadsheet, or calculate price comparisons while shopping on-line.</p>\n<h2 id=\"the-webos-user-interface\" tabindex=\"-1\">The webOS User Interface <a class=\"header-anchor\" href=\"https://hominidsoftware.com/tech-personal-growth/webos-desk-accessories/#the-webos-user-interface\">#</a></h2>\n<p>While webOS supports true multitasking, it only lets you interact with one card at a time. However, there are two kinds of webOS windows which a user can interact with while another app’s card is displayed: Dashboards and System popup alerts. You can’t divide your screen between two arbitrary apps, but you can have “desk accessories”: apps which use a part of the screen while leaving most of it for another app.</p>\n<p>Dashboards persist until dismissed by the user, and the user can display them with a single swipe at any time. However, they are always exactly 320 pixels wide and 52 pixels tall. The user can display and interact with multiple Dashboards simultaneously.</p>\n<p><picture><source type=\"image/avif\" srcset=\"https://hominidsoftware.com/img/notifications-dashboard-478w.avif 478w\" sizes=\"100vw\"><source type=\"image/webp\" srcset=\"https://hominidsoftware.com/img/notifications-dashboard-478w.webp 478w\" sizes=\"100vw\"><img alt=\"three dashboards on Touchpad\" loading=\"lazy\" decoding=\"async\" src=\"https://hominidsoftware.com/img/notifications-dashboard-478w.png\" width=\"478\" height=\"203\"></picture></p>\n<p>System popup alerts (don’t confuse them with popups, toasters, and alerts managed by Enyo or Mojo) must be 320 pixels wide, but the height is configurable. Once closed, they are gone. Only one can be displayed at a time. While they’re available on both phones and tablets, Popups that are taller than about 240 pixels take up a majority of the screen on a phone, typically making the other app unusable – and if you can’t use the other app, you’re better off putting your app in a card.</p>\n<p><picture><source type=\"image/avif\" srcset=\"https://hominidsoftware.com/img/notes_portrait-750w.avif 750w, https://hominidsoftware.com/img/notes_portrait-768w.avif 768w\" sizes=\"100vw\"><source type=\"image/webp\" srcset=\"https://hominidsoftware.com/img/notes_portrait-750w.webp 750w, https://hominidsoftware.com/img/notes_portrait-768w.webp 768w\" sizes=\"100vw\"><img alt=\"Popup Calc over Memos\" loading=\"lazy\" decoding=\"async\" src=\"https://hominidsoftware.com/img/notes_portrait-750w.png\" width=\"768\" height=\"1024\" srcset=\"https://hominidsoftware.com/img/notes_portrait-750w.png 750w, https://hominidsoftware.com/img/notes_portrait-768w.png 768w\" sizes=\"100vw\"></picture></p>\n<div class=\"center-horizontal\">\n<picture><source type=\"image/avif\" srcset=\"https://hominidsoftware.com/img/ss_pre3_emu-480w.avif 480w\" sizes=\"100vw\"><source type=\"image/webp\" srcset=\"https://hominidsoftware.com/img/ss_pre3_emu-480w.webp 480w\" sizes=\"100vw\"><img alt=\"Popup Calc on phone\" loading=\"lazy\" decoding=\"async\" src=\"https://hominidsoftware.com/img/ss_pre3_emu-480w.png\" width=\"480\" height=\"800\"></picture>\n</div>\n<p>You can put any kind of widget in a Dashboard or System Popup, but there is a big limitation—neither receives keyboard events.</p>\n<p>Here are two example apps. <a href=\"https://web.archive.org/web/20141022053747/https://developer.palm.com/appredirect/?packageid=com.machiapps.dashboardutilities&amp;applicationid=7009\">Dashboard Utilities</a> is a desk accessory that primarily uses a Dashboard. <a href=\"https://hominidsoftware.com/popupcalc/index.html\">PopupCalc</a> is a desk accessory that primarily uses a System popup.</p>\n<div class=\"center-horizontal\">\n<picture><source type=\"image/avif\" srcset=\"https://hominidsoftware.com/img/ph_1-320w.avif 320w\" sizes=\"100vw\"><source type=\"image/webp\" srcset=\"https://hominidsoftware.com/img/ph_1-320w.webp 320w\" sizes=\"100vw\"><img alt=\"Dashboard Utilities dashboards\" loading=\"lazy\" decoding=\"async\" src=\"https://hominidsoftware.com/img/ph_1-320w.png\" width=\"320\" height=\"480\"></picture>\n</div>\n<h2 id=\"flow-of-activity\" tabindex=\"-1\">Flow of Activity <a class=\"header-anchor\" href=\"https://hominidsoftware.com/tech-personal-growth/webos-desk-accessories/#flow-of-activity\">#</a></h2>\n<p>Dashboards and System popups are simple to create, but you must consider all the flows of user activity. Desk accessories are little-known as yet to webOS users, so you would do well to have your app start by launching a card which explains how to open your Dashboard or Popup.</p>\n<p>Any window can be dismissed by the user at any time, so your app must deal with this. webOS keeps track of a “root window” for each app, where it sends events such as applicationRelaunch. For standard apps that don’t specify <code>&quot;noWindow&quot;: true</code> in appinfo.json, the root window is initially the first card opened, but if that card is tossed away, another window becomes the root window. For headless apps, that specify <code>&quot;noWindow&quot;: true</code> in appinfo.json, the root window is a headless, non-displayed window. You must deal with the situation where your app has only a Dashboard or Popup in existence when the user taps the app icon in the Launcher—the current root window will receive an applicationRelaunch event. One good way to respond to this is to re-display the card with basic orientation info. Your app icon may be tapped by a user who has no idea that your app is a desk accessory that’s already running.</p>\n<p><picture><source type=\"image/avif\" srcset=\"https://hominidsoftware.com/img/popupcalc_2011-01-09_153312-750w.avif 750w, https://hominidsoftware.com/img/popupcalc_2011-01-09_153312-1024w.avif 1024w\" sizes=\"100vw\"><source type=\"image/webp\" srcset=\"https://hominidsoftware.com/img/popupcalc_2011-01-09_153312-750w.webp 750w, https://hominidsoftware.com/img/popupcalc_2011-01-09_153312-1024w.webp 1024w\" sizes=\"100vw\"><img alt=\"Popup Calc instruction card\" loading=\"lazy\" decoding=\"async\" src=\"https://hominidsoftware.com/img/popupcalc_2011-01-09_153312-750w.png\" width=\"1024\" height=\"768\" srcset=\"https://hominidsoftware.com/img/popupcalc_2011-01-09_153312-750w.png 750w, https://hominidsoftware.com/img/popupcalc_2011-01-09_153312-1024w.png 1024w\" sizes=\"100vw\"></picture></p>\n<p>webOS has neither a Dock nor a Taskbar to provide ready access to apps. The only instant access is a swipe or tap to open all current Dashboards. Desk accessories must be closeable at any time, and users will expect them to open exactly as they closed. Thus, a Popup desk accessory will typically need a Dashboard to provide an “open” button. As long as either the Popup, Dashboard or card exist, the app will continue running and global variables will be preserved.</p>\n<p>Another UI issue for Popups is how to close them. The Center button on tablets and classic Pres will close them. An up-swipe on a phone will close a Popup and go to card mode, but on a tablet it just switches to card mode. A number of users find the Center button on TouchPads to be awkward, so it’s well to include another way to close. Unlike cards, the system does not support swipe-to-remove popups. A button labeled “Close” is easy, but uses precious screen real estate. One solution is some kind of swipe gesture, such as a dragging from inside the Popup to outside the Popup. This echoes the swipe-card-away gesture.</p>\n<p>The system does not close a Popup when it goes to Exhibition mode, but desk accessories generally should close themselves, since the user has by definition not interacted with them for a while. If the screen turns off, your Popup should close itself so it won’t display on the lock screen, where it would displace the dashboard notifications the user expects to see. To do this, your Popup should subscribe to the <a href=\"https://web.archive.org/web/20140921053848/https://developer.palm.com/content/api/reference/services/display-manager.html\">Display Manager service</a> and close itself if <code>inResponse.event === &quot;displayOff&quot;</code> or <code>inResponse.dockMode === true</code></p>\n<p>Many Dashboard desk accessories will set the window attribute <code>clickableWhenLocked</code>, to allow the user to interact with them on the lock screen. Alas, Popups don’t have that option, so you should not set <code>clickableWhenLocked</code> for the Dashboard for a Popup desk accessory.</p>\n<h2 id=\"state-variables\" tabindex=\"-1\">State Variables <a class=\"header-anchor\" href=\"https://hominidsoftware.com/tech-personal-growth/webos-desk-accessories/#state-variables\">#</a></h2>\n<p>Users expect desk accessories to maintain state, that is, to re-open exactly as they closed. Enyo maintains the object enyo.application in sync across all windows, so properties of enyo.application are a good place to store state variables for a Popup.\nDocumentation</p>\n<p><a href=\"https://web.archive.org/web/20141022050005/https://developer.palm.com/content/api/reference/enyo/enyo-api-reference.html#enyo.windows\">enyo.windows</a> allows you to directly create Dashboards and System popups. <a href=\"https://web.archive.org/web/20141022050005/https://developer.palm.com/content/api/reference/enyo/enyo-api-reference.html#enyo.Dashboard\">enyo.Dashboard</a> is a Kind that supports notifications in a Dashboard; typically a “desk accessory” will not use it.</p>\n<p>An overview of Mojo dashboards is on <a href=\"https://web.archive.org/web/20111111083909/https://developer.palm.com/content/api/dev-guide/mojo/dashboards-notifications.html\">this page</a>. Mojo “Dashboard Applications” are covered in the second part of <a href=\"https://web.archive.org/web/20141022052239/https://developer.palm.com/content/content/api/dev-guide/mojo/background-applications.html\">this page</a>.</p>\n<h2 id=\"demo-app\" tabindex=\"-1\">Demo App <a class=\"header-anchor\" href=\"https://hominidsoftware.com/tech-personal-growth/webos-desk-accessories/#demo-app\">#</a></h2>\n<p>To ease App Hack development, there is an Enyo demo app which has a card to orient the user, but “lives” in a Dashboard, which contains a button to display a System popup.</p>\n<p>You’ll find the demo app on our <a href=\"https://web.archive.org/web/20141022053748/https://github.com/webOS-DevRel/Weekly-App-Hack/tree/master/4%20-%20PopupDemo\">GitHub repo</a>.</p>\n<p>The Makefile requires <code>gmake</code>. The first time, and after running <code>make clean</code>, you must run <code>make dirs</code> to create the build directories. Run <code>make all</code> to create the .ipk, <code>make install</code> to create the .ipk and install it, or <code>make run</code> to create the .ipk, install, and run it.</p>\n<p>If your development environment includes Miller’s JavaScript Lint, uncomment the Makefile line</p>\n<pre><code>jsl -conf jsl-Enyo-emptyok.conf -nologo -nofilelisting -process $@\n</code></pre>\n<p>If your development environment includes YUI, uncomment the Makefile <code>#ifdef</code> after</p>\n<pre><code># App source files are copied for debug builds and minified for production builds.\n</code></pre>\n<p>and the line after</p>\n<pre><code># Always minifies CSS.\n</code></pre>\n<h2 id=\"the-rules\" tabindex=\"-1\">The Rules <a class=\"header-anchor\" href=\"https://hominidsoftware.com/tech-personal-growth/webos-desk-accessories/#the-rules\">#</a></h2>\n<ol>\n<li>\n<p>Submit your app based on the sample above to the App Catalog by November 1st at 11:59pm Pacific Daylight Time. We will be accepting both new apps as well as incorporation of the theme into existing apps as an improvement. A submission to the Beta catalog is acceptable.</p>\n</li>\n<li>\n<p>Notify us that you want to participate in the App Hack by sending us an email containing your app redirect link (it’s generated automatically and placed on the app’s detail page in “My Apps”) and any extra information you want to share with us at apphack@palm.com. This is also due by November 1st at 11:59pm Pacific Daylight Time.  If you do not send us this note, your app will not be considered for the App Hack.</p>\n</li>\n<li>\n<p>By the end of the day on Friday, November 4th 2011, the Developer Relations team will announce the winning app (along with honorable mentions and other entrants). The winner will get a blog post dedicated to him/her and his/her fantastic app.</p>\n</li>\n<li>\n<p>For this round, the winner (and only the winner) will also receive a 16GB TouchPad!</p>\n</li>\n</ol>\n",
			"date_published": "2011-10-25T00:00:00Z",
			"date_modified": "2024-08-21T23:57:12Z"
		}
		,
		{
			"id": "https://hominidsoftware.com/tech-personal-growth/popupcalc-with-speech/",
			"url": "https://hominidsoftware.com/tech-personal-growth/popupcalc-with-speech/",
			"title": "Adding Speech to PopupCalc",
			"summary": "Experiments revealed issues with latency and usefulness",
			"content_html": "<p>There are several places where speech output might be useful in a touchscreen calculator.</p>\n<p>Touchscreens have no tactile feedback, making it difficult for users to be sure they've tapped the correct button. Autocorrect is not possible for numbers. Thus, speaking the name of each button as it is pressed gives users the immediate feedback of a keyclick. However, this does not require text-to-speech, only a recording of each key name.</p>\n<p>Due to the large latency in using the <code>flite</code> plugin (<code>sdltts</code>), an implementation of this in PopupCalc failed to provide the immediate feedback users need.</p>\n<p>Speaking the name of each digit is not how humans say numbers, so a &quot;Speak Operand&quot; option was added. Numbers can't be spoken until they're completely entered, as signaled by an operator.</p>\n<p>Thus, a calculation is spoken as the phrases\n&quot;two times&quot;, &quot;three plus&quot;, &quot;four equals ten&quot;, rather than the natural &quot;two times three&quot;, &quot;plus four&quot;, &quot;equals ten&quot;. While an interesting user interface experiment, I judged this to not be useful for end users.</p>\n<div class=\"center-horizontal\">\n\t<video controls=\"\" width=\"320\" height=\"404\" src=\"https://hominidsoftware.com/no-multiviews/PopupCalc-speech-3.mp4\" poster=\"https://hominidsoftware.com/img/popupcalc.webp\" playsinline=\"\" preload=\"metadata\">\n\t\t\tDownload the <a href=\"https://hominidsoftware.com/no-multiviews/PopupCalc-speech-3.mp4\">PopupCalc with speech</a> MP4 video.\n\t</video>\n</div>\n<p>Speaking the result of a calculation is another approach.\nImplementing this using the <code>flite</code> plugin (<code>sdltts</code>) results in a noticeable latency, but might sometimes be useful.</p>\n<p>Another possibility is speaking the whole calculation.\nThis allows a user to check that the calculation was entered correctly, reducing the need for a &quot;paper tape&quot; widget. The latency is not a problem here.\nIt's also useful when one person is doing calculations for a group (say, at a meeting).\nIt's most useful when training someone to do calculations, but PopupCalc only handles simple calculations and more complicated calculations are rarely done with calculators anymore.</p>\n",
			"date_published": "2011-10-11T00:00:00Z",
			"date_modified": "2025-05-28T03:27:04Z"
		}
		,
		{
			"id": "https://hominidsoftware.com/tech-personal-growth/hp-exit-strategy-handhelds/",
			"url": "https://hominidsoftware.com/tech-personal-growth/hp-exit-strategy-handhelds/",
			"title": "HP&#39;s Exit Strategy for Handhelds",
			"summary": "It&#39;s easier to sell a going concern",
			"content_html": "<p>There is wide agreement that HP's hardware (and before that, Palm's hardware) for webOS was not as good as it needed to be, to compete.  HP failed, over the course of a year, to use its &quot;scale&quot; to properly sell the devices it did have.  So, it's reasonable for HP to stop making webOS hardware.</p>\n<p>webOS itself was widely praised for its elegance of design (if not so widely for its implementation).  Other manufacturers expressed interest in licensing webOS, despite the poor history of Apple and Palm directly competing against their licensees.</p>\n<p>Deciding to ax your hardware changes the proposition.  Windows CE/Windows Mobile and its licensees trundled along for over a decade. And as of this week, Android licensees are strongly motivated to look for a new OS to add to their lineup - so a deal is more reachable than ever before.</p>\n<p>What looks better to a licensee - a functioning ecosystem where you can add products, or a mothballed ecosystem that must be revived?   For the cost of shutting down webOS GBU suddenly, HP could easily have ramped down operations until new devices from new manufacturers were within reach.   If apps are truly as important as pundits say, it's better to have developers continuing to work during the transition, rather than trying to lure them back to a re-animated platform.</p>\n<p>With licensing deals much easier to make this week, there was no rush to announce the end of HP webOS devices, and kill off current sales and consumer interest.  Even if a licensing deal is announced within a month, HP has badly damaged the value of webOS.</p>\n<p>Leo Apotheker and the rest of HP's high management have done their shareholders a disservice by macho posturing instead of prudent operations.</p>\n",
			"date_published": "2011-08-19T00:00:00Z",
			"date_modified": "2024-08-12T04:00:50Z"
		}
		,
		{
			"id": "https://hominidsoftware.com/tech-personal-growth/just-type/",
			"url": "https://hominidsoftware.com/tech-personal-growth/just-type/",
			"title": "Just Type",
			"summary": "UI needs to be discoverable",
			"content_html": "<p>When a user needs to select one item out of hundreds (the typical case on a handheld device), there are a number user interface approaches. &quot;Browse&quot; approaches work when items fit in a hierarchy the user can remember, for example <em>Artist &gt; Album &gt; Song</em> or <em>Account &gt; Mailbox &gt; Message</em>.</p>\n<p>For some datasets there isn't a hierarchy, for others you could impose a hierarchy, but the user may not categorize items the same way.  For example, a user experiencing an &quot;out of memory&quot; error won't know to look in  FAQs on &quot;Configuration&quot;.  Here, you need some variation on search.</p>\n<p>The chief problem with search is that, typically, the user doesn't know how specific to be.  Too short a search phrase will return too many results.  Too long a search phrase may return no results, if the search phrase is not exactly right.  The solution is &quot;live search&quot; - returning search results as the user types.</p>\n<p>Until the release of the TouchPad, all webOS devices had a built-in hardware keyboard.  This allows a distinctive technique - when no text field has the focus, if a character is typed, start searching.  This allowed experienced users to search a list, without cluttering the small screen with a search field or button.  The problem is, there is no indication to new users they can search.  Since the Contacts app is unusable without this technique, one might assume that all users learn it.  But real users don't have to behave like we expect.</p>\n<p>Palm assumed that all users set up e-mail on their smartphone, thus requiring support requests be sent by e-mail</p>\n<p>There are four scenes in Outline Tracker which use FilterLists, and the hint or help for each was different.  The FAQ list was searchable, and the first FAQ was 'how to search the FAQs'.  This always bothered me, but I couldn't think of a better alternative when I first implemented the FAQ scene.</p>\n<p>While adding <a href=\"https://web.archive.org/web/20141022130716/https://developer.palm.com/distribution/viewtopic.php?f=11&amp;t=17285\">support for the on-screen keyboard</a> to my Mojo app  I rediscovered that the status message list is a FilterList.</p>\n<p>I have often had trouble finding the status message I was looking for. The typedown filter would have been great for this. But this is so non-discoverable, that I didn't know it existed in code I wrote myself.</p>\n<p>Given also that I added visible text to most of the FilterList scenes, telling users they could &quot;Just Type&quot;, I'm thinking the &quot;Just Type&quot; concept (that is, no visible UI to start search) is a real fail.</p>\n",
			"date_published": "2011-08-13T00:00:00Z",
			"date_modified": "2024-08-12T04:00:50Z"
		}
		,
		{
			"id": "https://hominidsoftware.com/tech-personal-growth/webos-under-windows/",
			"url": "https://hominidsoftware.com/tech-personal-growth/webos-under-windows/",
			"title": "How is HP-Palm going to port webOS to Windows?",
			"summary": "There are many technical and user experience challenges",
			"content_html": "<h2 id=\"porting\" tabindex=\"-1\">Porting <a class=\"header-anchor\" href=\"https://hominidsoftware.com/tech-personal-growth/webos-under-windows/#porting\">#</a></h2>\n<p>A build of WebKit for x86, should be straightforward, though there's many details that need to be got right. WebOS apps use an asynchronous protocol called PalmBus to communicate with system services, so that code must be ported from ARM webOS. Instead of sharing one small screen, each app can have its own window, sized appropriately.</p>\n<p>Services written in C/C++ may have been written assuming only ARM processors, but that's in-house code at least. Again, many details must be got right.</p>\n<p>JavaScript services are problematic, since Node for Windows is not yet fully working. Worse (from HP's standpoint), Cygwin (the Unix-compatability layer for Windows) is GPL, not LGPL:</p>\n<p>Most of the tools are covered by the GNU GPL, some are public domain, and others have a X11 style license. To cover the GNU GPL requirements, the basic rule is if you give out any binaries, you must also make the source available….</p>\n<p>The Cygwin™ API library found in the <code>winsup</code> subdirectory of the source code is also covered by the GNU GPL (with exceptions; see below). By default, all executables link against this library (and in the process include GPL'd Cygwin™ glue code). This means that unless you modify the tools so that compiled executables do not make use of the Cygwin™ library, your compiled programs will also have to be free software distributed under the GPL with source code available to all.</p>\n<p>If the Cygwin license only &quot;infects&quot; Node, that should be a win for everyone: HP-Palm supports Node under Windows, while the rest of webOS remains private to HP-Palm. However, Node in webOS is customized to add PalmBus support, which complicates matters.  HP-Palm will need good work from their programmer-lawyers to thread this strait.</p>\n<p>DB8 is the central database of user information in webOS 2. Replicating it and the user's Palm Profile from Windows to handhelds should be straightforward once the above is complete. Currently, PalmProfiles are only backed up once a day. Users will want faster replication between their PC and their handhelds. At the Palm Developer day in May 2010, CouchDB was mentioned in conjunction with DB8. CouchDB has real-time replication; let's hope no DB8 design decisions were made which make real-time replication difficult. This is also needed by users with a tablet and smartphone, so one can guess this is in-hand (or will be in-hand by June).</p>\n<p>What features of desktop computers will need support? File system requests already go over the PalmBus, so accessing desktop user files will be supported. TouchPads can print to network printers; presumably local Windows printers will be straightforward to add to that system. Presumably audio support will match that available in other WebKit builds such as Safari for Windows. Bluetooth I'd guess will not be supported in the first release, since audio and keyboards will be handled separately. There's no support for USB under webOS currently, so don't expect webOS under Windows to support it any time soon.</p>\n<h2 id=\"user-experience\" tabindex=\"-1\">User Experience <a class=\"header-anchor\" href=\"https://hominidsoftware.com/tech-personal-growth/webos-under-windows/#user-experience\">#</a></h2>\n<p>Mouse and pointer are different than a touchscreen, but the new Enyo framework has been demonstrated running in a browser, so developers will have the ability to test apps with both mouse and finger. Whether they succeed in well supporting both remains to be seen.</p>\n<p>&quot;Syncing to my desktop&quot; is the number-one feature request for Outline Tracker. Having the same interface on both will lower the friction of using both. Web apps are useful, but notes and tasks stored locally are better. Alas, Mac and Linux users will be left out for the foreseeable future.</p>\n<p>Currently, people use handhelds as an adjunct to desktop computers.  Many people do not work at a desk; current solutions (<a href=\"https://hominidsoftware.com/outlinetracker/case_study.html\">Outline Tracker &amp; Basecamp Classic Case Study</a>) use different apps on handhelds and the desktop. This (and/or the Motorola Atrix) could shift the balance.</p>\n<p>Does the future belong to the system that can best replicate users' data, and the user experience, across all of a user's devices? I don't know, but I look forward to finding out.</p>\n",
			"date_published": "2011-03-15T00:00:00Z",
			"date_modified": "2023-04-20T20:31:14Z"
		}
		,
		{
			"id": "https://hominidsoftware.com/tech-personal-growth/transitions/",
			"url": "https://hominidsoftware.com/tech-personal-growth/transitions/",
			"title": "Transitions",
			"summary": "Palm OS → webOS 1.x → webOS 2.x → ?",
			"content_html": "<p>HP/Palm's presentation yesterday showed some solid hardware and innovative user interfaces.  The new Enyo framework presented to developers is in position to make webOS live up to its initial promise of developing like developing for the web, rather than merely making use of web technologies.</p>\n<p>But I'm worried about how we get from the current webOS users, apps and developers to the bright future painted by HP.</p>\n<p>Apps become powerful when users enter a lot of data in them - and they'll only do that if they expect to use the apps for a long time.</p>\n<p>This can be seen with some Palm OS apps, such as FileMaker.  Users have YEARS of data accumulated, and won't move to another platform without it.   Currently, they nurse aging Palm OS hardware, and bemoan that no other platform will let them use their data.</p>\n<p>Palm promised the ability to run Palm OS apps in an emulator under webOS.  Classic from Motion Apps was that emulator, and technically it works well. But a finger isn't as precise as a stylus, making Palm OS apps a chore to use, even with the clever zoom-in-and-out.   The rating of Classic hovers around 3 out of 5 stars -- a poor showing for a product with so much work behind it.</p>\n<p>Then, last Fall, Motion Apps announced that HP/Palm was refusing to include the necessary files in webOS 2.0 to allow Classic to run.  Users of Palm OS software were left facing a dead end - apparently due to HP/Palm's intransigence, rather than technical limitations.</p>\n<p>Old platforms can't be supported forever, but if they aren't supported until there's a viable replacement, users won't trust their backers.   What lesson should Palm OS users draw about HP/Palm's commitment to them, from this?</p>\n<p>Early webOS adopters took a leap of faith and signed two-year contracts, believing that 3rd-party apps would come. After a short 16 months in public, HP/Palm announced at the NYC Dev day that Mojo (the framework most webOS apps are based on) was obsolete, and not guaranteed to be included on webOS devices after 2011.  As a webOS user, should you buy apps now, that won't work next year?  Should you stay with a platform that declares your current apps obsolete, months before any replacement could possibly arrive?</p>\n<p>Early webOS developers took a leap of faith and learned the intricacies of Mojo, a framework new even to seasoned JavaScript developers.  While amateur developers contribute many worthwhile apps, large powerful apps that make a device more than a toy, and users more than mayflies flitting from platform to platform, usually come from professional developers. Developers who need to make a profit.   It's hard to make a profit on a platform that's only around for 16 months.   While Mojo apps will remain runnable through the end of 2011, app sales are primarily made to users new to the platform.   And large, expensive apps do particularly poorly when their platform is obsolete.  So, sales of powerful Mojo apps have tanked (and lighter apps aren't doing so well, either).   As a developer, what lesson should you draw, about the profitability of developing for webOS?</p>\n<p>Yesterday, we learned that webOS 2.x will not be available over-the-air (OTA) to devices that shipped with webOS 1.x (almost every device not possessed by a developer).  While HP/Palm has promised a &quot;path to webOS 2&quot; for owners, no details are available.  Will this be a webOS Doctor, which erases 3rd-party data and requires a desktop computer? This is similar to the upgrade mechanism for Palm OS, a mechanism that most users did not use.  Will the path be credit toward a new device?  No one knows.</p>\n<p>Microsoft has excelled at creating fear, uncertainty and doubt (FUD) about it's competitors.  HP/Palm has done a surprising job of creating FUD about their own product.  HP/Palm appears to pin its hopes on one exciting future technology after another, with inadequate concern for current users.</p>\n<p>None of these problems are beyond remedy.   The Palm OS ROM needed for Classic, and the Mojo framework, may consume valuable space on new devices, but there's no visible reason they can't be made optional downloads for those who need them. And HP/Palm can commit to keeping them available until users have real alternatives.  Users would see that HP/Palm cares about their long-term needs.  Developers could have confidence that apps they develop now can be sold for years.   Developers of existing apps would be motivated to improve them and convert them to use Enyo.</p>\n<p>There are many Palm OS apps that have committed user bases, even today.  Users who bought one Palm device after another.  Users that promoted Palm OS to everyone they knew.  How many webOS apps can boast that today?</p>\n<p>Good design and a lot of work has gone into webOS 2 (and 3!)  There's a bright future out there for webOS -- if the transitions of users, apps, and developers are properly smoothed.   And HP/Palm is the one that has to do it.</p>\n",
			"date_published": "2011-02-11T00:00:00Z",
			"date_modified": "2024-08-12T04:00:50Z"
		}
		,
		{
			"id": "https://hominidsoftware.com/tech-personal-growth/procrastination-vs-system/",
			"url": "https://hominidsoftware.com/tech-personal-growth/procrastination-vs-system/",
			"title": "Procrastination vs. System",
			"summary": "To-do items need to be actionable, with adequate detail",
			"content_html": "<p>Another wedding was coming up (boy, there have been a lot of them this year).  When I checked my suit to be sure it was clean, the pants were missing.  A call the next day to the cleaner verified that they were still there.</p>\n<p>Several months ago, I had a nagging feeling something needed to be picked up from the cleaners, so I put an item on my to-do list: phone cleaners.  Months later, I still hadn't made a simple phone call.</p>\n<h2 id=\"thesis\" tabindex=\"-1\">Thesis <a class=\"header-anchor\" href=\"https://hominidsoftware.com/tech-personal-growth/procrastination-vs-system/#thesis\">#</a></h2>\n<p>My task &quot;phone cleaners&quot; was vague and thus not compelling.  If I had written down &quot;pick up pants from cleaners&quot; when I dropped them off, the item would have been focused and actionable.  Better if I set it with a deadline.  Better yet if I set a lead time (start date), so I wouldn't see the task until it was time to act on it.</p>\n<p>Tasks in a to-do system must be specifically phrased, with proper metadata, to induce action.</p>\n<h2 id=\"antithesis\" tabindex=\"-1\">Antithesis <a class=\"header-anchor\" href=\"https://hominidsoftware.com/tech-personal-growth/procrastination-vs-system/#antithesis\">#</a></h2>\n<p>Without any system, I remembered what I needed to do, in adequate time.</p>\n<p>(Counterargument: If I hadn't checked my suit a week in advance of the wedding, there wouldn't have been enough time.)</p>\n<h2 id=\"synthesis\" tabindex=\"-1\">Synthesis <a class=\"header-anchor\" href=\"https://hominidsoftware.com/tech-personal-growth/procrastination-vs-system/#synthesis\">#</a></h2>\n<p>A task system should contain tasks that are non-routine, or otherwise non-memorable.  It should not contain items that will come to your attention anyway (a full trash can is its own reminder).</p>\n",
			"date_published": "2010-07-10T00:00:00Z",
			"date_modified": "2023-04-20T20:31:14Z"
		}
		,
		{
			"id": "https://hominidsoftware.com/tech-personal-growth/synergy-for-tasks/",
			"url": "https://hominidsoftware.com/tech-personal-growth/synergy-for-tasks/",
			"title": "Synergy for Tasks",
			"summary": "webOS Tasks should be reworked using the Palm Synergy paradigm",
			"content_html": "<h2 id=\"background\" tabindex=\"-1\">Background <a class=\"header-anchor\" href=\"https://hominidsoftware.com/tech-personal-growth/synergy-for-tasks/#background\">#</a></h2>\n<p>To-Do List/Tasks was one of the four core apps to have a dedicated button under Palm OS. Yet <em>Tasks</em>, its analog under webOS, was not reworked using the Synergy idea of presenting data from different back ends with a common UI.</p>\n<p>There is value in keeping a to-do list for oneself, but much greater value in tracking tasks performed by a team – what has been done, what needs to be done, when it is due, who’s responsible for what. Most groupware supports some form of task list management. Properly implemented and used, it increases productivity by reducing the number of phone calls, e-mails and meetings required. These services are more than simple to-do lists; they are the working face of modern project management.</p>\n<p>Accessing groupware from handheld devices increases its value – project plans can be reviewed and updated during a meeting (without requiring workers to have and bring distracting laptops), indeed any time people are away from their work stations: <a href=\"https://hominidsoftware.com/outlinetracker/case_study.html\">case study</a> With full-time access to groupware, project plans become living documents.</p>\n<h2 id=\"synergy-a-prime-differentiator-of-webos\" tabindex=\"-1\">Synergy: A Prime Differentiator of webOS <a class=\"header-anchor\" href=\"https://hominidsoftware.com/tech-personal-growth/synergy-for-tasks/#synergy-a-prime-differentiator-of-webos\">#</a></h2>\n<p>WebOS users praise the way it handles contacts and calendars, using Palm Synergy. Pulling the disparate elements of users’ lives together has been one of the biggest selling points of webOS. Yet the user experience has not been consistently compelling. Jon Stokes of Ars Technica wrote one of the best thought-out reviews of the Pre on its launch (<a href=\"https://arstechnica.com/gadgets/2009/06/ars-reviews-the-palm-pre-part-1-the-blackberry-killer/\">Ars Reviews the Palm Pre, part 1: the BlackBerry killer</a>), but bailed out six months later, in part because webOS apps were largely clients for single cloud services – there was nothing compellingly different about the experience for him (<a href=\"https://arstechnica.com/gadgets/2010/03/rip-palm-its-over-and-heres-why/\">RIP Palm: it’s over, and here’s why</a>). He could access cloud services just as well from an Android phone.</p>\n<h2 id=\"webos-task-list-managers\" tabindex=\"-1\">webOS Task List Managers <a class=\"header-anchor\" href=\"https://hominidsoftware.com/tech-personal-growth/synergy-for-tasks/#webos-task-list-managers\">#</a></h2>\n<p>Many users bemoaned the lack of a decent built-in task list manager, finding the existing Tasks application too simplistic for their needs. Some reviews of webOS devices found the built-in Tasks application adequate for their needs, but none cite it as a reason to switch to webOS. Existing third-party task list managers had some traction – reviews in the App Catalog often praise them in comparison to the built-in Tasks application. <em>Outline Tracker Free</em> made Computerworld’s list of <a href=\"https://www.computerworld.com/article/1543114/10-must-have-free-palm-webos-apps-2.html\">“10 must-have free webOS Apps”</a>. The application “To Do Classic” was popular, despite having essentially the same feature set as the built-in Tasks application.</p>\n<p>However, almost no task list managers were included in the lists of must-have paid apps being blogged during Palm’s Summer Half Off sale. The best-selling task list manager in the Palm Hot Apps promotion, Outline Tracker, placed around #52. Just under 20,000 users downloaded Outline Tracker Free (as of the start of July 2010). Using estimates of the total number of webOS devices sold, this is perhaps 2% of the user base.</p>\n<p>Task list managers did not become “must-have” apps for the average webOS user.</p>\n<h2 id=\"proposal-synergy-for-tasks\" tabindex=\"-1\">Proposal: Synergy for Tasks <a class=\"header-anchor\" href=\"https://hominidsoftware.com/tech-personal-growth/synergy-for-tasks/#proposal-synergy-for-tasks\">#</a></h2>\n<p>I propose that Tasks be reworked using Synergy. DB8 would hold tasks from various back-ends, all inheriting from a common task type. The new Tasks app would display a unified view - users could see their in-house tasks from Outlook in the same view as client-related tasks from Basecamp.</p>\n<h3 id=\"data-model\" tabindex=\"-1\">Data Model <a class=\"header-anchor\" href=\"https://hominidsoftware.com/tech-personal-growth/synergy-for-tasks/#data-model\">#</a></h3>\n<p>We would need to harmonize the differences between Google Tasks, Done!, Basecamp, etc.\nby developing a paradigm which allows the user a single interface to all of them. Any task app has two main controls: one which controls which tasks appear, and one which controls what order they appear in.</p>\n<h4 id=\"controlling-which-tasks-appear\" tabindex=\"-1\">Controlling Which Tasks Appear <a class=\"header-anchor\" href=\"https://hominidsoftware.com/tech-personal-growth/synergy-for-tasks/#controlling-which-tasks-appear\">#</a></h4>\n<p>A data model in which each task has zero or more “tags” (and tags can be added at any time) can encompass most paradigms. Tag names are one or a few words.</p>\n<p>List-based apps, such as webOS Tasks, allow the user to display the tasks from one list. This can be generalized by treating the list name as a “tag”. When the user selects the list name from a list of “tags”, the list items are displayed, as they match the “tag”.</p>\n<p>Apps based on David Allen’s “Getting Things Done” system allow displaying the user’s set of tasks by “context” or “location”. Contexts can be directly modeled as tags.</p>\n<p>Additional tags can also be generated. Project-based systems would add a tag for the project name. The account name or task source would also be a tag, allowing selection of all your Google Tasks, for example.</p>\n<p>A key point is that tags can “mean” different different things. Some tags could be to-do list names, while others are GTD contexts and still others are “project” names.</p>\n<p>The Tasks app wouldn’t care - the user selects a tag from the list of all tags, and the app displays tasks that match.</p>\n<p>A beginning user can assign a single tag to each task, and treat it like a bunch of to-do lists. If he later adds multiple tags to slice up his tasks differently, he doesn’t need to copy his tasks to a different system.</p>\n<h4 id=\"controlling-the-order\" tabindex=\"-1\">Controlling the Order <a class=\"header-anchor\" href=\"https://hominidsoftware.com/tech-personal-growth/synergy-for-tasks/#controlling-the-order\">#</a></h4>\n<p>Many task apps have a concept of “priority” or “importance”.\nAny system with two, three, four, five, six, ten or twelve levels can be mapped to a 60-level scale - and back again.\nSometimes the desired order is by Due Date. Some systems also support a Start Date.\nAlternatively, the user may wish to order tasks herself.\nA popup list selecting between these alternatives (much like the webOS Tasks app) should meet most users’ needs</p>\n<h3 id=\"synergy-connectors\" tabindex=\"-1\">Synergy Connectors <a class=\"header-anchor\" href=\"https://hominidsoftware.com/tech-personal-growth/synergy-for-tasks/#synergy-connectors\">#</a></h3>\n<p>A Connector would need to be written for each back end.\nLike Calendar, there’s no need to de-dupe tasks from different sources, so each Connector must map data from the backend into the harmonized format. In particular, each Connector would need to assign appropriate tags for incoming data, and map tags to appropriate backend data structures.</p>\n<h3 id=\"task-insertion\" tabindex=\"-1\">Task Insertion <a class=\"header-anchor\" href=\"https://hominidsoftware.com/tech-personal-growth/synergy-for-tasks/#task-insertion\">#</a></h3>\n<p>Complementing the Connectors would be a service allowing any app to create a task, with user consent. (Analogous to the API for creating a Contact: <a href=\"http://www.openwebosproject.org/docs/developer_reference/application_apis/add_contact/\">Add Contact</a></p>\n<p>A task may arrive on a user’s plate from a number of sources (“inboxes” in GTD terms): e-mail, instant messaging, phone, in person, a meeting, or a project review. A task from the real world requires the user to type it in, but digital sources should not. The best typing is none at all.</p>\n<p>Many times, receipt of an e-mail should generate a task. If users can only cut and paste the text of an e-mail, it arrives in the task list manager as an undigested blob. Metadata, such as the sender, is lost. There is no way for a task list manager to automatically assign metadata such as due date, nor to tag a task depending on which e-mail account it was sent to. Email apps could use the API to create tasks with pre-filled tags. The e-mail app knows about e-mails, so it is best positioned to create a task from an e-mail. Likewise, the phone app could inject tasks pre-populated with contact information.</p>\n<h3 id=\"a-task-service-inboxes-and-non-task-list-manager-apps\" tabindex=\"-1\">A Task Service, “Inboxes” and non-Task List Manager Apps <a class=\"header-anchor\" href=\"https://hominidsoftware.com/tech-personal-growth/synergy-for-tasks/#a-task-service-inboxes-and-non-task-list-manager-apps\">#</a></h3>\n<p>The operating system generates a small number of tasks for the user. Updating third-party apps currently depends on the user running the Updates application. While the webOS notification system is exemplary in handling do-it-now or do-it-in-ten-minutes things, it’s not designed for do-it-today or do- it-next-week things. It would be natural for update notices to go on the user’s To-Do list.</p>\n<p>Shopping search apps could create and update shopping lists integrated with a user’s other activities. While these apps <em>could</em> target the built-in Tasks application with their Tasks, that would give the user no flexibility in which task list manager he or she used.</p>\n<p>It is often possible to create a task-oriented view of cloud services which are not primarily task list managers, such as software bug-tracking systems. It is not cost-effective for developers of third party task list managers to support backends like this, but it would be cost-effective in many instances to write glue code between a webOS Task Service and such a backend. Integrating domain-specific systems with general task list management would be a killer app for many users and businesses.</p>\n<h3 id=\"universal-search\" tabindex=\"-1\">Universal Search <a class=\"header-anchor\" href=\"https://hominidsoftware.com/tech-personal-growth/synergy-for-tasks/#universal-search\">#</a></h3>\n<p>It would be straightforward to add a unified Task Service to webOS Universal Search.</p>\n<h2 id=\"palm-synergy-for-tasks\" tabindex=\"-1\">Palm Synergy for Tasks <a class=\"header-anchor\" href=\"https://hominidsoftware.com/tech-personal-growth/synergy-for-tasks/#palm-synergy-for-tasks\">#</a></h2>\n<p>A unified Task Service would thus extend Palm Synergy the logical next step. It would make webOS a preferred front-end to groupware. It would help make the webOS experience compellingly different than other smartphone platforms. I propose that Palm should develop a unified Task Service now.</p>\n",
			"date_published": "2010-06-06T00:00:00Z",
			"date_modified": "2024-08-10T22:21:05Z"
		}
		,
		{
			"id": "https://hominidsoftware.com/tech-personal-growth/maps/",
			"url": "https://hominidsoftware.com/tech-personal-growth/maps/",
			"title": "Maps — Digital vs. Paper",
			"summary": "Limitations of digital maps",
			"content_html": "<p>My pre-electronic handheld mapping tool was a Rand-McNally road atlas.  50 states, 12 provinces, and Mexico if I ever needed it.  I always made sure I had human-written directions for the last few streets.  And, you know, the only problems I had were bad signs (and my poor ability to spot small signs while driving). It only took a few seconds to flip to the right page, and the detail maps were there, too.   Of course, the detail for cities was limited, and often there was no detail map at all where I was headed.  But it got me there.</p>\n<p>My brother had Mapopolis on his Palm, which looked pretty useful (though the vector maps were hard to interpret without a scale) but I never used it enough to be sure -- certainly not enough to plunk down money for it.</p>\n<p>When Google brought out Google Maps Mobile for Palm, I downloaded it right away.  I was still using dialup, so it was painfully slow, and version 1.0 would go catatonic without a data connection.  Later they fixed that, but it was never convenient enough to take time for -- I would fire it up when I was a passenger, but the near-real-time traffic data never guided us away from traffic jams.</p>\n<p>Now I have Google Maps on my Palm Pre, and a 3G connection.  My wife and I headed off to a wedding without directions to the site.  This wedding was in Canada, where Sprint charges me 60 cents per minute, and data in proportion.   GPS is a real help in using mapping programs, when your question is &quot;how do I get there from HERE?&quot;</p>\n<p>So, I was looking up directions as we closed in on the border.  Google Maps   Now, we hoped to get there in time to stop at the hotel room to freshen up, so I loaded the route and switched to &quot;airplane mode&quot; (radios off).</p>\n<p>We ran late and had to go directly to the site.\nSo, I had directions to a hotel, but not to the wedding site, and knew Sprint would charge me an arm and a leg to download it.  We were short on options, so I turned the radio on, and -- no data service.  Fortunately, we soon spotted a Provincial visitor info center, and asked the kind ladies there.  So, we got there (and in time!) not with 21st century electronic maps, nor even 17th century paper maps, but Bronze-age stop-and-ask-the-locals.  The people who are pushing web applications for mobile need to venture further afield, and learn how far we are from the seamless communication that demands.</p>\n<p>I think it's time to buy another Rand-McNally road atlas.</p>\n",
			"date_published": "2009-07-03T00:00:00Z",
			"date_modified": "2024-08-12T04:00:50Z"
		}
		,
		{
			"id": "https://hominidsoftware.com/tech-personal-growth/knowledge-handhelds/",
			"url": "https://hominidsoftware.com/tech-personal-growth/knowledge-handhelds/",
			"title": "Knowledge &amp; Handhelds",
			"summary": "My productivity path into PDAs",
			"content_html": "<p>I’ve been using handheld computers for nine years now (not counting an earlier stint programming for the Newton back in ‘94, nor writing packages for the TI-89 calculator, which has some symbolic mathematic features that MATLAB doesn’t, nor using my Casio Data Bank wristwatch). First a Palm III, briefly a Visor Prism, then a Kyocera 7135 and a Treo 650. I’ve had to handle tech support for several Windows Mobile devices, and have handled an iPhone just enough to be intrigued. (Sorry, Symbian, you just never came my way here in the States.) While I like gadgets as much as the next guy, I try to maintain an engineer’s perspective: what does this allow people to do, what does it let them do better? Much as we compare devices to each other, it’s still not clear that handhelds are gaining ground on the 900-pound gorilla: paper and pencil.</p>\n<p>For years, I kept a paper planner. It was fine for recording dates of upcoming events, it traveled with me, unlike a wall calendar, and was a useful place to scrawl notes that I might need later that week or month. (I still use datebook applications this way – no other program I’ve used made it easy for notes to drift out of sight as they became obsolete.) When my Palm III arrived (just before the Viking millennium – but that’s another story) I was thrilled – I’m often so into my work I lose track of time, so I might know I have a meeting in an hour, but by the time to leave, have totally forgotten about it.</p>\n<p>When Verizon replaced my Kyocera 7135 with a Treo 650, an email application was included, so I gave it a try. It was irksome to configure, and (since I wasn’t willing to pay Verizon’s extortionate rates for data, irksome and slow to use dialup, too) but I kept plugging away, thinking “there must be a use for receiving email when I’m away from a computer”. One factor retarding its usefulness was the fact that many emails were of little value if you couldn’t follow the URLs contained in them, and the Treo’s web browser was not adequate for viewing most of the web (which, yes, is largely the fault of the web, but I was at the short end of that lever).\nThis spring, a colleague pointed me toward Michael Mace’s blog post <a href=\"https://mobileopportunity.blogspot.com/2007/01/shape-of-smartphone-and-mobile-data.html\">“The shape of the smartphone and mobile data markets”</a>. Market research he did for PalmSource revealed three distinct groups of users (and a big chunk of non-users). It was an “aha!” moment – that’s why there were people excited over capabilities I didn’t care about. The group he calls “information-centric users” (a commenter suggested knowledge-centric users, and that describes them a bit better) describes my use to a T. We use handheld devices to record knowledge, and retrieve it again – a backing store for our brains. While it’s nice if our handheld can hold a whole reference manual (or access it online, these days), the key thing is our notes on the manual. So the old PDA-without-a-phone was fine for us, and we’re disappointed that our needs have been shuffled aside in the rush to pour more data through handhelds.</p>\n<p>In this blog, I’ll focus on knowledge and handhelds (with excursions into any topic that grabs my fancy). I close with the motto of Richard Wesley Hamming’s book “Numerical Methods for Scientists and Engineers”:</p>\n<blockquote>\n<p>The purpose of computing is insight, not numbers.</p>\n</blockquote>\n",
			"date_published": "2009-06-21T00:00:00Z",
			"date_modified": "2024-08-10T22:18:11Z"
		}
		,
		{
			"id": "https://hominidsoftware.com/tech-personal-growth/mastermyr-chest-as-seat/",
			"url": "https://hominidsoftware.com/tech-personal-growth/mastermyr-chest-as-seat/",
			"title": "The Mästermyr chest and ‘What did Vikings sit on?’",
			"summary": "The Mästermyr chest has several unexpected design features which point toward it being a seat.",
			"content_html": "<p><em>originally posted to the Norsefolk email list</em></p>\n<p>While constructing a chest based on the Mästermyr find, I have noticed\nseveral odd features. The bottom fits into a dado on the ends, which\nextend downward to form the feet, and is also mortised into the ends,\nso weight on the bottom of the chest is transmitted to the ends (not\nodd).</p>\n<ol>\n<li>The chest is 90” long, but only 28” wide, so the bottom, only\n3/4” thick, could use some support from the sides to enhance its\nrigidity. However, the sides have rabbets, which decrease the\nthickness of wood for the pegs which hold it together, and means the\nsides rest partly on the bottom.</li>\n<li>The sides are cut in such a way that they rest partly on the ends,\nwhich makes the chest more complicated and the tolerances much more\nfinicky.</li>\n<li>The top is carved as a shallow barrel arch, which is more work than\nthe whole rest of the chest and decreases the utility of the chest as\na work surface and makes it harder to stack.</li>\n</ol>\n<p><picture><source type=\"image/avif\" srcset=\"https://hominidsoftware.com/img/Skapti-Mastermyr-chest-504w.avif 504w\" sizes=\"100vw\"><source type=\"image/webp\" srcset=\"https://hominidsoftware.com/img/Skapti-Mastermyr-chest-504w.webp 504w\" sizes=\"100vw\"><img alt=\"Mästermyr chest replica\" loading=\"lazy\" decoding=\"async\" src=\"https://hominidsoftware.com/img/Skapti-Mastermyr-chest-504w.png\" width=\"504\" height=\"360\"></picture></p>\n<p>The one thing these three design points do enhance is the ability of\nthe chest to carry weight on top of the lid, at some expense to the\nability of the chest to carry weight inside. Also, the chest is long\nenough for two adults to sit on.</p>\n<p>The majority of the half-dozen chests depicted in <a href=\"https://openlibrary.org/books/OL1743095M/From_Viking_to_crusader\"><em>From Viking to Crusader</em></a>\nare similarly long and narrow, with curved tops. I don’t know if they\nshare the other design characteristics of the Mastermyr chest as well.</p>\n<p>From this, I conclude that many, if not most, chests were designed to function well as seats.\nThis may go some way toward explaining the paucity of chairs and stools discovered.</p>\n<p>However, the Mästermyr chest has no carrying handles, making it inconvenient as a portable\nseat.  Either</p>\n<ol>\n<li>\n<p>It was expected to be placed in a good place for a seat indoors,\nand something <em>different</em> was used outdoors and for any task where you\nneeded to move your seat.  Or,</p>\n</li>\n<li>\n<p>It was not expected to be used as a portable seat very often.</p>\n</li>\n</ol>\n<p>Adding the info that there are lots of partial finds of stools, this suggests\nthe following hierarchy of seating:</p>\n<ol>\n<li>\n<p>Built in benches and/or several chests as the fixed indoor seats; enough\n(or almost enough) for the usual residents of the farm.</p>\n</li>\n<li>\n<p>Stools for moveable indoor seats and usual outdoor seats.</p>\n</li>\n<li>\n<p>Chests as extra seating for guests at feasts, weddings, and all the\nother big gatherings that were a significant part of Norse culture.</p>\n</li>\n</ol>\n<p>This would avoid the needs for lots of stools, benches, or chairs which\nwould only get used at feasts, and would need to be stored in-between times.</p>\n",
			"date_published": "2002-07-03T00:00:00Z",
			"date_modified": "2024-08-21T23:57:12Z"
		}
		,
		{
			"id": "https://hominidsoftware.com/tech-personal-growth/Late-Viking-Age-Ship-Terminology/",
			"url": "https://hominidsoftware.com/tech-personal-growth/Late-Viking-Age-Ship-Terminology/",
			"title": "Late Viking Age Ship Terminology",
			"summary": "Runestones &amp; skaldic poetry help us understand how vikings described their ships and crews.",
			"content_html": "<p><em>originally posted to the Viking Age Vessels email group</em></p>\n<p>From <em>Ships &amp; Men in the Late Viking Age</em>, by Judith Jesch, a book which studies the runestone corpus and skaldic verse from the latter half of the Viking age (there’s not much earlier material), to determine what terminology was actually used then.</p>\n<p><strong>Skip</strong> and <strong>skeið</strong> are the most common terms for ship, skip being used in many contexts showing it did not refer to any particular type or use of ship. Skeið, on the other hand, is almost always used of a ship “either on the way to or in the thick of battle and clearly connotes a warship”. Langskip (longship), despite its common use in the sagas written down post-Viking-age, means any ship that is long, i.e. not not necessarily a warship and “is not a technical term”. “The most common compound with skip is herskip ‘warship’”</p>\n<p><strong>Dreki</strong> (pl. drekkar) (‘dragon’), derived from the dragon heads on the prow (and sometimes also on the stern). It is used primarily as poetic metaphor for a ship, and “there is no evidence that it was a technical term for any particular type of ship”.</p>\n<p>Jesch confirms that <strong>knorr</strong> is more often used for a ship of trade, but notes the many places where it refers to a ship used for war. She quotes Ole Crumlin-Pedersen (1997a, 189-90 [does anyone have a copy of this?]) “that the relative beam of ships ‘changed drastically in the early phase of the process of adapting ships to carry sail, in order to provide sufficient stability at the initial stage’”. Thus, since early Viking warships such as Tune and Gokstad [anyone have length-to-beam ratios for these?] had similar proportions to cargo ships, and later ones were more slender, early overlap of knorr and terms for warship giving way to a later (late- or post-Viking) distinction is consistent with shipbuilding practice.</p>\n<p><picture><source type=\"image/avif\" srcset=\"https://hominidsoftware.com/img/Strouds-Run-0709-2867-750w.avif 750w, https://hominidsoftware.com/img/Strouds-Run-0709-2867-2032w.avif 2032w\" sizes=\"100vw\"><source type=\"image/webp\" srcset=\"https://hominidsoftware.com/img/Strouds-Run-0709-2867-750w.webp 750w, https://hominidsoftware.com/img/Strouds-Run-0709-2867-2032w.webp 2032w\" sizes=\"100vw\"><img alt=\"the Blackbird sailing at Stroud's Run\" loading=\"lazy\" decoding=\"async\" src=\"https://hominidsoftware.com/img/Strouds-Run-0709-2867-750w.jpeg\" width=\"2032\" height=\"1354\" srcset=\"https://hominidsoftware.com/img/Strouds-Run-0709-2867-750w.jpeg 750w, https://hominidsoftware.com/img/Strouds-Run-0709-2867-2032w.jpeg 2032w\" sizes=\"100vw\"></picture></p>\n<p><strong>Anchors</strong> are mentioned several times in the skaldic corpus, perhaps explained by [lacuna]. Crumlin-Pedersen (1997b, 146) makes the point that anchors are ‘the largest examples of forged ironwork’ known from the Viking Age and that, because of their cost, they were used only on the largest ships.” So, perhaps having an iron anchor on our boats would be a sign of their high quality.</p>\n<p>The skaldic corpus also provides evidence of slipways using simple log rollers to beach ships during the Viking Age. This and the references to harbors (and the pilings at the trading center on Lake Malar), suggest the Vikings only hauled their ships up on an undeveloped beach when they had to.</p>\n<p><strong>Styrimaðr</strong> (lit. ‘steersman’) is usually taken to mean captain, often captain-owner, and can also be used like a title. Sometimes it helps commemorate the sailing skills of a man, without implying command.</p>\n<p><strong>Skipari</strong> (pl. skipan) is the root of the modern Scandinavian and English ‘skipper’, but the author finds its use in the Viking Age to more often make sense as a crew member. This would be especially true of the plural skipan. Sometimes it appears to be an officer subordinate to a Styrimaðr.</p>\n<p><strong>Motunautr</strong> (pl. motunautar), ‘mess-mate’ also appears in nautical contexts.</p>\n<p><strong>Sogn</strong> and <strong>Sókn</strong> (etymologically a ‘seeking’ -&gt; attack or battle) can refer to any assemblage of people; in a nautical context this means a ship’s crew.</p>\n<p><strong>Sessi</strong>, derived from sess, rowing-bench, means ‘bench-mate’, either in the hall or on a ship.</p>\n<p><strong>Lið</strong> has a wide range of meanings, basically a group of people, “in most cases it can be translated as ‘troop’”. Sometimes, by extension, it means ‘fleet’. It occurs in many compounds. Skiplið is often taken to mean crew who will or must man a ship (as Ragnar used in the Fydraka Skiplið magnets); the author finds that in many cases ‘collection of ships’ makes inscriptions make more sense. Thingalið is much discussed by scholars, but a straightforward compound of Thing and lið should be Thinglið. Most scholars take it to refer to the retainers of a great man, but Jesch finds more sense translating it as ‘contracted troop’ from the sense of thing in which it means ‘battle’. Liðsmenn are troops strongly associated with a ship or fleet.</p>\n<p><strong>Floti</strong> refers to a large fleet, which it will take us some time to assemble. :-) Sometimes it can also refer to the crew of the fleet as well.</p>\n<p>In medieval Scandinavia, <strong>leiðangr</strong> refers to the royal levy of men and ships, but the Viking age evidence does not confirm any meaning more specific than ‘fleet’. Thus, the question of when the levy system came into use must rest on other evidence.</p>\n<p>As always, while we strive to improve our understanding, we should always remember that many interpretations of the evidence is available and be courteous about suggesting different word usage.</p>\n<p>So, may I suggest to my bench-mates that we are the Vestrus skipan?</p>\n",
			"date_published": "2002-02-15T00:00:00Z",
			"date_modified": "2025-05-28T03:27:04Z"
		}
		,
		{
			"id": "https://hominidsoftware.com/tech-personal-growth/WWDC%201994%20Newton%20Track%20Report/",
			"url": "https://hominidsoftware.com/tech-personal-growth/WWDC%201994%20Newton%20Track%20Report/",
			"title": "WWDC 1994 Newton Track Report",
			"summary": "The Apple Newton ecosystem is maturing, but the Newton isn&#39;t a great way to take notes.",
			"content_html": "<p><em>This was originally posted to a Usenet newsgroup</em></p>\n<p>I attended the Newton track of Apple's World Wide\nDevelopment Conference today. (WWDC continues until Friday)</p>\n<p>The Development Overview session was a reasonable\nintroduction to the Newton Tool Kit environment. The\nBuilding Newton Solutions session focused on four or five\napplications for specific markets. One was a program for the\nState of California's disaster evaluation. The user filled\nout a form using popup menus, lists and so forth, got the\nlocation from an attached GPS unit, and could sketch the\nscene. Another was for farmers and talked to a Windows\ndatabase. Monsato had started the project three years ago,\nfound interest by farmers in having information in the\nfield, but no interest in using laptops PC's on truck\ndashboards. The PIE pioneers program will be restructured\nat the end of the summer.</p>\n<p>I skipped the Newton Communication Wired &amp; Wireless session\nand the Bookmaker session to take advantage of the\ndebugging lab, where the Apple engineer fixed one bug in our\napplication and identified what needed to be done for\nanother.</p>\n<p>The synchronization session was very interesting,\nidentifying various levels of ease of use. Users were\nclassified as using the Newton as either a lunch box, a\ncredit card, or a collector. PIE's strategy involves PIE\ndoing the enabling work to allow third party developers to\ndevelop communications software. &quot;Code less, ship more&quot;\nNewton Connection is considered a first generation product,\nand they are moving toward toolboxes and API's for direct\nMac &amp; Windows application communication. Integration\nLibraries will be available sometime during the summer to\nallow developers to produce Mac files from the synch files.\nNewton Connection for Developers was announced, which has a\nListener window similar to the Inspector window in NTK to\nallow debugging of Meta Datas. It has been seeded to some\ndevelopers and will come out this summer.</p>\n<p>The feedback forum was lively, with developers stating their\ndesires and the PIE DTS people giving an idea how soon\nvarious upgrades and interfaces will be available. The\ncompiler is still under development. One fellow complained\nthat there was no solution for the 30 app barrier that\nworked on original MessagePad's, but another member of the\naudience said he had one in hand. Most of the concerns\nexpressed here were addressed and a number of others besides.</p>\n<p>Some notable facts I gathered:</p>\n<ul>\n<li>Transparent 110's were for sale, and a number of Apple people\nhad them.</li>\n<li>Application storage fills up separately from frames storage\n(used by running applications). The division between these\ntwo domains is fixed.</li>\n<li>Running applications from Flash RAM cards or static RAM\ncards is not noticeably slower than running from main\nmemory.</li>\n<li>Don't use full justification in print formats, it's broken.</li>\n<li>No Newton on a Mac any time soon.</li>\n<li>TCP-IP is 6-12 months away</li>\n<li>There will probably be a Newton Development conference in\nthe fall.</li>\n<li>The Alpha draft of the Human Interface guidelines has been\nposted to various sources.</li>\n<li>There is hope of support for application deletion, as\ndistinct the RemoveScript, so applications that are being\ndeleted (not just having their card removed) can deleted\ntheir soups, etc.</li>\n</ul>\n<p>Don't take any of this as gospel, I'm just typing this out\nquickly.</p>\n<p>So, overall, nothing earth-shattering, but the development\nenvironment is maturing and more and more applications are\ncoming out.</p>\n<p>I used a MP100 to gather notes, and looking back, my note\ngathering was rather inefficient in gathering information\nand spending time wisely. I didn't waste any time pawing\nthrough paper notes to find the one I wanted, but I lost\nmore time trying to get notes into the Newton. However, I\ndid get answers to almost all of my questions because I had\na To Do list of them on hand. I exchanged electronic\nbusiness cards with about two dozen people, and that was\nnice because I have the information in a usable database.\nIt was also quite useful to be able to show off the\napplications I'm working on. The Newton was also a great\nway to kill time and accomplish modest amounts of work while\ntraveling. I killed a half hour in the San Jose airport\nentering the data from the two paper business cards I\nreceived. This echoes the direction that many developers\nare taking, limiting the amount of written input necessary\nto use the program.</p>\n<p>For the next conference, I suggest speakers have their\nlecture outline available for downloading, by beaming or\notherwise. If I had the outline as a base, I could have\nadded comments and extensions and ended up with decent\nnotes. Text editing is much more feasible on the Newton than\nprimary text entering.</p>\n",
			"date_published": "1994-05-18T00:00:00Z",
			"date_modified": "2024-08-12T04:00:50Z"
		}
		
	]
}
