Developer docs
Start
Build with AI
Themes
Apps
- App development
- App development best practices
- Hooks and filters
- The App API
- Sending email from apps
- Admin bar for apps and themes
- Public routes for apps
- Admin screens, routes and UI components
- Dashboard widgets
- Data tables
- AJAX actions
- Media and uploads for apps
- App permissions
- Content types, blocks and widgets
- Content types, taxonomies and custom fields
- Search
- When an app fails: fault isolation and recovery
API and AI agents
Security and contributing
Configuration and the .env file
Basehim keeps install-specific settings and secrets in a .env file at the site root. The installer writes it for you. Everything else (site title, timezone, permalinks, SEO, mail) is set in the admin under Settings and stored in the database. This page lists every key Basehim reads from .env.
How .env works
- Plain
KEY=valuelines. Quote values that contain spaces:APP_NAME="My Site". trueandfalseare read as booleans..envis denied to browsers by the bundled.htaccess. Never commit it, and never put it in a public folder on nginx (see Installation).- Changes take effect on the next request. There is nothing to restart.
.env.example in the repository is a template with the common keys.
Application
| Key | Default | What it does |
|---|---|---|
APP_NAME | Basehim | Informational; the site title is set in Settings → General |
APP_ENV | production | Informational; use production on live sites |
APP_DEBUG | false | true shows errors with file and line. Development only: it can reveal paths and SQL |
APP_URL | http://localhost | The site's canonical address, e.g. https://example.com. Used for absolute links, mail, the JWT issuer and trusted origins |
APP_KEY | (generated) | Secret for signing internal values. At least 16 characters |
APP_TIMEZONE | UTC | Fallback only. The site timezone is set in Settings → General |
APP_LOCALE | en | Informational |
INSTALLED | true after install | Locks the installer. Don't remove it from a live site |
Database
| Key | Default | What it does |
|---|---|---|
DB_HOST | 127.0.0.1 | Database server |
DB_PORT | 3306 | Port |
DB_SOCKET | (none) | Unix socket, instead of host and port |
DB_DATABASE | basehim | Database name |
DB_USERNAME, DB_PASSWORD | root, empty | Credentials |
DB_CHARSET, DB_COLLATION | utf8mb4, utf8mb4_unicode_ci | Leave as they are |
DB_PREFIX | random, chosen by the installer | Prefix for every table, including app tables, so several sites can share one database. Since 1.2.70 the installer picks a random three-character prefix (e.g. k1y_) that no table in the database uses yet. To choose your own, set it in .env before installing. Never change it later |
Security and tokens
| Key | Default | What it does |
|---|---|---|
JWT_SECRET | (generated) | Signs API access tokens (JWT, HS256). Use 32+ random bytes. Changing it signs everyone out of the API |
CORS_ALLOWED_ORIGINS | empty | Comma-separated origins (e.g. https://app.example.com) allowed to call the API from a browser. They are also accepted as same-site by the AJAX gateway |
TRUSTED_PROXIES | empty | Comma-separated IPs or CIDR ranges whose X-Forwarded-For is believed. Set this behind Cloudflare or a load balancer; otherwise the AJAX gateway counts every visitor as the proxy's address for its rate limits |
HTTP_TLS_VERIFY | true | false turns off certificate checks for outgoing requests. A last resort for broken hosts, and only for a short time |
Generate secrets with PHP:
php -r "echo 'APP_KEY=' . bin2hex(random_bytes(16)) . PHP_EOL;"
php -r "echo 'JWT_SECRET=' . bin2hex(random_bytes(32)) . PHP_EOL;"
Note: If
.envever leaks, rotate the database password,APP_KEYandJWT_SECRETtogether, and revoke API keys under API → Keys.
AJAX gateway
These tune POST /ajax, which the admin and apps use (see AJAX actions).
| Key | Default | What it does |
|---|---|---|
AJAX_MAX_BODY | 65536 | Largest request body in bytes. One action can set its own, up to 1 MB |
AJAX_RATE_LIMIT | 300 | Requests per minute per client address, across all actions |
AJAX_RATE_LIMIT_FAIL | open | If the rate-limit store is down: open lets requests through, closed answers 503 |
Apps
Both are optional. They tune how Basehim checks apps before loading them (see When an app fails).
| Key | Default | What it does |
|---|---|---|
PHP_CLI_BINARY | found automatically | Path to the PHP command line, e.g. /opt/cpanel/ea-php83/root/usr/bin/php. Basehim uses it to test-load an app in a separate process. It must be the same PHP version as the site. Set it only if the app report says the isolated load test could not run |
APP_HEALTH_DIR | storage/app-health | Where reports about apps that failed are kept. The test suite points it at a temporary folder; sites leave it alone |
Updates
| Key | Default | What it does |
|---|---|---|
UPDATE_HUB_URL | https://www.cloudhim.com | Where the site checks for core, app and theme updates. Only change it if you run your own hub |
Site defaults
SITE_TITLE, SITE_TAGLINE and ADMIN_EMAIL seed the first values at install time. After that, the values in Settings are what count.
Reading configuration in code
Apps read config files with $this->config('app.url') (dot notation over the files in config/). They should not read .env directly. The static scanner flags direct .env reads in apps, and the site owner sees the warning on the Apps screen.
$siteUrl = $this->config('app.url'); // from APP_URL
$debug = (bool) $this->config('app.debug'); // from APP_DEBUG
Site settings (the ones edited under Settings) come from the settings service. A theme uses bh_setting($group, $key, $default), for example bh_setting('general', 'timezone', 'UTC').
Leave a comment