Documentation
How to use Oash Mini-PHP
Read this once. Then copy the pattern for every page. PHP 8+, no Composer, no database. New to the web? Start with Aim, Vision, and client–server diagrams. Need a human? contact@oashsocial.in.
The flow (always this order)
- Config — identity and menu in
app/config.php. - Route —
caseinapp/routes.phpfor the URL path. - Page — body HTML in
app/views/pages/…php. - Render —
index.phpasks the route, View wraps the page in the layout. - SEO — pass
titleanddescriptionfrom the route; the layout prints tags. - Sitemap — add the path to
app/data/sitemap.php, then generate. - Broken links — crawl the site and fix anything that 404s.
1. Config — app/config.php
This file is the site. Set name, tagline, site_url (live domain, no trailing slash), email, github, upi_id, and nav.
debug => trueon your laptop.falseon the live server.site_urlis used for canonical URLs, Open Graph, and the sitemap generator.- Nav items become the Laravel-style header. Nested
itemsare dropdowns.
Do not put secrets in config if the file is public on GitHub. Mailbox passwords belong in includes/mail-config.php and should stay off the repo if they are real.
2. Route — app/routes.php
The first URL segment is $seg[0]. Home is an empty string. Extra segments you do not handle must return not_found() so /about/hacker is a 404.
case 'about':
if (count($seg) > 1) {
return not_found();
}
return page('about', [
'title' => 'About us',
'description' => 'Who we are — one sentence for Google.',
]);
That page('about', …) name is the file app/views/pages/about.php. Arrays you pass become variables in the view ($title, $description).
Never header('Location: about.php'). Never link to about.php. Use url('about').
3. Page — content only
Create app/views/pages/services.php. Write the <h1> and sections. Do not paste the header or footer. Those live in partials.
Always:
e($text)for anything that came from a human or a data file.url('contact')for internal pages.asset('images/hero.jpg')for files inassets/.
Optional menu: add the path under nav in config so it appears in the header and footer can link it too.
4. Render — what the engine does
A request hits index.php (Apache rewrite or router.php locally). App reads the path, calls your route function, then View::render:
- Load the page view into a string.
- Load
layouts/main.php. - Print
$contentbetween header and footer.
You do not call the layout yourself. If the view file is missing, you get an error locally (debug) or a short 500 on live.
Real files still win: /assets/css/style.css and /includes/send-form.php are not routes. Do not name a route assets or includes.
5. SEO setup
Every route should pass a unique title and description. The layout then emits:
<title>and meta description- canonical URL from
site_url+ current path - Open Graph / Twitter tags
- JSON-LD for the framework (SoftwareApplication)
- keywords from config (keep them honest: mini framework php, static framework php)
404 pages should set 'robots' => 'noindex' if you pass it; the default is index, follow.
After go-live, Search Console should fetch /sitemap.xml and /robots.txt. llms.txt is a short map for AI crawlers.
6. Sitemap — and auto-generate
Do not hand-edit sitemap.xml if you can avoid it. The list of public pages lives in app/data/sitemap.php.
- Add a row: path, changefreq, priority, title.
- Set
site_urlin config to the live domain. - Run:
php tools/generate-sitemap.php
That command writes sitemap.xml, updates the Sitemap: line in robots.txt, and refreshes the page list in llms.txt. Run it whenever you add or remove a public URL.
robots.txt already allows /, /assets/, sitemap and llms, and disallows /app/, /core/, /includes/.
7. Broken links — find and fix
Broken internal links are usually a typo in url('…'), a missing route, or a sitemap path you never routed. After the local server is running:
php -S localhost:8000 router.php
php tools/check-links.php http://localhost:8000
The checker starts from every sitemap URL, follows internal hrefs, and prints anything that is not a 2xx/3xx. Fix by:
- adding the missing
caseand page file, or - correcting the
url()in the view, or - removing the dead link.
Also click every new nav item once. Trailing slashes are fine (/about/ = /about). /about.php must 404. Extra segments must 404.
Install
git clone https://github.com/codingtodecoding/oash-mini-php.git
cd oash-mini-php
php -S localhost:8000 router.php
Open http://localhost:8000. On Apache, upload the folder. .htaccess rewrites internally to index.php.
Do not edit core/, index.php, router.php, or .htaccess unless you are changing the engine. Work in app/ and assets/.
Lists without a database: arrays in app/data/, load with data('name'), unknown slugs → not_found().
Email (contact form)
The page URL stays clean (/contact). The browser posts JSON to includes/send-form.php — a real file, not a route. Recipients, From address, and the live site link are in includes/mail-config.php. Mail is sent as a plain-text template that includes https://mini.oashsocial.in. This project inbox is contact@oashsocial.in. Include the honeypot partial. Hosting must allow PHP mail().
Logs
There is no application log database. Use the host:
debug => truelocally shows PHP errors in the browser.- On live,
debug => false. Failures become a short 500 message. - Read Apache/Nginx/PHP error logs on the server for the stack trace.
- Form failures return JSON to the page; they are not stored in Oash.
If you need an audit trail, append a line to a file outside the web root. Do not put logs in assets/.
Hosting
Any PHP 8 shared host with mod_rewrite. Upload, confirm AllowOverride All, set debug false, set mail, set site_url, run the sitemap generator. That is the deploy.
Security short version: no SQL, escaped views, private app/ and core/, honeypot on forms. Full notes on Security.