Hi, I have built a serverless runtime for <observa...
# share-your-work
t
Hi, I have built a serverless runtime for observablehq.com called https://webcode.run. This extends Observable's reactive notebooks to the backend. Its unique features are instant deploys, and it can redirect traffic to your browser, so you can do devtool or console.log debugging against production traffic. It's a unique way of sharing code across frontend and backend. My aim is to create a serverless environment that is a pleasure to use as a developer. I am really desperate for feedback, so if you give it a go let know the positives and negatives.
đź‘Ť 5
k
Interesting! Also a bit frustrating for me. This looks like something I could and would like to use, for making custom computations easily accessible as Web services, but it also seems to be aimed at Web professionals familiar with a lot of technology that I merely know the names of.
t
You are not the first person to say this. I am a bit worried about getting sucked into an effort vortex to teach HTTP fundamentals. I am also worried about making a simplified version that cannot be applied to novel situations because expressivity has been lost. It is as complicated as HTTP is (i.e. very). Though perhaps it is time to think of a simple version. If you want to expose a computation maye could be guided with functional programming.
Copy code
//server
remoteFunction = serve((x) => x*x), options)
Copy code
answer = await remoteFunction(5)
I think there is enough wiggle room for people to add their own abstractions, and because the result is a promise we can put in network errors. Would this cover your usecase? (if anyone knows of any simple RPC abstractions I should draw inspiration from I would love to see)
Is this hlepful? https://observablehq.com/@endpointservices/servefunction but I am wondering how you could use this outside the ecosystem as it has some custom encoding on the URL endpoint
I guess not.
k
Simple RPC-style interaction covers most use cases I can personally think of. The role of your serverless runtime would then be to make the code called via RPC debuggable. That looks useful in the abstract. Unfortunately, I can't really say what features would be required to make it useful in real life.
Another question I wonder about: how does your project differ from other interactive systems being used on the server via some remote control? Thinking of Common Lisp image managed from Emacs (SLIME) from a desktop machines, or of Smalltalk systems (e.g. via TelePharo, https://github.com/pharo-ide/TelePharo). Are you doing the same but in JavaScript? Or is there a more fundamental difference I am missing?
t
Why webcode is different 1. a notebook is both front end and the backend and the technical documentation and the code repository and runtime. True seamless code sharing. No additional infra required. corrorally -> libraries can be packaged as frontend and backend too 2. The environment is 100% browser. No tools to install. No "pip install", no "webpack", no compiling. You can do it all from a chromebook or mobile device, for instance 3. It takes about 40ms for code changes to become visible remotely. Compared to 2 mins for lambda. The inner development loop is supercharged. You can develop live in prod. The iteration speed is incredible, partly due to instant deploys, partly due to Observable hot code reloading No setup required, its like that out of the box. 4. True production debugging using vanilla browser tools. No simulacrum of a debugger. It's just the normal debugger everyone already uses, which means other debugging technology can be layered on top without problems (e.g. time travel debugging https://www.replay.io/) This is built on Observablehq, so it gets all its FoC features. Literate programming, Commenting, 1-click forking, version control, Functional Reactive Programming env, partial recompilation etc. No need for Github or git, remember, this is 100% browser based, you get all this on any device that supports a web browser. You can fix and deploy things on your mobile phone. You can manage a whole microservice, including technical documentation and project management, in a single page of web editable code. For instance, this twitter bot is hosted on webcode https://observablehq.com/@endpointservices/twitter-bot. This is a whole IndieAuth oauth server. (https://observablehq.com/@endpointservices/auth)
❤️ 2
So if you want your own Oauth server, its 1-click fork, change the config to point to your Firebase, and its live. There is no deploy step required, a notebook becomes infra instantly. I guess the overall draw is it's a single tool to do everything (Observablehq.com being the single tool, webcode is just filling a missing gap)
k
Thanks @Tom Larkworthy, those are all very good arguments! But I have to admit that some sound too good to be true. A one-click fork to get an Oauth server? I need to set up some server first, right? There must be some physical machine doing the work, and also hosting my domain. Also, I doubt many practically useful server applications can do without any preinstalled dependencies. Sure, I can in theory rewrite everything as notebooks, but in practice everything is based on a lot of existing code.
t
I need to set up some server first, right?
No! The webcode runtime is a generic container [1] that knows how to run notebooks (it has puppeteer inside it). So that one container runs all the notebooks. If you looks at the outbound requests to webcode, the URL encodes which notebook to dynamically lookup. The Oath implementation is at the application level in a notebook. Often, you also need persistence, so I use Firebase as that works well with browser. The server is pupeteer, i.e., also a browser. So if you want to run your own Oauth server you need to bring-your-own-firebase after forking my notebook. [1] https://github.com/endpointservices/webcode.run/blob/main/Dockerfile
practically useful server applications can do without any preinstalled dependencies.
All dependencies come in via normal Javascript imports. The major limitations is that many javascript dependencies are node only, but that is changing to ES6 modules (if no other reason than to support Deno). It's kind of like Deno but when you mix in Observablehq you have a whole IDE and its trivial to switch the execution from serverside to clientside and vice versa as they are all just browsers. When you turn on "live debugging", a tunnel is setup like ngrok, that tunnels production traffic to the developers machine. The developers browser processes the request (giving opportunity for debugging) and sends back the response. This is how code changes are immediate with 0 latency, the developers latest code is the server when in live mode. This is enabled by the browser being the normalized environment.
đź‘€ 1
Oh another headwind is if your server needs a TCP connection, like a postgres db connection. There is no easy way to achieve that, you are limited to HTTP and websocket comms. I do have a plan to get TCP deployed but not currently
k
OK, thanks for the details! I was indeed thinking of the node-based JS packages as an obstacle. If people are moving away from that, that's good news!
t
I dunno if you are familiar with skypack, but that is a huge adapter for npm -> ES6 (i.e. browser compatibility) https://www.skypack.dev/, there are a few others but that's currently the coolest one. There is a lot of JS in the world so you are not hugely limited except unless their is a network technology requirement. (BTW, my serverside puppeteer has CORS disabled). If it has an API, no problem (even if not configured for CORS).
f
@Tom Larkworthy Wow I really like the user experience aspect of this: you can write and document “server” code, fork it and there’s not really a “deploy” step other than saving. This is really compelling. My only concern: since your piggybacking ObservableHQ does that mean that your own server code/infrastructure depends/relies on that? What if you write a crazy service that causes way too much load? Do you think this can fly for real world projects? Or is there a way to host/install the environment on your own cloud infrastructure of choice? Or am I getting it wrong? Is only the source code (as text) from Observable used but the actual executing server is deployed elsewhere?
t
What if you write a crazy service that causes way too much load?
1. Its rate limited but also 2. I hit their "embed" endpoint which is hosted on a CDN and targeted at 3rd party embedding on external websites.
Do you think this can fly for real world projects?
Yes! Most features are implemented as webcode, for example, the secrets API is webcode hosted and wraps Google Secret Manager The latency prober I use to measure performance is also webcode implemented. We have got hot performance down to 30ms! It's not quite as fast as a dedicated lambda but its in an acceptable engineering trade off zone IMHO (devX for a little perf hit).
is there a way to host/install the environment on your own cloud infrastructure of choice?
Yes it is technically possible, if you look at the API options, you can set the remote and region, so you can host your own webcode.run container (and you can set it to localhost for testing). I have not documented the self hosting path yet, but I would like to encourage it when I have some demand for that. The runtime is in a single container, so it should be fairly portable. I use Cloud Run.
Is only the source code (as text) from Observable used but the actual executing server is deployed elsewhere?
Yeah Observable is the code hosting platform + reactive runtime. The compute is external (webcode.run uses Google Cloud Run but any docker hosting service "should" work, I am thinking about migrating to fly.io). The realtime user control plane is Firestore though, and that is unlikely to be switchable. I would say the state of it is still a little pre-production. I am not providing an SLO or carrying a pager yet, but it is actively monitored and robustness has hugely improved in the last 6 months. I think it's amazing for API glue, but it struggles when you need a filesystem, like technically it can be a webserver, but uploading static assets is kinda hard so it can only really do small util endpoints at the moment.
❤️ 1
Oh I have a how-it-works notebook (which is very much work in progress) so do leave comments in places that need expanding https://observablehq.com/@endpointservices/how-it-works
đź‘€ 1
I just make a fake Firebase realtime database in the browser, to demonstrate reverse engineering the Firebase realtime database wire protocol and showing that it can all be done 100% in the browser, with one click forking https://observablehq.com/@tomlarkworthy/rtdb-protocol
🎉 1
f
Feels like “View Source” but for server code. But even better because it comes with a notebook full of explanations ;)
t
Another way its beyond "view source" is because you can change the source and the thing updates. view source is read only. This is read/write
I have listed webcode.run on product hunt. I hope maybe some people like it here??? I am not sure people like Observable that much but I see it as a future of code technology. I made WEBCode.run so Observable could work with more things by adding a serverless compute layer. Now it can be part of the internet network and combine with other tools better. Anyway, here is the listing 🙏 https://www.producthunt.com/posts/webcode-run Ask me anything though. Most of webcode is written in webcode, you can surf most of its implementation on Observable. I have a side hope of teaching people how to build secure backend services as that knowledge took a long time to learn and I think open forkable literate notebooks containing executing services is a good way to learn how to build services. We shall see!
❤️ 1
đź‘Ť 2
So I hope to demonstrate the ability for webcode to scale to difficult programs, and to actually improve development readability, by creating a database within webcode. I want my reference code to exploit the literate programming affordances to create compelling artifacts that are simultaneously interesting to read and actually solve difficult problems. In other words I want to smoosh marketing and development together. So here is the next component of my 3rd party Firebase compatible realtime database. It's the messaging and storage backend, which is built with causal consistency in mind. If you don't know what causal consistency is, you might find the notebook interesting! https://observablehq.com/@tomlarkworthy/redis-backend-1