laravel-class-obf maintained by urgorri
Laravel Class Obfuscator (laravel-class-obf)
A native Laravel package that provides build-time CSS class obfuscation and runtime Blade/PHP class translation. Reduces frontend UI code readability in production builds to discourage trivial code scraping and asset plagiarism.
- 📦 Packagist Package: packagist.org/packages/urgorri/laravel-class-obf
- 🚀 Live Playground & Demo: urgorri.github.io/laravel-class-obf
💡 What This Package Does
- Build-Time Scanning: Scans Blade templates, HTML, Vue, JS, and CSS stylesheets to discover unique CSS class names.
- Deterministic HMAC Tokenization: Hashes class names deterministically using
CLASS_OBF_SECRET(HMAC-SHA256 Base62 prefixing withc). The same class name always produces the same obfuscated token for a given project secret. - Whitelist Protection: Excludes interactive toggles, ARIA roles, and data attributes (e.g.
data-*,aria-*,is-*,has-*,active,open) using glob and regex patterns. - AST Selector Rewriting: Renames class selectors inside CSS stylesheets losslessly using PostCSS AST without breaking pseudo-classes (
:hover,:is(),:where(),:has()) or@media/@keyframesrules. - Runtime Blade & PHP Translation: Provides the
@cls(...)Blade directive andcls()/asset_obf()helper functions to translate class strings seamlessly in production while remaining zero-overhead in development mode.
📦 Installation
composer require urgorri/laravel-class-obf
Install Node tool dependencies for asset building:
cd tools && npm install
Publish configuration:
php artisan vendor:publish --tag=classobf-config
⚙️ Configuration
Set your environment variables in .env:
# Required: Project secret key for deterministic token generation
CLASS_OBF_SECRET=your_long_random_project_secret_key
# Mode: 'dev' (no obfuscation) or 'production' (obfuscates classes)
CLASS_OBF_MODE=production
# Generated token length (default: 8)
CLASS_OBF_TOKEN_LENGTH=8
Inspect or customize config/classobf.php:
return [
'secret' => env('CLASS_OBF_SECRET'),
'mode' => env('CLASS_OBF_MODE', 'dev'),
'token_length' => env('CLASS_OBF_TOKEN_LENGTH', 8),
'scan' => [
'paths' => [
resource_path(),
public_path(),
],
'extensions' => [
'.blade.php',
'.html',
'.css',
'.js',
'.vue',
],
],
'mapping_path' => storage_path('app/class-obf-mapping.json'),
'out_dir' => public_path('build-obf'),
'whitelist' => [
'/^data-.+$/',
'/^aria-.+$/',
'active', 'open', 'show', 'hidden',
'/^is-.+$/',
'/^has-.+$/',
],
];
🔧 Usage
1. In Blade Templates
Use the @cls directive to wrap your CSS class strings:
<div class="@cls('container card shadow-sm')">
<div class="@cls('card-header bg-primary text-white')">
<h3 class="@cls('title')">Dashboard</h3>
</div>
</div>
In dev mode: Renders <div class="container card shadow-sm">.
In production mode: Renders <div class="c89abcd0 c1234567 shadow-sm">.
2. In PHP Helpers & Controllers
Use the cls() helper for dynamic class expressions:
$buttonClass = cls('btn btn-primary') . ($isActive ? ' ' . cls('active') : '');
Use asset_obf() to link obfuscated CSS bundles:
<link rel="stylesheet" href="{{ asset_obf('css/app.css') }}">
🏗️ Build Command
Run the build command in your CI/CD pipeline or before deployment:
php artisan classobf:build --mode=production
This command will:
- Scan configured directories for HTML, Blade, Vue, JS, and CSS files.
- Extract all class names and filter against your whitelist.
- Generate deterministic hash tokens for mapped classes.
- Save the mapping to
storage/app/class-obf-mapping.json. - Rewrite and output obfuscated stylesheets into
public/build-obf/.
🧪 Testing
Run PHP test suite:
vendor/bin/phpunit
Run Node JS tool tests:
cd tools && npm test
📄 License
MIT License — see LICENSE.