Setting up for development
To work on TomeCMS itself, you run Astro’s development server on your computer, with PostgreSQL and SeaweedFS, the S3-compatible file store, in Docker. One command prepares all of it. This setup is for development only. A site for readers is installed as Installing on a VPS describes.
What you need
Section titled “What you need”- Docker Desktop, running
- Node.js 22.12 or newer, with npm
- Git
- Ports
4321,5432and9000free on your computer
Check the main tools:
node --versionnpm --versiondocker versiondocker compose versionOn macOS
Section titled “On macOS”macOS is the main development workflow, and the one that is validated. From the project directory:
npm run dev:macosThe helper goes through these steps, and stops with a message at the first one that fails:
- It checks that it is running on macOS, that
node,npmanddockerare installed, and that Docker Desktop is running. - It runs
npm ciwhen the packages are not installed yet. - It checks that the three ports are free, and creates
.env.localwhen there is none yet, with generated secrets and local addresses, readable by you alone. - It starts PostgreSQL and SeaweedFS and waits until both are ready. SeaweedFS creates the media bucket as it starts.
- It applies the database migrations.
- It prints the installer’s address and the installation token.
- It starts Astro.
You need no storage account and no license file. Open http://localhost:4321/install and go through the first-run wizard, which asks for the installation token. To see the token again:
grep '^TOME_CMS_INSTALL_TOKEN=' .env.localKeep the terminal open while you work. Ctrl+C stops Astro. PostgreSQL and SeaweedFS keep running in Docker until you stop them:
npm run infra:downThis removes the two containers. The database and the files stay in Docker volumes, and come back the next time the helper runs.
.env.local holds your local secrets, and the repository’s .gitignore leaves it out.
When the helper stops
Section titled “When the helper stops”| Message | What to do |
|---|---|
Error: Docker Desktop is not running. |
Start Docker Desktop and run the helper again. |
Port 5432 is unavailable. |
Something else is using that port. Stop it and run the helper again. The message names whichever of the three ports is taken. |
Existing .env.local needs updates; rerun with --force to merge values while preserving secrets. |
Newer code needs values your .env.local does not have yet. Look through the file, then run npm run dev:macos -- --force. |
Set .env.local permissions to 0600 before continuing. |
Others can read the file. Run chmod 600 .env.local, or run the helper with -- --force, which writes it back readable by you alone. |
--force merges the new defaults into .env.local and keeps every secret already in it.
On Windows
Section titled “On Windows”Windows is a secondary workflow. Use Windows 11 with Docker Desktop, Node.js 22.12 or newer, npm, Git and PowerShell. In PowerShell, from the project directory:
npm run dev:windowsThe helper checks the same tools and then runs the same scripts/bootstrap-core.mjs as on macOS. On Windows it starts npm through npm.cmd, and it skips the check that only you can read .env.local, because Node reports every writable file on Windows as readable by others. This path has not yet been tried on a Windows machine. If the helper stops at the migrations, run npm run db:migrate and then npm run dev yourself. The token is in .env.local.
Infrastructure and Astro in separate terminals
Section titled “Infrastructure and Astro in separate terminals”The helper ends by running Astro in the terminal it started in. To keep the two apart, so that you can restart Astro without preparing everything again, run the steps yourself. Install the packages first with npm ci, then:
npm run bootstrap:corenpm run devbootstrap:core is the helper without its first two steps and its last: it checks the ports, creates .env.local when there is none, starts PostgreSQL and SeaweedFS, applies the migrations, prints the token, and ends with Start the application with npm run dev. The database and the file store go on running in Docker, so the terminal is free again. npm run dev runs Astro in whichever terminal you start it in, and you can stop and start it there as often as you like.
These commands work on the same setup:
| Command | What it does |
|---|---|
npm run infra:up |
Starts PostgreSQL and SeaweedFS with the values in .env.local, and waits until they are ready |
npm run db:migrate |
Applies the migrations that have not run yet |
npm run media:cleanup |
Lists expired upload reservations and files whose deletion failed. With -- --execute, it asks you to type a confirmation, then removes them. |
npm run infra:down |
Stops PostgreSQL and SeaweedFS and removes their containers, keeping their data |

