# After how many days shall the login-cookie expire?
- LOGOUT_AFTER_DAYS=40
+
+ # Set the BASE_PATH if you are running DailyTxT under a subpath (e.g. /dailytxt).
+ # - BASE_PATH=/dailytxt
ports:
# Change the left port to your needs.
# You often would only see 8000:80. But this way, port 8000 is publicly accessible (without TLS!).
// - all users with their disk usage
// - free disk space
// - migration-info
+// - app settings (env-vars)
func GetAdminData(w http.ResponseWriter, r *http.Request) {
if !validateAdminPasswordInRequest(r) {
http.Error(w, "Invalid admin password", http.StatusUnauthorized)
AllowedHosts []string `json:"allowed_hosts"`
Indent int `json:"indent"`
AllowRegistration bool `json:"allow_registration"`
+ BasePath string `json:"base_path"`
}
// Global settings
AllowedHosts: []string{},
Indent: 0,
AllowRegistration: false,
+ BasePath: "/",
}
fmt.Print("\nDetected the following settings:\n================\n")
}
fmt.Printf("Allow Registration: %t\n", Settings.AllowRegistration)
+ if basePath := os.Getenv("BASE_PATH"); basePath != "" {
+ Settings.BasePath = basePath
+ }
+ fmt.Printf("Base Path: %s\n", Settings.BasePath)
+
fmt.Print("================\n\n")
// Create data directory if it doesn't exist
# After how many days shall the login-cookie expire?
- LOGOUT_AFTER_DAYS=40
+
+ # Set the BASE_PATH if you are running DailyTxT under a subpath (e.g. /dailytxt).
+ # - BASE_PATH=/dailytxt
ports:
# Change the left port to your needs.
# You often would only see 8000:80. But this way, port 8000 is publicly accessible (without TLS!).
#!/bin/sh
set -e
-# Start the Go backend in background
-# Environment variables consumed by backend (see utils.InitSettings):
-# DATA_PATH, DEVELOPMENT, SECRET_TOKEN, LOGOUT_AFTER_DAYS, ALLOWED_HOSTS, INDENT, ALLOW_REGISTRATION, ADMIN_PASSWORD
-
# Ensure data directory exists
mkdir -p "${DATA_PATH:-/data}"
-# Run backend
+# Run backend in background
/usr/local/bin/dailytxt &
BACKEND_PID=$!
echo "Started backend (PID $BACKEND_PID)"
+# Edit some files to make dailytxt work on a subpath provided by BASE_PATH
+if [ -n "${BASE_PATH:-}" ]; then
+ echo "Configuring frontend for BASE_PATH: $BASE_PATH"
+
+ # remove leading and trailing slash if exists
+ BASE_PATH="${BASE_PATH#/}"
+ BASE_PATH="${BASE_PATH%/}"
+ # print the BASE_PATH being used
+ echo "Using BASE_PATH: '$BASE_PATH'"
+
+ # Update base href in app.html
+ sed -i "s|href=\"/|href=\"|g" /usr/share/nginx/html/index.html
+
+ # Update base path in app.html
+ sed -i "s|base: \"|base: \"/$BASE_PATH|g" /usr/share/nginx/html/index.html
+
+ # Update import-paths in app.html
+ sed -i "s|import(\"|import(\"/$BASE_PATH|g" /usr/share/nginx/html/index.html
+
+ # Update manifest.webmanifest base
+ sed -i "s|start_url\":\"/|start_url\":\"/$BASE_PATH|g" /usr/share/nginx/html/manifest.webmanifest
+ sed -i "s|src\":\"|src\":\"/$BASE_PATH|g" /usr/share/nginx/html/manifest.webmanifest
+fi
+
# Start nginx in foreground
exec nginx -g 'daemon off;'
"error_reordering_files": "Error changing the order of files",
"error_saving": "Error saving the text!"
},
- "written_on": "Written on:"
+ "written_on": "Posted on:"
},
"login": {
"alert": {
import { goto } from '$app/navigation';
import { selectedDate } from '$lib/calendarStore.js';
import { formatBytes } from '$lib/helpers';
+ import { resolve } from '$app/paths';
const { t } = getTranslate();
const tolgee = getTolgee(['language']);
}
// Navigate to write page
- goto('/write');
+ goto(resolve('/write'));
}
function initTooltips() {
import Fa, { FaLayers } from 'svelte-fa';
import { goto } from '$app/navigation';
import { onDestroy, onMount } from 'svelte';
+ import { resolve } from '$app/paths';
import {
readingMode,
settings,
});
$effect(() => {
- if ($readingMode === true && page.url.pathname !== '/read') {
- goto('/read');
+ if ($readingMode === true && !page.url.pathname.endsWith('/read')) {
+ goto(resolve('/read'));
} else if ($readingMode === false) {
- goto('/write');
+ goto(resolve('/write'));
}
});
if (!$isAuthenticated && needsReauth) {
// Save current route for return after reauth
localStorage.setItem('returnAfterReauth', window.location.pathname);
- goto('/reauth');
+ goto(resolve('/reauth'));
return; // Stop further initialization
}
getVersionInfo();
loadTags();
- if (page.url.pathname === '/read') {
+ if (page.url.pathname.endsWith('/read')) {
$readingMode = true;
- } else if (page.url.pathname === '/write') {
+ } else if (page.url.pathname.endsWith('/write')) {
$readingMode = false;
}
.then(() => {
localStorage.removeItem('user');
if (errorCode) {
- goto(`/login?error=${errorCode}`);
+ goto(resolve(`/login?error=${errorCode}`));
} else {
- goto('/login');
+ goto(resolve('/login'));
}
})
.catch((error) => {
import {redirect} from '@sveltejs/kit'
+import { resolve } from '$app/paths';
export const load = () => {
const user = localStorage.getItem('user');
if (!user) {
- throw redirect(307, '/login');
+ throw redirect(307, resolve('/login'));
}
}
\ No newline at end of file
.log {
border-radius: 15px;
- margin-left: 1rem;
- margin-right: 1rem;
+ }
+
+ @media screen and (min-width: 576px) {
+ .log {
+ margin-left: 1rem;
+ margin-right: 1rem;
+ }
}
:global(body[data-bs-theme='dark']) .log {
import {redirect} from '@sveltejs/kit'
+import { resolve } from '$app/paths';
export const load = () => {
const user = localStorage.getItem('user');
if (!user) {
- throw redirect(307, '/login');
+ throw redirect(307, resolve('/login'));
}
}
\ No newline at end of file
import { FormatIcu } from '@tolgee/format-icu';
import { darkMode } from '$lib/settingsStore.js';
import { registerSW } from 'virtual:pwa-register';
+ import { resolve } from '$app/paths';
const tolgee = Tolgee()
.use(DevTools())
.get(API_URL + '/users/logout')
.then(() => {
localStorage.removeItem('user');
- goto(`/login?error=${error.response.status}`);
+ goto(resolve(`/login?error=${error.response.status}`));
})
.catch((error) => {
console.error(error);
calculateResize();
// if on login page, generate neon mesh
- if (page.url.pathname === '/login') {
+ if (page.url.pathname.endsWith('/login')) {
generateNeonMesh($darkMode);
}
}
});
- let routeToFromLoginKey = $derived(page.url.pathname === '/login');
+ let routeToFromLoginKey = $derived(page.url.pathname.endsWith('/login'));
</script>
<main class="d-flex flex-column background" use:focus={generateNeonMesh}>
import { redirect } from "@sveltejs/kit";
+import { resolve } from '$app/paths';
export function load() {
// Redirect to the /write route
- throw redirect(307, "/write");
+ throw redirect(307, resolve("/write"));
}
\ No newline at end of file
import { redirect } from '@sveltejs/kit';
+import { resolve } from '$app/paths';
// Catch-all for unknown routes: redirect to /write (primary app surface)
// If /write itself handles auth, unauthenticated users will still be bounced to /login there.
// Adjust here if you later want a different fallback (e.g. redirect to /login when not authenticated).
export function load() {
- throw redirect(307, '/write');
+ throw redirect(307, resolve('/write'));
}
import {redirect} from '@sveltejs/kit'
+import { resolve } from '$app/paths';
export const load = () => {
const user = localStorage.getItem('user');
if (user) {
- throw redirect(307, '/write');
+ throw redirect(307, resolve('/write'));
}
}
\ No newline at end of file
import { getTranslate, getTolgee } from '@tolgee/svelte';
import { isAuthenticated, loadFlagEmoji } from '$lib/helpers.js';
import { fade } from 'svelte/transition';
+ import { resolve } from '$app/paths';
const { t } = getTranslate();
const tolgee = getTolgee(['language']);
} else {
$isAuthenticated = true;
localStorage.setItem('user', response.data.username);
- goto('/write');
+ goto(resolve('/write'));
}
})
.catch((error) => {
import { generateNeonMesh, isAuthenticated } from '$lib/helpers';
import { getTranslate } from '@tolgee/svelte';
import logo from '$lib/assets/locked_heart_with_keyhole.svg';
+ import { resolve } from '$app/paths';
const { t } = getTranslate();
$isAuthenticated = true;
// Authentication successful - return to original route
- const returnPath = localStorage.getItem('returnAfterReauth') || '/write';
+ const returnPath = localStorage.getItem('returnAfterReauth') || resolve('/write');
localStorage.removeItem('returnAfterReauth');
goto(returnPath);
} else {