Repository navigation
htaccess
Pair's starter project uses a root .htaccess to forward requests internally to public/, then public/.htaccess to route application URLs to index.php. These are internal rewrites, not browser redirects.
The examples below follow that two-level layout and use Apache 2.4 authorization syntax. Compare them with the starter project's root rules and public rules when adopting them in an existing application. Preserve application-specific routes and public assets.
Forwarding to public/ alone does not protect private files. Deny dotfiles, project metadata, and private directories explicitly:
Options -Indexes -MultiViews
<FilesMatch "^\.|^(composer\.(json|lock|phar)|migrate-cli\.php|migrate\.php|README\.md|cronjob\.php|routes\.php|rsync-exclude\.txt)$">
Require all denied
</FilesMatch>
RewriteEngine On
RewriteRule ^(classes|migrations|translations|vendor|widgets|tests)/ - [R=404,L]
RewriteRule ^public/ - [L]
RewriteRule ^(.*)$ public/$1 [L]The ^public/ guard prevents repeated forwarding when Apache processes the rewritten request. Add application-owned private directories to the deny rule when necessary.
Options +FollowSymLinks -Indexes -MultiViews
RewriteEngine On
# Deny dotfiles and executable/configuration files except the front controller.
<FilesMatch "^\.|^manifest\.xml$|\.(php|ini)$">
Require all denied
</FilesMatch>
<Files "index.php">
Require all granted
</Files>
# Serve existing public files and directories directly.
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^ - [L]
# Return 404 for missing assets instead of rendering an application page.
RewriteCond %{REQUEST_FILENAME} \.(css|js|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot|otf|webp|mp4|webm|ogg|mp3|wav|json|xml|map)$ [NC]
RewriteRule ^ - [R=404,L]
# Route application requests through Pair.
RewriteRule ^ index.php [L]Applications with dynamic routes ending in one of those asset extensions must add their exception before the missing-asset rule. Existing files with denied names remain protected by the authorization rules.
Older starter configurations may use Order, Allow, and Deny. Apache 2.4 provides these only through the compatibility module; use Require for new configurations and avoid mixing the two authorization styles. See the Apache 2.4 upgrade guide.
- Enable
mod_rewriteand permit the relevant directives throughAllowOverrideorAllowOverrideList. WithAllowOverride None, Apache ignores.htaccessfiles. - If
Optionsis forbidden by the hosting configuration, set the required options in the virtual host or ask the host to provide them. A forbidden directive can produce HTTP 500; inspect the Apache error log before changing rules. - Keep
FollowSymLinksor the server's permitted equivalent aligned with its rewrite policy; do not disable it blindly when diagnosing a routing error. - Keep the document root, internal rewrite layout, and Pair's request-derived
URL_PATH/BASE_HREFconsistent, particularly when hosting under a subdirectory. - Nginx does not read
.htaccess; configure equivalent routing and private-file restrictions in its server configuration.
Apache recommends putting rules in the main server configuration when you control it. See the official .htaccess tutorial for directive permissions and troubleshooting.
After applying rules to a test application:
- Open a normal application route and verify it reaches the front controller without exposing
/public/in the browser URL. - Load an existing public CSS or JavaScript file and confirm it is served directly.
- Request a missing asset and confirm HTTP 404 rather than an HTML application page.
- Confirm
/.env,/composer.json,/vendor/,/classes/, and direct PHP files other than the front controller cannot be downloaded. - Repeat the checks with the application's URL prefix if it runs in a subdirectory.
See also: index.php, Application, Configuration file.
Maintained by Viames Marino — VM Ingegneria · Professional enquiries
Home · Setup · Configuration
Build with Pair 4
- Generator
- Controllers and responses
- Read models
- ActiveRecord and queries
- Forms and validation
- PairUI.js and HTML fragments
APIs and authentication
- API guide and CRUD
- Middleware and rate limits
- Users, sessions, and ACL
- Passkeys and social login
- Native mobile setup
Integrate and operate
- Integrations
- Runtime extensions and adapter keys
- Cache and cache stores
- Logs and observability
- PWA and push
- Packages and distribution
- Upgrade to v4