Wholesale rate update (2021-09-22) – with NO dirty surcharges

By Simwood

We will be updating our Managed A-Z Termination rates and codes on September 22nd 2021. As usual, these changes are colour coded in our full rate files available through the portal as below. This update includes the new UK geographic breakouts described here. Please note the important posts made regarding UK origination charging. Unlike other operators, […]

VoIP DDoS Preparations – update

By Simwood

By Simon Woodhead It has been a week or so since we last updated on the emerging threat, so we wanted to update you. Whilst nobody (except George W Bush) wants to be the one to call the end of hostilities, things appear to be returning to normal. Of course, ‘normal’ is hostile and nobody […]

Ofcom’s new loyalty scheme

By Simwood

By Simon Woodhead Our Regulator has the Statutory power to fine you. Pretty scary right? Well, it is unless you’re the former state funded monopolist! Then, you don’t just get a Crown Guarantee on your pension scheme, as well as your ‘competitors’ needing your permission to do anything, as well as them funding your forays […]

Hubble Tension

Oh, wait, I might've had it set to kph instead of mph. But that would make the discrepancy even wider!

The danger of open redirects!

By Scott Helme

Like everyone else, I get a lot of spam emails that range from downright annoying through to deceptive phishing emails that are really dangerous. Today I got one of the latter and when I do, I like to see what can be done about them.

When they make it to

Vaccine Research

Honestly feel a little sheepish about the amount of time and effort I spent confirming "yes, the vaccine helps protect people from getting sick and dying" but I guess everyone needs a hobby.

Weekly Update 260

By Troy Hunt

Presently sponsored by: 1Password is a secure password manager and digital wallet that keeps you safe online

An early one today as I made space in the schedule to get out on the water 😎 I'm really liking the new Apple AirTags, I'm disliking some of the international media coverage about Australia's COVID situation, another gov onto HIBP and a blog

Lab Equipment

I've been working on chocolate bar annealing techniques to try to produce the perfect laser s'more. Maybe don't mention that on the grant application though.

You Don't Need to Burn off Your Fingertips (and Other Biometric Authentication Myths)

By Troy Hunt

Presently sponsored by: 1Password is a secure password manager and digital wallet that keeps you safe online

111 years ago almost to the day, a murder was committed which ultimately led to the first criminal trial to use fingerprints as evidence. We've all since watched enough crime shows to understand that fingerprints are unique personal biometric attributes and to date, no two people have ever

Cowley Rd is a disaster zone for cycling

By danny

This map shows the collisions on the north-western end of Cowley Rd (the B480) between 2005 and 2019. The purple stars are serious collisions (resulting in overnight hospital stays) and the pink ones are slight ones (that resulted in police reports). collisions on Cowley Rd, 2005-2019 This map includes walking casualties as well, but the […]

Saturn Hexagon

Sorry, in SI units that's "there's a big football in there."

VoIP DDoS Preparations – Mandatory Testing

By Simwood

By Simon Woodhead Alongside recent posts here (this, this and this), shared with our mailing list, Status Page notifications drawing attention to them, and of course our Community Slack, we have highlighted on Slack voluntary testing for the last two nights. This testing is of the contingency unpublished Availability Zone which may require network operators […]

What a week!

By [email protected] (RevK)

This has been a hell of a week, and far more actual hard work than I am used too, and after it all (averaging over 15k steps a day) I have not even lost any weight!

The plan was simple, replace existing 7 door system, and PIRs and exit contacts, and so on. 28 modules in total. I have carefully made and tested all the modules and spares. All ready to go.

But I ended up making work for myself by tidying the wiring. The new system just needs power, so ended up with 6 battery boxes, and removing the old power and bus wiring. Much neater. I also needed to change the exits from rangers (that were unreliable) to new exit buttons, and hence also needed to change the break-glass boxes as they were integral. And I wanted to move the break-glasses further from the letter box (for obvious reasons). This meant running wires down the aluminium door frames on the front doors (to be tidy), which is easier said than door. I probably wasted a day on that (and I had some help). I can recommend NYLON CABLE & FLEX DRAW TAPE 30M (98FT) (screwfix 75807) for the job :-)

Finding the cable runs to bell boxes was also fun, and I gave up chasing wires to original PIR and door sensors and just ran new cables. Ceiling tiles for the win.

We actually have a mystery - the original alarm when we moved in was removed something like a decade ago, but the PIRs were still in place. When the new galaxy alarm was installed new PIRs were put in. I have actually put in new PIRs this time with integral ESP32 WiFi modules in the PIR. Part of the work was removing the galaxy system which replaced have already replaced what was there before, and removing all the old battery boxes. The original PIRs still have power and blink when people move? But there are *NO* battery boxes nor alarm panels in the building at all. I have literally removed them all, and the new battery boxes only go to my new kit. So WTAF. If I had time I'd have investigated further, but it is a mystery!

The result is it took a whole week, and I have to admit I was losing my enthusiasm somewhat during the week.

What did not help is finding some bugs and issues. I expected some, and a couple of small snags were simple, but the biggest issue was the wifi mesh being unstable. It was fine at the start but got worse during the week. I found issues with multiple wifi channels (2.4GHz) which I fixed with config changes on the APs. But I would find the mesh unstable. Reseting the wifi could fix, but not always, and changes to wifi config helped, but not in a concrete way. I wasted a lot of time on that. But ploughed on with the installed.

But Friday it was clear the problem was now intractable - the modules were all resetting every 30 seconds or so. The nice thing is the system was still usable. People in the office could come and go, as it resets very quickly and works autonomously. But it cannot work as an alarm if the mesh is not working.

It seems (and I have to do a lot more bench test and investigation to be sure) that the modules may be running out of memory when the mesh gets beyond around 12 units. This is very disappointing as I I can't see why the mesh would need much memory at all - each routing entry is a 6 byte MAC and very little else. It will be interesting to investigate.

Thankfully the site is two distinct adjacent units, so the fix was to make it two sites. That is a pain, as it means provisioning fobs for two sites, and if someone had not mistakenly ordered only 2k DESFire fobs, that would be easy, so new fobs were programmed, again! Just means slightly more admin. I cut down the sites slightly and ended with both sides with 12 units. When one had 13 it was not quite stable, but 12 seems fine. So we have a work around.

It may be that in longer term we need some modules using ESPs with extra RAM to act as root nodes, something to consider if I cannot track down the memory footprint problem.

Even so, the end result seems really good. Time will tell.

P.S. I have improved stability a lot with some tweaks to the way we work the mesh, but not solved the underlying issue. I suspect big step will be waiting for mesh code in ESP IDF to mature a little. Like cheese.

VoIP DDoS Preparations – Remember your Regulatory Obligations

By Simwood

By Peter Farmer There’s a bit of a fracas going on now, as we know from reports about sustained and targeted DDoS attacks against at least two voice providers. We do not know why these organisations were targeted – whether they were singled out for personal reasons only known to the hackers, or whether they […]

Creating a Home Alarm System with Home Assistant

By Scott Helme

I've not talked too much about my Home Assistant installation but it's absolutely amazing and I've just done something even more awesome with it. Creating a home alarm system was much easier than I'd anticipated and I'm going to share

Do adults need tetanus booster shots?


AP Computer Science Tips


The ownership and future of Mullvad VPN


Use of eBPF in CPU Scheduler




Show HN: Qsh – Improved database querying from your terminal


A search engine that favors text-heavy sites and punishes modern web design


ChowJS: An AOT JavaScript engine for game consoles


Algofi (YC S21) Is Hiring


Genius Sells to Media Lab for $80M


Deno 1.14


Show HN: Dieter Rams' design principles applied to software engineering


SSC Engine: Golang Front End Components


Please stop closing forums and moving people to Discord


Provenance: iOS and tvOS multi-emulator front end


Piers Morgan to launch new show on Rupert Murdoch-owned network

It is the controversial presenter's first major new job since he left Good Morning Britain in March.

Military to be called in to help Scottish ambulance crews

Nicola Sturgeon says she is finalising a request for "targeted military assistance" for Scotland's ambulance service.

Dowden out, Dorries in: Is UK data protection in safe hands?

By Lindsay Clark

It's a new dawn, it's a new day, it's a new life... for Dorries

Comment  Nadine Dorries is the latest government minister charged with steering the data protection law through the choppy straits between the UK's desire to unleash "data's power across the economy and society for the benefit of British citizens and British businesses", and the boring need to comply with EU data protection law.…

Chelsea's James has medals stolen in burglary while playing in Champions League

England defender Reece James says his house was broken into while he was playing for Chelsea against Zenit St Petersburg in the Champions League on Tuesday.

John Lewis charters ships to ensure Christmas stock arrives

The department store chain says it is trying everything to get goods to the UK for the holiday season.

Emma Raducanu reunited with her parents in Bromley

Emma Raducanu is photographed with father Ian after becoming Britain's youngest Grand Slam champion.

If it were possible to evade facial-recognition systems using just subtle makeup, it might look something like this

By Katyanna Quach

Interested in poking away at machine-learning models? This academic study could be a good start

Makeup carefully applied to the forehead, cheeks, and nose may help you evade facial recognition systems, judging from these computer scientists' experimental work.…

Alex Murdaugh: The hot shot US lawyer and the hit man

Months after his wife and son were found dead, police say a lawyer arranged a hit - on himself.

'I have very vivid memories' - Ricciardo on his lack of sleep since Monza win

You would think, after a troubled first half to the season, Daniel Ricciardo's taste of victory would afford him some rest - not a bit of it.

Aukus: China denounces US-UK-Australia pact as irresponsible

The alliance will allow Australia to build and deploy nuclear-powered submarines for the first time.

What have the Romans ever done for us? In ServiceNow's new Rome release, replaced intranets, for one

By Simon Sharwood

Adds Teams integration for new ‘Employee Centre’, automated automation for service desk

ServiceNow has loosed the new "Rome" release of its SaaS workflow platform on a waiting world.…

Sara Pascoe revealed as new Great British Sewing Bee host

The comic and writer is taking over from Joe Lycett, who has hosted the last three series.

Nadhim Zahawi: Iraqi refugee to education secretary

Iraqi refugee, Teletubby merchandise salesman, pollster, millionaire - meet the new education secretary.

Mother wins court case over Staffordshire landfill site emissions

Rebecca Currie says her son's breathing difficulties have been made worse by landfill emissions.

Marks & Spencer blames Brexit as it closes 11 French stores

Brexit has made it "near impossible" for it to supply fresh and chilled products to France, the retailer says.

Wrong room, buddy.

By /u/MachenSie

Wrong room, buddy. submitted by /u/MachenSie to r/gaming
[link] [comments]

Prankster harassing a man just trying to do his shopping

By /u/violetdragons

Prankster harassing a man just trying to do his shopping submitted by /u/violetdragons to r/iamatotalpieceofshit
[link] [comments]

I entered my drawing into the Village Show. There were 4 entries. I came fourth. I am unreasonably upset by it.

By /u/HotPinkLollyWimple

I entered my drawing into the Village Show. There were 4 entries. I came fourth. I am unreasonably upset by it. submitted by /u/HotPinkLollyWimple to r/CasualUK
[link] [comments]

Denis Villeneuve on the MCU

By /u/l_l_l-illiam

Denis Villeneuve on the MCU submitted by /u/l_l_l-illiam to r/marvelstudios
[link] [comments]

Northern Line new content unlocked.

By /u/lodge28

Northern Line new content unlocked. submitted by /u/lodge28 to r/london
[link] [comments]

No Tesco I do not want to round up my purchase for charity, maybe you could donate the £825 million profit you made last year instead or the 1million bonus your CEO got this year.

By /u/woolygoldfish99

submitted by /u/woolygoldfish99 to r/britishproblems
[link] [comments]

What kind of fish is this? Found in North Wales if that helps

By /u/Linthoughts

submitted by /u/Linthoughts to r/CasualUK
[link] [comments]

How Adrien Deschryver stopped a charging silverback gorilla

By /u/UnironicThatcherite

How Adrien Deschryver stopped a charging silverback gorilla submitted by /u/UnironicThatcherite to r/Damnthatsinteresting
[link] [comments]

America under socialism

By /u/xxxSexMan69xxx

America under socialism submitted by /u/xxxSexMan69xxx to r/ToiletPaperUSA
[link] [comments]

I would quite like to go to Cornwall next year. Turns out, it's cheaper to go 100 miles up north to FLY DOWN THERE than it is to get a train. Not only that, but it's £100 CHEAPER. Our rail system is broken

By /u/Twisted_nebulae

Yep, you heard that correct. It's cheaper to go 100 miles up north to Manchester and fly down than it is to get a train.

Proof of train price

Flight price, £20!

Not that I'd be able to get accommodation for a reasonable price anyway, but you get the point.

If anyone has any recommendations for other nice places to go, please let me know

submitted by /u/Twisted_nebulae to r/britishproblems
[link] [comments]

What social customs do we need to retire?

By /u/alebenchhe

submitted by /u/alebenchhe to r/AskReddit
[link] [comments]

The Pope meets Baby Pope

By /u/aracdmfgdfg

The Pope meets Baby Pope submitted by /u/aracdmfgdfg to r/nextfuckinglevel
[link] [comments]

I dont know if I want to know

By /u/brobo-baggins

I dont know if I want to know submitted by /u/brobo-baggins to r/PrequelMemes
[link] [comments]

Aston Martin F1 Team - Aston Martin Cognizant Formula One™ Team announces 2022 driver line-up (Vettel and Stroll confirmed)

By /u/glenn1812

Aston Martin F1 Team - Aston Martin Cognizant Formula One™ Team announces 2022 driver line-up (Vettel and Stroll confirmed) submitted by /u/glenn1812 to r/formula1
[link] [comments]

$GME Daily Discussion Thread

By /u/AutoModerator

$GME Daily Discussion Thread


This is the official $GME Megathread for r/Superstonk.

Please keep ALL conversations contained to Gamestop and related topics.

(review the Superstonk Rules before commenting or posting on r/Superstonk.)


Not enough karma? Here's a quick guide on how to get it.


Announcements 📣

  • Make sure to check the Announcements regularly. Large updates will be made as posts using the Moderator flair, but smaller updates will be listed in the Announcements.


Flair Links

Check out our flair system, which is easily accessible via the sidebar button widget on desktop or the About menu on mobile.

Daily Discussions | DD | Possible DD | Discussion | Question | Education & Data | News & Media | MEGA Thread | Social Media | HODL | Meme | Fluff | Opinion | Shitpost | Art & Writing | Stonky Pets | Daily News | SuperstonkBot | AMA | | Moderator


Important Links 🚨

SuperstonkBot Anonymous Whistleblower Post Bot (with review)

Want to learn more? Check out our extensive Wiki and FAQ

Daily discussion threads are created at 4:00 a.m. EDT

submitted by /u/AutoModerator to r/Superstonk
[link] [comments]

Datasette Desktop 0.2.0: The annotated release notes

Datasette Desktop is a new macOS desktop application version of Datasette, an "open source multi-tool for exploring and publishing data" built on top of SQLite. I released the first version last week - I've just released version 0.2.0 (and a 0.2.1 bug fix) with a whole bunch of critical improvements.

You can see the release notes for 0.2.0 here, but as I've done with Datasette in the past I've decided to present an annotated version of those release notes providing further background on each of the new features.

The plugin directory

A new plugin directory for installing new plugins and upgrading or uninstalling existing ones. Open it using the "Plugins -> Install and Manage Plugins..." menu item. #74

Demo showing installing and upgrading a plugin

This was the main focus for the release. Plugins are a key component of both Datasette and Datasette Desktop: my goal is for Datasette to provide a robust core for exploring databases, with a wide array of plugins that support any additional kind of visualization, exploration or data manipulation capability that a user might want.

Datasette Desktop goes as far as bundling an entire standalone Python installation just to ensure that plugins will work correctly, and invisibly sets up a dedicated Python virtual environment for plugins to install into when you first run the application.

The first version of the app allowed users to install plugins by pasting their name into a text input field. Version 0.2.0 is a whole lot more sophisticated: the single input field has been replaced by a full plugin directory interface that shows installed v.s. available plugins and provides "Install", "Upgrade" and "Uninstall" buttons depending on the state of the plugin.

When I set out to build this I knew I wanted to hit this JSON API on datasette.io to fetch the list of plugins, and I knew I wanted a simple searchable index page. The I realized I also wanted faceted search, so I could filter for installed vs not-yet-installed plugins.

Datasette's built-in table interface already implements faceted search! So I decided to use that, with some custom templates to add the install buttons and display the plugins in a more suitable format.

The first challenge was getting the latest list of plugins into my Datasette instance. I built this into the datasette-app-support plugin using the startup() plugin hook - every time the server starts up it hits that API and populates an in-memory table with the returned data.

The data from the API is then extended with four extra columns:

The data needed to build the plugin table is gathered by these three lines of code:

plugins = httpx.get(
# Annotate with list of installed plugins
installed_plugins = {
    plugin["name"]: plugin["version"]
    for plugin in (await datasette.client.get("/-/plugins.json")).json()
default_plugins = (os.environ.get("DATASETTE_DEFAULT_PLUGINS") or "").split()

The first line fetches the full list of known plugins from the Datasette plugin directory

The second makes an internal API call to the Datasette /-/plugins.json endpoint using the datasette.client mechanism to discover what plugins are currently installed and their versions.

The third line loads a space-separated list of default plugins from the DATASETTE_DEFAULT_PLUGINS environment variable.

That last one deserves further explanation. Datasette Desktop now ships with some default plugins, and the point of truth for what those are lives in the Electron app codebase - because that's where the code responsible for installing them is.

Five plugins are now installed by default: datasette-vega, datasette-cluster-map, datasette-pretty-json, datasette-edit-schema and datasette-configure-fts. #81

The plugin directory needs to know what these defaults are so it can avoid showing the "uninstall" button for those plugins. Uninstalling them currently makes no sense because Datasette Desktop installs any missing dependencies when the app starts, which would instantly undo the user's uninstall action decision.

An environment variable felt like the most straight-forward way to expose that list of default plugins to the underlying Datasette server!

I plan to make default plugins uninstallable in the future but doing so require a mechanism for persisting user preference state which I haven't built yet (see issue #101).

A log on the loading screen

The application loading screen now shows a log of what is going on. #70

The first time you launch the Datasette Desktop application it creates a virtual environment and installs datasette, datasette-app-support and the five default plugins (plus their dependencies) into that environment.

Animated demo of the Datasette Desktop launch screen showing the log scrolling past

This can take quite a few seconds, during which the original app would show an indeterminate loading indicator.

Personally I hate loading indicators which don't show the difference between something that's working and something that's eternally hung. Since I can't estimate how long it will take, I decided to pipe the log of what the pip install command is doing to the loading screen itself.

For most users this will be meaningless, but hopefully will help communicate "I'm installing extra stuff that I need". Advanced users may find this useful though, especially for bug reporting if something goes wrong.

Under the hood I implemented this using a Node.js EventEmitter. I use the same trick to forward server log output to the "Debug -> Show Sever Log" interface.

Example CSV files

The welcome screen now invites you to try out the application by opening interesting example CSV files, taking advantage of the new "File -> Open CSV from URL..." feature. #91

Previously Datasette Desktop wouldn't do anything at all until you opened up a CSV or SQLite database, and I have a hunch that unlike me most people don't have good examples of those to hand at all times!

The new welcome screen offers example CSV files that can be opened directly from the internet. I implemented this using a new API at datasette.io/content/example_csvs (add .json for the JSON version) which is loaded by code running on that welcome page.

I have two examples at the moment, for the Squirrel Census and the London Fire Brigade's animal rescue data. I'll be adding more in the future.

The API itself is a great example of the Baked Data architectural pattern in action: the data itself is stored in this hand-edited YAML file, which is compiled to SQLite every time the site is deployed.

To get this feature working I added a new "Open CSV from URL" capability to the app, which is also available in the File menu. Under the hood this works by passing the provided URL to the new /-/open-csv-from-url API endpoint. The implementation of this was surprisingly fiddly as I wanted to consume the CSV file using an asynchronous HTTP client - I ended up using an adaption of some example code from the aiofile README.

Recently opened files and "Open with Datasette"

Recently opened .db and .csv files can now be accessed from the new "File -> Open Recent" menu. Thanks, Kapilan M! #54

This was the project's first external contribution! Kapilan M figured out a way to hook into the macOS "recent files" mechanism from Electron, and I expanded that to cover SQLite database in addition to CSV files.

When a recent file is selected, Electron fires the "open-file" event. This same event is fired when a file is opened using "Open With -> Datasette" or dragged onto the application's dock.

This meant I needed to tell the difference between a CSV or a SQLite database file, which I do by checking if the first 16 bytes of the file match the SQLite header of SQLite format 3\0.

.db and .csv files can now be opened in Datasette starting from the Finder using "Right Click -> Open With -> Datasette". #40

Registering Datasette as a file handler for .csv and .db was not at all obvious. It turned out to involve adding the following to the Electron app's package.json file:

  "build": {
    "appId": "io.datasette.app",
    "mac": {
      "category": "public.app-category.developer-tools",
      "extendInfo": {
        "CFBundleDocumentTypes": [
            "CFBundleTypeExtensions": [
            "LSHandlerRank": "Alternate"

The Debug Menu

A new Debug menu can be enabled using Datasette -> About Datasette -> Enable Debug Menu".

The debug menu existed previously in development mode, but with 0.2.0 I decided to expose it to end users. I didn't want to show it to people who weren't ready to see it, so you have to first enable it using a button on the about menu.

The most interesting option there is "Run Server Manually".

Most of the time when you are using the app there's a datasette Python server running under the hood, but it's entirely managed by the Node.js child_process module.

When developing the application (or associated plugins) it can be useful to manually run that server rather than having it managed by the app, so you can see more detailed error messages or even add the --pdb option to drop into a debugger should something go wrong.

To run that server, you need the Electron app to kill its own version... and you then need to know things like what port it was running on and which environment variables it was using.

Here's what you see when you click the "Run Server Manually" debug option:

Run server manually? Clicking OK will terminate the Datasette server used by this app. Copy this command to a terminal to manually run a replacement

Here's that command in full:

DATASETTE_API_TOKEN="0ebb45444ba4cbcbacdbcbb989bb0cd3aa10773c0dfce73c0115868d0cee2afa" DATASETTE_SECRET="4a8ac89d0d269c31d99059933040b4511869c12dfa699a1429ea29ee3310a850" DATASETTE_DEFAULT_PLUGINS="datasette datasette-app-support datasette-vega datasette-cluster-map datasette-pretty-json datasette-edit-schema datasette-configure-fts datasette-leaflet" /Users/simon/.datasette-app/venv/bin/datasette --port 8002 --version-note xyz-for-datasette-app --setting sql_time_limit_ms 10000 --setting max_returned_rows 2000 --setting facet_time_limit_ms 3000 --setting max_csv_mb 0

This is a simulation of the command that the app itself used to launch the server. Pasting that into a terminal will produce an exact copy of the original process - and you can add --pdb or other options to further customize it.

Bonus: Restoring the in-memory database on restart

This didn't make it into the formal release notes, but it's a fun bug that I fixed in this release.

Datasette Desktop defaults to opening CSV files in an in-memory database. You can import them into an on-disk database too, but if you just want to start exploring CSV data in Datasette I decided an in-memory database would be a better starting point.

There's one problem with this: installing a plugin requires a Datasette server restart, and restarting the server clears the content of that in-memory database, causing any tables created from imported CSVs to disappear. This is confusing!

You can follow my progress on this in issue #42: If you open a CSV and then install a plugin the CSV table vanishes. I ended up solving it by adding code that dumps the "temporary" in-memory database to a file on disk before a server restart, restarts the server, then copies that disk backup into memory again.

This works using two custom API endpoints added to the datasette-app-support plugin:

These APIs are called from the startOrRestart() method any time the server restarts, using a file path generated by Electron using the following:

backupPath = path.join(

The file is deleted once it has been restored.

After much experimentation, I ended up using the db.backup(other_connection) method that was added to Python's sqlite3 module in Python 3.7. Since Datasette Desktop bundles its own copy of Python 3.9 I don't have to worry about compatibility with older versions at all.

The rest is in the milestone

If you want even more detailed notes on what into the release, each new feature is included in the 0.2.0 milestone, accompanied by a detailed issue with screenshots (and even a few videos) plus links to the underlying commits.

Quoting Matt Levine

Imagine writing the investment memo for “20% of a picture of a dog” and being like “the most we should pay is probably about $2 million because the whole picture of the dog sold for $4 million three months ago and it can’t realistically have appreciated more than 150% since then; even if the whole picture of the dog is worth, aggressively, $10 million, this share would be worth $2 milllion.” What nonsense that is!

Matt Levine

Datasette Desktop - a macOS desktop application for Datasette

I just released version 0.1.0 of the new Datasette macOS desktop application, the first version that end-users can easily install. I would very much appreciate your help testing it out!

Datasette Desktop

Datasette Desktop screenshot

Datasette is "an open source multi-tool for exploring and publishing data". It's a Python web application that lets you explore data held in SQLite databases, plus a growing ecosystem of plugins for visualizing and manipulating those databases.

Datasette is aimed at data journalists, museum curators, archivists, local governments, scientists, researchers and anyone else who has data that they wish to explore and share with the world.

There's just one big catch: since it's a Python web application, those users have needed to figure out how to install and run Python software in order to use it. For people who don't live and breath Python and the command-line this turns out to be a substantial barrier to entry!

Datasette Desktop is my latest attempt at addressing this problem. I've packaged up Datasette, SQLite and a full copy of Python such that users can download and uncompress a zip file, drag it into their /Applications folder and start using Datasette, without needing to know that there's a Python web server running under the hood (or even understand what a Python web server is).

Please try it out, and send me feedback and suggestions on GitHub.

What the app does

This initial release has a small but useful set of features:

How the app works

There are three components to the app:

The first is the macOS application itself. This is currently written with Electron, and bundles a full copy of Python 3.9 (based on python-build-standalone by Gregory Szorc). Bundling Python is essential: the principal goal of the app is to allow people to use Datasette who aren't ready to figure out how to install their own Python environment. Having an isolated and self-contained Python is also a great way of avoiding making XKCD 1987 even worse.

The macOS application doesn't actually include Datasette itself. Instead, on first launch it creates a new Python virtual environment (currently in ~/.datasette-app/venv, feedback on that location welcome) and installs the other two components: Datasette and the datasette-app-support plugin.

Having a dedicated virtual environment is what enables the "Install Plugin" menu option. When a plugin is installed the macOS application runs pip install name-of-plugin and then restarts the Datasette server process, causing it to load that new plugin.

The datasette-app-support plugin is designed exclusively to work with this application. It adds API endpoints that the Electron shell can use to trigger specific actions, such as "import from this CSV file" or "attach this SQLite database" - these are generally triggered by macOS application menu items.

It also adds a custom authentication mechanism. The user of the app should have special permissions: only they should be able to import a CSV file from anywhere on their computer into Datasette. But for the "network share" feature I want other users to be able to access the web application.

An interesting consequence of installing Datasette on first-run rather than bundling it with the application is that the user will be able to upgrade to future Datasette releases without needing to re-install the application itself.

How I built it

I've been building this application completely in public over the past two weeks, writing up my notes and research in GitHub issues as I went (here's the initial release milestone).

I had to figure out a lot of stuff!

First, Electron. Since almost all of the user-facing interface is provided by the existing Datasette web application, Electron was a natural fit: I needed help powering native menus and bundling everything up as an installable application, which Electron handles extremely well.

I also have ambitions to get a Windows version working in the future, which should share almost all of the same code.

Electron also has fantastic initial developer onboarding. I'd love to achieve a similar level of quality for Datasette some day.

The single biggest challenge was figuring out how to bundle a working copy of the Datasette Python application to run inside the Electron application.

My initial plan (touched on last week) was to compile Datasette and its dependencies into a single executable using PyInstaller or PyOxidizer or py2app.

These tools strip down a Python application to the minimal required set of dependencies and then use various tricks to compress that all into a single binary. They are really clever. For many projects I imagine this would be the right way to go.

I had one big problem though: I wanted to support plugin installation. Datasette plugins can have their own dependencies, and could potentially use any of the code from the Python standard library. This means that a stripped-down Python isn't actually right for this project: I need a full installation, standard library and all.

Telling the user they had to install Python themselves was an absolute non-starter: the entire point of this project is to make Datasette available to users who are unwilling or unable to jump through those hoops.

Gregory Szorc built PyOxidizer, and as part of that he built python-build-standalone:

This project produces self-contained, highly-portable Python distributions. These Python distributions contain a fully-usable, full-featured Python installation as well as their build artifacts (object files, libraries, etc).

Sounds like exactly what I needed! I opened a research issue, built a proof-of-concept and decided to commit to that as the approach I was going to use. Here's a TIL that describes how I'm doing this: Bundling Python inside an Electron app

(I find GitHub issue threads to be the ideal way of exploring these kinds of areas. Many of my repositories have a research label specifically to track them.)

The last key step was figuring out how to sign the application, so I could distribute it to other macOS users without them facing this dreaded dialog:

Datasette.app can't be opened because Apple cannot check it for malicious software

It turns out there are two steps to this these days: signing the code with a developer certificate, and then "notarizing" it, which involves uploading the bundle to Apple's servers, having them scan it for malicious code and attaching the resulting approval to the bundle.

I was expecting figuring this out to be a nightmare. It ended up not too bad: I spent two days on it, but most of the work ended up being done by electron-builder - one of the biggest advantages of working within the Electron ecosystem is that a lot of people have put a lot of effort into these final steps.

I was adamant that my eventual signing and notarization solution should be automated using GitHub Actions: nothing defangs a frustrating build process more than good automation! This made things a bit harder because all of the tutorials and documentation assumed you were working with a GUI, but I got there in the end. I wrote this all up as a TIL: Signing and notarizing an Electron app for distribution using GitHub Actions (see also Attaching a generated file to a GitHub release using Actions).

What's next

I announced the release last night on Twitter and I've already started getting feedback. This has resulted in a growing number of issues under the usability label.

My expectation is that most improvements made for the benefit of Datasette Desktop will benefit the regular Datasette web application too.

There's also a strategic component to this. I'm investing a lot of development work in Datasette, and I want that work to have the biggest impact possible. Datasette Desktop is an important new distribution channel, which also means that any time I add a new feature to Datasette or build a new plugin the desktop application should see the same benefit as the hosted web application.

If I'm unlucky I'll find this slows me down: every feature I build will need to include consideration as to how it affects the desktop application.

My intuition currently is that this trade-off will be worthwhile: I don't think ensuring desktop compatibility will be a significant burden, and the added value from getting new features almost for free through a whole separate distribution channel should hopefully be huge!

TIL this week

Releases this week

Datasette Desktop 0.1.0

Datasette Desktop 0.1.0

This is the first installable version of the new Datasette Desktop macOS application I've been building. Please try it out and leave feedback on Twitter or on the GitHub Discussions thread linked from the release notes.

Via @simonw

Quoting Solomon Hykes

We never shipped a great commercial product. The reason for that is we didn’t focus. We tried to do a little bit of everything. It’s hard enough to maintain the growth of your developer community and build one great commercial product, let alone three or four, and it is impossible to do both, but that’s what we tried to do and we spent an enormous amount of money doing it.

Solomon Hykes

Making world-class docs takes effort

Making world-class docs takes effort

Curl maintainer Daniel Stenberg writes about his principles for good documentation. I agree with all of these: he emphasizes keeping docs in the repo, avoiding the temptation to exclusively generate them from code, featuring examples and ensuring every API you provide has documentation. Daniel describes an approach similar to the documentation unit tests I've been using for my own projects: he has scripts which scan the curl documentation to ensure not only that everything is documented but that each documentation area contains the same sections in the same order.

Via Hacker News

Talking to the Competition and Markets Authority about Apple

By sil

Last week I was part of a meeting with the UK’s Competition and Markets Authority, the regulator, to talk about Apple devices and the browser choice (or lack of it) on them. They’re doing a big study into Apple’s conduct in relation to the distribution of apps on iOS and iPadOS devices in the UK, in particular, the terms and conditions governing app developers’ access to Apple’s App Store, and part of that involves looking at browsers on iOS, and part of that involves talking to people who work on the web. So myself and Bruce Lawson and another UK developer of iOS and web apps put together some thoughts and had a useful long meeting with the CMA on the topic.

They asked that we keep confidential the exact details of what was discussed and asked, which I think is reasonable, but I did put together a slide deck to summarise my thoughts which I presented to them, and you can certainly see that. It’s at kryogenix.org/code/cma-apple and shows everything that I presented to the CMA along with my detailed notes on what it all means.

A slide from the presentation, showing a graph of how far behind Safari is and indicating that all other browsers on iOS are equally far behind, because they're all also Safari

Bruce had a similar slide deck, and you can read his slides on iOS’s browser monopoly and progressive web apps. Bruce has also summarised our other colleague’s presentation, which is what we led off with. The discussion that we then went into was really interesting; they asked some very sensible questions, and showed every sign of properly understanding the problem already and wanting to understand it better. This was good: honestly, I was a bit worried that we might be trying to explain the difference between a browser and a rendering engine to a bunch of retired colonel types who find technology to be baffling and perhaps a little unmanly, and this was emphatically not the case; I found the committee engaging and knowledgeable, and this is encouraging.

In the last few weeks we’ve seen quite a few different governments and regulatory authorities begin to take a stand against tech companies generally and Apple’s control over your devices more specifically. These are baby steps — video and music apps are now permitted to add a link to their own website, saints preserve us, after the Japan Fair Trade Commission’s investigation; developers are now allowed to send emails to their own users which mention payments, which is being hailed as “flexibility” although it doesn’t allow app devs to tell their users about other payment options in the app itself, and there are still court cases and regulatory investigations going on all around the world. Still, the tide may be changing here.

What I would like is that I can give users the best experience on the web, on the best mobile hardware. That best mobile hardware is Apple’s, but at the moment if I want to choose Apple hardware I have to choose a sub-par web experience. Nobody can fix this other than Apple, and there are a bunch of approaches that they could take — they could make Safari be a best-in-class experience for the web, or they could allow other people to collaborate on making the browser best-in-class, or they could stop blocking other browsers from their hardware. People have lots of opinions about which of these, or what else, could and should be done about this; I think pretty much everyone thinks that something should be done about it, though. Even if your goal is to slow the web down and to think that it shouldn’t compete with native apps, there’s no real reason why flexbox and grid and transforms should be worse in Safari, right? Anyway, go and read the talk for more detail on all that. And I’m interested in what you think. Do please hit me up on Twitter about this, or anything else; what do you think should be done, and how?

Per-project PostgreSQL

Per-project PostgreSQL

Jamey Sharp describes an ingenious way of setting up PostgreSQL instances for each of your local development project, without depending on an always-running shared localhost database server. The trick is a shell script which creates a PGDATA folder in the current folder and then instantiates a PostgreSQL server in --single single user mode which listens on a Unix domain socket in that folder, instead of listening on the network. Jamey then uses direnv to automatically configure that PostgreSQL, initializing the DB if necessary, for each of his project folders.

Via John Wiseman

Free software activities in August 2021

This is my monthly update covering what I have been doing in the free software world throughout August 2021 (view report for July).


Reproducible Builds

The motivation behind Reproducible Builds is to ensure no flaws have been introduced during compilation processes by promising identical results are always generated from a given source. This allows multiple third-parties to come to a consensus on whether a build was compromised or not.

This month, I:

I also made the following changes to diffoscope, including uploading versions 180, 181 and 182 to Debian.



I also sponsored an upload of adminer version 4.8.1-1 for Alexandre Rossi.


Debian LTS

This month I have worked 18 hours on Debian Long Term Support (LTS) and 12 hours on its sister Extended LTS project.

This month, I:

You can find out more about the LTS and ELTS projects via the following video:

Quoting Avery Pennarun

Unshipped work is inventory and it costs you money as it spoils

Avery Pennarun

Building a desktop application for Datasette (and weeknotes)

This week I started experimenting with a desktop application version of Datasette - with the goal of providing people who aren't comfortable with the command-line the ability to get Datasette up and running on their own personal computers.

Update 8th September 2021: I made a bunch more progress over the week following this post, see Datasette Desktop—a macOS desktop application for Datasette for details or download the app to try it out.

Screenshot of the new Datasette desktop app prototype with several open windows

Why a desktop application?

On Monday I kicked off an enormous Twitter conversation when I posted:

I wonder how much of the popularity of R among some communities in comparison to Python comes down to the fact that with R you can install the RStudio desktop application and you're ready to go

This ties into my single biggest complaint about Python: it's just too hard for people to get started with. Setting up a Python development environment for the first time remains an enormous barrier to entry.

I later put this in stronger terms:

The more I think about this the more frustrated I get, thinking about the enormous amount of human potential that's squandered because the barriers to getting started learning to program are so much higher than they need to be

Which made me think of glass houses. My own Datasette project has exactly the same problem: to run it locally you need to install Python and then install Datasette! Mac users can use Homebrew, but telling newcomers to install Homebrew first isn't particularly welcoming either.

Ideally, I'd like people to be able to install a regular desktop application and start using Datasette that way, without even needing to know that it's written in Python.

There's been an open issue to get Datasette running as a standalone binary using PyInstaller since November 2017, with quite a bit of research.

But I want a UI as well: I don't want to have to teach new users how to install and run a command-line application if I can avoid it.

So I decided to spend some time researching Electron to see how hard it would be to make a basic Datasette desktop application a reality.

Progress so far

The code I've written so far can be found in the simonw/datasette.app repository on GitHub. The app so far does the following:

Here's a video demo showing these features in action:

It's very much an MVP, but I'm encouraged by the progress so far. I think this is enough of a proof of concept to be worth turning this into an actual usable product.

How this all works

There are two components to the application.

The first is a thin Electron shell, responsible for launching the Python server, managing windows and configuring the various desktop menu options used to configure it. The code for that lives in main.js.

The second is a custom Datasette plugin that adds extra functionality needed by the application. Currently this consists of a tiny bit of extra CSS to make the footer stick to the bottom of the window, and a custom API endpoint at /-/open-database-file which is called by the menu option for opening a new database.

Initial impressions of Electron

I know it's cool to knock Electron, but in this case it feels like exactly the right tool for the job. Datasette is already a web application - what I need is a way to hide the configuration of that web application behind an icon, and re-present the interface in a way that feels more like a desktop application.

This is my first time building anything with Electron - here are some of my initial impressions.

Up next: packaging the app

I was hoping to get to this before writing up my progress in these weeknotes, but it looks like it's going to be quite a challenge.

In order to produce an installable macOS app (I'll dive into Windows later) I need to do the following:

I'm expecting figuring this out to be a long-winded and frustrating experience, which is more the fault of Apple than of Electron. I'm tracking my progress on this in issue #7.

Datasette 0.59a2

I pushed out a new alpha of Datasette earlier this week, partly driven by work I was doing on datasette.app.

The biggest new feature in this release is a new plugin hook: register_commands() - which lets plugins add additional commands to Datasette, e.g. datasette verify name-of-file.db.

I released a new plugin that exercises this hook called datasette-verify. Past experience has shown me that it's crucial to ship an example plugin alongside a new hook, to help confirm that the hook design is fit for purpose.

It turns out I didn't need this for datasette.app after all, but it's still a great capability to have!

sqlite-utils 3.17

Quoting the release notes in full:

  • The sqlite-utils memory command has a new --analyze option, which runs the equivalent of the analyze-tables command directly against the in-memory database created from the incoming CSV or JSON data. (#320)
  • sqlite-utils insert-files now has the ability to insert file contents in to TEXT columns in addition to the default BLOB. Pass the --text option or use content_text as a column specifier. (#319)

evernote-to-sqlite 0.3.2

As a follow-up to last week's work on my personal Dogsheep, I decided to re-import my Evernote notes... and found out that Evernote has changed their export mechanism in ways that broke my tool. Most concerningly their exported XML is even less well-formed than it used to be. This new release works around that.

TIL this week

Releases this week

Dynamic content for GitHub repository templates using cookiecutter and GitHub Actions

GitHub repository templates were introduced a couple of years ago to provide a mechanism for creating a brand new GitHub repository starting with an initial set of files.

They have one big limitation: the repositories that they create share the exact same contents as the template repository. They're basically a replacement for duplicating an existing folder and using that as the starting point for a new project.

I'm a big fan of the Python cookiecutter tool, which provides a way to dynamically create new folder structures from user-provided variables using Jinja templates to generate content.

This morning, inspired by this repo by Bruno Rocha, I finally figured out a neat pattern for combining cookiecutter with repository templates to compensate for that missing dynamic content ability.

The result: datasette-plugin-template-repository for creating new Datasette plugins with a single click, python-lib-template-repository for creating new Python libraries and click-app-template-repository for creating Click CLI tools.


I maintain three cookiecutter templates at the moment:

Having installed cookiecutter (pip install cookiecutter) each of these can be used like so:

% cookiecutter gh:simonw/datasette-plugin
plugin_name []: visualize counties
description []: Datasette plugin for visualizing counties
hyphenated [visualize-counties]: 
underscored [visualize_counties]: 
github_username []: simonw
author_name []: Simon Willison
include_static_directory []: y
include_templates_directory []: 

Cookiecutter prompts for some variables defined in a cookiecutter.json file, then generates the project by evaluating the templates.

The challenge was: how can I run this automatically when a new repository is created from a GitHub repository template? And where can I get those variables from?

Bruno's trick: a self-rewriting repository

Bruno has a brilliant trick for getting this to run, exhibited by this workflow YAML. His workflow starts like this:

name: Rename the project from template

on: [push]

    if: ${{ github.repository != 'rochacbruno/python-project-template' }}
    runs-on: ubuntu-latest
       # ...

This means that his workflow only runs on copies of the original repository - the workflow is disabled in the template repository itself by that if: condition.

Then at the end of the workflow he does this:

      - uses: stefanzweifel/[email protected]
          commit_message: "Ready to clone and code"
          push_options: --force

This does a force push to replace the contents of the repository with whatever was generated by the rest of the workflow script!

This trick was exactly what I needed to get cookiecutter to work with repository templates.

Gathering variables using the GitHub GraphQL API

All three of my existing cookiecutter templates require the following variables:

I need values for all of these before I can run cookiecutter.

It turns out they are all available from the GitHub GraphQL API, which can be called from the initial workflow copied from the repository template!

Here's the GitHub Actions step that does that:

- uses: actions/[email protected]
  id: fetch-repo-and-user-details
    script: |
      const query = `query($owner:String!, $name:String!) {
        repository(owner:$owner, name:$name) {
          owner {
            ... on User {
            ... on Organization {
      const variables = {
        owner: context.repo.owner,
        name: context.repo.repo
      const result = await github.graphql(query, variables)
      return result

Here I'm using the actions/github-script action, which provides a pre-configured, authenticated instance of GitHub's octokit/rest.js JavaScript library. You can then provide custom JavaScript that will be executed by the action.

await github.graphql(query, variables) can then execute a GitHub GraphQL query. The query I'm using here gives me back the currenty repository's name and description and the login and display name of the owner of that repository.

GitHub repositories can be owned by either a user or an organization - the ... on User / ... on Organization syntax provides the same result here for both types of nested object.

The output of this GraphQL query looks something like this:

  "repository": {
    "name": "datasette-verify",
    "description": "Verify that files can be opened by Datasette",
    "owner": {
      "login": "simonw",
      "name": "Simon Willison"

I assigned an id of fetch-repo-and-user-details to that step of the workflow, so that the return value from the script could be accessed as JSON in the next step.

Passing those variables to cookiecutter

Cookiecutter defaults to asking for variables interactively, but it also supports passing in those variables as command-line parameters.

Here's part of my next workflow steps that executes cookiecutter using the variables collected by the GraphQL query:

- name: Rebuild contents using cookiecutter
    INFO: ${{ steps.fetch-repo-and-user-details.outputs.result }}
  run: |
    export REPO_NAME=$(echo $INFO | jq -r '.repository.name')
    # Run cookiecutter
    cookiecutter gh:simonw/python-lib --no-input \
      lib_name=$REPO_NAME \
      description="$(echo $INFO | jq -r .repository.description)" \
      github_username="$(echo $INFO | jq -r .repository.owner.login)" \
      author_name="$(echo $INFO | jq -r .repository.owner.name)"

The env: INFO: block exposes an environment variable called INFO to the step, populated with the output of the previous fetch-repo-and-user-details step - a string of JSON.

Then within the body of the step I use jq to extract out the details that I need - first the repository name:

export REPO_NAME=$(echo $INFO | jq -r '.repository.name')

Then I pass the other details directly to cookiecutter as arguments:

cookiecutter gh:simonw/python-lib --no-input \
  lib_name=$REPO_NAME \
  description="$(echo $INFO | jq -r .repository.description)" \
  github_username="$(echo $INFO | jq -r .repository.owner.login)" \
  author_name="$(echo $INFO | jq -r .repository.owner.name)"

jq -r ensures that the raw text value is returned by jq, as opposed to the JSON string value which would be wrapped in double quotes.

Cleaning up at the end

Running cookiecutter in this way creates a folder within the root of the repository that duplicates the repository name, something like this:


I actually want the contents of that folder to live in the root, so the next step I run is:

mv $REPO_NAME/* .
mv $REPO_NAME/.gitignore .
mv $REPO_NAME/.github .

Here's my completed workflow.

This almost worked - but when I tried to run it for the first time I got this error:

![remote rejected] (refusing to allow an integration to create or update .github/workflows/publish.yml)

It turns out the credentials provided to GitHub Actions are forbidden from making modifications to their own workflow files!

I can understand why that limitation is in place, but it's frustrating here. For the moment, my workaround is to do this just before pushing the final content back to the repository:

mv .github/workflows .github/rename-this-to-workflows

I leave it up to the user to rename that folder back again when they want to enable the workflows that have been generated for them.

Give these a go

I've set up two templates using this pattern now:

Both of these work the same way: enter a repository name and description, click "Create repository from template" and watch as GitHub copies the new repository and then, a few seconds later, runs the workflow to execute the cookiecutter template to replace the contents with the final result.

You can see examples of repositories that I created using these templates here:

Quoting Ron Amadeo

Allo shows the ultimate failure of Google's Minimum Viable Product strategy. MVP works when you have almost no competition, or if you are taking a radically different approach to what's on the market, but it completely falls on its face when you are just straight-up cloning an established competitor. There's no reason to use a half-baked WhatsApp clone when regular WhatsApp exists.

Ron Amadeo

API Tokens: A Tedious Survey

API Tokens: A Tedious Survey

Thomas Ptacek reviews different approaches to implementing secure API tokens, from simple random strings stored in a database through various categories of signed token to exotic formats like Macaroons and Biscuits, both new to me.

Macaroons carry a signed list of restrictions with them, but combine it with a mechanism where a client can add their own additional restrictions, sign the combination and pass the token on to someone else.

Biscuits are similar, but "embed Datalog programs to evaluate whether a token allows an operation".



A new project by FastAPI creator Sebastián Ramírez: SQLModel builds on top of both SQLAlchemy and Sebastián's Pydantic validation library to provide a new ORM that's designed around Python 3's optional typing. The real brilliance here is that a SQLModel subclass is simultaneously a valid SQLAlchemy ORM model AND a valid Pydantic validation model, saving on duplicate code by allowing the same class to be used both for form/API validation and for interacting with the database.

Mini Hovercraft

I challenged myself to build a mini hovercraft in only a few days as part of a new video series!

Aviation Weather Map

Sure, you could look outside for the current weather, but isn't it a lot more fun to build a live-updating map instead?

E-Paper Weather Display

What happens when you combine two-colour e-paper with bad Python? Weather! Well, weather displays.

The RFID Checklist

What do you do when you want to massively over-engineer a solution to forgetting your phone charger?

The Long Drive

Over a thousand miles over some of the loneliest areas of the USA. What's not to love?

Travel Equipment: 2019 Edition

Taking a look at some of the key travelling equipment I've grown to like in the last year of travel.

ASGI 3.0

Upgrading the ASGI spec to simplify it, while keeping backwards compatibility.

A Django Async Roadmap

Taking a look at what it would take to make Django async-native, what it enables, and if we should even do it at all.

Python & Async Simplified

Event loops, coroutines and awaits, oh my!

Channels 2.0

Finally, the promised land is here and Channels 2.0 is released. But how much has changed? And why?

CodeSOD: Subbing for the Subcontractors

By Remy Porter

Back in the mid-2000s, Maurice got less than tempting offer. A large US city had hired a major contracting firm, that contracting firm had subcontracted out the job, and those subcontractors let the project spiral completely out of control. The customer and the primary contracting firm wanted to hire new subcontractors to try and save the project.

As this was the mid-2000s, the project had started its life as a VB6 project. Then someone realized this was a terrible idea, and decided to make it a VB.Net project, without actually changing any of the already written code, though. That leads to code like this:

Private Function getDefaultPath(ByRef obj As Object, ByRef Categoryid As Integer) As String Dim sQRY As String Dim dtSysType As New DataTable Dim iMPTaxYear As Integer Dim lEffTaxYear As Long Dim dtControl As New DataTable Const sSDATNew As String = "NC" getDefaultPath = False sQRY = "select TAXBILLINGYEAR from t_controltable" dtControl = goDB.GetDataTable("Control", sQRY) iMPTaxYear = dtControl.Rows(0).Item("TAXBILLINGYEAR") 'iMPTaxYear = CShort(cmbTaxYear.Text) If goCalendar.effTaxYearByTaxYear(iMPTaxYear, lEffTaxYear) Then End If sQRY = " " sQRY = "select * from T_SysType where MTYPECODE = '" & sSDATNew & "'" & _ " and msystypecategoryid = " & Categoryid & " and meffstatus = 'A' and " & _ lEffTaxYear & " between mbegTaxYear and mendTaxYear" dtSysType = goDB.GetDataTable("SysType", sQRY) If dtSysType.Rows.Count > 0 Then obj.Text = dtSysType.Rows(0).Item("MSYSTYPEVALUE1") Else obj.Text = "" End If getDefaultPath = True End Function

Indentation as the original.

This function was the culmination of four years of effort on the part of the original subcontractor. The indentation is designed to make this difficult to read- wait, no. That would imply that the indentation was designed. This random collection of spaces makes the code hard to read, so let's get some big picture stuff.

It's called getDefaultpath and returns a String. That seems reasonable, so let's skip down to the return statement, which of course is done in its usual VB6 idiom, where we set the function name equal to the result: getDefaultPath = True Oh… so it doesn't return the path. It returns "True". As a string.

Tracing through, we first query t_controltable to populate iMPTaxYear. Once we have that, we can do this delightful check:

If goCalendar.effTaxYearByTaxYear(iMPTaxYear, lEffTaxYear) Then End If

Then we do some string concatenation to build a new query, and for a change, this is an example that doesn't really open up any SQL injection attacks. All the fields are either numerics or hard-coded constants. It's still awful, but at least it's not a gaping security hole.

That gets us a set of rows from the SysType table, which we can then consume:

If dtSysType.Rows.Count > 0 Then obj.Text = dtSysType.Rows(0).Item("MSYSTYPEVALUE1") Else obj.Text = "" End If

This is our "return" line. You wouldn't know it from the function signature, but obj as Object is actually a textbox. So this function runs a pair of queries against the database to populate a UI element directly with the result.

And this function is just one small example. Maurice adds:

There are 5,188 GOTO statements in 1321 code files. Error handling consists almost entirely of a messagebox, and nowhere did they use Option Strict or Option Explicit.

There's so much horror contained in those two sentences, right there. For those that don't know VisualBasic, Option Strict and Option Explicit are usually enabled by default. Strict forces you to respect types- it won't do any late binding on types, it won't allow narrowing conversions between types. It would prohibit calling obj.Text =… like we see in the example above. Explicit requires you to declare variables before using them.

Now, if you're writing clean code in the first place, Option Strict and Option Explicit aren't truly required- a language like Python, for example, is neither strict no explicit. But a code base like this, without those flags? Madness.

Maurice finishes:

This is but one example from the system. Luckily for the city, what took the subcontractors 4 years to destroy only took us a few months to whip into shape.

[Advertisement] Otter - Provision your servers automatically without ever needing to log-in to a command prompt. Get started today!

CodeSOD: The Programmer's Motto and Other Comments

By Remy Porter

We've got a lovely backlog of short snippets of code, and it's been a long time since our last smorgasbord, so let's take a look at some… choice cuts.

Let's open with a comment, found by Russell F:

//setting Text="" on the front end some how stoped a error on tftweb-02a on prealpha it may have also needed a new compiled version //but after two + hours it doesnt work and i am not shure i acutal did anything

"After two+ hours, it doesn't work, and I'm not sure I actually did anything," describes the experience of being a programmer so well, that I honestly think it's my new motto. The key difference is that, if it doesn't work after two hours, you do have to keep going until it does.

From an Anonymous submitter, we have:

[Required(ErrorMessage = "This field is required."), ValidateMaxLength(Length = 10)] [Range(typeof(bool), "false", "true", ErrorMessage = "Enter valid value.")] public Nullable<bool> Nonbillable { get; set; }

Now, this is probably actually correct, because it's possible that the underlying data store might have invalid entries, so marking a Required field as Nullable probably makes sense. Then again, the chance of having invalid data in your datastore is a WTF, and apparently, it's a big problem for this API, as our submitter adds: "Looking at a very confused public-facing API - everything is like this."

"R3D3-1" was checking a recent release of Emacs, and found this function in python.el.gz:

(defun python-hideshow-forward-sexp-function (arg) "Python specific `forward-sexp' function for `hs-minor-mode'. Argument ARG is ignored." arg ; Shut up, byte compiler. (python-nav-end-of-defun) (unless (python-info-current-line-empty-p) (backward-char)))

"Shut up, byte compiler". In this case, the programmer was trying to get an "unused parameter" warning to go away by using the parameter.

"R3D3-1" adds:

The comment made me chuckle a little, not a major WTF.
The correct solution in Emacs Lisp would have been to rename arg to _arg. This would be clear to not only the byte compiler, but also to other programmers.

And finally, a frustrated Cassi found this comment:

// TODO: handle this correctly

Cassi titled this "So TODO it already!" If you're writing code you know is incorrect, it might be a good time to stop and re-evaluate what you're doing. Though, Cassi goes on to add:

I suppose it could be argued, since I'm only coming across it now, that this comment was a good enough "solution" for the five years it's been sitting in the code.

Perhaps correctness isn't as important as we think.

[Advertisement] Keep the plebs out of prod. Restrict NuGet feed privileges with ProGet. Learn more.

CodeSOD: Wise About Bits

By Remy Porter

The HP3000 was the first mini-computer that supported time-sharing. It launched in 1972, and HP didn't end-of-life it until 2010, and there are still third-party vendors supporting them.

Leonora's submission is some code she encountered a number of years ago, but not as many as you might think. It's in Pascal, and it's important to note that this version of Pascal definitely has bitwise operators. But, if you're programming on a 40 year old minicomputer, maybe you couldn't do an Internet search, and maybe Steve from down the hall had bogarted the one manual HP provided for the computer so you can't look it up because "he's using it for reference."

So you end up doing your best with no idea:

FUNCTION BITON(A , B : INTEGER): BOOLEAN; VAR C : INTEGER; BEGIN CASE A OF 15 : C:=1; 14 : C:=2; 13 : C:=4; 12 : C:=8; 11 : C:=16; 10 : C:=32; 9 : C:=64; 8 : C:=128; 7 : C:=256; 6 : C:=512; 5 : C:=1024; 4 : C:=2048; 3 : C:=4096; 2 : C:=8192; 1 : C:=16384; 0 : C:=32768; OTHERWISE BITON:=FALSE; END; IF ((B DIV C) MOD 2) = 1 THEN BITON:=TRUE ELSE BITON:=FALSE; END;

One thing I appreciate about Pascal code is that, even if you haven't touched the language since 1998 when you were the last class in your high school to learn Pascal instead of C++, it's incredibly readable. This method is very clear about what it does: it maps bits to powers of two, and then checks via division and modulus if that bit is set. It's, in some ways, the most obvious way to implement a bit check if you didn't know anything about bitwise operations in your language.

This BITON function lays the foundation for an entire family of bitwise operations, re-implemented from scratch. You want to set bits individually? You already know how it works.

FUNCTION SETBITON(A, B : INTEGER) : INTEGER; VAR C : INTEGER; BEGIN CASE A OF 15 : C:=1; 14 : C:=2; 13 : C:=4; 12 : C:=8; 11 : C:=16; 10 : C:=32; 9 : C:=64; 8 : C:=128; 7 : C:=256; 6 : C:=512; 5 : C:=1024; 4 : C:=2048; 3 : C:=4096; 2 : C:=8192; 1 : C:=16384; 0 : C:=32768; OTHERWISE C:=0; END; IF NOT BITON(A,B) THEN SETBITON:=B + C ELSE SETBITON:=B; END; FUNCTION SETBITOFF(A, B : INTEGER) : INTEGER; VAR C : INTEGER; BEGIN CASE A OF 15 : C:=1; 14 : C:=2; 13 : C:=4; 12 : C:=8; 11 : C:=16; 10 : C:=32; 9 : C:=64; 8 : C:=128; 7 : C:=256; 6 : C:=512; 5 : C:=1024; 4 : C:=2048; 3 : C:=4096; 2 : C:=8192; 1 : C:=16384; 0 : C:=32768; OTHERWISE C:=0; END; IF BITON(A,B) THEN SETBITOFF:=B - C ELSE SETBITOFF:=B; END;

The same pattern, complete with 16 bits hand-coded, and a check: if the bit is on, we add or subtract a value to set it off.

And, if you want an and operator, why, that's just going to call those methods:


Again, I want to stress, while different Pascal compilers have different implementations of bitwise operations, this version absolutely had bitwise operations. As do most of them. The key difference is whether or not it supports C-style <</>> operators, or uses a more Pascal-flavored shl/shr.

This developer obviously didn't know about them, and didn't know about the right way to do exponentiation either, which would make those giant case statements go away. Not as well as bitshifting, but still, away. But they clearly did their best- the code is readable, clear, and obvious in how it functions. Just, y'know, not as obvious as using the built-ins.

[Advertisement] Otter - Provision your servers automatically without ever needing to log-in to a command prompt. Get started today!

CodeSOD: A Coded Escape

By Remy Porter

When evaluating a new development tool or framework, the first thing the smart developer does is check out the vendor documentation. Those docs will either be your best friend, or your worst enemy. A great product with bad documentation will provide nothing but frustration, but even a mediocre product with clean and clear documentation at least lets you get useful stuff done.

Stuart Longland's company has already picked the product, unfortunately, so Stuart's left combing through the documentation. This particular product exposes a web-socket based API, and thus includes JavaScript samples in its documentation. Obviously, one could use any language they like to talk to web-sockets, but examples are nice…

webSocket.onopen = function () { let session_id = "SESSION-ID"; // Received from API create session request let network_id = "NETWORK-ID"; // Received from API create session request let reference = "REFERENCE-ID"; // Reference handle created by client to link messages to relevant callbacks let wire = 1; // Connection ID, incremental value to identify messages of network/connection let type = 1; // Client type, use value 1 (FRONTEND) const OPEN = JSON.stringify({ "method": "open", "id": network_id, "session": session_id, "ref": reference, "wire": wire, "type": type }); this.send(decodeURIComponent(escape(OPEN))); };

This all seems mostly reasonable until you get to the last line:


escape is a deprecated method similar to encodeURIComponent. So this encodes our JSON string, then decodes it, then sends it over the web-socket. Which seems… like a useless step. And it probably is- this is probably a developer's brain-fart that happened to end up in the code-base, and then later on, ended up in the documentation.

But it might not be. Because escape and encodeURIComponent are not the same method. They don't escape characters the same way, because one of them is unicode compliant, and the other isn't.

escape('äöü'); //"%E4%F6%FC" encodeURIComponent('äöü'); //"%C3%A4%C3%B6%C3%BC"

And that unicode awareness goes for the inverse method, too.

unescape(escape('äöü')); //outputs "äöü" decodeURIComponent(encodeURIComponent('äöü')); //outputs "äöü" unescape(encodeURIComponent('äöü')); //outputs "äöü" decodeURIComponent(escape('äöü')); // throws a URIError exception

Now, it's unlikely that this particular JSON message contains any characters that would cause any problems- REFERENCE-ID, SESSION-ID and the others are probably just long hex-strings. So in real-world use, this probably would never cause an actual problem.

But in the situations where it does, this would create a surprising and probably annoying to debug glitch.

Character encodings are hard, but good documentation is even harder.

[Advertisement] ProGet’s got you covered with security and access controls on your NuGet feeds. Learn more.

Error'd: Swordfish

By Lyle Seaman

Despite literally predating paper, passcodes and secret handshakes continue to perplex programmers, actors, and artists alike.

For our first example, auteur Andy stages a spare play in three acts.
Nagg: Hello I'm not the account owner and shouldn't be logged in to this account. Can you help me?
Nell: Sure, here are the owner's credit card details. Please use those to say that you are the account owner.



Fellow arts enthusiast Paul shares some Surrealism "snatched from the official Greek government site for emergency communications."



Web comics fan Geoff G. alludes to a classic (we all know which one) with his "Now I have two problems..."



While an anonymous gourmand mumbles, mouth full, "Unicode Tofu is my secrets ingredient!"



And oldworlder Jan declares this bit of user experience needs no words. "Who needs a description when you have clear symbols?" It's like a watercolor about a novel.



Finally, Dima R. brings down the curtain with this little mind blower. Quoth he: "It's secured by shibboleths." Or encrapted by wishes.



[Advertisement] Keep the plebs out of prod. Restrict NuGet feed privileges with ProGet. Learn more.

CodeSOD: Going Through Some Changes

By Remy Porter

Dave inherited a data management tool. It was an antique WinForms application that users would use to edit a whole pile of business specific data in one of those awkward "we implemented a tree structure on top of an RDBMS" patterns. As users made changes, their edits would get marked with a "pending" status, allowing them to be saved in the database and seen by other users, but with a clear "this isn't for real yet" signal.

One developer had a simple task: update a text box with the number of pending changes, and if it's non-zero, make the text red and boldfaced. This developer knew that some of these data access methods might not return any data, so they were very careful to "handle" exceptions.

int changes = 0; try { changes = DataNode.DataNodeDataSet(Convert.ToInt32(Status.PendingNew)).Tables[0].Rows.Count; } finally{} try { changes += DataVersion.GetVersionTable(Convert.ToInt32(Status.PendingNew)).Rows.Count; } finally{} try { changes += DataOrderVersion.DataOrderVersionDataSet(Convert.ToInt32(Status.PendingNew)).Tables[0].Rows.Count; } finally{} if (changes > 0) { Pending.Font.Bold = true; Pending.ForeColor = System.Drawing.Color.Red; } Pending.Text = changes.ToString();

The indentation is this way in the original source.

This… works. Almost. They set the changes variable to zero, then wrap all the attempts to access potentially null values in try blocks. In lieu of having an empty catch, which I suspect their linter was set to complain about, they opted to have an empty finally. Unfortunately, without that empty catch, the exception does get just tossed up the chain, meaning this doesn't work.

But even if it worked, I hate it.

And then there's the seemingly random indentation. Visual Studio automatically corrects the indentation for you! You have to work hard to get it messed up this badly!

In any case, I definitely have some pending changes for this code.

[Advertisement] BuildMaster allows you to create a self-service release management platform that allows different teams to manage their applications. Explore how!

CodeSOD: Columns of a Constant Length

By Remy Porter

Today's submitter goes by "[object Object]", which I appreciate the JavaScript gag even when they send us C code.

This particular bit of C code exists to help output data in fixed-width files. What you run into, with fixed-width files, is that it becomes very important to properly pad all your columns. It's not a difficult programming challenge, but it's also easy to make mistakes that cause hard-to-spot bugs. And given that most systems using fixed-width files are legacy systems with their own idiosyncrasies, things could easily go wrong.

Things go more wrong when you don't actually know the right way to pad strings. Thus this excerpt from constants.h.

#define LABEL_SIZE1 1 #define LABEL_SIZE2 2 #define LABEL_SIZE3 3 #define LABEL_SIZE4 4 #define LABEL_SIZE5 5 #define LABEL_SIZE6 6 #define LABEL_SIZE7 7 #define LABEL_SIZE8 8 #define LABEL_SIZE9 9 #define LABEL_SIZE10 10 #define LABEL_SIZE11 11 #define LABEL_SIZE12 12 #define LABEL_SIZE14 14 #define LABEL_SIZE15 15 #define LABEL_SIZE16 16 #define LABEL_SIZE21 21 #define LABEL_SIZE20 20 #define LABEL_SIZE23 23 #define LABEL_SIZE24 24 #define LABEL_SIZE25 25 #define LABEL_SIZE30 30 #define LABEL_SIZE31 31 #define LABEL_SIZE32 32 #define LABEL_SIZE33 33 #define LABEL_SIZE37 37 #define LABEL_SIZE39 39 #define LABEL_SIZE40 40 #define LABEL_SIZE43 43 #define LABEL_SIZE45 45 #define LABEL_SIZE48 48 #define LABEL_SIZE50 50 #define LABEL_SIZE53 53 #define LABEL_SIZE73 73 #define LABEL_SIZE80 80 #define LABEL_SIZE121 121 #define LABEL_SIZE100 100 #define LABEL_SIZE149 149 #define LABEL_SIZE150 150 #define LABEL_SIZE170 170 #define LABEL_SIZE175 175 #define LABEL_SIZE205 205 #define LABEL_SIZE208 208 #define LABEL_SIZE723 723 #define LABEL_SIZE725 725 #define LABEL_SIZE753 753 #define LABEL_SIZE825 825 #define LABEL_SIZE853 853 #define SPACE_1 " " #define SPACE_2 " " #define SPACE_3 " " #define SPACE_4 " " #define SPACE_5 " " #define SPACE_8 " " #define SPACE_10 " " #define SPACE_11 " " #define SPACE_12 " " #define SPACE_13 " " #define SPACE_14 " " #define SPACE_15 " " #define SPACE_19 " " #define SPACE_20 " " #define SPACE_21 " " #define SPACE_23 " " #define SPACE_25 " " #define SPACE_29 " " #define SPACE_30 " " #define SPACE_31 " " #define SPACE_32 " " #define SPACE_37 " " #define SPACE_39 " " #define SPACE_41 " " #define SPACE_53 " " #define SPACE_57 " " #define ZERO_1 "0" #define ZERO_2 "00" #define ZERO_3 "000" #define ZERO_4 "0000" #define ZERO_5 "00000" #define ZERO_8 "00000000" #define ZERO_10 "0000000000" #define ZERO_11 "00000000000" #define ZERO_14 "00000000000000" #define ZERO_29 "00000000000000000000000000000" #define NINE_11 "99999999999" #define NINE_29 "99999999999999999999999999999" // Min max values #define MIN_MINUS1 -1 #define MIN_0 0 #define MIN_1 1 #define MIN_111 111 #define MAX_0 0 #define MAX_1 1 #define MAX_2 2 #define MAX_3 3 #define MAX_4 4 #define MAX_7 7 #define MAX_9 9 #define MAX_12 12 #define MAX_15 15 #define MAX_63 63 #define MAX_99 99 #define MAX_114 114 #define MAX_127 127 #define MAX_255 255 #define MAX_256 256 #define MAX_999 999 #define MAX_1023 1023 #define MAX_4095 4095 #define MAX_9999 9999 #define MAX_16383 16383 #define MAX_65535 65535 #define MAX_9_5 99999 #define MAX_9_6 999999 #define MAX_9_7 9999999 #define MAX_9_8 99999999 #define MAX_9_9 999999999 #define MAX_9_10 9999999999 #define MAX_9_11 99999999999

The full file is 500 lines long, all in this pattern. It's also delightfully meta: these constants are used for generating fixed-width files, and this file is itself a fixed-width file, thanks to the developer wearing their tab key out.

[Advertisement] BuildMaster allows you to create a self-service release management platform that allows different teams to manage their applications. Explore how!

CodeSOD: Insertion

By Remy Porter

Shalonda inherited a C# GUI application that, if we're being charitable, has problems. It's slow, it's buggy, it crashes a lot. The users hate it, the developers hate it, but it's also one of the core applications that drives their business, so everyone needs to use it.

One thing the application needs to do is manage a list of icons. Each icon is an image, and based on user actions, a new icon might get inserted in the middle of the list. This is how that happens:

/// <summary> /// Inserts an object (should be an Image) at the specified index /// </summary> /// <param name="index">the index where to add the object at</param> /// <param name="val">the object (an Image) to be added to this ImageCollection</param> public void Insert(int index, object val) { object[] icons = new object[this.list.Count]; object[] newicons = new object[this.list.Count + 1]; for (int i = 0; i < newicons.Length; i++) { if (i != index) newicons[i] = icons[i]; else newicons[i] = val; } this.list.Clear(); this.list.AddRange(newicons); }

A comment like "Inserts an object (should be an Image)", in a strongly typed language, is always a bad sign. And sure enough, the signature of this method continues the bad signs: object val. Insert, in this case, is not a method defined in an interface, there's no reason for it to be val here other than the fact that the original developer probably had a snippet for handling inserting into lists, and just dropped it in.

Then we create two new arrays, both of which are empty. Then we iterate across those empty arrays, copying emptiness from the first one into the second one, except when we're at the index supplied by the caller, in which case we put our input value into the array.

Fortunately, at this point, our program is guaranteed to throw an exception, since icons has one fewer index than newicons, and they're both being indexed by i, which goes up to newicons.Length. This is actually the best case for this block of code, because of what comes next: it empties the list and then inserts the newicons (which is all nulls except for one position) into the list.

List, in this case, is an ArrayList, which definitely doesn't already have an insert method which actually does what it's supposed to.

Shalonda replaced this method with a call to the built-in Insert. This stopped the exceptions from being thrown, but that in turn uncovered a whole new set of bugs that no one had seen yet. As the song goes: "99 little bugs in the tracker, 99 little bugs. Take one down, patch it around, 175 bugs in the tracker!"

[Advertisement] Continuously monitor your servers for configuration changes, and report when there's configuration drift. Get started with Otter today!

Classic WTF: Crazy Like a Fox(Pro)

By Remy Porter

It's Labor Day in the US. We're busy partaking in traditional celebrations, which depending on who you ask, is either enjoying one of the last nice long weekends before winter, or throwing bricks at Pinkertons. So we dig back into the archives, for a classic story about databases. Original --Remy

“Database portability” is one of the key things that modern data access frameworks try and ensure for your application. If you’re using an RDBMS, the same data access layer can hopefully work across any RDBMS. Of course, since every RDBMS has its own slightly different idiom of SQL, and since you might depend on stored procedures, triggers, or views, you’re often tied to a specific database vendor, and sometimes a version.

Keulemans Chama fox.png

And really, for your enterprise applications, how often do you really change out your underlying database layer?

Well, for Eion Robb, it’s a pretty common occurrence. Their software, even their SaaS offering of it, allows their customers a great deal of flexibility in choosing a database. As a result, their PHP-based data access layer tries to abstract out the ugly details, they restrict themselves to a subset of SQL, and have a lot of late nights fighting through the surprising bugs.

The databases they support are the big ones- Oracle, SQL Server, MySQL, and FoxPro. Oh, there are others that Eion’s team supports, but it’s FoxPro that’s the big one. Visual FoxPro’s last version was released in 2004, and the last service pack it received was in 2007. Not many vendors support FoxPro, and that’s one of Eion’s company’s selling points to their customers.

The system worked, mostly. Until one day, when it absolutely didn’t. Their hosted SaaS offering crashed hard. So hard that the webserver spinlocked and nothing got logged. Eion had another late night, trying to trace through and figure out: which customer was causing the crash, and what were they doing?

Many hours of debugging and crying later, Eion tracked down the problem to some code which tracked sales or exchanges of product- transactions which might not have a price when they occur.

$query .= odbc_iif("SUM(price) = 0", 0, "SUM(priceact)/SUM(" . odbc_iif("price != 0", 1, 0) . ")") . " AS price_avg ";

odbc_iif was one of their abstractions- an iif function, aka a ternary. In this case, if the SUM(price) isn’t zero, then divide the SUM(priceact) by the number of non-zero prices in the price column. This ensures that there is at least one non-zero price entry. Then they can average out the actual price across all those non-zero price entries, ignoring all the “free” exchanges.

This line wasn’t failing all the time, which added to Eion’s frustration. It failed when two very specific things were true. The first factor was the database- it only failed in FoxPro. The second factor was the data- it only failed when the first product in the resultset had no entries with a price greater than zero.

Why? Well, we have to think about where FoxPro comes from. FoxPro’s design goal was to be a data-driven programming environment for non-programmers. Like a lot of those environments, it tries its best not to yell at you about types. In fact, if you’re feeding data into a table, you don’t even have to specify the type of the column- it will pick the “correct” type by looking at the first row.

So, look at the iif again. If the SUM(price) = 0 we output 0 in our resultset. Guess what FoxPro decides the datatype must be? A single digit number. If the second row has an average price of, say, 9.99, that’s not a single digit number, and FoxPro explodes and takes down everything else with it.

Eion needed to fix this in a way that didn’t break their “database agnostic” code, and thus would continue to work in FoxPro and all the other databases, with at least predictable errors (that don’t crash the whole system). In the moment, suffering through the emergency, Eion changed the code to this:

$query .= "SUM(priceact)/SUM(" . odbc_iif("price != 0", 1, 0) . ")") . " AS price_avg ";

Without the zero check, any products which had no sales would trigger a divide-by-zero error. This was a catchable, trappable error, even in FoxPro. Eion made the change in production, got the system back up and their customers happy, and then actually put the change in source control with a very apologetic commit message.

[Advertisement] Keep the plebs out of prod. Restrict NuGet feed privileges with ProGet. Learn more.

Error'd: Just Doer It

By Lyle Seaman

Testing in production again, here's five fails for the fifth day of the week. Or the sixth. Or is it the fourth?

Anonymous Ignoronymous declares "Dude! Science tests were never popular!"



While pronouncedly polyonymous Scott Christian Simmons proffers "How do doers forget to do their ONE JOB"



And probably pseudonymous Like H. explains it's because "More doing, less testing"



But querulous Quentin quibbles "Only shown in test mode. Oh well, what the hell! Nothing like testing the full user base. "



Finally, longtime reader, rare contributor Robin Z. shares: "While trying to see if tickets for UK Games Expo are available yet, I saw they had a shop section - but nothing to see there, apart from some good old testing in production."



[Advertisement] Continuously monitor your servers for configuration changes, and report when there's configuration drift. Get started with Otter today!

CodeSOD: Dangerous Tools for Dangerous Users

By Remy Porter

Despite being a programmer, I make software that goes in big things, which means that my workplace frequently involves the operation of power tools. My co-workers… discourage me from using the power tools. I'm not the handiest of people, and thus watching me work is awkward, uncomfortable, and creates a sense of danger. I'm allowed to use impact drivers and soldering irons, but when it comes time to use some of the more complex power saws, people gently nudge me aside.

There are tools that are valuable, but are just dangerous in the hands of the inexperienced. And even if they don't hurt themselves, you might end up boggling at the logic which made them use the tool that way. I'm talking, of course, about pre-compiler macros.

Lucas inherited some C++ code that depends on some macros, like this one:

#define CONDITION_CHECK(condition, FailureOp) if(!(condition)){FailureOp;}

This isn't, in-and-of-itself, terrible. It could definitely help with readability, especially with the right conditions. So what does it look like in use?

switch( transaction_type ) { case TYPE_ONE: case TYPE_TWO: return new CTransactionHandlerClass(/*stuff*/); default: break; } CONDITION_CHECK( false, return NULL );


Even if we generously wanted to permit the use of literal true/false flags as some sort of debugging flag, this clearly isn't one of the situations where that makes sense. We always want to return NULL. There's never a time where we'd flip that flag to true to not return NULL.

CSpecificTransactionClass* pTrans = dynamic_cast< CAbstractTransactionClass* >( command ); if ( pTrans ) { CONDITION_CHECK( pTrans, return false); //stuff… }

So, we do a dynamic cast, which if it fails is going to return a null value. So we have to check to see if it succeeded, which is what our if statement is doing. Once we know it succeeded, we immediately check to see if it failed.

In this case, that CONDITION_CHECK is just useless. But why be useless when you can also be too late?

CBaseCustomer *pCustomer; CRetailCustomer *pRetail = new CRetailCustomer; pCustomer = pRetail; pCustomer->SetName( pName ); CONDITION_CHECK( pRetail, return false );

So, here, we have a safety check… after we interact with the possibly-not-intitialized object. Better late than never, I suppose.

Once, at work, someone handed me a bit of lumber and a hand saw, and told me to cut it. So I started, and after about a minute of watching me fail, they pointed out that the way I'd supported the lumber was causing it to bind the saw and pinch, because I had no clue what I was doing.

Which is to say: I think the developer writing and using this macro is much like me and the handsaw. It should be simple, it should be obvious, but when you have no clue what you're doing, you might not hurt yourself, but you'll make your co-workers laugh at you.

[Advertisement] Keep the plebs out of prod. Restrict NuGet feed privileges with ProGet. Learn more.

CodeSOD: Maintaining Yourself

By Remy Porter

When moving from one programming language to another, it's easy to slip into idioms that might be appropriate in one, but are wildly out of place in another. Tammy's company has some veteran developers who spent most of their careers developing in COBOL, and now' they're developing in C#. As sufficiently determined programmers, they're finding ways to write COBOL in C#. Bad COBOL.

Methods tend towards long- one thousand lines of code isn't unusual. Longer methods exist. Every method starts with a big long pile of variable declarations. Objects are used more as namespaces than anything relating to object-oriented design. So much data is passed around as 2D arrays, because someone liked working with data like it lived in a table.

But this method comes from one specific developer, who had been with the company for 25+ years. Tammy noticed it because, well, it's short, and doesn't have much by way of giant piles of variables. It's also, in every way, wrong.

public static bool _readOnlyMode; public static bool _hasDataChanged; //... public bool HasDataChanged() { try { if (_readOnlyMode == false) { _hasDataChanged = true; btnPrint.Enabled = true; btnPrintPreview.Enabled = true; btnSave.Enabled = true; btnCancel.Enabled = true; } } catch (Exception ex) { } }

So, first, we note that _reandOnlyMode and _hasDataChanged are static, reinforcing the idea that this class isn't an object, but it's a namespace for data. Except the method, HasDataChanged isn't static, which is going to be fun for everyone else trying to trace through how data and values change. Note, also, that these names use the _ prefix, a convention used to identify private variables, but these are explicitly public.

The method is marked as a bool function, but never returns a value. The name and signature imply that this is a simple "question" method: has the data changed? True or false. But that's not what this method does at all. It checks if _readOnlyMode is false, and if it is, we enable a bunch of controls and set _hasDataChanged to true. Instead of returning a value, we are just setting the global public static variable _hasDataChanged.

And the whole thing is wrapped up in an exception handler that ignores the exception. Which, either none of this code could ever throw an exception, making that pointless, or there's no guarantee that all the btn… objects actually exist and there's a chance of null reference exceptions.

Tammy has inherited this application, and her assignment is to perform "maintenance". This means she doesn't touch the code until something breaks, then she spends a few days trying to replicate the error and then pick apart the thicket of global variables and spaghetti code to understand what went wrong, then usually instead of changing the code, she provides the end user with instructions on how to enter that data in a way that won't cause the application to crash, or manually updates a database record that's causing the crash. "Maintenance" means "keep in the same way", not "fix anything".

[Advertisement] BuildMaster allows you to create a self-service release management platform that allows different teams to manage their applications. Explore how!

CodeSOD: Mark it Zero

By Remy Porter

Sometimes, we get a submission and the submitter provides absolutely no context. Sometimes, the snippet is even really short, or the problem is "subtle" in a way that means we can't spot it when skimming the inbox.

Which is why this submission from "Bus Error" has been sitting in the inbox for seven years, and why just today, as I was skimming old submissions, I finally saw what was great about this little block of C-code.

struct sockaddr_in serv_addr; memset(&serv_addr, '0', sizeof(serv_addr));

The goal of this block of code is to ensure that the serv_addr variable is set to all zeros before it gets used elsewhere. But instead of doing that, this sets it to all '0'- the character, not the number. So instead, this initializes all the memory to 0x30.

Now, given that the first field in a sockaddr_in is the address family, which must be AF_INET on Linux, this is definitely not going to work. Even if it was actually memsetting to 0, it still wouldn't be a correct thing to do in this case. Plus, there's a whole family of methods meant to initialize this structure to the correct usable values, so this memset shouldn't be there at all.

Without context, I suspect this was programming by incantation: someone learned the hard way that variables in C don't start with a known value, so they decided to make sure that every variable they declared got zeroed out. It was a magic spell that solved a problem they didn't understand.

[Advertisement] BuildMaster allows you to create a self-service release management platform that allows different teams to manage their applications. Explore how!

CodeSOD: By Any Other Name

By Remy Porter

One of the biggest challenges in working with financial data is sanitizing the data into a canonical form. Oh, all the numeric bits are almost always going to be accurate, but when pulling data from multiple systems, is the name "John Doe", "John Q. Doe", "J. Doe"? What do we do when one system uses their mailing address and another uses their actual street address, which might use different municipality names? Or in all the other ways that important identifying information might have different representations.

This is Andres' job. Pull in data from multiple sources, massage it into some meaningful and consistent representation, and then hand it off to analysts who do some capitalism with it. Sometimes, though, it's not the data that needs to be cleaned up- it's the code. A previous developer provided this Visual Basic for Applications method for extracting first names:

Function getFirstnames(Name) Dim temp As String Dim parts Dim i As Long parts = Split(Trim(Name), " ", , vbTextCompare) 'For i = LBound(parts) To UBound(parts) For i = UBound(parts) To UBound(parts) temp = parts(i) temp = Replace(Trim(Name), temp, "") Exit For Next i getFirstnames = Trim(temp) End Function

Setting aside the falsehoods programmers believe about names, this is… uh… one way to accomplish the goal.

We start by splitting the string on spaces. Then we want to loop across it… sort of.

Commented out is a line that would be a more conventional loop. Note the use of LBound because VBA and older versions of Visual Basic allow you to use any starting index, so you can't assume the lower-bound is zero. This line would effectively loop across the array, if it were active.

Instead, we loop from UBound to UBound. That guarantees a one iteration loop, which opens a thorny philosophical question: if your loop body will only ever execute once, did you really write a loop?

Regardless, we'll take parts(i), the last element in the array, and chuck it into a temp variable. And then, we'll replace that value in the original string with an empty string. Then, just to be sure our loop which never loops never loops, we Exit For.

So, instead of getting the "first names", this might be better described as "stripping the surname". Except, and I know I said we were going to set aside the falsehoods programmers believe about names, the last name in someone's name isn't always their surname. Some cultures reverse the order. Spanish tradition gives everyone two surnames, from both parents, so "José Martinez Arbó" should be shortened to just "José", if our goal is the first name.

But there's still a more subtle bug in this, because it uses Replace. So, if the last name happens to be a substring of the other names, "Liam Alistair Li" would get turned into "am Astair", which is a potentially funny nickname, but I don't think a financial company should be on a nickname basis with their clients.

[Advertisement] ProGet’s got you covered with security and access controls on your NuGet feeds. Learn more.

Error'd: Hunger

By Lyle Seaman

No real theme this week, just a handful of whoopses, culminating in a whoopsiedaisytopsyturvysuperduper huh?

Excited Python fan Adam B. sneaks in some low-key publicity for the 3.10 release, saying "The community is so excited about the upcoming 3.10 release, they ensured that everyone notices the announcement."



Disoriented Jon who is not from Oceania puzzles "Upon noting the two close buttons, I wondered if it would make any more sense if I actually did turn my monitor upside-down."



Inspired by a novel recipe, Michael now thirsts for knowledge. "I really want to find out more about this promotion."



While on the other hand, soupless Carl C. hungers for sustenance of the more mundane form: "Fascinating, DoorDash, but what do I have to do to get my FOOD?"



Finally, big spender Steve Y. flexes his heptakaideca-digit budget: "I guess they wanted to give me a REALLY precise figure of how much I've spent." I didn't even know you could do that with decimals!



[Advertisement] BuildMaster allows you to create a self-service release management platform that allows different teams to manage their applications. Explore how!

La rentrée chez North

By [email protected] (Jon North)

September, and the internet in France is as ever full of ads for school goods - French students are obliged to stock up on a whole list of supplies, and stationery businesses and supermarkets alike want you to believe that theirs are the best pencils, calculators, school bags or whatever at reasonable prices.  For us older folk, it is a time when all sorts of activities restart - in the next three weeks my choir, Mary's chamber music and cello lessons and our SEVE network (which includes our Tuesday language groups) all restart and the Anglophone Library in Montpellier reopens.  And we need to check our diaries more often to avoid missing appointments in a still uncrowded week.

An old library layout now being changed
The latter is now under new management after the kind of enforced committee reshuffle I was familiar with in England - old hands and practices became creaky and cracks showed in organisation.  Inevitably (as a retired librarian among other things) I have been drafted in to help, but it is a pleasure - I have already staffed the library on a few of its twice weekly openings - and there is a big job to do in reviving and broadening the book selection process.  These days I do most of my reading on the Kindle, but I still have an affection for physical books.

This blog has often been about health.  As I write Mary is at the ophthalmologists for a checkup following two apparently successful cataract operations.  When cleared she has promised herself new glasses, though her consultant says the prescription has not changed much.  I meanwhile am on a plateau of manageable pain with my new doctor (a 4th in a year following our surviving Dr Cayla's retirement) trying to persuade me that too much painkiller is poisonous.  I don't really need convincing, and it's quite interesting to find out how little gradual reductions in doses changes things.

Twin dogs Edmond and Elvire have just celebrated their 12th birthdays.  They are in good spirits and health, now that we have sorted out Elvire's bladder problem - I need to take her for a quick pee in the middle of the night, which is really no problem since I wake often anyway and get back to sleep easily enough after the brief foray.  I'm gradually returning to normal after I recovered from my broken arm at the beginning of the year.

We had a nice moment today. I was anxious over the past week because our 🍷 cooling system had broken down and over 200 bottles were (still are) at risk in this hot weather. I could not for the life of me remember who had repaired it last time - it ran faultlessly for over 9 years then, after repair, another 5+. Anyway, Mary phoned Languedoc Depannage, who mended our dishwasher a few months since, and lo, it was them! The very nice lady instantly knew about the last repair and understanding (as people down here do) the dangers of cooling failure for wine stores, is sending one of her nice young men to look this afternoon, estimate tomorrow, repairs on the horizon. Service is not dead!

Something lighthearted to end with. We are off to celebrate our own birthdays in Burgundy for a few days!


New discoveries and old friends

By Jon North ([email protected])

At the Mas de Bellevue above Lunel to the north

I've nearly begun this post several times over the summer.  I do so now in memory of my recently deceased friend Alan Byars, married to Mary's cousin Barbara.  Although he made his money from another liquid, oil, this larger than life Texan shared my interest in wine and encouraged me to revive this blog when we met over good glasses whether in New Mexico or the Rhône valley.  He was an atypical American, (many I know don't even have passports) having lived and worked in Europe as well as in the US, and he and Barbara shared many holidays with us in England and in France as well as America.

Last time I wrote of our winter excursions into Spanish wines, and we have continued to enjoy the fruits of  our discovery of the Barcelona wine merchant Decántalo whose deliveries and service are very good.  Now I want to write a little about more local wines, which of course have been at the heart of our enjoyment of wine since our first excursions to France in the 1990s.   Our most recent discovery has been a wine truck, a motorised market stall that turns up at markets and evening events in Lunel and other local towns.  It's based near the Pic Saint Loup, one of our best-known local appellations, which can be seen (as here from the Mas de Bellevue) on the horizon from many places around here, and it's called Dégustez Sud, run by a nice couple who spend a lot of time picking out good wines from small producers across the area from Spanish border to the Rhône.  The wines are not necessarily cheap, but this is largely because smaller producers have higher overheads than larger-scale winemakers.

So far we have tried two whites, Folio, a grenache gris from Collioure near the Spanish border and a Mas d'Amile terret blanc, neither cheap but both out of the ordinary and enjoyable.  White wines can be more expensive than run-of-the-mill reds despite the generally shorter making time, because the process has to be cleaner and more temperature controlled.

Pleasant evening outings into Lunel to try wines from Dégustez Sud, the second with oysters for Mary!

Terret used to be a grape only used for fortified apéritif wines like Noilly Prat, but recently some delicious dry white wines have been made from this grape, and one from the Domaine de la Fadèze near Mèze has long been one of our favourites.  Interestingly, in a comparative tasting of that and the Amile wine the other day, we both preferred the cleaner, lemony Fadèze to the more recent discovery, and it has the benefit of being less than a third of the price, but that may be partly because we go to the producers for the Fadèze.  They make a range of red, white and rosé single-variety wines, all at very good prices.  

I'm ending with a few of the labels of recently enjoyed wines - 2 from the Rhône valley, a 10-year-old Beaumes de Venise from the left bank of the Rhône, in perfect condition from Durban, one of the first producers we visited there and the other from the right bank, the newere additions to the Rhône area in the Gard, in fact near the Pont du Gard and so named Domaine de l'Aqueduc.   And 2 from the Rive droite of the Garonne, one of the good sweet wines opposite the great Sauternes châteaux, and a very good Entre Deux Mers white from our good friend Jérôme whom we met recently in the Drôme, another proof that good white wines can keep for several years.



Les vacances continuent

By [email protected] (Jon North)


in the Drôme near Crest

Last week we went on holiday.  Since we can only now start planning trips to England, our current breaks are in France, and this trip was to the area we know well on the other side of the Rhône.  In fact it was the twinning link with Die that pulled us towards France from 1992 onwards, and over more than 10 years we visited the area 2 or 3 times a year.  We made friends there, and gradually got to know the neighbouring areas of Provence to the south and then the Languedoc further west, where we eventually decided to live.

Die is mountainous, and we prefer the flatter lands to live in, but we love revisiting our old haunts and discovering new bits - this was our second visit to the Crest area, between Die and Valence.  We found a simple comfortable gîte and drove around to Die, Châtillon-en-Diois and Saint Andéol-en-Quint (also an early holiday place for us, the first place we took Sam to, and where other ex-Wirksworth friends have now settled), and combined some gentle tourism and a bit of wine buying with visits to several good friends.

The countryside south of Crest and towards Saillans is dominated by an extraordinary mountainous area, a kind of long oval with forest in the centre, the forêt de Saou.  The mountains culminate at their eastern end by the Trois Becs, peaks visible from the A7 motorway as you approach from the south.  Jérôme, whom we welcomed to stay with us in Wirksworth in the 1990s and who now lives and works in Germany, invited us to eat with him in the little village of Saou, only 10 minutes from our gîte, which has a slightly alternative air and was humming with post-covid enjoyment the evening we ate their with him and his son Oscar.  It's a centre for walking and climbing, and Jérôme has known the area well since his youth growing up in Châtillon.

We were delighted to be able to visit Jérôme's parents Pierre and Michelle during our holiday.  Pierre was the percepteur (tax official) in Châtillon while Michelle was a teacher - over the years we stayed several times in their flat over the trésorerie and, when they retired, they built a house in the village righ on the little market square, the Champ de Foire.  they had both had covid but luckily were not too seriously ill.

We spent a morning wandering round Crest and had lunch in a pleasant restaurant there.  The tower, a former prison, is a landmark in the area, and we also visited Die itself, and spent some time with Krys, one of our oldest twinning friends.  On our final evening we also visited old Wirksworth friends Clare and Alan who moved to the area permanently after retirement - a very good evening meal in their garden in St Andéol, but the storm that accompanied our drive back to the gîte was not so much fun!  The links forged by twinning have stood the test of time.

the 7 deadly sins carved on a building in Crest - sloth, pride, envy, wrath, avarice, gluttony and lust

The Tour ends and the blog returns

By [email protected] (Jon North)

Photos mostly of skies and garden to accompany this blog post

I'm glad to sit down and write again after some weeks taken up with following a fascinating Tour de France.  The news is full of Covid still of course , but now mingled with every louder cries of freedom, of liberté and of the irrepressible French need to protest, so that although France is much more controlled than the UK Macron, is seen as a dictator denying people their rights.  The latest manifestation of the gilet jaune mentality - I prefer the cycling version.

Our view of 'getting back to normal' is coloured by ever-closer knowledge of the dangers of the pandemic, most recently when Mary met our friends  Daniel & Josette in the street last week.  They were among the first French friends we made through casual meeting at a musical event soon after we arrived, and both have had their share of health problems, but recently Daniel came close to death through Covid, and it is a great blessing that he recovered.

Vaccination was a concern for us in the late spring, but thanks to help from our doctors' practice we both had appointments and double doses fairly promptly and now have all the QR coded documents to confirm it.  We are now also legitimate residents of la belle France.  My permit arrived by post soon after our February interviews at the Préfecture, but we are grateful to another French friend (again since the early days of our arrival here): he works for a mairie, and Mary was convinced that council officers did not have to flounder in the labyrinth of internet contacts and phone queues to be able to phone up and chase her application.  He told us afterwards that it had taken even him several attempts to get through to the right person, but within a week or of his calls Mary had not one but two appointments at the Préfecture in Montpellier, and now has her card.

On the home front I've sold my bike, which gave me over 10 years of enjoyment.  I still enjoy riding in
theory, but feel a little uncertain of my balance since my accident so have decided to get my exercise by walking or daily sessions on the static bike I have.  A pity though that I'll not get to ride the two new cycle routes from Lunel, to Marsillargues and to La Grande Motte - maybe I'll hire a bike sometime and ride them.  That and the cross trainer I also use most days have confirmed their excellent value compared with gym subs, especially since they are on site and I can choose my own music or podcasts.  Podcasts are a never-ending source of interest and variety - I'll do a round-up of our favourites during the summer.

The man who bought my bike is our gardener and handyman, M. Beaumann, introduced to us by friend Dawn who lives the other side of Lunel, who has just built our new shed to replace the ramshackle one I put up soon after we arrived.  He cleared the bottom of the garden and put up a new fence too, and although we wondered if we'd lose privacy, in practice it has been a real improvement to the garden, and an old vine and bamboo in pots have rapidly made the boundary green again.  I enjoy the garden at night as well as during the day because I need to take Elvire out for a pee in the early hours, and on one occasion she took a time to perform.  One of the neighbours must have seen me and called the police in case I and was an intruder - when I got back inside I saw blue flashing lights cruising in front of the house, but they must have had a good look and decided I belonged here - they just drove off and we heard no more.

Our Tuesday language groups are starting again - we are hosting tomorrow - and it's quite strange getting back into a rhythm of meeting and learning, but we really enjoy seeing our friends French, English and American plus some other Europeans!

In a week or so we are looking forward to a holiday in the Drôme, near our old twin area of the Diois - a gîte where dogs are allowed, and our first time away since we visited Nigel & Elizabeth.  Of course we still have no idea when we'll be able to travel to see our family and friends in the UK.  We're just beginning to plan other trips around France, not unconnected with wine!

By [email protected] (Jon North)

After a beautifully sunny start to June, his week in Lunel has turned muggy and grey.  Little rain though, despite rain and storms all round us.

The blog is back. Not really a break but a lazy delay in putting together this next post.  That means there are plenty of pictures to share, and the news here is that we have a new garden shed - our friendly workman M. Beaumann is just finishing the concrete floor as I write.

The first pic shows the old and very ramshackle shed, which lasted nearly 15 years.  You can see the tortoise in front of her little shelter in the second photo

Last week we paid a welcome visit to our friends Nigel & Elizabeth near Narbonne.  Four sets of photos, one of the river Aude near their house, seen during our dog walks, and three others at Narbo Via, the new and impressive Norman Foster museum on the outskirts of Narbonne.  This town was the commercial centre of the Roman empire in France, but without the monumental buildings of Nîmes or Arles.  So the remains had to be reassembled from the later buildings into which they'd been incorporated, and the main display is a kind of giant library of stone carvings.  Foster, we think, has done France proud!

This summer the town has come to life a bit more with brightly coloured animal sculptures

Finally the garden continues to provide colour and interest - this time from lilies and (ornamental) pomegranates as well as ever-changing light on our own sculptures.

A month of holidays

By [email protected] (Jon North)

I begin this blog with a boast about our wonderful daughter-in-law Fi, who has just been awarded an honorary doctorate by Keele University.  Here's the announcement, excellent news for the theatre too because her colleague Theresa also received an award as you can see.  The New Vic has just reopened after a long layoff - in France too, culture and arts are tentatively coming back to life, and choral singing is not lagging behind - we hear that in England it has still been singled out as especially risky

May in France is, it seems, stuffed with holidays.  It is not the first time I've commented that many of these are Catholica, Christian, religious festivals - as I write this Monday afternoon we have the Pentecôte holiday, what in England would be called Whit Monday.  Years ago when our new library, the médiatheèque, opened to fanfares (rightly) and soon afterwards the town announced that it would be open on the first Sunday of each month.  That year, the first one, the first Sunday of April was April, was Easter Sunday and - guess what - the Library was closed!  France will continue to honour its Catholic heritage but inconsistently refuses to acknowledge equally other religions such as Islam.

I was intrigued this week by this piece by Duncan Campbell about Bow Street on its final day as a functioning court.  On that day in 2006 he was a member of the press bench  "I still have my pass). A young woman, arrested for posting advertisements for sex workers in telephone boxes, was given a conditional discharge and ordered to surrender her Blu Tack. A businessman facing extradition to Germany for a £14 million fraud case was remanded in custody. Two Kosovans were accused of paying £4000 to buy a Moldovan woman from an Albanian gang in a deal agreed in a pod on the London Eye. They denied forcing her into the sex trade but were rejected for bail because false documents had been found at their home. A young Londoner who had stuffed £200 worth of Marks & Spencer lingerie down his trousers was remanded for reports.  At last, the list-caller, Angela Georgiou, told the magistrate, Timothy Workman: ‘With sadness, I call your last case ever at Bow Street, sir.’ The honour fell to a 32-year-old Scot from Kirkcaldy, who had breached an Asbo (Anti-Social Behaviour Order) – he was found in possession of a bottle of red wine and some lighter fluid – and little knew that the hand of history had landed on his collar the previous night in the Covent Garden piazza. It was his fifth visit to the court and he pleaded guilty. ‘The closure of the court, with its great legal heritage and its history,’ Workman said, ‘is of great sadness to me and to all who are associated with this court.’ He was the 33rd chief magistrate, a role once held by Henry Fielding, who presided over the first detective force, the Bow Street Runners."  All that was happening the same year, 2006, as we moved to France.

I read a lot, and am frequently caught up in discussions about tablet (Kindle or iPad - I have both) vs the traditional book.  Lots of things jostle for importance in my mind.  Librarians like me were constantly surrounded by books, arranging them on shelves and keeping them by the bed or armchair.  I love our shelves of books, and know most of them pretty well.  So although the electronic formats are less evocative, but more practical for two reasons.  One is often the sheer size and weight: reading in bed holding a large heavy hardback is a struggle, but my Kindle has one other advantage I've come to appreciate reading in French - I can click on a word I don't know and find its translation instantly.  And since we are now of an age when we have to start thinking of downsizing, getting rid of many metres of shelves may in future be a necessity though not yet!  The seemingly limitless capacity of a little Kindle to hold a library of books, and its ability to search for characters whose identity has been forgotten, are great assets.  And, living in France, our regular periodicals like The Week and The London Review of Books arrive right on time.  Mary nevertheless prefers to wait for the paper versions a few weeks later!

We are constantly reminded of litter and waste.  As a dog-walker I  see the endless trail of muck and litter (and of course picking up our own) on the daily trips round the neighbourhood; and of course we have to keep track of regular council rubbish collections, feeling pleased that our own local refuse service has widened out its plastics recycling service, but at the same time wary that we don't really know what happens to the sorted plastics, tin cans and card we throw away.  There is a relatively new, large incinerator in the next village, not at all liked by people living there but clearly it has to be kept busy so one always wonders if some of our waste is not recycled but burnt.  All the same our local authority makes big efforts to encourage us to recycle and has special collections for metal and large electronic items etc - our old computer printer has to be disposed of soon.  And also, the local paper is regularly full of stories and pictures of fly tipping in town centres.  Not a simple process to manage either for us or for the authorities.

My next blog will include a tour of the garden, much changed since our arrival 15 years ago.  The photos each time often chart its simple pleasures, and in the glorious weather we've been having it is a constant joy to watch things growing and glowing.

By [email protected] (Jon North)

May brings looser travel restrictions in France.  The 10 km radius we’ve been confined in was lifted this week, although night time curfews still remain, gradually starting later as we head towards midsummer.  This was the second time we’d had to stay within the circle, and after last time I lost the map, so I am keeping it to hand this time in case it pops up again!  As you can see it would not quite take us to Aigues Mortes or Mauguio, but St Christol was within range, and a corner of the Étang d’Or for flamingo-spotting, but no seaside – our nearest at La Grande Motte is at least 12 km away.

bye bye to one restriction
My life has been disturbed recently by Elvire the dog’s problem of peeing during the night.  It’s easy enough to deal with since we have tiled floors, but it has meant getting up early.  But she seems in good spirits all the same, and our vet has now diagnosed a hyperparathyroid problem which will need surgery – a delicate operation but one which will have to be done, so we are in touch with a surgeon.  Here’s the explanation if you’re interested.  We spend quite' a lot on vets' fees and treatments, but we feel very pleased to have two happy lively dogs, good companions who give us both cause to take a little more exercise than we otherwise might.  The tortoise at least (sadly only one who appears twice below - they are I keep reminding myself they are wild animals and the other escaped more than  a year ago)

As France approaches regional elections, and Presdiential elections are on the horizon, the perennial question 'will the far right make significant gains?' resurfaces.  President Macron is not popular everywhere and tries sometimes to face both ways.  Since France is celebrating the centenary of another controversial leader, Napoleon, this cartoon caught my eye.

Consensual commemoration of Napoleon - the rift between left and right is so out of fashion

Finally a couple of quotes from The Week:  'America innovates, China duplicates, and Europe regulates' (quoted in The Daily Telegraph); and 'At every party there are two kinds of people – those who want to go home and those who don’t. The trouble is, they are usually married to each other (Ann Landers, quoted in the San Francisco Chronicle).  

Despite gradual easing and more vaccinations, there's not much chance of parties to escape from just now...

Animals, an Amelanchier and the wider world

By [email protected] (Jon North)

This weekend the French Covid restrictions will start, cautiously, to be eased - from Monday the 10 km radius for our journeys within France will be lifted though the evening curfew will only be lifted bit by bit.  That affects me taking the dogs for their late evening walk (for which I must carry an attestation until mid May - our shopping lists are written on old attestations for the moment!)  

Our lives have not varied much, but this week we bought a new garden tree/shrub/bush from a newly-discovered nursery not far from here.  We wondered if Amelanchiers, which we had in English gardens, would survive our hotter, drier climate, but were reassured by the man in charge of our excellent local arboretum and by the nurseryman., so our new little bush is proudly in the middle of the lawn near the tortoise enclosure and, lo, just as Mary was planting it the tortoise emerged muddily from her hibernation!  A week or so later than last year, but it is really good to have her back in view.

article about children reading more in lockdown in the Guardian offered me a moment to take notice of the everyday, and to be thankful that my mum encouraged me to read and use the public library. Reading is invaluable, and makes little noise in a time when many media are incredibly noisy. But laughing out loud was, I recall, still risky in my childhood: reading and enjoying Just William books under the bedclothes caused me occasional parental censure, especially when I disturbed the Quaker study groups downstairs! I try to ignore extraneous noise, but it drives me bonkers when someone's Facebook post unexpectedly bursts into speech or music - better to invite sounds in rather than have them blast out without warning (occasionally even waking a sleeping partner at night).

As we continue to mourn the lost opportunity to travel to Armenia again (it would have been a year ago) we take an interest in the terrible difficulties of the people in that tiny country for the sake of our friends there, and one of many good things coming out of the new USA last week was the announcement that President Biden formally recognises the  Armenian genocide.  It is incredible that (kowtowing to Turkey) they have been so slow to acknowledge such a blatant historic human rights abuse.

And among the fairly petty concerns people in the UK and Europe worry about, the appalling situation in countries further away, hooked into hard-line political agendas and too poor to afford the vaccines and treatments, even adequate health services, to cope with a flood of infections.  The people of India are in a profound crisis, somehow in scale with the terrible disasters and episodes of violence in the country’s history. European countries, and the US, have dithered and made false steps - I think we have to remember how fortunate we are. But political dogma and rigidity will always cap ineptitude.

Not my photo, but a beautiful shot of a vine near Pic Saint Loup which survived the recent frosts
Back to plants.  My normal shots of plants are pretty, but these have a whole different focus, and great importance for the future if you’re a wine lover. Looks rather more demanding than your average day in the garden!

At the St Christol Domaine de Coste Moynier

I have good memories of Glendurgan in Cornwall so am delighted to see it at the head of this article, as I am to celebrate spring flowers and blossom everywhere. But this campaign seems to have created a new kind of tree, a ‘blossom tree’. Not sure what that is - most blossom is a transient pleasure on the way to some fruit or other, or in cases like our beautiful grenadier, not due to flower for a month or more yet, categorised as flowering or ornamental trees or shrubs. Ah well, living language...

Podcasts are now a frequent source of information and entertainment for us, and one from the Guardian caught my attention last week - a real-life clown.  Have a listen.  Police spies seem to have been on the radar for ever. I read the book Undercover https://amzn.eu/anWjLlM at least 10 years ago, and it seems to be trickling throughthe judicial process just now.

It turns out a lot of my preoccupations are UK-related - somehow they are more spicy than the French ones I can disentangle!  May day, the fête du travail, is tomorrow, and it has just been announced that the traditional lilies of the valley will be able to be sold, though there are Covid restrictions on roadside sales and it turns out that some of the flowers on sale beside the road are stolen in the first place!

More on words and language

By [email protected] (Jon North)

Our house with its tall conifer - a landmark for those lost around the neighbourhood!

I love maps, but not always on the internet - atlases and other printed maps often seem more satisfactory although less searchable.   You can see from these two maps from the Petit Larousse (too heavy to hold for long, so useful transferred to a screen) that Lunel is right at the eastern edge of the Hérault département.  So many places in the Hérault are actually a long way from us, and many of our contacts and meeting places when we can travel are in the Gard which wraps itself round the right hand side of the Hérault.  Most départements in France are named for rivers - the Gard is unusual in modifying the river name (Gardon), but in any case many rivers spend a lot of their lengths in other départements.  The river closest to us is the Vidourle which is notorious for its floods, every 25 years or so, which forms the eastern border of the Hérault with the Gard.

A scene in our garden some years ago for a lunch after our Tuesday French conversation group. The garden has not changed much but even before the pandemic the personnel has, several of these people have departed from our group in various ways, and there's little chance of gatherings like this again in the near future.

Our life here revolves round the non-stop process of learning French.  After nearly 15 years we've made a lot of progress, but it is still a minefield and equally a source of constant fascination.  There are two dimensions - one, the many-faceted business of written French (easier because you can usually go away and look it up) and spoken French which can vary both in speed (you discover that English people too seem to rattle away too fast) and regional accent, to say nothing of the difference between slang, jargon, technical vocabulary and formal statements.  We have found the Government press conferences models of clarity (even when the news is unwelcome) as are magazine tv shows like the excellent travel magazine programme  Des racines et des ailes, but catching chatter among friends is often difficult, as if speaking and hearing on the phone, especially when you don't know in advance the topic of the call.  Sadly we have all too little friendly chatter at the moment.

The first poppies a week or two ago

The issue of sexist language is very topical here now.  France is some way behind the English-speaking world in this, partly because of the additional complexity that all nouns have gender, and historically because of the Académie française which has for centuries laid down the law about what is correct and incorrect.  Now inclusive names of the 'man includes woman' kind are much less common - names of professions (professeuse as well as professeur, for instance) have increasingly been feminised since the 1980s and mor recently there have been official circulars defining how inclusive pronouns like 'he or she' should be written - I have always tended to use / , but one hotly debated method here is the use of the point médian, a kind of decimal point when for instance masculine and feminine endings are indicated, for example professeu·r·se.  As with much to do with language in French, this gets rather complicated (just typing the thing is complicated enough!)

Such cultural debates are often long and heated - a supplement in Midi Libre was headed to "cette écriture qui divise tant" and referred to a veritable (ardente) battle of Hernani - what on earth is that?  Well, it's a reference to a play Hernani by Victor Hugo (the name is from a Spanish town).  It became notorious for the demonstrations at its first performance between the romantics (Hugo had Berlioz and Théophile Gautier, poet of Les nuits d'été' among his champions) and classicists who saw the play as a direct attack on their values.  Verdi also wrote an opera, Ernani, apparently.  So passions were roused then, and people today recognise the reference nowadays well enough for it to be used in a local newspaper.

Clearly understanding culture, popular or not, is a complicated process.  Meanwhile, we listen to frequen official press conferences on Covid as much to hear the very clear language ministers and officials use as to keep up with the latest information.  Restrictions in movement are to be eased, and in any case we have now both been vaccinated, but our lives are quiet and the chance of travelling to England is very small just now, so sadly our family and friends there remain at the end of phones and video calls.  This week the physiotherapist, Emma, who has helped me through over 3 months' healing of broken arm is leaving for her next placement, working with children in the hills somewhere.  I'll miss her, but of course the team practice she works in will provide me with a replacement.  And April continues to bring mostly beautiful weather.

Roses starting to show in the front yard

Solemn news, and, What's in a name?

By [email protected] (Jon North)

National figureheads aged all but 100 do not die often, so the passing of Prince Philip deserves more than a mention.  ‘Figurehead’ is an apt description for this naval man whose function was mainly ornamental. 

These days my day starts early, since Elvire the dog needs letting out.  This Saturday the usual selection on Radio 3 (and I’m guessing all over the BBC) was replaced with nearly continuous music which is not disagreeable.  It leaves space for reflection - I’m not a royalist but I think the mood was right at a time of national mourning following the death of Prince Philip at a venerable age.  For my friends who already think there is too much fuss about posh people in the media, I find the response of wall-to-wall music ideal.  And despite the increasing rarity of chimney sweeps, I recall Shakespeare’s verse

Thou thy worldly task hast done,
Home art gone, and ta’en thy wages:
Golden lads and girls all must,
As chimney-sweepers, come to dust.



Here are the 20 top names (boys and girls, 40 in all) registered in Montpellier over the last 20 years.

Local expats (people like me, but I don't share their views!)) commented that the names were ‘not very French’.  But two things strike me – the people commenting are probably much older than the people (many being parents of the new babies) who chose the names, even if not as old as me.  One comment expressed surprise  that Catholic names do not figure more prominently – but France is a secular state and prides itself on its republican values, even though saints’ days still figure on all published diaries and calendars, and many public holidays are still church hangovers. 

 So yes, we live in a very contradictory country!  Second, saying things are not very French is a bit odd, since they are by definition French choices. I find the absence of more north African names a little surprising given the significant proportion of families of north African  origin in the area.

Among the podcasts we’ve listened to recently is Tim Harford's Cautionary Tales.  These are really good at adding a dose of reality and realism to the mad hype of modern life.  As well as reality checks on the pandemic, his subjects range from the Charge of the Light Brigade to Harold Shipman, and art forgery, and much, much more.

Our weekend has also been enlivened by watching two Rugby League Challenge Cup matches - the only French representatives, Catalan Dragons, gave a very spirited performance to win their tie against Wakefield Trinity.  Rugby here is almost all Union rather than the rugby à treize we were watching, but the Catalan team is more or less local to us, and we've always enjoyed watching this form of the game.

Meanwhile the news here has also been full of  grim news of frozen vines and fruit trees - lots of growers have lost their crop this year thanks to at least one night of temperatures as low as -8°C.  Not uncommon further north but pretty unusual here, and thus less likely to be insured.

Vines bursting into leaf near Luc's garden in Aigues Mortes, befiore the very cold weather  

More hopeful signs of spring with our latest dwarf irises

Spanish winter

By Jon North ([email protected])


My encounters with Spanish wines go back to my teens, when my father returned from holiday in Spain (with my mum of course, but I’m not sure if Pam and/or Tom went too) lugging on the train 12 bottles of Rioja.  We have carried many bottles in our car over the years, but on the train with all the suitcases too…  Only my Dad!

More recently it all started in the autumn when Mary sighed that she missed Fino sherry, and we both recalled our love of PX (short for Pedro Ximenes, a grape variety used for sweet fortified wines in southern Spain, and so used in blends with drier wines to make the ubiquitous 'cream sherries' well-known in the UK).  We first encountered 100% PX 20 years ago at Rick Stein’s Padstow restaurant when the dessert was simply vanilla ice cream with a schooner of PX poured over.  

So I hunted idly to try and satisfy Mary’s craving and came across the Barcelona wine merchant Decántalo.  They specialise in Spanish wines but a quick scan shows they have plenty from other countries too – it seems to me to be as reliable and well-organised as the UK Wine Society with the advantage for us that it is just down the road, not in what we have now sadly to think of as a foreign country!

On top of this, this wine merchant packs things in super-safe cartons – we've had one or two disasters with breakages in the past, but bottles really have a hard time getting broken in these deliveries.  We began before Christmas with Tio Pepe Palomino Fino and Gonzalez Byass Nectar PX, plus a couple of  unfortified wines.  One of the first of these we tried was Protos Clarete, a light red or dark pink from Ribera de Duero, an area now quite well-known, top centre/north Spain a bit SW of Rioja.  This reminds me of the light red clairet which is produced in Bordeaux and whose name of course links to the red clarets from there we all know and love.  But the dark pink, or light red, style is distinct there as it turns out to be in Spain.

We also tried 3 Muga Riojas (red, white and rosé), all of them very good – a friend who knows this whole field well says white Rioja is hard to find, and remembering Dad’s samples I was really interested in this – Oz Clarke says white Rioja is a bit of an afterthought, but we have really liked this Muga, so still have some bottles to enjoy!   We then spotted a Christmas offer of 18 different wines, all red,

·         6 from Ribera del Duero (see above – we have already enjoyed these, wines and makers included Juegabolos, Malleolus, Corimbo I, Pago de los Capellanes Reserva, Pícaro del Águila and Astrales);

·         6  from Priorat(wines and makers include Ferrer Bobet Vinyes Velles, Salanques, Laurel, Mas d'en Compte Negre, Planetes de Nin, and Coma Vella) – we are halfway through these and have been so impressed by the  Ferrer Bobet that we have spent a small fortune on some of these bottles to lay down for the next few years;

·         and 6 other reds, 3 from Montsant: (Fredi Torres Lectores Vini Montsant; Sindicat La Figuera; and Orto - we shared the  Figuera wine with friends yesterday and were very impressed), another Rioja: (Diez-Caballero Crianza 2018) and two from further south (Jumilla - SE Spain N of Murcia: Casa Castillo; and from Valencia: Parotet Vermell)

In the huge country of Spain and its many contrasting wine areas, I was surprised to find that two of these 3 appellations are tucked into a tiny hilly area SW of Barcelona: 

Priorat,  which according to Hugh Johnson's pocket guide produces some of Spains finest wines. It's named after a former monastery tucked under craggy cliffs. The key is the slate soil – known as llicorella. 

Montsant, tucked in around Priorat 

The thing to look forward to is a trip to these areas of Spain, relatively close to us although the travel complexities of travel with Covid, national restrictions and of course Brexit remain to be discovered! 


Springing forward

By [email protected] (Jon North)

This week's blog is mostly about health.  The good news this week is that my doctor has fixed Covid vaccinations for both of us today, which is a relief.  Of course, the rapidity with which vaccines has been developed and made safely available is pretty extraordinary.  It's interesting how many of the fears about vaccine denial have faded, though there is still negative babble at the fringes - I think most people see it as the only possible route back to 'normality', though there are hundreds of questions about what that should be or how things may change.

But the unholy tangle of new strains being discovered, problems about bulk manufacture and distribution of vaccines, political mud-slinging and bureaucratic delays, justifiable or unjustifiable caution about safety and side-effects, all of these created an unsettled atmosphere in ordinary people who worry about jobs as well as getting ill, with more time than usual to ponder things.  So other quite trivial things - for example the jamming of the automatic ignition on our gas hob, issuing a stream of crackling sparks for 24 hours - add yet more tension, and it took longer than it should have done to discover the off switch!

Hopeful buds on a drought-hit lemon tree, recovering this spring

I've written before about my physiotherapy, mostly a very positive experience this time (previous sessions of treatment for knee and sciatica were far less useful).  But I keep on realising how much better things will be as and when I can take responsibility for my own exercise and recovery.  When I was in a clinic after my knee operation I spent one hour out of 24 actually being treated; now I have a good half hour's intensive massage, and 20 minutes a session wrapped in a kind of cold blanket where icy water is pumped through.  And above all I have exercise machines at home which I can use when it suits me.  I've kept up the static bike throughout, and now I'm about to experiment gently with the cross-trainer whose arm movements seem to fit into what is allowed, applied gently!

Dogs meanwhile provide a structure and timetable to our days.  I've been able to resume early morning and late evening short walks, which takes pressure off Mary.  They have some digestive and bladder problems which need vet checkups.  But although these vet sessions are expensive, they are also reassuring, and the dogs are OK, and continue to provide us with enjoyment.

Marching on, and on

By [email protected] (Jon North)


Tom with me and sister Pam

13 March would have been my brother Tom's 70th birthday. He and his family are very much in our minds - departed far too soon. 

Meanwhile 12 March was another milestone in progressing our established status as French residents. That morning Mary and I surrendered our temporary EU cartes de séjour at the préfecture; our new cards as permanent foreign residents should arrive by post in a few weeks. Despite gripes elsewhere I have always respected French bureaucracy - if you follow the instructions you get the right results. The woman who dealt with our dossiers was very friendly and the whole rendez-vous more or less on time. We even had time, in a strangely quiet Montpellier, to buy some excellent kitchen gear before heading home to the dogs by midday. A good morning’s work.

There was some other welcome news for we Britons living abroad this week, or at least a promising development.  Buried in the details of the UK budget was news that the government plans to scrap the rule that bars those who have lived abroad for more than 15 years (as we shall soon have done) from voting in UK elections "the government is providing an additional £2.5m to remove the limit preventing British citizens who live overseas from voting after 15 years.”  So we shall be able to continue to vote in the West Derbyshire constituency where we lived before leaving the country.  

One story in the local paper caught my eye - of the revival of a traditional industry making fabric in Nîmes.  The blue denim, named ‘de Nîmes’ by the Americans who popularised it for jeans, is now going to be manufactured by a family firm in this area.  Among other local news, another story this month of wartime good deeds - A Jewish man has bequeathed a sizeable chunk of his fortune to the French village whose residents hid him and his family during the Second World War, despite the risk to their own lives. Eric Schwam, who died aged 90 on Christmas Day, is believed to have left s2m to the remote mountain village of Le Chambon-sur-Lignon, which gave shelter to 3,500 Jews during the war. Schwam and his family arrived in 1943 and stayed until 1950. In his will, he said the gift was an expression of his gratitude, and suggested it be spent on youth services.  We have friends whose family shared in the efforts to rescue Jewish people in this part of France during the war -  this strikes many chords with me.

This cartoon is for our daughter-in-law and many other friends involved in theatre and music. The Paris Odéon-Théâtre de l'Europe has been occupied by protestors, with Union support demanding reopening of theatres and extension of government support to the so-called intermittents who would normally be working there. The Minister Roselyne Bachelot has intervened but has not apparently been able to reassure all protestors. 

Sport has been a frequent interest for us as always.  I'm still reeling a little from the turbulent reversal of fortunes in the final stage of the Paris-Nice cycle race. Having led for most of the week, Primoz Roglič ended up 16th overall with ripped clothing and having dislocated a shoulder, and the winner in the end was Max Schachmann who also won last year. Riveting watching all the same.  Meanwhile the 6-nations rugby has caught fire despite the absence of spectators with a fizzing match between France and England and an absorbing on between Scotland and Ireland.  Meanwhile the woes of 'my' football team Liverpool continue, but it is after all only sport.  Another picture to end with.

Spring into March

By [email protected] (Jon North)

our house (on the right beyond the car park) and street a couple of weeks ago

2 months after I broke my arm, it is well on the way to healing.  If you happened to read this blog some years ago when I had a knee replacement you’ll recall that I had a poor view of physiotherapy – some essential exercises to get me back on track but too much time left hitched to electrodes.  This time, it has been much better – an enthusiastic team of young therapists who know how to help reduce swelling and prevent inappropriate movements.  But in any case I have a tongue in my head, and I am working out (even in French) what questions to ask and how to time them!  The physiotherapy team has two cramped rooms and too many people – therapists, students and patients – so we cannot expect miracles.  Even though everyone wears masks and washes hands regularly, social distancing is downright impossible – the therapists have to change to and from working clothes in corners, and the small collection of rubber balls, poles and cool jackets in constant use cannot possibly be sterilised well enough.  Anyway, on the whole I count my blessings and enjoy yet more sunshine as spring arrives.

So to other things that have caught my attention lately.  Vegetarianism has gained ground here in France since we started to come regularly in the 90s, and like many cases in the past, ‘veggie’ apparently includes fish in this report. But it seems always to raise heat and fury. 50 years ago a friend came for a meal and exclaimed she had ‘never eaten vegetarian’, and I thought then as I do still that this was odd - in any case, we love our vegetables in this southern French horticultural paradise, and while I like meat and fish, I am very happy to eat vegetables   Our favourite local greengrocers' reopened this week and I was able to go on my first solo shopping walk to find things like lovely fresh salads.

A fascinating chalky article here linking three things important to me - the chalk landscape of the Chilterns where I grew up, sparkling wine from Sussex closely linked to Champagne, and the continuity between southern England and northern France.

From Apollo Magazine : “Dolly Parton, the one public figure almost everyone would agree deserves a statue, has urged lawmakers in her home state of Tennessee to withdraw a bill to erect a statue of her in the grounds of the State Capitol building in Nashville. ‘Given all that is going on in the world,’ Parton tweeted, ‘I don’t think putting me on a pedestal is appropriate at this time.’ Which only makes her more deserving, of course.”

One of the constant struggles we have to improve our French is knowing about singular and plural. We have long known that trousers are singular (un pantalon), and we as a family also (les North rather than the Norths), but I realised today that the opposite can apply - ‘off the beaten track’ is ‘hors des sentiers battus’ 

Our minds, M’s especially, are often on Fair Isle knitting this year, so we were fascinated to find fashionable in yet another catalogue. The slimmer model’s ‘tank’ retails at nearly £150, but lacks the loving care that went into mine! Thanks again M xx

There are voies vertes, foot-and cycle paths made from old railways all around us, and the upgrade of the canal path from here to the coast at La Grande Motte is due to be completed shortly - I'm looking forward to riding it when I get back on my bike soon.   Of course we had the High Peak Trail near our old home in Wirksworth, where I'd sometimes cycle with dog Ruff running alongside.   There are also plenty of urban cycleways too - in Paris we have walked more than once on the Promenade Plantée SE of the city centre - so I was fascinated to see this article about another in an area of London . Old railways deserve a second life.

after lunch




By [email protected] (Jon North)

The first sign of spring, our neighbours' almond tree in bloom

I read last week that Amazon was running out of cardboard.  Not really a surprise to us, since the last delivery we had from them was a smallish item in a huge box padded with screwed-up paper.  I don't really make much apology for using them - we are in a vulnerable group better avoiding busy shopping centres even were they open.  Besides, lots of our Amazon purchases come from small suppliers only via Amazon, and often we have made links with the original merchant and bought direct from them the next time.  But Mr Bezos and his like are certainly getting rich on the bonanza of online purchases - I saw today that he is saving his pennies to fund a space project!

Macron is doing his best to seem green - not the first politician to jump on this bandwaggon - and this cartoon suggests a citizen's panel he set up has talked a lot to come up with very little.  But as new hope appears following the transition from Trump to Biden, I guess we are all hoping there will be some positive movement on climate change.

more signs of spring this week - cyclamen, daffodils and bay flowers in the garden

Meanwhile back in Lunel, like most French communes we have had various recycling options since the beginning of the millennium or before, but for the past year or two we get a small amount of local tax relief if we throw away less general rubbish (measured per collection by a microchip in the bin) and we have just heard that from next month all our plastic waste will be collected in the yellow bins we've always used for card, tins and plastic bottles.  This is a big change for us - hitherto we have always avoided adding it to the general rubbish by taking it to one of the local supermarkets which took its share of responsibility by collecting back its packaging.  But now, no more storing separately and carting round bags of used packaging - all simply added to the yellow recycling bin.  Cynics with more energy than I have might try and check what happens to it back at the depot, but I am just pleased some efforts are being made.  Glass and paper are also collected, separately and in different ways.

Over 40 years ago I was in charge of Friends House in London, and one of our perennial worries was whether the waste paper man would turn up to collect the paper we  generated in quantity.  It depended then as I expect it still does on the market for scrap paper, but I think things are a little more secure now - in the 70s, when the paper price dropped we had problems, sometimes for months on end.

Two 'new' expressions - obvious but suddenly part of everyday conversation.  First unboxing, simply the act of taking a new purchase out of its packaging, but now acquiring a kind of mystique as people start making unboxing videos.  Over the years I've suddenly found it really useful to look at videos about 'how to install' this or that, most recently a new counterbalance system for the dishwasher door when it broke, but apparently now it gives people a kind of kick to watch the process.  The most amusing things recently have been receiving large parcels which turn out to have tiny things inside - perhaps indicating that Amazon had run out of smaller boxes!

Then there is the whole concept of the podcast.  I was puzzled by this - you see a random title and lo you have a whole series of things to listen to.  Not always polished - you have to put up with noises off, and sometimes ums and ers.  And I thought they might be hard to find, but as soon as you look you trip over them everywhere.  So far this month I have tried two wine podcasts, another one called The Prime Ministers by Iain Dale which is serious stuff.  There's one following the publication The Week which we enjoy (it turns out the journalists are less good at talking about their chosen subjects than writing about them),  and two by the New Scientist which are excellent if slightly prone to publicise their own other stuff.  

The one Mary and I are beginning to enjoy together is the History of English podcast by a very well-organised American, Kevin Stroud, who is apparently a lawyer by trade but who knows is subject inside out and is exploring the history of the language thoroughly at least once a week for over 10 years after the first podcast.  I started looking for something to listen to while I do my 40 minutes' pedalling on the static bike each morning, but the range of things I can listen to now would keep me going day and night for ever!

As cycling is ever more popular in France there are now machines to
count the traffic, which may be confused by tandems!!

The McMansion Hell Yearbook: 1980

(back of a quirky literary novel voice): Sometimes, things are not what they seem. An architecture critic disappears for three months to follow bike racing around Europe, rife with questions of becoming and desire. A real estate agent uploads a listing to an aggregator, knowing that it will be a difficult sell but thinking not much of it, for, like Tolstoy’s unhappy families, all houses are difficult to sell in their own way. A house is built in 1980 in Staten Island and would have thrived as an anonymous bastion of tastelessness had the internet not been invented. But the internet had been invented. All of these things are brought together here, through truly unlikely circumstances.

Let’s not bother with the formalities this time.

None of you will buy this house.

Sitting Room

Does anything here make sense? The periwinkle sofa, the twinkling of bronze glass, a truly transitional material, a mall exiting stagflation and entering the sultry trap of Reaganite libertarianism that would leave it empty twenty-five years later. The sense that one is always changing levels, trapped in a landing of some sort, never quite arrived on stable footing. But that’s just the style, one assumes. One foot in the seventies, with all their strife, one foot in the beginning of what felt like the end of history. One’s ass on the iridescent pleather sofa, waiting for the centuries to change.

Sitting Room II

My suspicion is that there are no pictures of the mirrored mystery foyer because the photographer’s identity would be henceforth revealed, and the point of all real estate photography is for the viewer to imagine themselves as the only person in a given space.

Dining Room

The shinier things are, the richer one is, obviously.


This serious sociological research also happens to coincide with the Giro d'Italia, one hopes.


(crediting @cocainedecor on twitter for their term. but also, where can i get some chevron mirrors, asking for a friend.)

Master Bedroom

just asking questions

Bedroom 2

Ostensibly bad opinion that I will nevertheless defend: the corner bed slaps, let’s bring it back.


(Staten Island accent): Hey, I’m workshoppin’ some metaphors here!

Alright, we’ve entertained this monstrosity enough - time to wrap things up.

Rear Exterior

You know, McMansion Hell has been around for five years now, and has coined many terms - an art, ahoy matey, lawyer foyer, brass n’ glass, pringles can of shame - but I have to say, I hope fireplace nipples also sticks.

Anyway, that’s all for 1980 - join us next month for 1981.

If you like McMansion Hell, support it on Patreon!

short lease in a slick machine: a personal essay about apartments

Hi Everyone, you may have wondered where I’ve been for the last few months. The truth is, I, like most people must at some point in their lives, needed to take a little break and figure some things out, needed to go on some long personal journeys, needed to meet some heroes, needed to just not do this website for a short amount of time, but don’t worry, I’m back now, and I’m bringing the feels on the way in.

Before I present this essay, I would like to offer my deepest thanks to the people who kept supporting me on Patreon during this soul searching. I owe you everything.

I’m moving again. I’ve moved every single year since I’d left my parents’ house at the age of eighteen, with the exception of the apartment I had on the second story of a Queen Anne on S. Mendenhall Street in Greensboro, in which I stayed in for two years. The rest of my dwellings have been painfully temporary, with life inevitably coming around to its annual migratory upheaval. There have been many reasons why, of course, quotidian reasons that always feel devastating at the time – jobs, school, pestilence, crazy roommates, despicable slumlords, partners to be moved closer to, relocating just to get away from where one has been before. I could rank every apartment on a scale of worst to best, from most to least livable, but none of them were permanent.

above: the only apartment I ever lived in for more than a year, a sacred place.

I wanted to write about the apartment I’m moving away from in Chicago even though perhaps it’s not prudent to do so – it’s never prudent to be personal on the internet. Don’t worry, though, I won’t include anything incriminating that could be construed as defamation or whatever. You can just feel angry on my behalf, which is really, truly in the spirit of McMansion Hell. And this is, well, apartment hell. The apartment I’ve lived in this past year quite frankly and very succinctly encompasses everything I kind of hate about architecture, about design, about the ways people in the profession are expected to live their lives for the benefit and the consumption of others.

first impressions

When I first saw the apartment, it was the nicest apartment I’d ever been in, the finest I’d hitherto walked the halls of in my rubber Birkenstocks. It was big and full of light, with lovely maple floors, the kind where, at the right time of day, you could sometimes see the tiger pattern emerge in flecks and ribs like those on the backs of violins. When the landlord, an architect, showed it to us, he had his stuff in there still. A Bertoia chair that was probably real. Very carefully selected items from Design Within Reach alongside enough pieces from other places to make the whole getup seem more authentic. Sparse hangings on the walls, each big and well-framed. Single potted plants. A well-oiled cutting board.

There were European bath and kitchen fixtures and recessed lights that dimmed at the press of a button, which meant we could get rid of all of our floor lamps. In the kitchen, tall, elegant white cabinets above a slab of marble, dubbed, reverently at the time, a living material. Blinds on rollers meant no need for hanging curtains. A soaking tub and a Duravit toilet, you know, the floating kind cultured people had. Europeans. The rent was at the top of our budget but still doable. I signed the lease fast, with unbelievable giddy excitement. Finally, a nice place to live after years and years and years in what could only be deemed as shitholes. Shitholes and the nice midcentury apartment building I lived in in DC, but that was a studio and DC was a place I wanted to get so immensely far from that we ended up in Chicago, the only city in America I ever really wanted to live in.

cracks in the facade, so to speak

As soon as we moved in, an unsettled feeling crept in. I can place it now as the sense that this apartment was too nice for people like us – people with particle board furniture and student loan debt. That it wasn’t really ours, we were just borrowing it before someone worthier came. Subconsciously, we knew this. We never hung anything on the walls save for the Mondaine clock my husband bought at the MoMA Design Store and the Giro d’Italia jersey signed by Tom Dumoulin, which I’d had framed. The walls were a blinding white. Putting tacks in them felt like an unlawful penetration. Our landlord fussed over the stuff we had on the back porch. One time he criticized where my husband had situated the soap on the kitchen counter, the living material which, in reality, is just a fancy term for “stains easily.”

All of a sudden, we were living under a microscope.

We weren’t using the apartment the right way; namely, we didn’t decorate or live like an architecture critic and a mathematician theoretically should. Our apartment wasn’t photogenic. There were too many bikes in the living room. We still had a garbage $300 Wayfair sofa that felt like sitting on cardboard. There was clutter. This beautiful apartment wasn’t meant for our kind of ordinary and this was made known several times in subtle and rather degrading ways, after which our lease was not renewed, to the relief of all parties involved. Even if it meant moving again.

The longer I lived in the apartment, the more I hated it, the more I realized that I had been fooled by nice finishes and proximity to transit into thinking it was a good apartment. As soon as we’d got in there, things started to, well, not work. European fixtures aren’t well-liked by American plumbers. The dimmable lights would sputter and spit little blinking LEDs for reasons totally unknown and we’d have to pull a tab to reset them. Everything was finicky and delicate. The shower head, the kitchen sink that fell in two times somehow (which we had been accused of being rough with, an absurd thought – it’s a kitchen sink!), the bedroom doors that didn’t close right, the bathroom door that would trap you inside if it shut during a hot shower. All of the niceness, the glitzy brand names, the living materials were not meant for everyday use, even by gentle individuals like ourselves. They were made solely for looking at, as though that were the point of all habitation.

Suddenly, we were in a prison of design. This was a place for performing living, and we, as normal people, simply wanted to live – wanted to leave clothes in front of the washer as we pleased, wanted to bake cakes that got flour everywhere, wanted to just collapse somewhere and go to sleep, wanted to have a private life not dominated by the curation and fussiness and pressures of taste that govern careers like mine. Our house was always just for our consumption, not that of others. I spend most of my life in the worlds of design and architecture, and to be honest, you wouldn’t know it aside from all the heavy books and the tapered legged coffee table. I never had it in me to turn my house into a museum of my own clever delectations, a proof of concept of my skills as a critic. I just wanted to dwell naively. Off Instagram.

But the worst part of the apartment was that it was designed by someone who didn’t know how to live, couldn’t think of anyone’s world other than the sparse one of the architect who owned nothing save for color-coordinated books and limited edition lithographs. It had all the functions of living, technically speaking, but the way in which they were allocated and arranged made no sense. There were no closets in any of the rooms, just open storage, which only works for people who don’t actually have things. The tub wasn’t caulked to the wall so that it would appear to float, a nice aesthetic effect which made taking showers annoying and perhaps bad for the walls.

Above all, I hated the kitchen the most. The kitchen was basically ten feet of counter space, with giant cabinets extending to the ceiling, far beyond what any normal person could reach without a stepladder, the upper shelves of which being where things went to be forgotten. A sink punctuated the center of the marble countertop – and marble is a terrible material for a countertop. It stains and wears with water. It shows all mess mercilessly. There was a stove and a fridge just, like, in the kitchen attached to nothing. The gas stove had no overhead ventilation and every time we used it we had to open the door so the smoke alarm wouldn’t go off. It was a kitchen designed by people who never cooked: too small, inefficient, laid out in the way it was, like so many apartment kitchens, so that it shared services with the same wall as the bathroom. We couldn’t put anything in the finicky sink to soak so the counter was always crowded with dishes. We had no dishwasher because that would mean ceding the only bottom cabinet that was truly usable.

It angered me, really, as an architecture critic, that this apartment, which had so very much been made to be ogled and looked at and oohed and ahhed over by people of taste was absolutely, for a lack of a better word, bullshit. That it was beautiful but unlivable, like some kind of joke made only for people like me to laugh at. I love design, obviously, but I hate the pressure to have to perform taste in the most intimate of one’s settings and this was the epitome of that, the untouchableness of it, the smug superiority of its flavorless emptiness. I’m not a curator of other people’s gazes when I’m in my pajamas or sweating it out on the trainer. I’m simply Kate Wagner, living with a husband and a dog, like a lot of twenty-seven year old white girls in cities. By the end of the lease, I just wanted to move somewhere where I’d feel at home, whatever that meant. I never had the type A personality needed for pristine white walls. I hated how the recessed lights made all our stuff look cheap, like a museum of stunted adulthood.

Our new apartment has a two-year lease, which is about as much stability people like us could ever hope for or afford. It’s the first floor of a worker’s cottage dominated by a palladian window on the second story that would be pretentious were it not so earnest. The house itself is a hodgepodge of the vernacular, which is what I deserve, as its chronicler. The interior walls are painted lively colors – a soft blue, a slate purple, a taupe, a mint green. It’s gritty enough to be cool and old enough to be livable. There are closets. The bathroom is covered in chiclet glass tile that’s different shades of blue, which I find endearing. But what I love most of all is the kitchen.

All my life, I’d been in search of an apartment with a decent kitchen, and I’ve always wondered why apartment kitchens suck so bad save for the obvious answer (landlords are cheap.) Like I said earlier, the desire to route services (plumbing, electricity) in the most efficient way possible governs most things, though this is more true of renovations or new builds than the adaptation of single family homes into multi-family dwellings. In the case of the latter, the second floor apartments are always the worst off, in fact, almost all apartments are worse off than the one that houses the actual original full-sized kitchen to begin with.

Adapting a space that was meant for sleeping into one where food could be cooked often required some inventiveness with regards to fire safety and ventilation and this usually took the path of least resistance, hence why most kitchens are positioned to the rear of the house, especially if there is outdoor access. (Plumbing in older houses also tends to be positioned on interior walls to avoid pipes freezing in the winter.) In Chicago, most layouts of familiar single-family vernacular housing styles are similar to one another on the ground floor, but the apartments on the second floor are always quite varied, especially with regard to where the kitchen is placed. Often it’s done, again, in a way that allows existing services to be used or for new ones to be built that are on the same wall as another unit. Adding new plumbing where it wasn’t before is expensive and a pain.

However, service routing aside, most apartment kitchens are only ever satisfactory – kitchens for people who ate nothing but takeout or miniature versions of the real thing as though apartment living were just an audition for owning a house, something that’s just no longer true in this economy. This one – with its vintage 50s aluminum cabinetry and its enameled countertops with glitter infused in them like some kind of demure bowling ball and its full-sized appliances and dishwasher, and mint green penny tile, its wonderful quirkiness and its ample cabinet space beneath the counters – is functional. It works like a kitchen should, towards a domestic life engineered by modernism and scientific management with a dash of feminism to be less arduous. This is nothing short of a miracle to me. When I think about it, I get emotional. I have been searching for so long for any kind of semblance of a place tailored in any way towards my needs, towards my desires, which is to have enough space to help rather than hinder in the preparation of meals. Meals we now enjoy as a very small family. The kitchen was never really important to me until I had someone to share it with, as insipid and mawkish and introduction-to-a-gluten-free-recipe as that sounds. I’m no longer living for one, but for two, and I didn’t realize how much that changed living.

I didn’t realize how much autonomy meant until I lived in a place where I felt I had none.

Our new landlords, a school-teacher and private investigator (what a combo) are there right now cleaning the house, fixing the little nicks left by the previous tenants, pulling out their picture hanging apparatuses, which, they assure us, we can leave too. We can put stuff up on the walls, the very thought! They’ve already stickered our names on the mailboxes, have installed a doorbell, which strikes me as a very post-COVID gesture. They hope we will stay there a long time, and so do we. There’s a yard for the dog to play in with garden beds that house burgeoning bell peppers. Our friends are allowed to come over, which they weren’t before — well, not officially, but it felt like it. There are sounds in the house, of those who dwell above and below, the sounds of life. There’s a window I wish I was sitting by writing, and soon, I will be.

So many of us ask the simple question, what is home? What should it be? And the only real, genuine answer I have to give after ten-odd moves is that home is the only place in the world where one can be truly unselfconscious. Even if that means having particleboard furniture and a bunch of bicycles.

That’s my business, not yours.

If you liked this post, check out the McMansion Hell Patreon, or, if so inclined, drop a tip in the tip jar.

r/McMansionHell - Hello r/McMansionHell, I'm Kate Wagner, creator of McMansion Hell and architecture critic at The New Republic. AMA!

r/McMansionHell - Hello r/McMansionHell, I'm Kate Wagner, creator of McMansion Hell and architecture critic at The New Republic. AMA!:

Howdy, Folks! If you’re not busy right now, I’m doing an AMA on the McMansion Hell Subreddit! Stop by and ask me some questions!

The McMansion Hell Yearbook: 1979

Howdy, folks! I hope all of my fellow Midwesterners are enjoying this year’s false spring. Seventy-degree days notwithstanding, the snow will indeed be back, and, as such, I have prepared for you a house to enjoy (?) alongside a miserably late-in-the-year hot cocoa. 

Now, this house isn’t as oppressively horrible as the last one, however, the point of the Yearbook is to show off how houses evolved overtime, and also to celebrate some of the kookier time capsules left out there. Our current house falls into the latter category, and to be honest, I find it weirdly endearing. 

Located just outside of Detroit, this 5 bed, 4.5 bath house tops out at over 10,000 square feet. Yes, you read that right. 10,000. You’ll see why later. Anyways, if you want to purchase said house, it can be all yours for just under $1,000,000. A steal!

??? Foyer

In America we don’t have barons, only robber barons, so I’m going to assume whoever built this house did so on the backs of thousands of exploited 19th century child laborers or whatever. Bad stuff. 

??? Room

Unsure of the purpose of this room, genuinely, because all other rooms are accounted for. This one’s just empty. It’s just existing. Vibing, as one might say.

TV (???) Room

Don’t mind me, I’m just getting out my birding binoculars in order to watch Seinfeld reruns.


Considering the history of the Midwest and the fact that Sears and co. cut down all our old growth forests in order to do cheap furniture and balloon framing, this whole wood paneling bit is really part of a much larger historical milieu.  

Dining Room

The American Bicentennial lurks in the background of all of these houses, its legacy permanently ingrained in too-dark rooms across the nation. 

Main Bedroom

Shivering at the thought of my feet touching cold tile floor every morning. That’ll wake you up. 

Other Bedroom

You know, the grandness of the chandelier has diminishing returns if you put one in every single room. Then it becomes just another light fixture. 

Random Bathroom

BROWN TUB BROWN TUB BROWN TUB (the rarest of all mid-century tubs)

Pleasure Grotto

Ok now this is why I chose this house. It also explains why this house is 10,000 square feet - at least half of that is just this pool alone. The funniest bit is, I can’t for the life of me tell WHERE this pool is by looking at the exterior of the house. In fact, I’m not sure how they managed to fit so much house in that small of an envelope, but at this point, it’s so weird I’m inclined not to ask further questions. Some things in the universe are not meant to be known to us. 

Rear Exterior


Anyways, I’ll let that haunt you for a little while. 

In the mean time, I’d like to take this space at the end of the post to announce that I’ve started a little side project devoted to my other love in life, professional cycling. It’s a newsletter called derailleur that aims to tell the stories of contemporary professional cycling in an unconventional, narrative-driven way. If you’re into such things, feel free to check it out: derailleur.substack.com 


If you like this post, and want to see more like it, consider supporting me on Patreon!

There is a whole new slate of Patreon rewards, including: good house of the month, an exclusive Discord server, monthly livestreams, free merch at certain tiers and more!

Not into recurring donations but still want to show support? Consider the tip jar!

Or, Check out the McMansion Hell Store! Proceeds from the store help protect great buildings from the wrecking ball.

i draw cyclists

i draw cyclists:

hey so in my spare time, when i am not an architecture critic, i like to draw. this has merged with my other love in life (professional cycling) and as such i have dedicated the last six months of my evening hours to drawing cyclists. 

tl;dr i made a tumblr where i’m posting my art if you’re into that kind of thing. this isn’t monetized in any way and i don’t take commissions - it’s just a nice (if strange) hobby i enjoy.

see you all monday with a new house post <3

The McMansion Hell Yearbook: 1978

Howdy Folks! Today’s house comes to us from Iredell County, North Carolina, and trust me, it is quite a doozy - just in time for Valentines Day, too! If you don’t fall in love with it, I don’t know what to tell you. 

This 5300 square foot, 4 bedroom, 4.5 bath house, comes in at $625,000, making it more of a bargain than most McMansions usually are, and while the Tudors never came to America, a place that had not yet been “discovered” by the time the Tudors were in power in England, fear not - for all the repression and stuffiness of 15th century Britain can still be found within these darkened doors. 

Lawyer Foyer

If your house doesn’t constantly give off I AM MARRIED vibes, your spouse might start having indecent thoughts. One must stay vigilant at all times. 

Dining Room

Look, hutches are good storage, okay. Sturdy. We as a generation (millennials) need to get back into knickknacks. Minimalism is dead. Long live kitsch. 

Living Room

Honestly, this house is so dark and repressed it makes high school me look like a libertine. 


“What do you mean ‘dopeness’ isn’t a qualifier for granting a property historical landmark status?” 

Main Bedroom

Love is in the air. Also the air is really, really stale in here right now. 


If your bathroom doesn’t emulate a luxuriant grotto, wyd???

Bedroom 2

please, my floor ducks, they are so cold,,,,


I have got to stop using epic ironically. I already lived through 2008 once. 

That’s it for the interior! Let’s just step outside for a quick breather…

Rear Exterior

Well, I hope you had a good time traipsing through what can only be described as a treasure trove of different matching fabrics. Be sure to stick around for the next part of “Underground” which is coming your way shortly!

If you like this post, and want to see more like it, consider supporting me on Patreon!

There is a whole new slate of Patreon rewards, including: good house of the month, an exclusive Discord server, weekly drawings, monthly livestreams, a reading group, free merch at certain tiers and more!

Not into recurring donations but still want to show support? Consider the tip jar! 

Or, Check out the McMansion Hell Store! Proceeds from the store help protect great buildings from the wrecking ball.

Underground, Part 1

[Author’s Note: A year ago, when waiting for the DC Metro, I came up with an idea for a short story involving two realtors and the infamous Las Vegas Underground House, typed up an outline, and shoved it away in my documents where it sat neglected until this month. The house recently resurfaced on Twitter, and combined with almost a year of quarantine, the story quickly materialized. Though I rarely write fiction, I decided I’d give it a shot as a kind of novelty McMansion Hell post. I’ve peppered the story with photos from the house to break up the walls of text. Hopefully you find it entertaining. I look forward to returning next month with the second installment of this as well as our regularly scheduled McMansion content. Happy New Year!

Warning: there’s lots of swearing in this.]



Back in 1997, Mathieu Rino, the son of two Finnish mechanical engineers who may or may not have worked intimately with the US State Department, changed his name to Jay Renault in order to sell more houses. It worked wonders.

He gets out of the car, shuts the door harder than he should. Renault wrinkles his nose. It’s a miserable Las Vegas afternoon - a sizzling, dry heat pools in ripples above the asphalt. The desert is a place that is full of interesting and diverse forms of life, but Jay’s the kind of American who sees it all as empty square-footage. He frowns at the dirt dusting up his alligator-skin loafers but then remembers that every lot, after all, has potential. Renault wipes the sweat from his leathery face, slicks back his stringy blond hair and adjusts the aviators on the bridge of his nose. The Breitling diving watch crowding his wrist looks especially big in the afternoon glare. He glances at it.

“Shit,” he says. The door on the other side of the car closes, as though in response. 

If Jay Renault is the consummate rich, out-of-touch Gen-Xer trying to sell houses to other rich, out-of-touch Gen-Xers, then Robert Little is his millennial counterpart. Both are very good at their jobs. Robert adjusts his tie in the reflection of the Porsche window, purses his lips. He’s Vegas-showman attractive, with dark hair, a decent tan, and a too-bright smile - the kind of attractive that ruins marriages but makes for an excellent divorcee. Mildly sleazy.

“Help me with these platters, will you?” Renault gestures, popping the trunk. Robert does not want to sweat too much before an open house, but he obliges anyway. They’re both wearing suits. The heat is unbearable. A spread of charcuterie in one hand, Jay double-checks his pockets for the house keys, presses the button that locks his car. 

Both men sigh, and their eyes slowly trail up to the little stucco house sitting smack dab in the center of an enormous lot, a sea of gravel punctuated by a few sickly palms. The house has the distinct appearance of being made of cardboard, ticky-tacky, a show prop. Burnt orange awnings don its narrow windows, which somehow makes it look even more fake. 

“Here we go again,” Jay mutters, fishing the keys out of his pocket. He jiggles them until the splintered plywood door opens with a croak, revealing a dark and drab interior – dusty, even though the cleaners were here yesterday. Robert kicks the door shut with his foot behind him.

 “Christ,” he swears, eyes trailing over the terrible ecru sponge paint adorning the walls. “This shit is so bleak.”

The surface-level house is mostly empty. There’s nothing for them to see or attend to there, and so the men step through a narrow hallway at the end of which is an elevator. They could take the stairs, but don’t want to risk it with the platters. After all, they were quite expensive. Renault elbows the button and the doors part. 

“Let’s just get this over with,” he says as they step inside. The fluorescent lights above them buzz something awful. A cheery metal sign welcomes them to “Tex’s Hideaway.” Beneath it is an eldritch image of a cave, foreboding. Robert’s stomach’s in knots. Ever since the company assigned him to this property, he’s been terrified of it. He tells himself that the house is, in fact, creepy, that it is completely normal for him to be ill at ease. The elevator’s ding is harsh and mechanical. They step out. Jay flips a switch and the basement is flooded with eerie light. 

It’s famous, this house - The Las Vegas Underground House. The two realtors refer to it simply as “the bunker.” Built by an eccentric millionaire at the height of Cold War hysteria, it’s six-thousand square feet of paranoid, aspirational fantasy. The first thing anyone notices is the carpet – too-green, meant to resemble grass, sprawling out lawn-like, bookmarked by fake trees, each a front for a steel beam. Nothing can grow here. It imitates life, unable to sustain it. The leaves of the ficuses seem particularly plastic.

Bistro sets scatter the ‘yard’ (if one can call it that), and there’s plenty of outdoor activities – a parquet dance floor complete with pole and disco ball, a putt putt course, an outdoor grill made to look like it’s nestled in a rock, but in reality better resembles a baked potato. The pool and hot tub, both sculpted in concrete and fiberglass mimicking a natural rock formation, are less Playboy grotto and more Fred Flintstone. It’s a very seventies idea of fun.

Then, of course, there’s the house. That fucking house. 

A house built underground in 1978 was always meant to be a mansard – the mansard roof was a historical inevitability. The only other option was International Style modernism, but the millionaire and his wife were red-blooded anti-Communists. Hence, the mansard. Robert thinks the house looks like a fast-food restaurant. Jay thinks it looks like a lawn and tennis club he once attended as a child where he took badminton lessons from a swarthy Czech man named Jan. It’s drab and squat, made more open by big floor-to-ceiling windows nestled under fresh-looking cedar shingles. There’s no weather down here to shrivel them up.


“Shall we?” Jay drawls. The two make their way into the kitchen and set the platters down on the white tile countertop. Robert leans up against the island, careful of the oversized hood looming over the electric stovetop. He eyes the white cabinets, accented with Barbie pink trim. The matching linoleum floor squeaks under his Italian loafers. 

“I don’t understand why we bother doing this,” Robert complains. “Nobody’s seriously going to buy this shit, and the company’s out a hundred bucks for party platters.”

“It’s the same every time,” Renault agrees. “The only people who show up are Instagram kids and the crazies - you know, the same kind of freaks who’d pay money to see Chernobyl.” 

“Dark tourism, they call it.”

Jay checks his watch again. Being in here makes him nervous.

“Still an hour until open house,” he mutters. “I wish we could get drunk.”

Robert exhales deeply. He also wishes he could get drunk, but still, a job’s a job.

“I guess we should check to see if everything’s good to go.”

The men head into the living room. The beamed, slanted ceiling gives it a mid-century vibe, but the staging muddles the aura. Jay remembers making the call to the staging company. “Give us your spares,” he told them, “Whatever it is you’re not gonna miss. Nobody’ll ever buy this house anyway.” 

The result is eclectic – a mix of office furniture, neo-Tuscan McMansion garb, and stuffy waiting-room lamps, all scattered atop popcorn-butter shag carpeting. Hideous, Robert thinks. Then there’s the ‘entertaining’ room, which is a particular pain in the ass to them, because the carpet was so disgusting, they had to replace it with that fake wood floor just to be able to stand being in there for more than five minutes. There’s a heady stone fireplace on one wall, the kind they don’t make anymore, a hearth. Next to it, equally hedonistic, a full bar. Through some doors, a red-painted room with a pool table and paintings of girls in fedoras on the wall. It’s all so cheap, really. Jay pulls out a folded piece of paper out of his jacket pocket along with a pen. He ticks some boxes and moves on.

The dining room’s the worst to Robert. Somehow the ugly floral pattern on the curtains stretches up in bloomer-like into a frilly cornice, carried through to the wallpaper and the ceiling, inescapable, suffocating. It smells like mothballs and old fabric. The whole house smells like that. 

The master bedroom’s the most normal – if anything in this house could be called normal. Mismatched art and staging furniture crowd blank walls. When someone comes into a house, Jay told Robert all those years ago, they should be able to picture themselves living in it. That’s the goal of staging. 

There’s two more bedrooms. The men go through them quickly. The first isn’t so bad – claustrophobic, but acceptable – but the saccharine pink tuille wallpaper of the second gives Renault a sympathetic toothache. The pair return to the kitchen to wait.


Both men are itching to check their phones, but there’s no point – there’s no signal in here, none whatsoever. Renault, cynical to the core, thinks about marketing the house to the anti-5G people. It’s unsettlingly quiet. The two men have no choice but to entertain themselves the old-fashioned way, through small talk.

“It’s really fucked up, when you think about it,” Renault muses.

“What is?”

“The house, Bob.”

Robert hates being called Bob. He’s told Jay that hundreds of times, and yet…

“Yeah,” Robert mutters, annoyed.

“No, really. Like, imagine. You’re rich, you founded a major multinational company marketing hairbrushes to stay-at-home moms, and what do you decide to do with your money? Move to Vegas and build a fucking bunker. Like, imagine thinking the end of the world is just around the corner, forcing your poor wife to live there for ten, fifteen years, and then dying, a paranoid old man.” Renault finds the whole thing rather poetic. 

“The Russkies really got to poor ol’ Henderson, didn’t they?” Robert snickers.

“The wife’s more tragic if you ask me,” Renault drawls. “The second that batshit old coot died, she called a guy to build a front house on top of this one, since she already owned the lot. Poor woman probably hadn’t seen sunlight in God knows how long.”

“Surely they had to get groceries.”

Jay frowns. Robert has no sense of drama, he thinks. Bad trait for a realtor.

“Still,” he murmurs. “It’s sad.”

“I would have gotten a divorce, if I were her,” the younger man says, as though it were obvious. It’s Jay’s turn to laugh.

“I’ve had three of those, and trust me, it’s not as easy as you think.”

“You’re seeing some new girl now, aren’t you?” Robert doesn’t really care, he just knows Jay likes to talk about himself, and talking fills the time.  

“Yeah. Casino girl. Twenty-six.”

“And how old are you again?”

“None of your business.”

“Did you see the renderings I emailed to you?” Robert asks briskly, not wanting to discuss Jay’s sex life any further.

“What renderings?”

“Of this house, what it could look like.”

“Oh. Yeah.” Jay has not seen the renderings.

“If it were rezoned,” Robert continues, feeling very smart, “It could be a tourist attraction - put a nice visitor’s center on the lot, make it sleek and modern. Sell trinkets. It’s a nice parcel, close to the Strip - some clever investor could make it into a Museum of Ice Cream-type thing, you know?”

“Museum of Ice Cream?”

“In New York. It’s, not, like, educational or anything. Really, it’s just a bunch of colorful rooms where kids come to take pictures of themselves.”

“Instagram,” Jay mutters. “You know, I just sold a penthouse the other week to an Instagram influencer. Takes pictures of herself on the beach to sell face cream or some shit. Eight-point-two million dollars.”

“Jesus,” Robert whistles. “Fat commission.”

“You’re telling me. My oldest daughter turns sixteen this year. She’s getting a Mazda for Christmas.”

“You ever see that show, My Super Sweet Sixteen? On MTV? Where rich kids got, like, rappers to perform at their birthday parties? Every time at the end, some guy would pull up in, like, an Escalade with a big pink bow on it and all the kids would scream.”

“Sounds stupid,” Jay says.

“It was stupid.”

It’s Robert’s turn to check his watch, a dainty gold Rolex.

“Fuck, still thirty minutes.”

“Time really does stand still in here, doesn’t it?” Jay remarks.

“We should have left the office a little later,” Robert complains. “The charcuterie is going to get –“

A deafening sound roars through the house and a violent, explosive tremor throws both men on the ground, shakes the walls and everything between them. The power’s out for a few seconds before there’s a flicker, and light fills the room again. Two backup generators, reads Jay’s description in the listing - an appeal to the prepper demographic, which trends higher in income than non-preppers. For a moment, the only things either are conscious of are the harsh flourescent lighting and the ringing in their ears. Time slows, everything seems muted and too bright. Robert rubs the side of his face, pulls back his hand and sees blood.

“Christ,” he chokes out. “What the hell was that?”

“I don’t know,” Jay breathes, looking at his hands, trying to determine if he’s got a concussion. The results are inconclusive – everything’s slow and fuzzy, but after a moment, he thinks it might just be shock.

“It sounded like a fucking 747 just nosedived on top of us.” 

“Yeah, Jesus.” Jay’s still staring at his fingers in a daze. “You okay?”

“I think so,” Robert grumbles. Jay gives him a cursory examination.

“Nothing that needs stitches,” he reports bluntly. Robert’s relieved. His face sells a lot of houses to a lot of lonely women and a few lonely men. There’s a muffled whine, which the two men soon recognize as a throng of sirens. Both of them try to calm the panic rising in their chests, to no avail.

“Whatever the fuck happened,” Jay says, trying to make light of the situation, “At least we’re in here. The bunker.”

Fear forms in the whites of Robert’s eyes.

“What if we’re stuck in here,” he whispers, afraid to speak such a thing into the world. The fear spreads to his companion.

“Try the elevator,” Jay urges, and Robert gets up, wobbles a little as his head sorts itself out, and leaves. A moment later, Jay hears him swear a blue streak, and from the kitchen window, sees him standing before the closed metal doors, staring at his feet. His pulse racing, Renault jogs out to see for himself.

“It’s dead,” Robert murmurs. 

“Whatever happened,” Jay says cautiously, rubbing the back of his still-sore neck, “It must have been pretty bad. Like, I don’t think we should go up yet. Besides, surely the office knows we’re still down here.”

“Right, right,” the younger man breathes, trying to reassure himself.

“Let’s just wait it out. I’m sure everything’s fine.” The way Jay says it does not make Robert feel any better. 

“Okay,” the younger man grumbles. “I’m getting a fucking drink, though.”

“Yeah, Jesus. That’s the best idea you’ve had all day.” Renault shoves his hands in his suit pocket to keep them from trembling.  


If you like this post, and want to see more like it, consider supporting me on Patreon!

There is a whole new slate of Patreon rewards, including: good house of the month, an exclusive Discord server, weekly drawings, monthly livestreams, a reading group, free merch at certain tiers and more!

Not into recurring donations but still want to show support? Consider the tip jar! 

Or, Check out the McMansion Hell Store! Proceeds from the store help protect great buildings from the wrecking ball.

We Interrupt This Broadcast to Bring You an Especially Cursed House

Hello everyone. Originally, this post was supposed to be devoted to the year 1978, however something came up, and by something, I mean this 2.2 million-dollar, 5,420 sq ft 4 bed/4.5 bath house in Colt’s Neck, NJ. 

You see, usually, when a listing goes viral, I’m content to simply retweet it with a pithy comment, but this house genuinely shook something in me, genuinely made me say “what the (expletive)” out loud. It is only fair to inflict this same suffering onto all of you, hence, without further ado: 

Looks normal, right? Looks like the same low-brow New Jersey McMansion we’re all expecting, right? Oh, oh dear, you couldn’t be more wrong

Guess who’s making a list and checking it twice? 

Guess who’s gonna find out who’s naughty or nice?

Guess who’s coming to town? 

Guess who’s coming to town to drag your ass into hell?

A gentle reminder that it is not yet Thanksgiving. 

But oh. Oh. It continues:

If you’re wondering what’s happening here, you’re not alone, and sadly there is no convenient way to find out via a kind of haunted house hotline or something. 

I can’t even label these rooms because frankly I’m not even sure what they are. All I am sure of is that I want out of them as soon as humanly possible. 

r̸̘̆e̴̝̻̽m̵̡̼̚ȩ̵͑̎ͅm̷͍̮̉b̸̥̈e̶̯̺̽͗r̸̝͊͠ ̸̡͎̅̀t̴̯̲̓ȯ̷̮̫ ̷̜̅̀ŵ̶̟̱ā̴̭̘s̸̥͋h̴͉̿ ̵̡̑y̸̩͈͑o̷̹̭͛͝ů̷̩̮̔r̶̜̃ ̴̠̗͋ẖ̴̈́͛a̸̢̟̐͒n̶̩̟̆ḍ̵̍̀s̴̨̈́

How is it that a room can simultaneously threaten, frighten, and haunt me? Me, of all people!

My eyes do not know where to go here. They go to the window, they go to the fireplace, they go to the massive mound of fake plant and statuary currently gorging on the leftmost corner of the room, they go to my hands, which are shaking. 

“Hello, I would like to get in touch with the Ministry of Vibes? Yes, I’ll hold.” 

I haven’t been this afraid of a shower since I went to Girl Scout camp in the fifth grade and there was a brown recluse spider in the camp shower and I screamed until the counselor came in and told me it was only a wolf spider but it turns out those still bite you and it hurts

I love watching Still Images on my Television Set :)

Nobody make a sound. He’s watching you. 

i spy with my evil eye:


Their souls are trapped in these photographs forever :)

Okay, phew, we made it out alive. Here’s the back of the house I guess. 

Well, I hope you’re as thoroughly disturbed as I am. Seriously, I’m going to have trouble sleeping. I mean, I already have trouble sleeping, but this is just making that existing problem so much worse. 

If you like this post, and want to see more like it, consider supporting me on Patreon!

There is a whole new slate of Patreon rewards, including: good house of the month, an exclusive Discord server, weekly drawings, monthly livestreams, a reading group, free merch at certain tiers and more!

Not into recurring donations but still want to show support? Consider the tip jar! (Tips are much appreciated since I am making a cross country move in two weeks!!!)

Or, Check out the McMansion Hell Store! Proceeds from the store help protect great buildings from the wrecking ball.

The McMansion Hell Yearbook: 1977

Howdy, folks, and happy October! (It’s snowing here in Chicago lol) 

Before I get down to business on today’s post, I want to let you know of two big events coming up this week: 

First, I’ll be in conversation with Susan Chin and Vinson Cunningham tomorrow evening (10/28) to talk about urbanism during the pandemic (virtually) at the Museum of the City of New York. More info and tickets here

 I am giving this year’s Brendan Gill Lecture in Architectural Criticism at Yale via Zoom on Thursday the 29th of October at 6:30 Eastern Time. Admission is free. Here’s a link to the talk which includes info on how to register. 

Alright, now back to the main event. We’re back in Cook County, Illinois because of course we are, and this house falls into the rare McMansion Hell category of “this house is terrible but also kind of cute somehow????” 

It’s a shame you can’t really see the turret because it adds so much. Anyways, this house is peak 70s McMansion: longer than it is tall, involves a mansard, big picture windows, not too adventurous roof-wise. Still, it’s 6900 square feet boasting 5 bedrooms and 6.5 baths all at a whopping $1.5 million dollars. Just some pocket change, you know…

Let’s see inside, shall we?

Lawyer Foyer

All I want is some Looney Tunes action where some’s coming up from the basement and someone’s coming in the front door and WHAM!!!! 

Sitting Room

I kind of stan the dog pots though… 

Dining Room

I think the wallpaper might be crabs???? (????)


Pros of tile countertops: v twee and cute
Cons of tile countertops: grout 

Also we NEED to bring back the kitschy farmhouse aesthetic from 40 years ago. No more quartz countertops. It’s time for tiles with chickens on them!!!


Is this room supposed to be like weirdly tropical?? or Parisian??? or Martha Stewart??? or???

Vibe check: [please calibrate vibe checker and try again]


After all, inside every middle manager is a languishing Hemingway…

Main Bedroom

“Struggled hard for these views (six arm flexing emojis)”

Also, disclosure: McMansion Hell will no longer use the term “master bedroom” because it’s antiquated and never made much sense after the (American) Civil War if you really think about it for more than three seconds. 

Main Bathroom

where to purchase malachite wallpaper asking for a friend (the friend is my office)

Spare Bedroom

Nothing says “I am a fun-loving carefree and slightly cRaZy girl” like this font:

Alright, that’s it for the inside. Instead of the rear exterior though, I’m going to end this post with a fun aerial shot instead just to show that my suspicions about this house have been confirmed. 

Secret Aerial Footage (helicopter sounds)

See, this house is actually very weird!!!! It is not as cute when all of its wily tricks have been revealed!!!!

Okay, that’s it for 1977. Stay tuned for 1978! 

If you like this post, and want to see more like it, consider supporting me on Patreon!

There is a whole new slate of Patreon rewards, including: good house of the month, an exclusive Discord server, weekly drawings, monthly livestreams, a reading group, free merch at certain tiers and more!

Not into recurring donations but still want to show support? Consider the tip jar! (Tips are much appreciated since I am making a cross country move in two weeks!!!)

Or, Check out the McMansion Hell Store! Proceeds from the store help protect great buildings from the wrecking ball.

Public opinion has softened its views on Brutalism. That isn’t enough to stay the wrecking ball.

Public opinion has softened its views on Brutalism. That isn’t enough to stay the wrecking ball.:

I’m back in The Architect’s Newspaper, where I’m talking about my favorite subject (Brutalism) and my least favorite subject (capitalism).

The McMansion Hell Yearbook: 1976

Howdy, folks! Today’s house comes to us from my newly adopted county of Cook County, Illinois, and boy can this baby fit so many 70s house stereotypes in it. 

It’s got everything: weird spanish colonial revivalism, an external layout that can only be described as post-split-level, a 3 car garage, and it’s brown! This lovely 5 bedroom, 5 bath 5200 square foot estate is relatively affordable by McMansion Hell standards, coming in at around $600,000. There’s a lot of house to cover, so let’s get the ball rolling! 

Lawyer Foyer

This foyer has all the elements of a contemporary lawyer foyer (large chandelier, grand staircase, two stories) except for the oversized transom window over the front door. The fact that the house looks like a split-level on the outside is interesting because it’s a regular two-story house on the inside, furthering the hypothesis that the Lawyer Foyer itself is an offshoot of the 1.5 and two-story entrances present in split levels. In many ways this house is a transitional example nestled between two eras: the split-level/ranch of the 70s and the two-story neo-eclectic houses that would become popular in the 1980s. 

Sitting Room

Fun fact: a look at recent IKEA catalogs demonstrates that the grandma couch is slowly wedging its way back into America’s living rooms. 

Dining Room

I am weeping with envy at those chairs. (Instagram story vagueposting voice) Some people just don’t know what they have. 

Living Room

The overstuffed leather sofas might not be pretty but they are authentic.


Why I hate the kitchen island/peninsula stovetop recapped:
- can’t use the island for seating bc cooking stuff is hot and steamy
- one casual lean and you’re burned
- no backsplash to catch like overboiling pasta sauce
- wastes valuable counter space

I can go on.

Master Bedroom

Personally if I had all that extra space in my bedroom I’d put something cool like a pool table or a hot tub in there bc why not???

Speaking of tubs…

Master Bath

One must wonder why brown bathroom fixtures exist in the first place because frankly it’s not a very flattering color considering the functions. Let’s just say it was a different time. 

Bedroom 2

As someone who grew up in the era of Toyota Corolla hegemony, 70s cars are extremely funny to me - like they take up half a block and get 4 miles to the gallon??? No wonder there was an oil crisis!!! 

Bedroom 3

The virgin midcentury modern collector vs the chad grandma using a 1967 teak Dunbar sideboard as a display case for their doily collection 


This whole post is a ploy to get the zoomers to watch Cheers

Alright folks, our little house tour has come to a close - it’s time for our favorite part:

Rear Exterior

(looking enviously at other countries with functioning governments beginning to open back up): yeah ok you do you, i’m just gonna watch the tour de france in a bathrobe and rank the teams based on how cancelled their sponsors are.

Well that does it for 1976! Join us soon for another installment of the Brutalism Post and keep your eyes peeled for whatever wretched house the year 1977 has bestowed upon this cursed land. 

I know that these are economically uncertain times, but many creators including myself depend on Patreon for most of their income, so if you have a minimum of $12/year to spare and are into bonus content, then do I have some good news for you:

If you like this post, and want to see more like it, consider supporting me on Patreon!

There is a whole new slate of Patreon rewards, including: good house of the month, an exclusive Discord server, weekly drawings, monthly livestreams, a reading group, free merch at certain tiers and more!

Not into recurring donations but still want to show support? Consider the tip jar! (Tips are much appreciated since I am making a cross country move in two weeks!!!)

Or, Check out the McMansion Hell Store! Proceeds from the store help protect great buildings from the wrecking ball.

The McMansion Hell Yearbook: 1975

Howdy, folks! We’re halfway through the 70s, and I thought I’d celebrate with a time capsule house stuck weirdly enough, in the 80s. Our house this time comes to us from Fairfield County, Connecticut, and while it may not be an obvious contender on the exterior, I promise you won’t be disappointed once we head through that door. 

This house, despite its modest exterior, boasts 4 bedrooms, 4.5 bathrooms, and just over 5300 square feet. It can be yours for just over $2.2 million USD.  I know you’re dying to see what’s inside, so I won’t keep you any longer.

Lawyer Foyer

As you can see, painting the walls white did not take the 70s out of this house. The disappointing part is that this is the room with the most vestiges of its 70s past - that wrought iron railing, pink linoleum, and pseudo-gothic chandelier definitely affirm that originally this house was much, much groovier before its 80s redux. 

Great Room

The realtor described this house as “transitional” which in some cases is a polite way of saying “trapped between stylistic movements and terrified to death of choosing one.” 

Sitting Room

Alright, alright, here’s one for the 80s aesthetic blogs. You’re welcome. 

Dining Room

As a form of economic stimulus, I am willing to accept giant cabinets and twee bird knickknacks. Speaking of giant cabinets, that one is, like, hearse-sized. How many candelabras and cloth napkins could one family possibly possess? 

Also, for some reason, the listing did not include any pictures of the kitchen, so we’ll have to go right into the master bedroom. 

Master Bedroom

Even in the 80s, was there ever a time where this aesthetic didn’t look, well, grandmotherly?

Bedroom 2

I’m moving in a few weeks and my back hurts just thinking about trying to lift that furniture!!!!

Bonus Room

I have to give credit where credit is due: this room is cool, and I would absolutely chill in it. Which goes to prove how deeply uncool these rich people are for not using it for chilling or any other activities. 

Rec Room

The drop-ceiling/can light combo is somewhat rare in terms of McMansion bonus rooms, as is that diagonal wood paneling which I unironically stan. Forget shiplap!!!

Alright, that’s it for our interior. Now to check out the rear exterior which proves once and for all that this house is, in fact, a McMansion. 

Rear Exterior

Honestly, I don’t know what kind of house this is - my guess is that it’s, like, a post-split-level, whatever that means. Either way, it’s super tacky and I’m glad I found it so I could share it with all of you. Check back here soon for another 70s house, as well as a much-needed update to the Brutalism Post. 

I know that these are economically uncertain times, but many creators including myself depend on Patreon for most of their income, so if you have a minimum of $12/year to spare and are into bonus content, then do I have some good news for you:

If you like this post, and want to see more like it, consider supporting me on Patreon!

There is a whole new slate of Patreon rewards, including: good house of the month, an exclusive Discord server, weekly drawings, monthly livestreams, a reading group, free merch at certain tiers and more!

Not into recurring donations but still want to show support? Consider the tip jar! (Tips are much appreciated since I am making a cross country move in two weeks!!!)

Or, Check out the McMansion Hell Store! Proceeds from the store help protect great buildings from the wrecking ball.

#HousingLIVE Join The New Republic’s Kate Wagner for a special after-hours live action version of her satirical McMansion Hell blog. July 14, 2020 at 5.30pm EDT.

#HousingLIVE Join The New Republic’s Kate Wagner for a special after-hours live action version of her satirical McMansion Hell blog. July 14, 2020 at 5.30pm EDT.:

Howdy! Join me at the NewCities New Housing Solutions conference (along with much more important people like Ilhan Omar) where I’ll be roasting buildings and raising money for Moms4Housing! Link to submission and registration above. 

Design in Dialogue - Exhibitions - Friedman Benda

Design in Dialogue - Exhibitions - Friedman Benda:

Howdy folks! Join me on Design in Dialogue tomorrow (Monday, June 15th) at 11AM EDT for a (Zoom) talk on the best and worst impulses in contemporary architecture. More info and RSVP in link. 

How Normie Minimalism and Farmhouse Chic Took Over Contemporary Design

How Normie Minimalism and Farmhouse Chic Took Over Contemporary Design:

Hello! I wrote for Hyperallergic about how minimalism went from high design to normie chic.