Skip to content

Simple Mojolicious app to display Markdown files in the browser with a nice nested navigation sidebar.

License

Notifications You must be signed in to change notification settings

justinnamilee/mojdoc

Repository files navigation

πŸ“œ Simple Mojolicious Markdown Documents Viewer

Framework License Release Status

A tiny Mojolicious::Lite app that serves and renders a folder (and subfolders) of Markdown files.


MOJDOC Preview


πŸ’‘ Features

  • Renders markdown (.md/.markdown) files (recursively) from a docs folder (ignores everything else)
  • Nested filetree on the left hand side, great for navigation
  • GitHub-style fenced code block support
  • Syntax highlighting via highlight.js
  • Pluggable Markdown backends (first found wins):
    1. Text::MultiMarkdown (recommended)
    2. Text::Markdown
    3. Markdown::Tiny
    4. fallback to <pre>
  • Safe path resolution prevents path traversal
  • A fun cyberpunk theme (with theme support coming at some point)
  • Code written by someone with no Mojolicious experience, but lots of Perl experience

⚑ Quickstart

Let's just get it running!


πŸ“¦ Prerequisites

# Setup Mojolicious (see URL above for more details), for example
cpanm Mojolicious

# Install a Markdown Renderer, for example
cpanm Text::MultiMarkdown
# Or via apt, for example
apt install libmojolicious-perl libtext-multimarkdown-perl

🟒 Run Mojdoc

# Clone the app
git clone 'https://github.com/justinnamilee/mojdoc.git'

# Create the documents directory and fill it with Markdown files
cd mojdoc && mkdir -p private/dox

# Run in dev with hot-reload
morbo mojdoc

🧩 Deploy Methods

Below are some tested deployment methods that work well for small internal sites or lightweight self-hosting setups.


πŸŒ€ Systemd (with Hypnotoad)

This is the most β€œproduction-style” method for persistent deployment on Linux servers.

  • Runs via Hypnotoad, Mojolicious’s built-in pre-forking HTTP server.
  • Handles restarts and crash recovery automatically.
  • Well-documented in the Mojolicious Cookbook.

Example steps:

  1. Copy or adapt the provided service file: mojdoc.example.service

  2. Update the WorkingDirectory setting to your Mojdoc folder.

  3. Enable and start it:

    cp mojdoc.example.service /etc/systemd/system/mojdoc.service
    vim /etc/systemd/system/mojdoc.service
    systemctl daemon-reload
    systemctl enable --now mojdoc.service

Tip: Use journalctl -u mojdoc -f to follow logs live.

This setup is ideal for "set it and forget it" servers or internal documentation sites behind a reverse proxy.


βš™οΈ PM2 (Node.js Process Manager)

If you already use PM2 to manage other apps, Mojdoc can fit right in.

  • Run Hypnotoad in foreground mode, and PM2 will manage restarts and logs.

Example steps:

  1. Copy or adapt the provided ecosystem file: ecosystem.config.example.js

  2. Start it and save it:

    cp ecosystem.config.example.js ecosystem.config.js
    vim ecosystem.config.js
    pm2 start ecosystem.config.js
    pm2 save

Tip: Use pm2 log mojdoc to follow logs live. Assuming you haven't changed the name field.

This approach is lightweight and convenient for developers or mixed stacks.


🐳 Docker / Docker Compose

A container image is available for quick deployment.

Example minimal docker-compose.yml:

version: "3"
services:
  mojdoc:
    image: ghcr.io/justinnamilee/mojdoc:latest
    container_name: mojdoc
    ports:
      - "3000:3000"
    volumes:
      - ./private/dox:/opt/mojdoc/private/dox
      - ./mojdoc.conf:/opt/mojdoc/mojdoc.conf

Then just start it:

docker compose up -d

Note: This is the cleanest way to deploy on any host β€” minimal dependencies, easy upgrades.


πŸ§ͺ Development (Morbo)

For development or testing:

morbo mojdoc
  • Auto-reloads on file changes.
  • Logs everything to the console.
  • Perfect for previewing local documentation sets.

🧭 Summary

Method Best For Pros Cons
Systemd Servers Robust, auto-restart, native Needs root/system access
PM2 Dev/staging Simple restarts, cross-platform Requires Node/PM2
Docker Portability Zero setup, isolated Slightly more moving parts
Morbo Local dev Instant reloads Not for production

Author's Note: Of the two deploys I'm personally using, one is PM2 and one is Systemd. Β―\_(ツ)_/Β―


