Deploying an AdventureLog App
Introduction
AdventureLog is an open-source journaling and trip-tracking application designed for travelers, hikers, and outdoor enthusiasts who want to document their adventures with maps, photos, notes, and timelines. It typically exposes a web dashboard and an HTTP API for creating entries, attaching media, and browsing your travel history from any device.
Running AdventureLog on Klutch.sh with a Dockerfile gives you a secure, self-hosted platform for storing trip data, photos, and field notes—without relying on third-party SaaS tools. This guide walks through building a Docker image for AdventureLog, configuring persistent storage for user content, pushing your project to GitHub, and deploying it through the Klutch.sh dashboard at klutch.sh/app.
Prerequisites
Before deploying AdventureLog on Klutch.sh, ensure you have:
- A Klutch.sh account
- A GitHub account (GitHub is the only supported git source)
- Docker installed locally (optional but recommended for testing)
- Basic familiarity with Node.js or modern web apps (AdventureLog is commonly implemented as a Node/TypeScript or JavaScript service)
- Optional: a PostgreSQL or other database instance for production deployments
Project Setup for AdventureLog
1. Create a Project Directory
Start by creating a new project directory and initializing git:
mkdir adventurelog-klutchcd adventurelog-klutchgit init2. Basic AdventureLog Server (Example)
If you don’t already have an AdventureLog codebase, you can start from a simple Node.js HTTP API that acts as a journal and trip log backend. Create package.json:
{ "name": "adventurelog", "version": "1.0.0", "main": "server.js", "type": "module", "scripts": { "start": "node server.js" }, "dependencies": { "express": "^4.19.0", "cors": "^2.8.5", "body-parser": "^1.20.3" }}Then create a minimal server.js:
import express from 'express';import cors from 'cors';import bodyParser from 'body-parser';import fs from 'fs';import path from 'path';import { fileURLToPath } from 'url';
const __filename = fileURLToPath(import.meta.url);const __dirname = path.dirname(__filename);
const app = express();const PORT = process.env.PORT || 3000;const DATA_DIR = process.env.ADVENTURELOG_DATA_DIR || path.join(__dirname, 'data');
app.use(cors());app.use(bodyParser.json());
if (!fs.existsSync(DATA_DIR)) { fs.mkdirSync(DATA_DIR, { recursive: true });}
const entriesFile = path.join(DATA_DIR, 'entries.json');
function loadEntries() { if (!fs.existsSync(entriesFile)) return []; return JSON.parse(fs.readFileSync(entriesFile, 'utf8'));}
function saveEntries(entries) { fs.writeFileSync(entriesFile, JSON.stringify(entries, null, 2), 'utf8');}
app.get('/api/adventures', (req, res) => { res.json(loadEntries());});
app.post('/api/adventures', (req, res) => { const { title, location, date, notes } = req.body; if (!title) { return res.status(400).json({ error: 'Title is required' }); }
const entries = loadEntries(); const entry = { id: Date.now().toString(), title, location: location || '', date: date || new Date().toISOString(), notes: notes || '' };
entries.push(entry); saveEntries(entries); res.status(201).json(entry);});
app.listen(PORT, () => { console.log(`AdventureLog server listening on port ${PORT}`);});This simple AdventureLog API stores entries as JSON on disk in a configurable data directory. You’ll map that directory to a persistent volume when deploying on Klutch.sh.
Creating a Dockerfile for AdventureLog
Klutch.sh automatically detects a Dockerfile in your repository root and uses it for deployments. You don’t select Docker explicitly in the UI and you don’t specify a custom Dockerfile path—detection is automatic whenever a Dockerfile is present.
Create a Dockerfile in the project root:
FROM node:20-alpine AS base
WORKDIR /app
# Install dependenciesCOPY package*.json ./RUN npm install --only=production
# Copy sourceCOPY server.js ./server.js
# Configure data directory for AdventureLogENV ADVENTURELOG_DATA_DIR=/var/adventurelog/data
RUN mkdir -p /var/adventurelog/data
# Expose HTTP portENV PORT=3000EXPOSE 3000
# Start the AdventureLog serverCMD ["npm", "start"]Dockerfile Notes
- The AdventureLog API listens on port 3000, which you’ll use as the internal port when configuring the app on Klutch.sh.
- The data directory is set via
ADVENTURELOG_DATA_DIR=/var/adventurelog/data, which you will back with a persistent volume so that adventure entries and attached data survive redeployments. - This example uses a simple single-stage build; you can extend it to multi-stage if you add a frontend build or more complex tooling.
Optional: Local Testing with Docker
You can validate your AdventureLog image locally before pushing it to Klutch.sh:
docker build -t adventurelog-klutch .
docker run -d \ --name adventurelog-test \ -p 3000:3000 \ -e ADVENTURELOG_DATA_DIR=/var/adventurelog/data \ -v "$(pwd)/data:/var/adventurelog/data" \ adventurelog-klutchThen open http://localhost:3000/api/adventures to see the (initially empty) list of entries.
For more complex local setups (for example, combining AdventureLog with a database), you can use Docker Compose on your own machine. Docker Compose is strictly for local development; Klutch.sh does not deploy via Docker Compose.
Pushing Your AdventureLog Project to GitHub
Once your AdventureLog code and Dockerfile are ready, push them to GitHub:
git add .git commit -m "Initial AdventureLog Docker setup for Klutch.sh"git branch -M maingit remote add origin https://github.com/your-username/adventurelog-klutch.gitgit push -u origin mainKlutch.sh will use this repository as the source of truth when building and deploying your AdventureLog app.
Creating an AdventureLog App on Klutch.sh
With your repository in place, you can configure the AdventureLog service from the Klutch.sh dashboard.
Connect the GitHub Repository
- Sign in at klutch.sh/app.
- Navigate to Create Project and name your project (for example, adventurelog-api).
- Go to Create App and:
- Select GitHub as the git source.
- Choose your AdventureLog repository and the branch you want to deploy (for example,
main).
Klutch.sh will automatically detect the Dockerfile in your repository root and use it for the build.
Traffic Type and Internal Port
- Traffic Type: Select HTTP (AdventureLog exposes a REST API and can serve a web UI if you add one later).
- Internal Port: Set to
3000, which matches thePORTandEXPOSE 3000configuration in your Dockerfile.
This ensures that HTTP traffic to your Klutch.sh app is correctly routed to the AdventureLog server inside the container.
Environment Variables on Klutch.sh
In the app’s Environment section, configure the runtime environment variables you need:
PORT– set to3000to match your Dockerfile.ADVENTURELOG_DATA_DIR– set to/var/adventurelog/data, ensuring the app writes data into the directory you’ll mount as a persistent volume.- Any additional variables (for example, database URLs or API keys) if you extend AdventureLog to use external services.
If you ever deploy AdventureLog without a Dockerfile and rely on Nixpacks detection instead, you can customize commands using environment variables:
BUILD_COMMAND– override the default build command used by Nixpacks.START_COMMAND– override the default start command executed by Nixpacks.
Set these as environment variables in the Klutch.sh dashboard whenever you need to customize Nixpacks behavior for non-Docker deployments.
Attaching Persistent Volumes
AdventureLog stores user-generated content such as journal entries and potentially uploads or media. To keep this data safe across redeployments, attach a persistent volume.
In the app’s Storage/Volumes section:
- AdventureLog Data Volume
- Mount path:
/var/adventurelog/data - Size: Choose based on your expected usage—for example, start with
5 GiBor10 GiBand increase as your content library grows.
- Mount path:
This volume ensures that the JSON data or database files stored in /var/adventurelog/data remain intact even when the container is rebuilt or restarted.
Sample Client Code: Creating an Adventure via the API
Once AdventureLog is deployed on Klutch.sh, your app will be available at a URL like:
https://example-app.klutch.shYou can use the /api/adventures endpoint to create new entries from web or mobile apps.
JavaScript Fetch Example
async function createAdventure(entry) { const response = await fetch('https://example-app.klutch.sh/api/adventures', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify(entry), });
if (!response.ok) { throw new Error(`Failed to create adventure: ${response.status}`); }
return response.json();}
createAdventure({ title: 'Summit of Mount Example', location: 'Example Range', date: new Date().toISOString(), notes: 'Blue skies, light wind, and an incredible view at the summit.',}) .then((data) => { console.log('Adventure created:', data); }) .catch((err) => { console.error('Error creating adventure', err); });Fetching Adventures
async function listAdventures() { const response = await fetch('https://example-app.klutch.sh/api/adventures');
if (!response.ok) { throw new Error(`Failed to fetch adventures: ${response.status}`); }
const adventures = await response.json(); console.log('Loaded adventures:', adventures);}
listAdventures().catch((err) => { console.error('Error loading adventures', err);});You can integrate these patterns into your frontend apps to build a full-featured AdventureLog experience.
Verifying Your Deployment
After your first deployment completes:
-
Visit your app URL:
https://example-app.klutch.sh/api/adventures -
Confirm that:
- The API returns an empty list on first load.
- You can create a new adventure entry via the API (or a frontend client) and see it appear in subsequent requests.
- Adventure entries remain available after restarting the app, confirming that the
/var/adventurelog/datavolume is correctly configured.
If anything fails, review the logs in the Klutch.sh dashboard and double-check your internal port, environment variables, and volume mount paths.
Troubleshooting
API Not Reachable
- Ensure the app’s Traffic Type is set to HTTP.
- Verify the internal port is
3000and matches theEXPOSE 3000directive in the Dockerfile. - Check logs in the Klutch.sh dashboard for Node.js or AdventureLog runtime errors.
Data Not Persisting
- Confirm that a persistent volume is attached with mount path
/var/adventurelog/data. - Make sure
ADVENTURELOG_DATA_DIRis set to/var/adventurelog/data. - Verify that the volume size is appropriate and that the container has write permissions.
Build Failures
- Ensure your
package.jsonandserver.jsare present at the repository root (or update the Dockerfile paths accordingly). - Confirm that the Node.js version used in the Dockerfile is compatible with your dependencies.
- Inspect build logs in the Klutch.sh dashboard for missing modules or syntax issues.
Related Documentation
- Learn more about application deployment lifecycle in Deployments.
- Understand networking, ports, and routing behavior in Networking.
- Explore how to attach and manage persistent storage in Volumes.
- Browse the full platform docs at Klutch.sh Documentation.
- For AdventureLog-specific features and ecosystem, refer to the upstream project documentation or repository if you are using a community-maintained implementation.
Deploying an AdventureLog app on Klutch.sh with a Dockerfile gives you a flexible, self-hosted platform for recording your stories, routes, and trip memories. With a clean Dockerfile, correctly configured internal port, and persistent storage for /var/adventurelog/data, you can run a reliable AdventureLog backend on Klutch.sh and build rich web or mobile clients that keep all of your adventures in one place.