Getting started with Basehim development
Basehim is an open-source PHP CMS with a REST API and a built-in MCP server for AI agents. It runs on ordinary shared hosting: no Composer, no build step, no daemon. This page is the map for developers. It tells you which part of Basehim to work in, and where to read next.
Three ways to build on Basehim
| You want to… | Build a… | Lives in | Start with |
|---|---|---|---|
| Change how the public site looks | Theme | content/themes/{slug}/ | Theme development |
| Add features, screens, data or integrations | App | content/apps/{slug}/ | App development |
| Use Basehim from another program or an AI agent | API client | anywhere | REST API guide, MCP and AI agents |
The split is deliberate:
- A theme is presentation only. It can't register routes or create database tables. It can register filters, for example to adjust SEO tags.
- An app is PHP that runs on every request. It can do almost anything core can.
- An API client never touches the PHP at all.
If a theme needs behaviour, ship a small app next to it.
Run it locally in five minutes
You need PHP 8.1 or newer with pdo_mysql, and a MySQL 5.7+ or MariaDB 10.3+ database.
git clone https://github.com/basehim/basehim.git
cd basehim
php -S localhost:8000 server.php
Open http://localhost:8000. You'll be sent to the installer, which asks for your database details and creates the admin account. If you don't have a database handy, one container is enough:
docker run -d --name basehim-db -p 3306:3306 \
-e MARIADB_ROOT_PASSWORD=secret -e MARIADB_DATABASE=basehim mariadb:11
# installer: host 127.0.0.1, database basehim, user root, password secret
Note:
server.phpis the router for PHP's built-in server, for local work only. On a real host, Apache uses the bundled.htaccessandserver.phpanswers 404. See Installation.
While you develop, set APP_DEBUG=true in .env. Errors then show the file and line instead of a generic page. Turn it off again on a live site.
Where things live
basehim/
├── index.php front controller: every request starts here
├── bootstrap.php autoloader, .env, session, global helpers, boots the app
├── install.php web installer (locks itself when done)
├── server.php router for `php -S` (local only)
├── .env your settings and secrets (never commit it)
├── app/
│ ├── Core/ router, container, hooks, database, App base class
│ ├── Http/ controllers (Web, Admin, Api, Ajax) and middleware
│ ├── Services/ business logic: posts, media, users, SEO, scheduler…
│ └── Repositories/ data access
├── config/ app, database, auth, capabilities, ajax
├── routes/ ajax.php, api.php, admin.php, web.php
├── database/migrations/ numbered .sql files
├── admin/ the admin panel's views and assets
├── content/
│ ├── apps/ installed apps (one folder each)
│ └── themes/ installed themes (one folder each)
└── storage/ uploads, cache, sessions, logs (must be writable)
As a theme or app developer you only write inside content/. Everything else is core, and updates replace it.
How a request flows
index.phpworks out the install's base path, so subfolder installs work. If.envis missing it redirects to the installer.bootstrap.phpregisters the autoloader, reads.envand starts the session. It then callsApplication::boot(), which:- builds the service container and the hook registry;
- boots every active app, calling each app's
boot(); - runs the active theme's
boot.php.
- Routes are loaded in this order:
routes/ajax.php,api.php,admin.php,web.php. Apps added their own routes duringboot(), before any of these. - The router dispatches to a controller. A public page ends in
ThemeService::render(), which runs your theme's template with the page's data. - The response is sent. Core then adds the SEO tags to the finished page. After that, the scheduler may run due background tasks while the visitor is already reading.
Two things follow from this:
boot()runs on every request, so keep it cheap.- Hooks registered in
boot()are in place before any content renders.
The extension toolkit at a glance
- Hooks.
addAction()andaddFilter()let apps react to events (post.created,user.deleted…) and change values (post.content,seo.title…). See Hooks and filters. - The App API.
$this->api()gives an app posts, pages, media, users, comments, terms, menus, cache, mail, outbound HTTP and scheduling, all in-process. See The App API. - AJAX actions. One endpoint,
POST /ajax, with CSRF, capability, rate-limit and input checks done for you. See AJAX actions. - REST API.
/api/v1, using API keys or JWT. See REST API guide. - MCP.
/mcp, used by AI assistants over OAuth 2.1 or with an API key. Apps can add their own tools. See MCP and AI agents.
Your first hour
- Install locally (above) and sign in at
/admin. - Follow Build your first app to see the app lifecycle, an admin screen and front-end output.
- Follow Build a theme from scratch to see templates, partials and Customizer options.
- Create an API key under API → Keys and try the calls in the REST API guide.
Getting help
- Search these docs, or browse all tutorials.
- The source is on GitHub. Its
docs/folder has the reference notes these guides grew from, andcontent/themes/defaultis a small theme worth reading. - Found a security problem? Don't open a public issue. Follow
SECURITY.mdin the repository.
Leave a comment