A lightweight highly extensible, and highly configurable NodeJS web-based file explorer and utility kit.
The included plugins provide the following features:
- Directory listings with file/folder information
- Intelligent file type resolving
- Full web interface for viewing files
- Markdown rendered in browser
- Syntax highlighting for text files
- Embedded image, video and audio files
- Ability to serve raw files, and falls back to doing so
- Ability to upload files
- Live scratchpad
- Breadcrumb navigation
- Dark mode
- Non-browser clients are always served raw files
For more information, please read about each of the plugins below.
⚠️ Note that the package makes use of experimental node features and requires Node >= 18.
Clone this repo and run the following to install dependencies and compile:
yarn start
yarn buildRun using yarn start. Alternatively you can start using node directly:
node --experimental-wasm-modules --experimental-import-meta-resolve libFilexplorer can be installed as an NPM package, which is useful if you plan to embed it or develop a plugin.
npm i filexplorer --save
# or
yarn add filexplorerThe package also includes a CLI which can be used for impromptu serving:
Note the CLI does not load the appListing, upload, or scratchpad plugins by default.
λ fe help
Usage: fe [options] [command]
Commands:
help Display help
Options:
-H, --help Output usage information
-h, --hostname The host address to bind to
-P, --plugins The plugins to load, comma separated list
-p, --port The port to bind to
-s, --serveDirectory The path to the directory on disk to serve
A docker image is available and can be run like so:
docker run \
-p 5000:5000 \
-v config.corn:/opt/filexplorer/config.corn \ # Passing a config is optional
-v data.db:/data.db \ # necessary to persist plugin data
-v path/to/files:/srv/http \
jakestanger/filexplorerThe app works out of the box without any configuration, and by default all plugins are enabled.
To override the default configuration,
create a config file using one of the following supported formats:
config.js,config.mjs,config.cjsconfig.jsonconfig.yaml,config.ymlconfig.tomlconfig.corn(useful for environment variables! see here)
Plugins may provide their own configuration options,
which are namespaced under the plugin name.
For example, the showHidden option for the directoryListing plugin
should be set at directoryListing.showHidden.
| Name | Type | Default | Description |
|---|---|---|---|
hostname |
string | 127.0.0.1 |
Host address to listen on |
port |
number | 5000 |
Port to listen on |
cors |
boolean | false |
Whether to enable CORS support |
serveDirectory |
string | . |
Path on disk to the directory to serve |
baseUrl |
string | / |
URL path to use as 'root' |
caseSensitive |
boolean | true |
Whether file route handling should be case sensitive. Disable on Windows or on case-insensitive file systems. |
databasePath |
string | data.db |
Path to create/load database at |
plugins |
string[] | ["directoryListing", "appListing", "markdown", "textFile", "mediaFile", "raw", "upload", "scratchpad"] |
List of plugins to load, in the order they should be loaded |
The following environment variables are also respected and will override the configuration file:
HOSTNAMEPORTSERVE_DIRECTORYDATABASE_PATH
An example config file in yaml is shown below,
overriding the port, serve directory and directoryListing plugin options.
port: 5202
serveDirectory: '/srv/http/public'
directoryListing:
showHidden = true
relativeDates = falseThe following plugins are
Shows a table of files and folders inside a directory. Each row has a link to the item, file size, and created/modified dates.
| Name | Type | Default | Description |
|---|---|---|---|
showHidden |
boolean | false |
Show hidden files and folders |
relativeDates |
boolean | true |
Display created/modified dates as relative from current time |
Shows the contents of plain text files in the web interface.
Provides a link to the raw file (requires raw), a direct download, and the ability to copy to clipboard.
The file is syntax highlighted using highlight.js.
| Name | Type | Default | Description |
|---|---|---|---|
highlightTheme |
string | default |
The highlight.js theme to use for light mode. See here for a list |
highlightThemeDark |
string | dark |
The highlight.js theme to use for dark mode. See here for a list |
autoHighlight |
boolean | false |
Whether highlight.js should try to automatically detect syntax highlighting if the language could not be determined from the extension |
maxHighlightKb |
number | 50 |
The maximum file size in kB that should be highlighted |
handleSvg |
boolean | false |
Whether SVGs should be handled as text |
Shows the contents of images, videos and audio in the web interface.
Provides a link to the raw file (requires raw) and a direct download.
This plugin provides no configuration options.
⚠ This plugin must be loaded before
textFile
Renders markdown files in the web interface. Supports GFM and syntax highlighting.
| Name | Type | Default | Description |
|---|---|---|---|
highlight |
boolean | true |
Whether code blocks should be highlighted |
highlightTheme |
string | default |
The highlight.js theme to use for light mode. See here for a list |
highlightThemeDark |
string | dark |
The highlight.js theme to use for dark mode. See here for a list |
gfm |
boolean | true |
Whether to use Github Flavored Markdown |
⚠ This plugin must be loaded after any other file handling plugins
Serves files statically without the web interface, letting the browser handle them.
If a file's type cannot be determined, the plugin will test if is a text file and force-serve it as one.
This plugin provides no configuration options.
App URL:
/_/
Shows a list of available app plugins with the ability to navigate to each one.
This plugin provides no configuration options.
App URL:
/_/upload
Provides the ability to upload files. This can be done programmatically or via the web interface. Files are automatically given random names according to a chosen scheme.
For example to upload using cURL:
curl -F "file=@Pictures/Cake.png" -H "Authorization: 1234" http://localhost:5000| Name | Type | Default | Description |
|---|---|---|---|
maxFileSize |
number | null |
Maximum allowed file size |
authorization |
string | null |
Expected HTTP Authorization header value. Leave blank to disable authorization. |
path |
string | / |
Path relative to served root to upload files to. |
nameScheme |
hex | uuid | cuid | adjective-adjective-animal |
hex |
Naming scheme to use for generating random names for uploaded files. |
App URL:
/_/scratch
Provides a live scratchpad which can be used for quickly sharing text. Any client with the same URL will see the same content and will see changes apply near-instantly.
There are controls for instantly copying the scratchpad contents and URL.
This plugin provides no configuration options.
⚠ This is very experimental still. Any issues discussing bugs/improvements are very welcome.
import { App } from 'filexplorer/lib/App.js';
// the promise will not resolve until the server receives a shutdown signal
// you can optionally pass a config
await App.init({ port: 5678 })
// close the server once you're done with it
App.server.close();⚠ This is very experimental still. Any issues discussing bugs/improvements are very welcome.
Plugins can be loaded from inside this codebase or as a standalone npm package.
A very basic example plugin is shown below:
import {
InitEvent,
MiddlewarePlugin,
PluginManager,
} from '../../pluginManager.js';
interface IExampleConfig {
// put your plugin config options here
greeting: string;
}
// init hooks are called just before the web server starts
// and are useful for configuring any required modules based on the app config
const init: InitEvent<'example', IExampleConfig> = async ({ config }) => {
// do init things!
console.log(config.example.greeting ?? 'hello', 'world');
};
// middleware can be used for handling files/directories
// this is just express.js middleware under the hood
const exampleMiddeware: MiddlewarePlugin<'example', IExampleConfig> = async ({
req,
res,
next
}) => {
res.send('hello from example');
};
// other available features for plugins:
// - `withAppMiddleware`: register middleware on a specific route to create an app
// - `withSocketIO`: passes a socket to a callback when the socket connects
// - `withDatabaseTable`: Ensures a database table exists with the provided schema
PluginManager.register('example').onInit(init).withMiddleware(markdown);Your plugin can be loaded by adding it to the plugins config option. More information on this below:
Create a new folder in src/plugins that matches your plugin name.
This folder must contain an index.ts (or .js or .mts or .mjs) file.
Handlebars templates should be placed in the resources/plugins folder in the root of this repo.
To load an embedded plugin, add the plugin directory name to plugins config option.
Create a new package. If necessary add filexplorer as a dev/peer dependency for development.
Ensure your package has a main entrypoint set in the package.json.
Handlebars templates should be placed in the resources/plugins folder in the root of your package.
To load separate-package plugins, add the plugin package name to the plugins config option.
The app makes use of modern CSS features like custom properties to make theming as easy as possible.
To make global CSS changes, apply these in public/index.css.
For plugin-specific changes, these should be placed in the appropriate head.hbs template.






