Send users to the image and contributors to CONTRIBUTING

The README told everybody to clone the repository and run the development
stack, which builds nothing and installs nothing — so a user following it
got a crash-looping worker and a 500, and reported it as a bug (#1627).
They were reading the right document; it was pointing at the wrong stack.

Getting started now says what each path is for. Users fetch
compose.example.yaml and run the published image, which ships vendored and
pre-built and needs no toolchain — it has existed all along and was linked
from nowhere in the README. Contributors get one paragraph saying a clone
is a development copy, not an installation, and a pointer to
CONTRIBUTING.md, whose sequence was already correct.

CONTRIBUTING gains the sentence its readers were missing — why those steps
exist at all — plus the two things a contributor now meets: containers
that name the missing step instead of dying silently, and the fact that a
second checkout shares one Compose project name and will take over the
first one's containers. That last one cost me this working copy's stack
for a few minutes.

Also: DOCKER.md and INSTALL.md both linked README.md#development, an
anchor that has never existed. And UPDATE.md's build-from-source path told
operators to pull and rebuild with no dependency step, which is the same
trap on every release that moves composer.lock.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
ignacionelson
2026-08-15 02:17:20 -03:00
parent dad8d21dc8
commit 745f24c7d9
5 changed files with 32 additions and 12 deletions
+10 -2
View File
@@ -22,8 +22,10 @@ arrive without prior discussion are hard to review and often need rework.
## Setting up for development ## Setting up for development
The quickest way to a running copy is Docker — the steps that install ProjectSend are also the A clone is a development copy, not an installation: `vendor/` and `public/build/` are deliberately
steps that set it up for development. From a fresh clone: not in git, so nothing runs until Composer and npm have filled them. That is what these steps do,
and it is why the published Docker image — which ships both, already built — is what the README
sends users to instead. From a fresh clone:
```sh ```sh
cp .env.example .env cp .env.example .env
@@ -49,6 +51,12 @@ A few things worth knowing:
`docker compose --profile dev up -d adminer`. `docker compose --profile dev up -d adminer`.
- On later boots the container migrates automatically. The manual `migrate` above is only needed on - On later boots the container migrates automatically. The manual `migrate` above is only needed on
the first install, before `vendor/` exists. the first install, before `vendor/` exists.
- Until `composer install` has run, the `worker` and `scheduler` containers have no application to
run and exit with a message saying so; they pick themselves up once it has. If a page answers
"ProjectSend is not installed yet" or "not built yet", it is naming the step that is missing.
- Two checkouts of this repository share one Compose project name, so `docker compose up` in the
second one takes over the first one's containers. Pass `-p some-other-name` when you want them
side by side.
**Staff and clients are different things.** Staff — "system users" — administer the installation and **Staff and clients are different things.** Staff — "system users" — administer the installation and
upload files. Clients are the people files are shared with. There is no staff registration page: upload files. Clients are the people files are shared with. There is no staff registration page:
+1 -1
View File
@@ -8,7 +8,7 @@ data with it.
Read this before you put real files in ProjectSend, not after. Read this before you put real files in ProjectSend, not after.
> Getting started with Docker in the first place is covered in [README](README.md#development). > Getting started with Docker in the first place is covered in [README](README.md#getting-started).
> Installing without Docker, on a plain PHP server, is [INSTALL.md](INSTALL.md). > Installing without Docker, on a plain PHP server, is [INSTALL.md](INSTALL.md).
--- ---
+1 -1
View File
@@ -5,7 +5,7 @@ published with each release.
If you can run Docker, use Docker instead — it is one command, and everything on this page If you can run Docker, use Docker instead — it is one command, and everything on this page
(PHP extensions, the web server, the background worker, the scheduled tasks) is already wired up (PHP extensions, the web server, the background worker, the scheduled tasks) is already wired up
for you. See [the Docker instructions](README.md#development), and for you. See [the Docker instructions](README.md#getting-started), and
[DOCKER.md](DOCKER.md) for keeping your database and uploads outside the containers. Come back here [DOCKER.md](DOCKER.md) for keeping your database and uploads outside the containers. Come back here
if Docker is not an option on your hosting. if Docker is not an option on your hosting.
+13 -8
View File
@@ -68,17 +68,17 @@ per-seat pricing. It runs on your server, and the files stay there.
## Getting started ## Getting started
**With Docker** — the quickest path, and the one we recommend. **With Docker** — the quickest path, and the one we recommend. Nothing to build: the published
image ships with its dependencies and its frontend already compiled.
```sh ```sh
git clone https://github.com/projectsend/projectsend.git curl -O https://raw.githubusercontent.com/projectsend/projectsend/main/docker/production/compose.example.yaml
cd projectsend # edit the passwords and APP_URL in it, then:
cp .env.example .env # set PROJECTSEND_EDITION=community docker compose -f compose.example.yaml up -d
docker compose up -d
``` ```
The app is at `http://localhost:8090`, and the first thing it shows you is a setup screen that Open `APP_URL` and the first thing you see is a setup screen that creates your administrator
creates your administrator account. account — or set `ADMIN_EMAIL` and `ADMIN_PASSWORD` in the file first and it is created for you.
Before you put real files in it, read **[DOCKER.md](DOCKER.md)** — where your database and uploads Before you put real files in it, read **[DOCKER.md](DOCKER.md)** — where your database and uploads
actually live, how to move them onto paths you chose, and how to back them up so an upgrade can't actually live, how to move them onto paths you chose, and how to back them up so an upgrade can't
@@ -90,7 +90,12 @@ updating and troubleshooting. You do not need Composer or npm on the server; the
run. run.
**Already running it?** **[UPDATE.md](UPDATE.md)** is how you move to a new version — one command **Already running it?** **[UPDATE.md](UPDATE.md)** is how you move to a new version — one command
on Docker, a short sequence on your own server, and what to check afterwards either way. on Docker, one script on your own server, and what to check afterwards either way.
**Want to work on ProjectSend itself?** Cloning the repository gets you a development copy, not an
installation: the dependencies and the compiled frontend are deliberately not in git, so a clone
needs Composer and npm before it runs. **[CONTRIBUTING.md](CONTRIBUTING.md)** has the sequence, and
it is short.
## Coming from ProjectSend Legacy? ## Coming from ProjectSend Legacy?
+7
View File
@@ -80,8 +80,15 @@ Same idea, one extra step because the image is yours to build:
docker compose down # no -v, ever: -v deletes your data volumes docker compose down # no -v, ever: -v deletes your data volumes
git pull # or unpack the new release over the directory git pull # or unpack the new release over the directory
docker compose up -d --build docker compose up -d --build
docker compose exec app composer install # if composer.lock moved
npm ci && npm run build # if package-lock.json or the frontend moved
``` ```
The last two lines are what a source checkout has that an image does not: its dependencies and its
compiled frontend live outside git, so a release that changed either leaves them stale. If a page
comes back saying ProjectSend is "not installed yet" or "not built yet", it is naming which of the
two you skipped.
### What the container does on the way up ### What the container does on the way up
The entrypoint runs before the web server accepts a single request, in this order: The entrypoint runs before the web server accepts a single request, in this order: