SQLite is a fine single-file application file format, but if you want average users to be able to inspect and perhaps fix application data when things go wrong, a tree of JSON-format files is more friendly.
True, this requires care to ensure that such files are updated reliably, but that's not quite rocket science.
You need a recovery step on startup to retry the rename if tempfile is complete, or delete it if it isn't.
That means you need a way to verify that tempfile is complete. I do that by removing filename after completing tempfile. And that requires a placeholder for filename if it didn't already exist (e.g. a symlink to nowhwere).
On crash, rename may leave both files in place.
This technique doesn't work if you have hardlinks to filename which should refer to the new file.
True, this requires care to ensure that such files are updated reliably, but that's not quite rocket science.