Docly Developers
Knowledge base Pitfall By design

Keep private data under the # folder

In shortFiles in a published folder are reachable by their path, and a .docly document there is rendered by any display template for its schema. To keep data out of public reach, place it under the # folder: a request for a #/ path answers 404, even when a parent folder is published. The one exception is #/Root/, whose files are served at the site's own URLs.
Applies to APIPublishingDataSecurity
  1. What you'll see

    A developer puts data files — JSON documents, configuration, lookup tables, seed data, secrets — into an ordinary folder inside a published part of the workspace. The data is needed by API functions or templates, so it feels natural to drop it next to them.

    The problem: everything in a published folder is reachable over HTTP by its path. A file at /Data/customers.json in a published folder can be downloaded directly by anyone who requests https://yoursite/Data/customers.json. Uploaded data files are served as they are, and a .docly document is rendered through the display template for its schema — so whatever that template prints is public. Often nobody notices, because the application still works.

  2. What's actually happening

    When you publish a folder, Docly serves the files beneath it as web content: pages, images, stylesheets, scripts and uploaded files by their path, and .docly documents through the display template for their schema (#/<Schema>.hash). A document whose schema has no display template answers 404, not raw JSON — but that protection lasts only until someone adds a template, and every field the template prints is then public. This is exactly what you want for assets — and exactly what you do not want for data that should only be read server-side.

    The # folder is the designated private area. Files placed under # (and its subfolders such as #/API, #/Schemas, and any data folders you create there) are never served by their own path: a request for a #/ path answers 404, even when a parent folder is published. The one exception is #/Root/, whose files are served at the site's own URLs (#/Root/style.css answers on /style.css), so never put data there. Everything else under # remains fully available to server-side code — API functions, scheduled tasks and templates can read them with the filesystem functions — but a browser cannot download them by URL.

    So the rule is simple: if a file should only ever be read by your own server-side code and never handed directly to a visitor, it belongs under #. If a file is meant to be downloaded by the browser (an image, a stylesheet, a client script), it belongs in a normal published folder.

  3. What to do

    Move data files that back your application — but should not be publicly downloadable — into the # folder, and read them from server-side code with absolute tilde/hash paths.

    Don’t — data in a published folder is downloadable:

    /Data/customers.json        ← published, anyone can GET /Data/customers.json
    /Articles/secret-draft.docly ← rendered by any display template for its schema

    Do — keep data under #, read it server-side:

    #/Data/customers.json       ← a request for a #/ path answers 404
    // #/API/customers.js
    export default () => {
        if (!request.Jwt) return docly.denyAccess();
        let customers = docly.getJson("#/Data/customers.json");
        return customers;
    }

    The API function decides who may see the data and what subset to return; the underlying file is unreachable by direct URL. This gives you a controlled access point instead of an open download.

    Quick test: after publishing, try requesting a data file by its path in a browser (or an incognito window). If you can download it and you did not intend to, move it under #. Treat every file in a published folder as world-readable until proven otherwise.

Last reviewed 17 Oct 2026