Skip to content

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:

Terminal window
mkdir adventurelog-klutch
cd adventurelog-klutch
git init

2. 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 dependencies
COPY package*.json ./
RUN npm install --only=production
# Copy source
COPY server.js ./server.js
# Configure data directory for AdventureLog
ENV ADVENTURELOG_DATA_DIR=/var/adventurelog/data
RUN mkdir -p /var/adventurelog/data
# Expose HTTP port
ENV PORT=3000
EXPOSE 3000
# Start the AdventureLog server
CMD ["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:

Terminal window
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-klutch

Then 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:

Terminal window
git add .
git commit -m "Initial AdventureLog Docker setup for Klutch.sh"
git branch -M main
git remote add origin https://github.com/your-username/adventurelog-klutch.git
git push -u origin main

Klutch.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

  1. Sign in at klutch.sh/app.
  2. Navigate to Create Project and name your project (for example, adventurelog-api).
  3. 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 the PORT and EXPOSE 3000 configuration 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 to 3000 to 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 GiB or 10 GiB and increase as your content library grows.

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.sh

You 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:

  1. Visit your app URL:

    https://example-app.klutch.sh/api/adventures
  2. 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/data volume 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 3000 and matches the EXPOSE 3000 directive 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_DIR is set to /var/adventurelog/data.
  • Verify that the volume size is appropriate and that the container has write permissions.

Build Failures

  • Ensure your package.json and server.js are 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.

  • 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.