Skip to content

Creating projects ​

dqx init builds a project from a description. Flags for the simple case, a document when there is more to say than flags carry.

From flags ​

bash
dqx init ~/projects/foodback --scaffold laravel \
  --client-name "Foodback" --php 8.5 \
  --domain foodback.dqx --alias app.foodback.example.dqx

Two domains landing in one webroot is normal: an alias is a whole domain, and it reaches both the router's rule and the certificate.

From a document ​

Several sites, per-site aliases, a chosen container prefix - that is where flags stop being the right shape:

yaml
clientName: Zorgpad
layout: multi
php: "8.4"
scaffold: my-house-recipe
services: [db, redis, mailpit]
sites:
  - domains:
      primary: api.zorgpad.dqx
      aliases: [zorgpad.dqx]
    repository: zorgpad-api
    publicDir: public
bash
dqx init ~/projects/zorgpad --from zorgpad.yml

A flag wins over the same key in it.

A site can also say its branch, its own database schema, which services it uses, its hooks, its php or image, secured and nginx; the project its database (type, version, user), install settings and notes. Each lands in the written .dq/config.yml.

An existing .dq/config.yml works too, so a project can be recreated from its own config: client, services: [{name, image}] and a site's repositories are read as the request's clientKey, service names and repository. Anything a new project cannot be given yet - a compose block, fixed ports, a site's env - is refused with its name, never silently dropped: leave it out, and add it to the config after init.

What it decides, and what it will not ​

Everything it filled in is reported with its reason:

dqx init
text
scaffold.chain laravel:13 → my-house-recipe
services       db, mailpit, redis  (the `my-house-recipe` scaffold sets it)
clientKey      zorgpad  (derived from `Zorgpad`)
image          dolphiq/dqx-php85-alpine-slim:1.0  (dqx runs PHP 8.5 on it)

And what it will not guess, it asks:

text
needed  sites.api.zorgpad.dqx.repository
        Which repository is checked out for api.zorgpad.dqx? A multi-layout project clones one per site.

A container prefix derived from the name is an assumption dqx is happy to state. A prefix that collides with a project already on the machine is a question, because two projects sharing one is a class of confusion that takes an afternoon to find.

From the dashboard ​

+ add → start a new project… is the same command behind a form: it posts a request document to dqx init --from -, so there is one code path and the form gains a field the day the document does. See changing things from the dashboard.

Scaffolds ​

--scaffold laravel means dqx creates the application too, not only the environment around it. Recipes are data: they can extend one another, propose defaults, and run commands at two moments - before dqx writes .env, and after, with the database reachable.

dqx_scaffolds over MCP, or the scaffolds reference, lists what this machine knows. A machine or a project can add its own.

What each scaffold is ​

A name is not enough to choose by, so every recipe can say what it is in at most three lines - its runtime, its services, and what it installs plus what it needs from you:

bash
dqx init --scaffold ?
dqx init --scaffold ?
text
qore-cms
  laravel 13 · php 8.4 · mysql 8.4 · node 22
  services: db, mailpit, redis
  installs: qore-admin-base, qore-cms, qore-frontend · needs Flux credentials

The dashboard's dropdown and the recipe pages show the same three lines, from the same function.

From another project ​

A new project that starts with the shape of one you already have - its services, its PHP version, its layout, its install steps and its code - and then has nothing to do with it:

bash
dqx init ~/dockers/acme-two --like northwind \
  --repo git@ssh.bitbucket.org:dq-private/acme-two-api.git=api.acme-two.dqx

Every site needs a repository of its own, and the command refuses before copying anything when one is missing, naming the flag to add. The source's repositories are never kept: this project's pushes would otherwise go to that project's repository.

It writes and stops. No .git comes across, so the new project is not a repository until you make it one - which is a decision about where this project lives. The command prints what is left:

  cd ~/dockers/acme-two/www/api.acme-two.dqx
  git init && git add -A && git commit -m "from a copy"
  git remote add origin git@… && git push -u origin main

then `dqx install` in ~/dockers/acme-two.

--install runs it now instead, which is how you find out the copy works before committing it anywhere. Either way the database starts empty: the source's data is the source's.

It brings the env files, and their credentials

Every .env* comes across with its domains and schema names rewritten - which is what makes the new project runnable - and that includes whatever keys and passwords the source kept in them. The command names the ones that look like credentials when it finishes. Rotate them before the project becomes somebody else's: .env.production and .env.staging are never copied at all.

Not the same as a copy

dqx clone makes the same project again under a second set of names, and says so in its config. This makes a different project: its own key, its own domains, its own repositories, and nothing that points back.

Adopting instead ​

If the project already exists, adopt it rather than recreating it.

dqx v1.78.0