A site is a project folder DevCatz serves under a name of its own, such as https://shop.localhost. Every site
gets a page in Projects with a header, a row of tabs and its own settings. This page covers adding sites, their
domains and certificates, how Start and Stop behave, what happens when a folder goes missing, and the bigger shapes:
monorepos, folders of apps and Git worktrees.
Adding a site
Press Create New Site at the top of the Projects sidebar (or Create New Site… in the menu bar / tray menu). The dialog offers three ways in.
Link a project folder
Link a project folder… — Choose the folder, then set its name, domain and Node.js version. DevCatz looks at the folder, detects the stack (see Detected stacks) and fills in the site form.
Clone from Git
Clone from Git… — A repository of your GitHub / GitLab / Gitea / Bitbucket account, or any clone URL.
| Field | What it does |
|---|---|
| Repository URL | Any clone URL, or pick one from Your repositories… (the accounts connected under Git) |
| Into folder | The parent folder the repository is cloned into |
| Name | The folder name, and the site name |
| Shallow (latest commit only) | Faster for big repositories; fetch the rest later |
| Branch or tag | Clone that one instead of the default branch |
The clone shows live progress. Cancel clone stops it and leaves nothing behind. When it is done, the usual site form follows.
Park a folder of projects
Park a folder of projects… — Every project inside becomes a site, now and when you add more later. Drop a new project into a parked folder and it shows up as a site by itself.
Turn on Park as a group and give it a Group name to keep those sites together: the folder’s sites, and the ones added later, sit in a sidebar group named after the folder. Renaming or deleting the group in the sidebar carries over to the parked folder.
Parked folders are listed under Settings → Project → Parked folders, where Unpark removes one. A single site of a parked folder can be unlinked like any other (Unlink… in its Settings tab): it then stays out of the parked folder, listed there as unlinked with a Bring back button, until you bring it back.
Import from Laravel Herd
On a Mac with Laravel Herd sites that DevCatz does not serve yet, the dialog shows a quiet link, Import N sites from Laravel Herd…. DevCatz reads Herd’s linked sites and parked paths, lets you tick the ones you want, and serves them on its own domain suffix. Herd itself is not changed. This import reads Herd’s Mac folders, so it is Mac-only.
The site form
| Field | What it does |
|---|---|
| Project name | The site’s name in DevCatz |
| Domain | Filled in as <name>.localhost; change it if you like |
| Protocol | HTTPS or HTTP |
| PHP version / Go version / Node.js version | Shown for the stacks that need them |
| Start the dev server now | Starts the site as soon as it is created |
Under More settings:
| Field | What it does |
|---|---|
| Package manager | bun, npm, pnpm or yarn (Node.js projects) |
| Dev command | Leave empty to use the detected one |
| Let DevCatz assign dev ports | Each app gets its own port from 4100 up, so two sites never fight over 3000 |
| Start automatically when DevCatz launches | This site starts with DevCatz |
Press Create site.
Domains and your own TLD
Every site starts at <name>.localhost. Browsers send .localhost names to your own computer without any DNS.
On Windows that is true only for browsers — see DNS rules on Windows
for the rest.
A different suffix
To use another suffix such as .test or .devcatz, go to Settings → General → Default domain → Suffix →
Change…. DevCatz shows which sites would be renamed; Rename N site(s) applies it.
Some suffixes are refused:
- Real public TLDs such as
.comor.dev, so you never shadow a real website. .local, which belongs to mDNS (Bonjour).- A suffix another tool already resolves, such as Laravel Herd’s
/etc/resolver/testwith a DNS rule (NRPT) of its own. Free that suffix first, or pick another.
When you change the suffix, every site still on the old one is renamed. Domains you set by hand stay as they are.
The site page then lists .env values that still point at the old domain (APP_URL, CORS_ORIGIN,
NUXT_PUBLIC_* and the like). The proxy overrides those per request, so the site keeps working; your .env file is
not changed.
A suffix other than .localhost needs DevCatz’s own small DNS server, wired in through a file in /etc/resolver.
Press Install resolver for .<tld>… (Settings → General, or the third Welcome card once the suffix is set).
The steps, shown while it works:
- Start DevCatz’s DNS on
127.0.0.1:53531 - Create
/etc/resolver/<tld>— your administrator password - Check that
*.<tld>resolve to this Mac
Remove resolver takes it out again (Remove /etc/resolver/<tld> — your administrator password, then Check that they are gone). The badge next to the suffix reads *.<tld> resolves or does not resolve yet.
DNS rules on Windows
On Windows only browsers (Chrome, Edge, Firefox) resolve .localhost by themselves. Node, PHP, Python and curl do
not, so a site that calls another by name — an API from a frontend, a webhook, a test suite — fails. That is why
DevCatz on Windows always offers a DNS rule, even for .localhost: Settings → General → Default domain →
Add DNS rule for .<tld>…, or the third Welcome card, Site names for your code. The steps, shown while it
works:
- Start DevCatz’s DNS on
127.53.0.1:53 - Add Windows DNS rules (NRPT) for
*.<tld>and*.localhost— administrator approval - Check that
*.<tld>and*.localhostresolve to this PC
DevCatz’s DNS listens on 127.53.0.1, a loopback address of its own, because a Windows DNS rule names a server and
never a port, and it answers the suffix and localhost with 127.0.0.1 and ::1. The rules are kept by Windows
and survive restarts; Remove DNS rules takes them out (Remove the DevCatz DNS rules (NRPT) — administrator
approval, then Check that they are gone), and so does the uninstaller. The badge next to the suffix reads
*.<tld> resolves or does not resolve yet.
DoCatz runs the same DNS on the same address. When it is already there and answers DevCatz’s names, DevCatz simply uses it, and Settings → General → Default domain says so: DoCatz answers these names on the same address (it runs the same DNS), so DevCatz uses it. Once DoCatz quits, DevCatz takes the address back by itself.
If something else has port 53, DevCatz names the program on that address and offers Try again: a Mobile hotspot or Internet Connection Sharing (ICS) in Services, Docker Desktop (quit it), or another program to close.
No two things on one name
DevCatz checks every domain against other sites, apps inside sites, worktrees, Reverb, every DevCatz service and the database domain. While a name clashes, Save (and mod+S) stays disabled.
HTTPS and the local certificate
DevCatz makes its own certificate authority, DevCatz Local CA, valid for 10 years. Certificates for each host are made on demand when a browser asks for that name, and are valid for 397 days.
Your browser trusts these once the CA is trusted. Do it in the Welcome dialog, or under Settings → Project → HTTPS certificates with Trust certificate authority…. The steps are shown while it works:
- Prepare the DevCatz Local CA
- Add it to your login keychain — macOS asks for your password or Touch ID
- Check that it is trusted (Node.js and Bun get it too)
Once it is trusted the button reads Remove from keychain (Remove it from your login keychain — macOS asks for your password, then Check that it is gone). Show ca.crt reveals the file in Finder.
- Prepare the DevCatz Local CA
- Add it to your Trusted Root certificates — Windows asks install this certificate?
- Check that it is trusted (Node.js and Bun get it too)
The CA goes into your own user’s Trusted Root store, so no administrator is needed. If Windows’ question is not in front, click the flashing key icon in the taskbar. Once it is trusted the button reads Remove from Windows (Remove it from your Trusted Root certificates — Windows asks “delete this certificate?”, then Check that it is gone). Show ca.crt shows the file in File Explorer.
When it is done, reload your browser tabs. A few programs keep their own list of trusted certificates:
- Firefox needs
security.enterprise_roots.enabledset totrueinabout:config, orca.crtimported under its own certificate settings — on both platforms. - Node.js apps that call your HTTPS domains need
NODE_EXTRA_CA_CERTSpointing atca.crt.
What DevCatz changes on your computer explains what trusting does and how to undo it. If a browser still complains, see the troubleshooting page.
The proxy ports
All sites are served by one proxy. By default it listens on:
| Port | For |
|---|---|
8443 |
HTTPS |
8180 |
HTTP |
Change them under Settings → Project → Proxy and press Apply. The badge next to Proxy reads listening or down.
URLs without a port
With the defaults a site lives at https://shop.localhost:8443. To drop the :8443, press Enable clean URLs…
(Settings → Project → URLs without a port, or card 2 of the Welcome dialog, Names without a port). The steps
are shown while it works:
- Check ports 443 and 80
- Install the two port forwarders — your administrator password
- Check that sites answer without
:8443
The forwarders are launchd services (LaunchDaemons) on [::1]:443 and [::1]:80, which relay to the proxy on
8443 / 8180. Disable removes them (Remove the two port forwarders — your administrator password, then
Check that sites answer on :8443 again).
- Check ports 443 and 80
- Forward ports 443 and 80 to DevCatz — administrator approval
- Check that sites answer without
:8443
The forwarding is Windows’ own port proxy (netsh interface portproxy, run by the IP Helper service) from
[::1]:443 and [::1]:80 to the proxy on 8443 / 8180; it takes one administrator prompt, and the rules survive
restarts. Disable removes them (Remove the forwarding of ports 443 and 80 — administrator approval, then
Check that sites answer on :8443 again).
127.0.0.1 is covered too when nothing else listens on 127.0.0.1:443 and :80. If another program already holds
them, clean URLs work over IPv6 only until it lets go; the card then says when IPv4 has become free, so you can
disable and enable again. See What DevCatz changes on your computer
and URLs without a port stopped working.
The site header
At the top of a site’s page:
- Status: a dot and a badge, ★ for a favorite, the group badge, a parked badge, a worktree · <branch> chip for worktrees, and the URL chip.
- Always on — for PHP sites with nothing extra to run (see Start and stop).
- Start, or Start ▾ with Start and Start all (the site plus its worktrees). While it starts the button reads Starting n/m… or Building <package>…, with ✕ to cancel.
- Stop and Restart.
- Build, or Build ▾ with Build all and each app:
npm/pnpm/bun run build, the Vite or Mix assets of PHP sites, orgo build -o bin/<name>. - Open ▾ — each app’s domain, your Editor, FinderFile Explorer and Terminal (Warp, iTerm or Ghostty when installed, else TerminalWindows Terminal when installed, else a Command Prompt).
- Share — share the site on a public URL (see Expose). While it is shared, the button reads Shared and a chip shows the public URL (public · click to copy).
Below the header sit the site’s tabs. Those that do not fit move into More N. A site’s tabs walks through each one.
Desktop apps
An Electron or Tauri project is a site without a web address. Its header shows Desktop app · opens in its own
window with the framework’s mark instead of a URL chip, there is no Share, Open ▾ has no browser entries,
and the sidebar subtitle reads desktop app. In place of the preview, the Overview shows a card, A desktop app:
Start opens its window, the way npm start does in a terminal. It has no web address, so there is nothing to
preview or share here; its output is in Logs. In the Apps table its address reads — (its own window), and the
site’s Settings tab has no Domain or Protocol. A Tauri frontend’s dev port stays listed.
Per-site settings
The site’s Settings tab:
| Group | Settings |
|---|---|
| Site | Name, Domain (or Subdomain for a worktree), Protocol — the last two not for a desktop app |
| Dev server | Dev command (empty = detected), Package manager (bun / npm / pnpm / yarn), Node.js version, PHP version, Python version, Go version |
| Ports and start-up | Let DevCatz assign dev ports (off = ports come from .env), Start automatically when DevCatz launches |
| Apps: address and port | Per app: a subdomain <sub>.<site> (empty = the site’s own domain, Default = back to the default), Generate for a free port, Also write API_PORT to .env (only while the Env tab is unlocked) |
| Runs with Start | Queue worker (php artisan queue:work), Scheduler (php artisan schedule:work), Celery worker, Celery beat |
| Free up space | Move node_modules, vendor/, Python virtual environments or Rust target/ to the TrashRecycle Bin. Stopped sites only; Install dependencies brings them back |
Buttons at the bottom:
- Save (mod+S).
- Re-detect stack — look at the folder again after you change its framework or layout.
- Unlink… — type the domain to confirm. DevCatz forgets the site; the project files are untouched. A site from a parked folder stays out of it until you press Bring back under Settings → Project → Parked folders.
Some apps hard-code their port in the source. DevCatz cannot give those a managed port, and Apps: address and port explains why for that app.
Start and stop
What Start does depends on the stack:
- PHP sites are always on. PHP-FPMPHP (FastCGI) serves
them as soon as they exist. Start only runs the extras: Vite (with
laravel-vite-pluginon the same origin, honouringpublic/hot), Laravel Mix watch, the queue worker, the scheduler and Reverb. A PHP site with none of these shows Always on instead of Start. - Sites with several apps start app by app. Stop waits until every app has started before it stops them.
- One app can be restarted on its own with ↻ under Overview → Apps.
- Sites without a port — Burn, Candle, command-line tools — count as running once started.
- Desktop apps open their own window (see Desktop apps).
A few safety nets:
- Start all sites on launch (Settings → Project → Sites) is off by default: only sites with Start automatically when DevCatz launches in their own settings start. The site you had selected opens again.
- When you quit DevCatz or it updates itself, it remembers which sites were running and starts them again on the next launch.
- If the runtime is missing, Start says so instead of failing quietly. When dependencies are missing, Install dependencies appears.
- Install dependencies always answers. With nothing to install from it says so — No package.json here to install from: use Re-detect stack (Settings) if the project changed, or No package.json, composer.json, go.mod, Cargo.toml or pyproject.toml in the site’s folders to install from — and when Bun is the package manager but is not installed, it points at the Bun page. Afterwards a notice reads Dependencies installed, or The install finished, but … See Logs. when a folder still lacks its packages.
- Before you press Start, the Overview says why it would fail: Some packages are not installed names the
packages
package.jsonlists thatnode_modulesdoes not have yet (per app folder in a monorepo), and Electron is not fully installed — its binary download never ran — comes with Repair Electron. - A broken virtualenv is caught too. When a Python project’s
.venvwas made with a Python that is no longer installed, the Overview shows The virtualenv is broken and Start refuses; Install dependencies moves the old.venvto the TrashRecycle Bin, makes it again with the site’s Python and installs the packages.
When a site’s folder is gone
A linked site whose folder was deleted, renamed or moved outside DevCatz stays in the sidebar, dimmed, with the line This site is gone. Its page shows the path where the folder was and two buttons (also in the right-click menu):
- Locate… points the site at the folder where it is now, keeping its domain, ports and settings.
- Remove forgets the site.
Putting the folder back brings the site back by itself. If the folder you pick in Locate… looks like a different project (another folder name, another manifest name), DevCatz asks — This folder looks like another project. It is X, not Y. — and offers Link as a new site (it gets its own domain and default settings; the missing site stays in the list as gone), Use it for Y (it takes over Y’s domain and keeps its settings: dev command, runtime versions and so on), or Cancel.
Monorepos and folders of apps
JavaScript workspaces
A project with npm, yarn or bun workspaces, or a pnpm-workspace.yaml, is one site with several apps. Each app
gets a managed port. Plain vite, astro, nuxt or next dev scripts get --port N added (and --strictPort
for Vite), so the app really uses the port DevCatz gave it.
- When the root has no
devscript (sayapps/webandapps/api), Start runs each app from its own folder. - Go modules and Rust crates inside the workspace become apps too. DevCatz looks in
apps/,services/,backend/,server/,packages/and the root. - PHP and Python projects inside the workspace run as apps of their own — say
apps/apiwithartisanor apyproject.tomlbesideapps/web, with or without apackage.jsonof its own. Install dependencies runs Composer or uv in them too, since the JavaScript package manager skips them. - A dev script that sets its own
--port(TanStack Start’s starter does) gets DevCatz’s managed port instead.
A PHP or Python site with frontend folders
A Laravel, Django or FastAPI project at the root, with other projects in its folders — Laravel with a Vite app in
frontend/, Django with frontend/, FastAPI with a NestJS api/ — stays one site. The root keeps the site’s domain
(served by PHP-FPMPHP (FastCGI), or by its own dev server),
and each folder runs as an app on its own subdomain and port. A PHP site’s folder apps start with it, and the site
counts as running once they answer.
A folder of separate projects
Some repositories have a root that runs nothing itself, with project folders one level down (or in apps/,
services/, packages/ or projects/). DevCatz runs each folder with its own driver:
| Folder holds | Runs with |
|---|---|
| A JavaScript app | Its package manager’s dev script |
| Laravel | php artisan serve |
| Other PHP | php -S |
| Python | The detected framework’s command |
| Go | The Go dev command |
This applies when you link such a folder. A parked folder keeps its sub-projects as separate sites instead.
Domains for apps
The main web app — the folder named web, frontend, front, app, site, client, www or ui — gets the
site’s bare domain. The others get <folder>.<domain>, for example api.shop.localhost.
.env URLs that point at an app’s old port are rewritten to its managed port, and the Logs tab has a chip per
app (turbo’s web:dev: prefixes are recognised too).
Worktrees as sites
A Git worktree can become a site of its own, so two branches run side by side. A worktree site is a child of its parent: the sidebar indents it under the parent, and it gets its own ports and a domain built from the branch:
| Site | Worktree domain |
|---|---|
| One app | <branch>.<site>.<tld>, e.g. feat-login.shop.localhost |
| Several apps | <app>.<branch>.<site>.<tld> |
Making a worktree
Open the site’s Git tab → Worktrees → New worktree…:
- New branch or Existing branch, Start from, and Folder — by default outside the repository, at
<repo>.worktrees/<branch>. - Dependencies: Install fresh, Leave out, or clone them from the parent. On a Mac the clone uses APFS copy-on-write, so it is quick and takes almost no extra disk space.
- Database: shared with the parent by default, or a separate copy such as
shop_feat_login. SQLite files are copied.
The .env file is copied with the domains rewritten. The queue worker, scheduler and Reverb stay off in a worktree.
Each worktree gets its own Redis database index (Pick a free one) and its own Docker compose project name.
Worktrees made elsewhere
- Add as site turns a worktree made outside DevCatz into a site. Forget missing clears ones that no longer exist.
- Add new worktrees as sites automatically catches worktrees made by Claude Code, other agents or
git worktree add, with a notification and the preview URL. Worktrees you removed by hand are remembered and not added again.
Removing a worktree
Remove worktree… warns about uncommitted or unpushed work and offers Also drop its database when it had its own copy. More on worktrees and branches is on Git.
When a runtime is missing
The site’s Overview tells you what the project needs, for example PHP is needed or the project asks for
Node 20, with an Install button for that runtime and version. DevCatz picks the newest version that fits what
the project asks for in composer.json, .nvmrc, engines or go.mod.
Sites that call a framework tool — pnpm, Yarn, Air, Poetry and the like — find it on the runtime’s Tools tab, where it carries a needed by badge.
Rust sites list each missing tool: Rust itself, Trunk, Dioxus CLI, cargo-leptos, Tauri CLI, Solana CLI, Anchor, the WebAssembly target, or the SQLx, SeaORM or Diesel CLI. See Runtimes for each one. On Windows, Solana and Anchor run inside WSL, as their docs say; install them there.
Last updated 2026-11-03