Inhale slowly. Count to Three. Take a Deep Breath.
Let’s start at the beginning.
I’m creating a tool. The tool has grown from my numerous frustrations with complications in creating software, and particularly web software, and seeing where trying to find solutions to those frustrations take me.
I truly believe that the web is the worst of what we have to offer as engineers. And ironically, or maybe because of that same root cause, it tends to be what we use and work with the most in terms of computing these days.
That’s to say: I spend most of my life looking at a web browser. I’m looking at one now as I write this. I tend to spend very little day to day in my operating system proper.
Isn’t it odd? The way we’ve made full blown applications inside of a rendering language inside of another application that was meant to serve static pages of information like schedules and academic papers.
Some might see that as a modern marvel, but I see it for what it is: A disaster.
We’ve created layer upon layer of complicated tooling, and usually to patch up poor behavior in the proceeding layer.
If you write a web application…how many layers are between you and what you want to do?
Today, I wanted to write a file. That’s all I wanted to do.
I’m creating a progressive web app. You know, one of those single page application type deals. An application that is a web page. I know. That was my first mistake. But I’ve spent a good deal of my career at this point as a web developer. I know the tools, I can get it to work, or at least I thought I could.
It’s not desirable for me to suddenly switch to C#, Java, Go, or Rust and find out building a UI heavy application is even more out of reach there, but just for different reasons.
The app requires a code editor. And because it creates small components that are meant to wire into each other with a graph or snap in like legos…think something like Make or Noflo or even Scratch. It was important to me that I could save this data somewhere. Particularly on a file system. Sure I could use local browser storage…for now. But I want to be able to eventually export this data.
I’m using Vue, the progressive, reactive Javascript framework, to write my app. Mostly because I know Vue pretty intimately. Also because it feels FAST. It’s one of the few tools in my toolkit that actually does feel like it makes things easier…at least when making user interface.
And also because I’ve tried a host of reactive frameworks and Vue is my favorite, next to Svelte. The only problem with Svelte is it doesn’t seem to have the breadth of plugins and components I need. So Vue it is and has been.
On top of that development, I use Vite. Installing a Vue project generally bundles it with Vite. Vite is a local web server, builder, Javascript minifyer, and more. It serves a lot of needs. It also watches for code changes and does “HMR,” or hot module reloading, so that your changes reflect instantly in the browser. It breaks sometimes for me in the most random of ways, but it’s mostly reliably and a pretty cool thing.
Though…if I’m being honest. I long for and miss the WYSIWYG (What you see is what you get) days of web development. HMR is nice, but I think we need to move more towards that direction.
Ok. I have my app created, and it has some code in it. And I want to save it to a local file.
I get an error. I cannot save it because “fs,” the node package for the file system, is not something you can bundle and call from the front end. That makes sense. I’m working on the client and not the server. So how do we do this?
Well…I’d wish Vite, as it was a node program, came with its own server side ways to interact with the server. But it really doesn’t, and I can forgive it. It’s not Electron, and it’s meant to publish your web applications to the web.
Funny that, creating web applications as if they’re for the web. But…we have to acknowledge that “websites” are becoming applications whether we like it or not. And maybe the experience would be better for both developer and user alike if we focused on letting them behave like apps FIRST
Here’s a good talk on that:
So how do we write this damn file in the end?
I came up with 3 options.
I switch over to Electron, which prioritizes creating truly local applications with the node ecosystem…but…once I move over to Electron I’ve pretty much committed to just having a local app. Which is mostly fine, but I’d really like to make this a true web app for portability reasons.
Or…I could create a back end server…sigh…It’s one more thing to maintain, it’s one more thing to have up and running, but let’s do it…Vue even has a way to run it locally with a plugin so I don’t have to start two servers.
So I went to add the Express plugin into Vue. I set it up, I got it to load the routes as a middleware, but no matter how many times I try to hit the API endpoint to save the file that I set up. It just won’t. I followed documentation from the Vue express plugin from both the developers of the plugin and from ChatGPT…but I’m having no luck. I think Vue’s router is interfering…
But then I have the realization of my 3rd and probably preferable option.
Use Pocketbase. It is a server, it provides authorization. It’s built on SQLite. Ugh, it would be so easy. It would also be portable to other places as I move my app around and I could centralize the server, etc etc…
Great idea Robert. Pat yourself on the back. You’re a hero.
Pocketbase is really cool btw. It’s like a scaled down no frills Supabase that runs on SQLite and is self hosted. The way SQLite is just a de-make of MySQL or MSSQL or Postgres, and somehow it’s 50x easier to work with.
Ok, so I’ve been writing a wrapper library around pocketbase, Just need to do some testing, copy the library over and call it from inside my Vue/Vite environment.
Aaaaaaaaand…of course it fails. What now?
Ohhhhhhhhhhhh. Vite of course can’t make a call to my Pocektbase app. It’s running locally on localhost. Vite’s localhost is itself, IT is not running Pocketbase.
So….now this is a networking issue. I need to expose my Pocketbase app over my IP, and to do it I’ll either need to create some complicated local adapter or go into my router and expose the Pocketbase IP and ports. But I DO see that Vite may have a way to accommodate this…so maybe that will work…
But here’s the thing. It’s 7:30 AM, and I started trying to write a file at 6:00 AM. This has been 90 minutes of failure.
Also I want you to go back through this article and see how many technologies I mentioned: Node, Vue, Vite, Pocketbase, SQLite, Javascript. And it isn’t even to mention all the underlying technologies like HTTP, TCP, Chrome, Windows VSCode, HTML, CSS.
Not that these necessarily get in the way…though they often do. Chrome forces Cross Origin policies set by the server, even when it’s your server, in frustrating ways that you will almost ALWAYS stub your toe on as you’re developing local to remote communication between your app and some jerk’s server. (The jerk often being you in the development process)
I’m working with layers of technology, some I know more intimately than others, expecting each to fail in some way, somehow, at some point. Expecting it. This is the currency of my vocation: tedium.
90 minutes, and I have not written the file.
Here’s my long term strategy: back up my Pocketbase, move it to my local laptop server with an already exposed IP address (Because that’s useful to have anyway, I even have that server exposed to the net so I can write to it from anywhere in the world).
But now to write a file I have to do it over a network. It’s bound to be slower, and have latency and then what when the server goes down, as it inevitably will.
I’d love to be able to fall back to some kind of local storage.
The problem too, is that these “just for now” solutions become architecture. Something else to just spackle over.
Well..this article is becoming a stream of consciousness on how I will solve the problem and how many flaws in the solution there are. Welcome to being a computer engineer. It’s mostly failure.