Building A Dropserver App
This page is valid for version 0.11.0 and above.
This page gives a high level overview of how a Dropserver app is built. See the tutorial for a hands-on example.
A Dropserver app is made up of:
- Any additional backend code. All JS, TS or WASM files must run on Deno.
- Any additional asset needed, such as images and frontend HTML, CSS and JS.
You’re free to arrange your app’s code directory structure anyway you like, however there should be a directory that you can point the packaging system to that satisfies the following requirements:
- This directory must have a manifest file called
dropapp.jsonat its root. See the Dropserver app manifest reference.
- All files that need to be packaged with the app must be inside that directory.
- Do not use symlinks in the directory.
While a trivial app may have the package directory at the root of the code repository, like the tutorial does. A more typical application will have an
app subdirectory in the repo that is the root of the package. It includes
app/dropapp.json and any backend code and assets that do not need to be built. (Any other assets that need to be built have their sources outside the
app/ dir and the build process puts the built assets in
The entrypoint file is usually
app/app.js. If you use a different file name or if it’s not in the root directory of your package, then you must declare it in the
entrypoint field of your
If there is frontend that must be built, the source might be in
frontend/, and the build target might be
The Backend code
This “entrypoint” file should import
createApp from a pinned version of the
dropserver_app library. It should call the
createApp function with appropriate parameters to create the app. The value returned from
createApp can be exported and used to interact with the app elsewhere.
The dropserver_app library makes it convenient to write a Dropserver app without knowing its ever-changing internals.
Below are some aspects of writing a Dropserver application that differ from other code you may have written before. It’s a high level overview. For specifics refer to the tutorial and the dropserver_app docs.
You do not create a server in a Dropserver app. The server is run by Dropserver. You just declare routes with callbacks (or other parameters, see below) in
In the current version of Dropserver, app routes can only be created by using
createApp. This means you can not create or remove routes of a running app. Use wildcard routes to serve generated assets.
Different route types
When declaring routes, you can specify a route type. Currently there are just two route types: regular callback (which calls a function in the sandbox to respond to a request) and static file handler (which serves files from
@appspace or other valid directory).
Local file access
Your app will always run in a sandbox therefore it will not have access to just any part of the file system. In fact it is strictly restricted to the following subdirectories:
@appRead-only. This is the contents of the app package.
@appspaceRead-write. This is where the appspace gets to store its data files.
@avatarsRead-only. A special place for getting avatars for users.
To actually operate in any of these areas, you must first get the actual directory path by calling the appropriate method on your app instance, such as
app.appspacePath(). You should call this every time you need it because it may change if the appspace gets moved around.
User management is handled by Dropserver. Your app should not have any code to handle new user registration, passwords or any other auth, etc… You can get a full list of users from your app instance using
app.getUsers() or get a specific user with
A “proxy-id” is a string that uniquely identifies a user in your appspace. Your app does not have access to private identifiers such as email, etc…
Backend Code Caveats
🚫 localStorage and sessionStorage
Do not store data using
sessionStorage from the backend code. Deno stores that data at a location that is different from the appspace data files, as a result it will not be in appspace backups, and may be lost at any point. See this issue.
Note: this is strictly about backend code. Feel free to use localStorage and sessionStorage in your frontend.
Specify a file for Deno Key-Value DB
Similarly to the above, do not use Deno KV store without specifying a file path. When used in that manner, Deno stashes the data in the same obscure location as session and local storage, and it may be lost.
Your app code will exit
Assume your code will exit between requests. Any data not stored in the appspace directory may be lost as soon as you are done sending a response to a request.
🚫 Import map
Do not use a Deno import map. For now Dropserver uses import maps internally, and does not currently attempt to merge any other import maps.
Keep it lean
If no sandbox is running when a request is received,
ds-host must start one and then forward the request. Sandbox start time can become long if the app code imports large number of libraries. For this reason use good judgement when adding code dependencies.
If you do need to depend on a large library for some operations, consider loading asynchronously on an as-needed basis.
🚫 No outbound requests
Dropserver apps can not make outbound requests (meaning they can not initiate contact with other servers).
This is a temporary restriction that will be lifted as soon as an adequate permission model is written.
Frontend and clients
You are free to build any frontend you like for your Dropserver app. Here are some examples:
Generate HTML server-side
Generate HTML server-side using a template language of your choice and serve CSS as static files. See the Secret Santa app code for an example using Mustache and one static CSS file.
Progressive Web App
Create a PWA Single-Page Application that is built when packaging the app and served statically. See the Leftovers code for an example PWA SPA using Vue.
This is a great of providing near-native app experience without dealing with app stores.
Be aware that Dropserver serves files with a strict Content Security Policy of
Create a native app for your target environment (smartphone, desktop OS, or CLI) and interact with your app via a JSON API. Your native app would be packaged and distributed separately and would include a way to specify the appspace domain.
Note: authentication of appspace users from a native app has not been developed yet.
Server-Side Rendered 🤔
An SSR app may work as a Dropserver application, but it’s untested. First your SSR coded has to run in Deno, while most assume Node. Second, routing may be an issue.