A local file storage for the web and interopearability layer for web-based apps (submission)
Tags: dohackathon, showdev
Published: 2021-01-10 17:11:23

---
title: A local file storage for the web and interopearability layer for web-based apps (submission)
published: true
description: My submission to the DigitalOcean App Platform Hackathon!
tags: dohackathon, showdev
series: tmp.spacet.me devlog
canonical_url: https://notes.dt.in.th/20210109T141458Z5537
cover_image: https://static.dt.in.th/uploads/2021/01/10/tmp-cover.png
---

## What I built

I built [tmp.spacet.me](https://tmp.spacet.me/), 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.

![](https://static.dt.in.th/uploads/2021/01/09/tmp-builtins.png)

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](https://tmp-docs.spacet.me/tmp-webrtc.html) extension lets me send files from one device to another using peer-to-peer technology WebRTC.

![](https://static.dt.in.th/uploads/2021/01/09/image.png)

The [tmp-photopea](https://tmp-docs.spacet.me/tmp-photopea.html) extension lets me edit image files in Photopea.

![](https://tmp-docs.spacet.me/images/edit-with-photopea.png)

Users can build their own extensions to suit their needs.

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

![](https://static.dt.in.th/uploads/2021/01/09/tmp-uploader.png)

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

### App Link

<https://tmp.spacet.me/>

### Screenshots

[![](https://github.com/dtinth/timelapse/blob/master/projects/tmp.spacet.me_initial.png?raw=true)](https://tmp.spacet.me/)

### 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.

### Link to Source Code

{% github dtinth/tmp %}

- [dtinth/tmp](https://github.com/dtinth/tmp) — the main app
- [dtinth/tmp-webrtc](https://github.com/dtinth/tmp-webrtc) — extension to send/receive files over WebRTC
- [dtinth/tmp-photopea](https://github.com/dtinth/tmp-photopea) — extension to edit pictures in Photopea
- [dtinth/tmp-uploader](https://github.com/dtinth/tmp-uploader) — extension to let me upload pictures to my static files hosting
- [dtinth/tmp-dtinth](https://github.com/dtinth/tmp-dtinth) — extension for my personal use cases

### Permissive License

All code is MIT Licensed

## Background

There are so many great web-based tools. From [Markdown](https://stackedit.io/) [editors](https://dillinger.io/) to [file](https://www.sharedrop.io/) [sharing](http://www.instant.io/) [services](http://webdrop.space/) to [diagramming tool](https://www.diagrams.net/) to [design tool](https://figma.com/) to [image editor](http://www.photopea.com/) and [compressor](https://squoosh.app/) to [voice](https://vox.spacet.me/) and [screen](https://gifcap.dev/) recorder to myriad of cloud storage services, etc.

Many of these tools work with files. [But they tend to be its own silo](https://paul.kinlan.me/unintended-silos/) 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](https://en.wikipedia.org/wiki/Web_Intents) API which [failed](https://paul.kinlan.me/what-happened-to-web-intents/). More recently, there are also the [Web Share API](https://web.dev/web-share/) and the [Web Share Target API](https://web.dev/web-share-target/) 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](https://www.jsonrpc.org/specification)-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](https://github.com/feross/simple-peer#a-simpler-example). 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](https://github.com/subins2000/p2pt) library for peer discovery instead. P2PT uses public [WebTorrent trackers](https://github.com/webtorrent/bittorrent-tracker) 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](https://community.netlify.com/t/access-control-allow-origin-policy/1813/2), [Vercel](https://vercel.com/knowledge/how-to-enable-cors#enabling-cors-using-vercel.json) 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](https://dev.to/dtinth/freshly-baked-apps-every-midnight-1h99).

I also used other other cloud services other than DigialOcean. The [documentation site](https://tmp-docs.spacet.me/) 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!