{"id":37232811,"url":"https://github.com/b7s/lara-ink","last_synced_at":"2026-01-15T03:50:59.764Z","repository":{"id":322248702,"uuid":"1087531307","full_name":"b7s/lara-ink","owner":"b7s","description":"✒️ LaraInk - Turn your Blade files into a standalone reactive SPA with Alpine.js, powered by Laravel REST API + Bearer Token.","archived":false,"fork":false,"pushed_at":"2025-11-20T19:59:33.000Z","size":363,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-11-20T21:19:25.978Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/b7s.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"docs/security-hardening.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-11-01T05:12:49.000Z","updated_at":"2025-11-20T19:59:30.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/b7s/lara-ink","commit_stats":null,"previous_names":["b7s/lara-ink"],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/b7s/lara-ink","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/b7s%2Flara-ink","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/b7s%2Flara-ink/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/b7s%2Flara-ink/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/b7s%2Flara-ink/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/b7s","download_url":"https://codeload.github.com/b7s/lara-ink/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/b7s%2Flara-ink/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28419256,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-14T10:47:48.104Z","status":"ssl_error","status_checked_at":"2026-01-14T10:46:19.031Z","response_time":107,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-01-15T03:50:59.047Z","updated_at":"2026-01-15T03:50:59.751Z","avatar_url":"https://github.com/b7s.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cdiv style=\"text-align: center;\" align=\"center\"\u003e\n    \u003cimg src=\"docs/art/logo.webp\" width=\"256\" alt=\"[LaraInk]\"\u003e\n    \u003ch1\u003eLaraInk\u003c/h1\u003e\n\u003c/div\u003e\n\n[![PHP Version](https://img.shields.io/badge/PHP-%3E%3D8.3-blue)](https://php.net)\n[![Laravel Version](https://img.shields.io/badge/Laravel-%3E%3D11.0-red)](https://laravel.com)\n[![License](https://img.shields.io/badge/License-MIT-green)](LICENSE)\n\n---\n\n**Laravel Blade + Alpine.js = static to reactive SPAs in seconds.**\n\nA powerful DSL compiler that transforms Blade-like files into an independent SPA with [Alpine.js](https://alpinejs.dev), communicating with Laravel via REST API using Bearer Token authentication\n\n---\n\n## ✨ Features\n\n- 🚀 **Blade-to-Alpine.js Compiler** - Write familiar Blade syntax, get reactive Alpine.js components\n- 📦 **Independent SPA** - Deploy your frontend anywhere (CDN, Netlify, Vercel, S3)\n- 🔐 **Bearer Token Auth** - Secure API communication with Laravel Sanctum\n- ⚡ **Smart Caching** - Page-level caching with configurable TTL\n- 🎯 **Dynamic Routing** - File-based routing with parameter support\n- 🌍 **i18n Ready** - Built-in translation system\n- 🎨 **Layout System** - Reusable layouts with nested folder support\n- 📱 **SPA Router** - Client-side navigation with prefetching\n- 🔧 **PHP Variables** - Define variables in PHP blocks, auto-converted to Alpine.js reactive data\n- 🛡️ **Type Safety** - Automatic type detection and validation for variables (string, int, float, bool, array, Collection, Eloquent)\n- 🧪 **With a lot of tests**\n\n---\n\n## 📦 Installation\n\n```bash\ncomposer require b7s/lara-ink\n```\n\nRun the install command:\n\n```bash\nphp artisan lara-ink:install\n```\n\nThe package will automatically:\n- Create required directories (`resources/lara-ink/`, `public/build/`, etc.)\n- Publish configuration file to `config/lara-ink.php`\n- Set up default layout\n- Set up Vite plugin to project root\n\n---\n\n## 🚀 Quick Start\n\n### 1. Create Your First Page\n\nCreate `resources/lara-ink/pages/index.php`:\n\n```php\n\u003c?php\nink_make()\n    -\u003etitle(__('app.welcome'))\n    -\u003elayout('app')\n    -\u003eauth(true)\n    -\u003emiddleware(['auth', 'role:admin'])\n    -\u003ecache(now()-\u003eaddMinutes(10));\n\n$users = User::all()-\u003etoArray();\n/*\n// It returns something like this:\n[\n    ['id' =\u003e 1, 'name' =\u003e 'John Doe'],\n    ['id' =\u003e 2, 'name' =\u003e 'Max Mustermann'],\n];*/\n?\u003e\n\n\u003cdiv\u003e\n    \u003ch1\u003e{{ __('app.welcome_message', ['name' =\u003e auth()-\u003euser()-\u003ename]) }}\u003c/h1\u003e\n\n    @foreach($users as $user)\n        \u003cp\u003e\n            \u003ca href=\"{{ ink_route('see-user', $user['id']) }}\"\u003e\n                {{ $user['name'] }}\n            \u003c/a\u003e\n        \u003c/p\u003e\n    @endforeach\n\u003c/div\u003e\n```\n\n### 2. Build Your SPA\n\n```bash\nphp artisan lara-ink:build\n```\n\n### 3. Access Your App\n\nOpen `http://your-app.test/` in your browser!\n\nIf you are running inside Laravel, create a route to serve the index page:\n\n```php\nRoute::get('/{path?}', function () {\n    require ink_path('index.html');\n})-\u003ewhere('path', '.*');\n```\n\n---\n\n## 🔥 Hot Reload Development\n\nLaraInk offers two ways to enable hot reload during development:\n\n### Option 1: Native Dev Command (for quick start)\n\n```bash\nphp artisan lara-ink:dev\n```\n\nThis will:\n- ✅ Watch for changes in `resources/lara-ink/**`\n- ✅ Auto-rebuild when files change\n- ✅ Show build status in terminal\n- ✅ No Node.js required\n\n### Option 2: Vite Integration (Recommended - Full Browser Hot Reload)\n\nFor automatic browser refresh, integrate with Vite:\n\n**1. Install Vite (if not already installed):**\n\n```bash\nnpm install -D vite laravel-vite-plugin\n```\n\n**2. The Vite plugin is automatically copied to your project root during `composer install`. Just import it in `vite.config.js`:**\n\n```javascript\nimport { defineConfig } from 'vite';\n\n// Add this lines if not already added\nimport laravel from 'laravel-vite-plugin';\nimport laraInkPlugin from './vite-plugin-lara-ink.js';\n\nexport default defineConfig({\n    plugins: [\n        // Add laravel plugin if not already added\n        laravel({\n            input: ['resources/css/app.css', 'resources/js/app.js'],\n            refresh: true,\n        }),\n        \n        // Add LaraInk Hot Reload - No configuration needed!\n        laraInkPlugin(),\n    ],\n});\n```\n\n**3. Start Vite dev server:**\n\n```bash\nnpm run dev\n```\n\nThe plugin will:\n- ✅ Build all pages on startup (if not already built)\n- ✅ Watch for changes in `resources/lara-ink/`\n- ✅ Rebuild only affected pages when you save\n- ✅ Automatically reload your browser\n\n**Smart Compilation:**\n- **Page changed** → Rebuilds only that page\n- **Layout changed** → Rebuilds all pages using that layout\n- **Component changed** → Rebuilds all pages using that component\n\n**Custom Configuration (Optional):**\n\n```javascript\nlaraInkPlugin({\n    watchPaths: ['resources/lara-ink/**'],\n    buildCommand: 'php artisan lara-ink:build',\n    debounce: 1000  // milliseconds\n})\n```\n\n---\n\n## 📖 Documentation\n\n- [Overview](docs/README.md)\n- [Getting Started](docs/getting-started.md)\n- [Pages](docs/pages.md)\n- [Components](docs/components.md)\n- [Layouts](docs/layouts.md)\n- [Alpine.js Integration](docs/alpine.md)\n- [Middleware](docs/middleware.md)\n- [Development Workflow](docs/development.md)\n- [Tailwind CSS](docs/tailwind-css.md)\n- [Security Hardening](docs/security-hardening.md)\n\n---\n\n## 🎯 Example: Dynamic Page with API\n\n```php\n\u003c?php\nink_make()\n    -\u003etitle('User Profile')\n    -\u003eauth(true)\n    -\u003ecache(600);\n?\u003e\n\n\u003cdiv x-data=\"profile()\"\u003e\n    \u003ch1\u003eProfile: \u003cspan x-text=\"user.name\"\u003e\u003c/span\u003e\u003c/h1\u003e\n    \n    @foreach($posts as $post)\n        \u003carticle\u003e\n            \u003ch2\u003e{{ $post-\u003etitle }}\u003c/h2\u003e\n            \u003cp\u003e{{ $post-\u003eexcerpt }}\u003c/p\u003e\n        \u003c/article\u003e\n    @endforeach\n    \n    \u003cbutton @click=\"loadMore()\"\u003eLoad More\u003c/button\u003e\n\u003c/div\u003e\n\n\u003cscript\u003e\nfunction profile() {\n    return {\n        user: {},\n        posts: [],\n        \n        async init() {\n            const response = await lara_ink.newReq('/api/profile');\n            const data = await response.json();\n            this.user = data.user;\n            this.posts = data.posts;\n        },\n        \n        async loadMore() {\n            const response = await lara_ink.newReq('/api/posts?page=2');\n            const data = await response.json();\n            this.posts.push(...data.posts);\n        }\n    }\n}\n\u003c/script\u003e\n```\n\n### 🔐 Example: Protected Page with Middleware\n\n```php\n\u003c?php\nink_make()\n    -\u003etitle('Admin Dashboard')\n    -\u003emiddleware(['auth', 'verified', 'role:admin'])\n    -\u003ecache(false);\n?\u003e\n\n\u003cdiv x-data=\"adminDashboard()\"\u003e\n    \u003ch1\u003eAdmin Dashboard\u003c/h1\u003e\n    \n    \u003cdiv class=\"stats-grid\"\u003e\n        \u003cdiv class=\"stat-card\"\u003e\n            \u003ch3\u003eTotal Users\u003c/h3\u003e\n            \u003cp x-text=\"stats.users\"\u003e\u003c/p\u003e\n        \u003c/div\u003e\n        \u003cdiv class=\"stat-card\"\u003e\n            \u003ch3\u003eActive Sessions\u003c/h3\u003e\n            \u003cp x-text=\"stats.sessions\"\u003e\u003c/p\u003e\n        \u003c/div\u003e\n    \u003c/div\u003e\n\u003c/div\u003e\n\n\u003cscript\u003e\nfunction adminDashboard() {\n    return {\n        stats: {},\n        \n        async init() {\n            const response = await lara_ink.newReq('/api/admin/stats');\n            const data = await response.json();\n            this.stats = data;\n        }\n    }\n}\n\u003c/script\u003e\n```\n\n---\n\n## 🔧 Configuration\n\nEdit `config/lara-ink.php`:\n\n---\n\n## 🧪 Testing\n\n```bash\n# Run all tests\ncomposer test\n\n# Run specific test group\n./vendor/bin/pest --group=unit\n```\n\n---\n\n## 🤝 Contributing\n\nContributions are welcome! Please feel free to submit a Pull Request.\n\n---\n\n## 📄 License\n\nThe MIT License (MIT). Please see [License File](LICENSE) for more information.\n\n---\n\n## 🙏 Credits\n\n- **Author**: Bruno Tenorio\n- **Email**: b7s@outlook.com\n- Built with ❤️ using [Laravel](https://laravel.com) and [Alpine.js](https://alpinejs.dev)\n\n---\n\n## 🔗 Links\n\n- [Documentation](docs/)\n- [Issues](https://github.com/b7s/lara-ink/issues)\n- [Changelog](CHANGELOG.md)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fb7s%2Flara-ink","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fb7s%2Flara-ink","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fb7s%2Flara-ink/lists"}