Hi there, i am looking for a way to quickly upload my local dev website to my test server
www.mydomain.com/myproject for example.
I am unsure how what I am doing wrong.
What files are required to do so?
I have my .htaccess as
If your homepage is http://yourdomain.com/mysite,
set the RewriteBase to:
RewriteBase /my-project
What other files should be in my dist folder? Can someone give me a full list of the required files for kirby as frontend and panel?
The only way my live server works is when i upload anything in my project folder manually. Which is odd. (its cumbersome as i do not need the . files, the node_modules, so that is why i am looking for a /dist folder way.
I have a script that copies relevant code and folders based on what i see online. but it simply does not work.
#!/usr/bin/env node
const fs = require("fs");
const path = require("path");
const { execSync } = require("child_process");
// Configuration
const DIST_FOLDER = "dist";
const SOURCE_DIR = "./";
// Directories to include in production
const INCLUDE_DIRS = ["assets", "content", "kirby", "media", "site"];
// Individual files to include
const INCLUDE_FILES = ["index.php", ".htaccess", "robots.txt"];
// Files and folders to exclude (even if in included directories)
const EXCLUDE_PATTERNS = [
"node_modules",
"src",
"dist",
"vendor/bin",
".git",
".gitignore",
".gitattributes",
".editorconfig",
".DS_Store",
"package.json",
"package-lock.json",
"composer.json",
"composer.lock",
"build-dist.js",
"tailwind.config.js",
"README.md",
".env",
];
function log(message, type = "info") {
const colors = {
info: "\x1b[36m", // cyan
success: "\x1b[32m", // green
warning: "\x1b[33m", // yellow
error: "\x1b[31m", // red
reset: "\x1b[0m",
};
console.log(`${colors[type]}${message}${colors.reset}`);
}
function shouldExclude(filePath) {
return EXCLUDE_PATTERNS.some((pattern) => {
if (pattern.includes("*")) {
// Simple wildcard matching
const parts = pattern.split("*");
if (parts.length === 2) {
return filePath.startsWith(parts[0]) && filePath.endsWith(parts[1]);
}
}
return filePath.includes(pattern);
});
}
function copyFileSync(src, dest) {
const destDir = path.dirname(dest);
if (!fs.existsSync(destDir)) {
fs.mkdirSync(destDir, { recursive: true });
}
try {
fs.copyFileSync(src, dest);
} catch (error) {
throw new Error(`Failed to copy ${src} to ${dest}: ${error.message}`);
}
}
function copyDirectory(src, dest, rootPath = "") {
if (!fs.existsSync(dest)) {
fs.mkdirSync(dest, { recursive: true });
}
let items;
try {
items = fs.readdirSync(src);
} catch (error) {
log(`Error reading directory ${src}: ${error.message}`, "error");
return;
}
for (const item of items) {
const srcPath = path.join(src, item);
const destPath = path.join(dest, item);
const relativePath = path.join(rootPath, item);
// Skip if should be excluded
if (shouldExclude(relativePath)) {
log(`Skipping: ${relativePath}`, "warning");
continue;
}
let stat;
try {
stat = fs.statSync(srcPath);
} catch (error) {
log(`Skipping broken link/missing file: ${relativePath}`, "warning");
continue;
}
if (stat.isDirectory()) {
copyDirectory(srcPath, destPath, relativePath);
} else {
try {
copyFileSync(srcPath, destPath);
log(`Copied: ${relativePath}`);
} catch (error) {
log(`Failed to copy ${relativePath}: ${error.message}`, "error");
}
}
}
}
function buildDist() {
log("๐ Starting Kirby CMS build process...", "info");
// Clean dist folder
if (fs.existsSync(DIST_FOLDER)) {
log("๐งน Cleaning existing dist folder...", "warning");
fs.rmSync(DIST_FOLDER, { recursive: true, force: true });
}
// Create dist folder
fs.mkdirSync(DIST_FOLDER, { recursive: true });
// Copy included directories
for (const dirName of INCLUDE_DIRS) {
if (fs.existsSync(dirName) && fs.statSync(dirName).isDirectory()) {
const destPath = path.join(DIST_FOLDER, dirName);
log(`๐ Copying directory: ${dirName}`, "info");
copyDirectory(dirName, destPath, dirName);
} else {
log(`โ ๏ธ Directory not found: ${dirName}`, "warning");
}
}
// Copy included files
for (const fileName of INCLUDE_FILES) {
if (fs.existsSync(fileName) && fs.statSync(fileName).isFile()) {
const destPath = path.join(DIST_FOLDER, fileName);
log(`๐ Copying file: ${fileName}`, "info");
copyFileSync(fileName, destPath);
} else {
log(`โ ๏ธ File not found: ${fileName}`, "warning");
}
}
// Create a simple deployment info file
const deployInfo = {
buildDate: new Date().toISOString(),
version: process.env.npm_package_version || "1.0.0",
environment: "production",
includedDirs: INCLUDE_DIRS,
includedFiles: INCLUDE_FILES,
};
fs.writeFileSync(
path.join(DIST_FOLDER, "deploy-info.json"),
JSON.stringify(deployInfo, null, 2)
);
log("โ
Build completed successfully!", "success");
log(`๐ฆ Production files ready in: ${DIST_FOLDER}/`, "success");
// Show folder size
try {
const stats = execSync(`du -sh ${DIST_FOLDER}`).toString().trim();
log(`๐ Dist folder size: ${stats.split("\t")[0]}`, "info");
} catch (error) {
// Silently fail on systems without 'du' command
}
// List what was copied
log("\n๐ Summary of copied items:", "info");
const copiedDirs = INCLUDE_DIRS.filter((dir) => fs.existsSync(dir));
const copiedFiles = INCLUDE_FILES.filter((file) => fs.existsSync(file));
if (copiedDirs.length > 0) {
log(` Directories: ${copiedDirs.join(", ")}`, "success");
}
if (copiedFiles.length > 0) {
log(` Files: ${copiedFiles.join(", ")}`, "success");
}
}
// Run the build
try {
buildDist();
} catch (error) {
log(`โ Build failed: ${error.message}`, "error");
process.exit(1);
}