Get FrankPHP Running
By the end of this guide you’ll have FrankPHP installed on a subdomain, configured with a standard.env file, be logged in as a real user, and have built your first protected page. That’s enough to know the framework is working and to get a feel for how it thinks.
Your host needs PHP 8.x and MySQL. Nothing else. No Composer, no Node, no build tools.
Step 1: Create your MySQL database
Log in to your hosting control panel and create a new, empty MySQL database. Most shared hosts do this through phpMyAdmin or a dedicated “MySQL Databases” section (cPanel, Plesk, etc.). Note down the following — you’ll need them in the next step:- Database name
- Database username
- Database password
- Host (almost always
localhoston shared hosting)
Step 2: Configure FrankPHP locally with .env
Download the latest release from FrankPHP’s GitHub Releases page — grab the Source code zip (or git clone the repo directly). Either way you’ll get a single project folder containing both framework/ and app/ as siblings — a complete working starting point.
FrankPHP uses a standard .env file for environment-specific credentials. This keeps secrets out of your main config structure and makes FrankPHP feel more familiar if you’ve used other PHP frameworks before.
Copy app/env.example to app/.env. The example file documents every key the application supports — including mail credentials needed for password reset — so it’s the safer starting point than creating one from scratch.
Open app/.env and add your database credentials and core app settings:
The
.env file is for environment-specific settings only. Keep framework defaults and non-sensitive application settings in the normal config structure (app/Config/config.php). Use .env for things like database credentials, mail credentials, and other secrets.Step 3: Set up your directory structure on the server
Connect to your hosting account via FTP and navigate to your root directory. Create a project folder — name it whatever makes sense for what you’re building (your product’s own name, or just/frankphp). This guide uses /yourproject.
/www and /docs are optional and outside the scope of this guide — they’re here to show how a typical FrankPHP-based project organizes a hosting account. What matters right now is creating /yourproject.Some FrankPHP-based products also add a
/platform folder — a super-user layer that sits above individual tenant admins. This is a newer, still-emerging pattern and not yet part of the core framework release. Mention it here only if it’s relevant to what you’re building; most projects won’t need it yet.Step 4: Upload FrankPHP into your project directory
Upload the entire contents of your downloaded FrankPHP folder into/yourproject. You should end up with two sibling folders inside it:
app/bootstrap.php and framework/bootstrap.php should each sit at the root of their own folder, not inside a subfolder. Your .env file should sit at app/.env.
Step 5: Point your subdomain to the public folder
This is the most important configuration step, and it’s worth understanding why. FrankPHP’s web root isapp/public/ — a subdirectory inside app/, itself a subdirectory of /yourproject. This is the only folder your subdomain should point to. Your hosting control panel will have a setting for “Document Root” or “Web Root” when you create the subdomain — set it to:
app.yoursite.com to /yourproject/app/public.
Step 6: Let FrankPHP initialise the database
Nothing to do here by hand. The first time you visit the site, FrankPHP checks whether its core tables exist and, if not, creates them automatically fromframework/sql/schema.core.sql and seeds two starter accounts so you can log in immediately.
If you’d rather review the schema before your first visit, you can still import
framework/sql/schema.core.sql manually through phpMyAdmin’s Import tab, or by pasting its contents into the SQL command window. This is entirely optional — FrankPHP creates it automatically either way.Step 7: Open FrankPHP in your browser
Navigate tohttps://app.yoursite.com in your browser.
You should see the FrankPHP login screen.
If you see a login form, FrankPHP is installed correctly. Everything worked.
.envhas incorrect database credentials- The subdomain is pointing to
/yourproject/appinstead of/yourproject/app/public - Your database user doesn’t have permission to create tables (needed for the automatic first-boot schema setup)
- File permissions — your host may require folders to be
755and files644
Step 8: Log in
The schema seeds two accounts inside Tenant 1 — one owner-level, one standard user:
Log in with the owner account. After login you’ll land on the default dashboard at:
Step 9: Build your first page
FrankPHP is running. Now let’s prove it properly by building something — a simple protected page that only a logged-in user can see. This touches every layer of the framework in the most straightforward way possible.9a. Register the route
Openapp/bootstrap.php and find the route definitions. Add one new line inside the existing authenticated routes block:
HelloController@index, and run the Tenant and Auth middleware first.
9b. Create the controller
Create a new file:app/Controllers/HelloController.php
9c. Create the view
Create a new file:app/Views/hello/index.php
9d. Upload and visit
Upload just the two new files via FTP — no need to re-upload the whole framework. Then visit:If you can see the page, you’ve just built your first FrankPHP feature. The route, middleware, controller, and view are all working together correctly.
What just happened
It’s worth pausing to understand what FrankPHP did when you visited that URL:app/public/index.phploadedframework/bootstrap.php, which immediately calledEnv::load()to readapp/.envinto$_ENVbefore anything else ran- The database connection was established using credentials from
$_ENV, framework container bindings and framework routes were registered, thenframework/bootstrap.phphard-requiredapp/bootstrap.phpas its final step to register your application’s own routes and bindings — returning the router - The router dispatched the request, matched
/tenant/1/hello, and identified your controller - TenantMiddleware ran first — it read
1from the URL, loaded the tenant from the database, and attached it to the request - AuthMiddleware ran second — it checked your session, loaded your user, confirmed they belong to tenant 1, and attached them to the request
HelloController@indexreceived the request with$request->tenantand$request->useralready populated- The view rendered inside
app-main.php, the authenticated layout
Why .env is worth using
Moving credentials into .env gives FrankPHP a cleaner separation between code and secrets.
It also brings three practical benefits:
- Better security — credentials live outside the public web root and outside your main config file
- Cleaner deployments — each environment can have its own
.envwithout editing framework code - More familiar workflow — developers coming from Laravel, Symfony, and other PHP frameworks will immediately understand the pattern
Next steps
- Add a form — learn how to handle POST requests and save data to the database
- Understand middleware — see the full middleware cheatsheet and when to use each combination
- Start your application — work through Working with MYAPP.md to record your app’s name, tables, and routes as you build
- Configure version management — use the release tooling to track versions, changes, and packaged framework-only updates