the home site for me: also iteration 3 or 4 of my site
1#!/usr/bin/env bun
2
3import { watch } from 'fs';
4import { existsSync, mkdirSync, copyFileSync, unlinkSync, rmSync } from 'fs';
5import { spawn } from 'child_process';
6import { dirname, join } from 'path';
7
8let zolaProcess: any = null;
9
10function cleanup() {
11 if (zolaProcess) {
12 zolaProcess.kill();
13 }
14 rmSync('.zola-build', { recursive: true, force: true });
15 process.exit(0);
16}
17
18process.on('SIGINT', cleanup);
19process.on('SIGTERM', cleanup);
20
21function ensureDir(filePath: string) {
22 const dir = dirname(filePath);
23 if (!existsSync(dir)) {
24 mkdirSync(dir, { recursive: true });
25 }
26}
27
28function copyFile(src: string, dest: string) {
29 ensureDir(dest);
30 copyFileSync(src, dest);
31}
32
33function deleteFile(dest: string) {
34 if (existsSync(dest)) {
35 unlinkSync(dest);
36 }
37}
38
39async function initialSync() {
40 await Bun.$`rm -rf .zola-build`.quiet();
41 await Bun.$`mkdir -p .zola-build`.quiet();
42 await Bun.$`cp -r content .zola-build/`.quiet();
43
44 const optionalDirs = ['static', 'templates', 'sass', 'syntaxes'];
45 for (const dir of optionalDirs) {
46 if (existsSync(dir)) {
47 await Bun.$`cp -r ${dir} .zola-build/`.quiet();
48 }
49 }
50
51 await Bun.$`cp config.toml .zola-build/`.quiet();
52 await Bun.$`bun run scripts/preprocess.ts .zola-build/content`.quiet();
53}
54
55async function handleFileChange(dir: string, filename: string) {
56 const srcPath = join(dir, filename);
57 const destPath = join('.zola-build', dir, filename);
58
59 if (existsSync(srcPath)) {
60 copyFile(srcPath, destPath);
61 if (dir === 'content' && filename.endsWith('.md')) {
62 await Bun.$`bun run scripts/preprocess.ts ${destPath}`.quiet();
63 }
64 } else {
65 deleteFile(destPath);
66 }
67}
68
69async function handleConfigChange() {
70 copyFile('config.toml', '.zola-build/config.toml');
71}
72
73async function startServer() {
74 await initialSync();
75
76 zolaProcess = spawn('zola', ['serve', '--force', '--interface', '0.0.0.0', '--output-dir', '../public'], {
77 cwd: '.zola-build',
78 stdio: 'inherit'
79 });
80
81 zolaProcess.on('error', (err: Error) => {
82 console.error('Failed to start Zola:', err);
83 });
84}
85
86await startServer();
87
88const watchDirs = ['content', 'templates', 'sass', 'static', 'syntaxes'];
89
90for (const dir of watchDirs) {
91 if (existsSync(dir)) {
92 watch(dir, { recursive: true }, (event, filename) => {
93 if (filename && !filename.includes('.zola-build')) {
94 handleFileChange(dir, filename);
95 }
96 });
97 }
98}
99
100watch('config.toml', () => {
101 handleConfigChange();
102});