πŸ”§ Configuration

Configure via a Config plugin file (i.e. mojdoc.conf) or environment variables. For Docker, PM2, or Systemd deploys it is strongly recommended to use a config file (Docker config should be mounted to /opt/mojdoc/mojdoc.conf).


πŸͺΆ Specific Settings for mojdoc

Setting ENV Var Default What it does
badge MOJDOC_BADGE cyber-docs Label used by the template UI.
dox MOJDOC_DOX private/dox Root folder to scan for docs.
welcome MOJDOC_WELCOME public/welcome.md Welcome file rendered on /.
logit MOJDOC_LOGIT 0 Enable view GET logs with 1.

🧰 Useful Settings for Mojolicious

Setting ENV Var Default What it does
listen MOJO_LISTEN http://*:3000 List of listen URLs for the built-in server.
proxy MOJO_REVERSE_PROXY 0 (auto-on if trusted_proxies set) Treat X-Forwarded-* headers as authoritative (behind a trusted proxy).
trusted_proxies MOJO_TRUSTED_PROXIES empty CIDR/IP list of proxies to trust for client IP.
log_level MOJO_LOG_LEVEL trace (dev), info (otherwise) Forces logger level (trace/debug/info/warn/error/fatal).
max_request_size MOJO_MAX_REQUEST_SIZE 16 MiB Caps total HTTP request size (body + params).
keep_alive_timeout MOJO_KEEP_ALIVE_TIMEOUT 5 Seconds that idle connections may stay open.

πŸš€ Example mojdoc.conf File

{
  "badge": "super-secret-dox",
  "dox": "/var/www/secure/dox",
  "welcome": "/var/www/secure/welcome.md",
  "logit": 0,
  "hypnotoad": {
    "listen": "http://*:9009",
    "proxy": 1,
    "trusted_proxies": "127.0.0.1, ::1"
  }
}

For more information on this topic see The Mojolicious Cookbook.


πŸ›£οΈ Routes

  • GET / Renders the welcome page and shows a list of matching files discovered under DOX.

  • GET /view/*doc Renders a specific Markdown file. From files within the DOX tree.

  • GET /health Returns OK. Useful for health checks.


🀝 Maintainers / Support

For issues or feature requests, see GitHub Issues.


πŸ—‚οΈ Directory Structure

.
β”œβ”€β”€ docker-compose.yml           ## example compose file, it's in .gitignore
β”œβ”€β”€ docker-compose.example.yml   ## useful to deploy with Docker
β”œβ”€β”€ Dockerfile
β”œβ”€β”€ ecosystem.config.js          ## example pm2 config, it's in .gitignore
β”œβ”€β”€ ecosystem.config.example.js  ## useful to deploy with PM2
β”œβ”€β”€ LICENSE
β”œβ”€β”€ Makefile.PL
β”œβ”€β”€ mojdoc                       ## main application
β”œβ”€β”€ mojdoc.conf                  ## example application config, it's in .gitignore
β”œβ”€β”€ mojdoc.service               ## example service file, it's in .gitignore
β”œβ”€β”€ mojdoc.example.service       ## useful to deploy with Systemd
β”œβ”€β”€ private                      ## default public folder, it's in .gitignore
β”‚   β”œβ”€β”€ dox                      ## default path to look for documents (MOJDOC_DOX)
β”‚   β”‚   └── yourExample.md       ## example file that would be publicly served
β”‚   └── welcome.md               ## your replacement welcome.md if you wanted (MOJDOC_WELCOME)
β”œβ”€β”€ public
β”‚   β”œβ”€β”€ css
β”‚   β”‚   └── mojdoc.css
β”‚   β”œβ”€β”€ favicon.svg
β”‚   └── welcome.md               ## default welcome page
β”œβ”€β”€ README.md
β”œβ”€β”€ t                            ## a non-zero amount of testing
β”‚   └── ...
└── templates                    ## a non-zero amount of website
    β”œβ”€β”€ dox.html.ep
    β”œβ”€β”€ exception.html.ep
    β”œβ”€β”€ layouts
    β”‚   └── mojdoc.html.ep
    β”œβ”€β”€ nodox.html.ep
    β”œβ”€β”€ not_found.html.ep
    └── sidebar.html.ep

Made with πŸ’™ in Perl!

About

Simple Mojolicious app to display Markdown files in the browser with a nice nested navigation sidebar.

Topics

Resources

License

Stars

Watchers

Forks

Packages