# What I built

I built tmp.spacet.me(opens new window), a web-based local file storage application. Basically, you can put files into it, and you can get files out of it. It aims to support every possible methods that browsers allow web apps to work with files.

It also comes with an extensions system. Users can add extensions to enhance the functionalities of the app. The goal is to improve operability between web-based applications that work with files.

For example, the tmp-webrtc(opens new window) extension lets me send files from one device to another using peer-to-peer technology WebRTC.

The tmp-photopea(opens new window) extension lets me edit image files in Photopea.

Users can build their own extensions to suit their needs.

For example, I built an extension to upload images to my static file hosting.

Although tmp.spacet.me is built using React and Next.js, this is just an implementation detail and extension authors don’t need to know any React. That’s because extensions run on their own page and communicate with tmp.spacet.me via the postMessage API only.

# Category Submission

Random Roulette

https://tmp.spacet.me/(opens new window)

# Screenshots

(opens new window)

# Description

A web-based local file storage. You can put files into it, and you can get files out of it. More functionalities can be added through extensions.

{% github dtinth/tmp %}

# Permissive License

All code is MIT Licensed

# Background

There are so many great web-based tools. From Markdown(opens new window) editors(opens new window) to file(opens new window) sharing(opens new window) services(opens new window) to diagramming tool(opens new window) to design tool(opens new window) to image editor(opens new window) and compressor(opens new window) to voice(opens new window) and screen(opens new window) recorder to myriad of cloud storage services, etc.

Many of these tools work with files. But they tend to be its own silo(opens new window) and do not interoperate with other tools.

There has been attempts to solve this from the web platform side. There was an experimental Web Intents(opens new window) API which failed(opens new window). More recently, there are also the Web Share API(opens new window) and the Web Share Target API(opens new window) which integrates natively with the system’s Share dialog. Unfortunately Desktop devices don’t have them and so it’s only available on Android right now.

So, as I become more reliant on web-based tools, I want to try my take at a userland solution. So the missing piece, I think, is a central hub, where files can be sent to, which would then be forwarded to other web-based app or saved to disk. I want it to have an extension system, so anyone can build more integrations without having to modify the main app. Furthermore, deeper integrations with existing web-based apps can be implemented via browser extensions.

# How I built it

For the main app, tmp.spacet.me, I used DigitalOcean App Platform to host the app, which is a static web application. The main application is built using React and Next.js. Deployment to DigitalOcean App Platform is very straightforward and I’m impressed by how easy it is to set up. I’m looking forward to support for deployment previews in the future.

For the extension system, when the extension URL is entered, the main app fetches the manifest file, which contains the information about the extension, as well as which file types can be handled. Then, when the extension is activated, it opens a separate browser window and communicate with the main app via a JSON-RPC(opens new window)-based protocol. This gave me opportunities to put cross-site messaging and micro-frontend concepts into practice.

For the tmp-webrtc extension, at first I wanted to create a backend service to implement peer discovery(opens new window). That would also give me an opportunity to try out DigitalOcean’s paid services (like running backend apps and using a managed database). Unfortunately due to time constraints I didn’t get around to doing that and used the P2PT(opens new window) library for peer discovery instead. P2PT uses public WebTorrent trackers(opens new window) as a WebRTC signaling server, and so no backend services have to be deployed. So it ended up being another static app. This is my first time using P2PT and WebRTC for file transfers though, so I still think I learned a lot.

I really like that DigitalOcean’s App Platform makes setting up CORS very straightforward (can be set up via the console), while Netlify(opens new window), Vercel(opens new window) requires creating a configuration file. Having CORS is crucial for the extension system to work, because tmp.spacet.me needs to fetch the manifest file to discover the extension's functionalities.

The tmp-webrtc extension is built using Vue 3 and Vite. I have never used Vite before, so that’s another thing I learned. By the way, I don’t like running commands to generate new projects, so I took the opportunity to shave that yak, and created the Fresh App Factory(opens new window).

I also used other other cloud services other than DigialOcean. The documentation site(opens new window) is just a Jekyll site hosted on GitHub Pages, which I chose for simplicity. I like that DigitalOcean App Platform allows multiple static apps (or “components”) to be hosted on the same domain, but I could not get Jekyll to work on it.

The application’s UI is not polished at all and could use a lot of improvements. But I think it’s good enough for a proof-of-concept. Since I started building this, I have been using it a lot in my own personal workflow. Sending pictures and videos between my 4 devices, now I just use tmp.spacet.me.

Some areas for future improvements include:

  • Improving the user experience, accessibility and performance.
  • Allowing files to be stored temporarily in the in-memory storage first before committing to PouchDB.
  • Allowing other web apps to directly postMessage to tmp.spacet.me (without an extension), reducing the irony.

I hope you find the tool useful, and thanks for reading!