When you add a site, DevCatz reads the project folder and works out what it is: the language, the framework, the package manager, the port it listens on and the database library it uses. That decides how the site runs, which runtime it needs and which buttons its tabs get. You can always override the dev command in the site’s Settings tab, and Re-detect stack looks at the folder again.
How detection works
DevCatz tries one language driver after the other, and the first match wins:
| Order | Driver | Why it comes here |
|---|---|---|
| 1 | PHP | Before Node.js, because a Laravel app also has a package.json for Vite |
| 2 | Python | Before Node.js, because a Django app may have one for Tailwind |
| 3 | Rust | Before Node.js, because Leptos, Yew and Anchor projects keep a package.json too |
| 4 | Node.js | A Go module that also has a package.json is treated as a Node.js project |
| 5 | Go |
If the root runs nothing itself, DevCatz tries the folder layout: projects one level down, each with its own driver. Sites, domains and HTTPS explains monorepos and folders of apps.
The detected framework shows on the site’s Overview (Framework, Stack, Dev command) and as a tag in the sidebar, which the sidebar search matches too.
PHP
A folder is a PHP project when it has a composer.json together with artisan, public/index.php, index.php,
web/index.php, webroot/index.php, spark or yii — or a wp-load.php, a CodeIgniter 3 layout, or a plain
index.php without a package.json.
PHP sites are served by PHP-FPMPHP (FastCGI) workers, so there is no dev command to run: the site is Always on. Start only runs the extras, such as Vite or a queue worker (see Start and stop).
Frameworks, in the order DevCatz checks them:
| Framework | Recognised by | Served from | Tasks |
|---|---|---|---|
| Laravel | artisan plus laravel/framework |
public/ |
Artisan card: migrate, db:seed, migrate:fresh --seed |
| CodeIgniter 4 | spark |
public/ |
spark migrate, db:seed…, make:migration…, migrate:rollback |
| CodeIgniter 3 | Its classic layout | The root or public/ |
|
| Yii 2 advanced | The advanced template | frontend/web, plus backend/web on backend.<site> |
|
| Yii 2 basic | The basic template | web/ |
migrate, migrate/create…, migrate/down |
| Symfony | bin/console plus framework-bundle or runtime |
public/ |
doctrine:migrations:migrate, make:migration, cache:clear |
| CakePHP | Its layout | webroot/ |
migrations migrate / rollback, cache clear_all |
| WordPress | wp-load.php |
The root, or web/ for Bedrock |
WP-CLI: rewrite flush, cache flush, plugin list |
| Drupal | Its layout | The root or web/ |
Drush: cache:rebuild, updatedb |
| Joomla | Its layout | ||
| Slim | Its package | ||
| Plain PHP | Anything else PHP | The root or public/ |
A few things that make PHP apps feel at home:
- WordPress: the database is read from
wp-config.php, so the Database tab knows which one the site uses. .htaccess: the proxy understands a subset ofmod_rewrite,DirectoryIndex,PATH_INFOand a front-controller fallback, so pretty URLs of most PHP apps work as they do on Apache.- WP-CLI: the WordPress tasks need
wpon your path —brew install wp-cliputwp-cli.pharand awp.baton your Path (wp-cli.org); otherwise the task says so.
The tasks appear as buttons on the site’s Database tab (see Databases).
PHP data libraries
The Data access card on the Database tab names the library a PHP site uses: Eloquent ORM, Laravel DB Facade, Eloquent (Capsule), Doctrine, Phinx, Propel, Cycle ORM, RedBeanPHP, Medoo, Laminas DB and Hydrahon.
Python
A folder is a Python project when it has a pyproject.toml, requirements*.txt, a Pipfile, manage.py or
setup.py. A JavaScript app that happens to have a pyproject.toml stays a JavaScript site unless it is clearly a
Python web app.
The web framework is the first match of: Django, FastAPI, Litestar, Flask, Starlette, Quart, Sanic, Tornado, Pyramid, Falcon, Bottle, aiohttp and BlackSheep.
| Framework | Dev command | Tasks |
|---|---|---|
| Django | manage.py runserver |
migrate, makemigrations, collectstatic, check, createsuperuser |
| FastAPI, Starlette, Quart, Falcon, BlackSheep | uvicorn --reload, pointed at the app object it finds |
|
| Litestar | litestar run --reload |
|
| Flask | flask run --debug |
With Flask-Migrate: db upgrade, db migrate |
| Sanic | sanic --dev |
|
| Others (Tornado, Pyramid, Bottle, aiohttp, plain scripts) | python main.py (or app.py, server.py, run.py) — the app should read PORT |
Django, Flask, FastAPI and Litestar have their own label; every other framework in the list shows with its own name and mark, and anything else shows as Python.
Django’s createsuperuser… asks only for a user name and sets the password to password — change it in the
admin afterwards.
Across frameworks:
- Alembic:
upgrade head,revision --autogenerate,downgrade -1. - Celery: Celery worker and Celery beat switches in the site’s Settings tab, under Runs with Start.
- Package tool: uv (when there is a
uv.lock), Poetry, PDM or Pipenv — used by Install dependencies. See Python and uv.
Python data libraries
Django ORM, SQLAlchemy, SQLModel, Peewee, Tortoise ORM, Aerich, Pony ORM, Piccolo, PyPika, Alembic, Flask-Migrate and Yoyo.
Node.js and Bun
Every JavaScript or TypeScript project with a package.json and a dev script. The package manager follows the lock
file — bun.lock / bun.lockb → bun, pnpm-lock.yaml → pnpm, yarn.lock → yarn,
package-lock.json → npm — then the packageManager field, and npm otherwise. The dev command is the project’s
own dev script: bun run dev, pnpm run dev, yarn dev or npm run dev. Projects without one start with the
script their tool uses: NestJS with start:dev, Angular and Vue CLI with their serve / start script.
Frameworks, in the order DevCatz checks them:
| Framework | Recognised by | Default port |
|---|---|---|
| Nuxt | nuxt |
3000 |
| Next.js | next |
3000 |
| SvelteKit | @sveltejs/kit |
5173 |
| Astro | astro |
4321 |
| NestJS | @nestjs/core |
3000 |
| Angular | @angular/core — runs ng serve (usually the start script) |
4200 |
| TanStack Start | @tanstack/react-start or solid-start |
3000 |
| Vue | vite plus vue |
5173 |
| React | vite plus react |
5173 |
| Svelte | vite plus svelte (without SvelteKit) |
5173 |
| Vite | vite |
5173 |
| Fastify, Hono, Koa, Express | The server library (labelled in that order) | 3000 |
| Node.js | Anything else with a server |
DevCatz reads the port from the dev script, the framework’s config file (nuxt.config, vite.config…) or .env.
With Let DevCatz assign dev ports on, it hands the app a port of its own from 4100 up instead.
A few special cases:
- Electron apps —
electronindependenciesordevDependencies: electron-vite (itsdevscript), Electron Forge (itsstartscript, when there is nodev) or a plainelectron .. There is no port to wait for or to manage, and the site wears the Electron mark. An app that allows only one copy at a time (requestSingleInstanceLock) quits at once while its installed copy is open — close that one first. When Electron’s own download is missing (its install step failed or was skipped), the Overview says Electron is not fully installed and offers Repair Electron. The Docker tab makes no container Dockerfile for it: electron-builder or Electron Forge build its installers. - Tauri apps — a
tauriscript inpackage.jsonwithsrc-tauri/tauri.conf.jsonbeside it: the dev command is<pm> run tauri dev, which opens the app’s window and starts the frontend through Tauri’sbeforeDevCommand. The site wears the Tauri mark; the frontend’s port (Vite’s5173, say) stays listed in the Apps table. - Desktop apps (Electron and Tauri) are sites without a web address: see below.
- Prisma gets its own card on the Database tab:
migrate dev,db seed,generate,migrate reset…. - Workspaces (npm, yarn or bun
workspaces,pnpm-workspace.yaml): every app with adevscript becomes an app of the site. Packages without a server still run as part of the rootdevscript, but get no domain.
Desktop apps
An Electron or Tauri site is a desktop app: Start opens its window, the way npm start does in a terminal.
Because it has no web address, its page looks a little different — where other sites show their URL chip, it reads
Desktop app · opens in its own window with the framework’s mark; the sidebar says desktop app under its name;
there is no Share button and no browser entry in Open; the preview is replaced by a card, A desktop app
(Start opens its window … It has no web address, so there is nothing to preview or share here; its output is in
Logs); the Apps table shows — (its own window) where the URL would be (a Tauri frontend keeps its port); and the
site’s Settings tab has no Domain and Protocol fields. Everything else — Env, Database, Git, Logs, the
dependency checks — works as for any site. A Tauri app with no package.json is detected by the
Rust driver instead.
Node.js data libraries
Knex.js, Drizzle ORM, Sequelize, Kysely, TypeORM, MikroORM, Mongoose, Objection.js, node-pg-migrate, db-migrate, Umzug and Prisma.
Go
A folder with a go.mod. DevCatz recognises Gin, Echo, Fiber, Chi, Gorilla mux, Beego,
Iris, Buffalo, Hertz, Kratos, go-zero, GoFr and httprouter.
The dev command is the first that fits:
| When | Dev command |
|---|---|
air is declared as a Go tool (the tool directive of Go 1.24+) |
go tool air |
The project has an .air.toml |
air |
| Otherwise | go run ., or go run ./cmd/<module> when the main package lives there |
With air the server reloads on every save. The port comes from os.Getenv-style helpers in the code or a literal
port, and Build runs go build -o bin/<name>.
Go data libraries
GORM, ent, sqlc, sqlx, Bun, pgx, SQLBoiler, Squirrel and goqu, plus the migration tools goose, golang-migrate, Atlas, dbmate, sql-migrate and tern. A GORM / Go card on the Database tab runs AutoMigrate, goose and the like.
Rust
A folder with a Cargo.toml, or a src-tauri/tauri.conf.json without a package.json (with one, it is a Node.js
project — see Tauri apps above). Rust sites run on macOS and Windows; the toolchain comes from the
Rust page.
The framework is the first crate found of: anchor-lang, tauri, loco-rs, leptos, dioxus, yew, sycamore,
actix-web, axum, rocket, warp, poem, salvo, tide, tonic, hyper, bevy, burn and candle-*.
Rust web frameworks and apps
| Framework | Dev command | Port |
|---|---|---|
Anchor (Solana) — an Anchor.toml |
anchor build, then solana-test-validator with the programs deployed and the wallet funded — on Windows, Solana and Anchor run inside WSL, so install and run them there |
RPC on 8899 |
| Tauri | cargo tauri dev — a desktop app, with the frontend’s port read from tauri.conf.json (build.devUrl) |
|
| Leptos (SSR) | cargo leptos watch, with LEPTOS_SITE_ADDR set |
|
| Dioxus | dx serve |
|
| Yew, Sycamore, client-side Leptos | trunk serve |
From Trunk.toml, else 8080 |
| Loco | cargo loco start |
5150 |
| Actix Web | cargo run |
8080 |
| Axum | cargo run |
3000 |
| Rocket | cargo run |
8000 |
| Warp | cargo run |
3030 |
| Poem | cargo run |
3000 |
| Salvo | cargo run |
5800 |
| Tide | cargo run |
8080 |
| tonic (gRPC) | cargo run |
50051 |
| hyper | cargo run |
3000 |
| Burn, Candle | cargo run --release |
None |
| Bevy and command-line tools | cargo run |
None |
For servers run with cargo run, the port is read from PORT, ROCKET_PORT or a literal in the code; the table
shows the framework’s default when none is set. Sites without a port count as running once started. Plain crates
show as Rust.
In a Cargo workspace, each member with a server or a frontend becomes an app of the site. The tools these frameworks
need (Trunk, Dioxus CLI, cargo-leptos, Tauri CLI, the WebAssembly target, Solana CLI, Anchor)
can be installed from the site’s Overview or the Rust page — see Rust.
Solana and Anchor are the exception: on Windows they live in WSL, as their docs say. The Docker tab writes no
container for a Tauri app or an Anchor program; its Dockerfile says what builds them instead (cargo tauri build,
anchor deploy).
Rust data libraries
Diesel, SeaORM, SQLx, Loco (SeaORM), Rbatis, Toasty and refinery, plus the drivers rusqlite, tokio-postgres, mysql_async and mongodb.
Last updated 2026-11-01