Three things shipped this week, same move: the core leaves a seam, the host or a paid add-on fills it. - admin monetization slots a billing add-on takes over - an SEO kit for an Inertia SPA, no SSR daemon - a dismissible onboarding checklist open, under Pest. #larafoundry
Dmitry Isaenko
@dmitry-isaenko.bsky.social
Full-Stack Developer | Laravel & Vue.js | Building LaraFoundry.com - a modular SaaS engine battle-tested with Kohana.io (next-gen CRM/ERP) | Sharing architecture, code & lessons learned
I built Krokq: a light task tracker and chat under one shell, with a built-in AI assistant. The chat feels like the messengers you already use, nothing to learn. Create a task by voice, or turn a chat message into one in a click. Installs as an app, 10 languages, free. #BuildInPublic #larafoundry
Shipped AGENTS.md and CLAUDE.md inside the composer package, so a coding agent understands my Laravel engine the moment you require it. The rules ride next to the code: never edit the host, fail closed, config over hardcoded lists. A fresh chat reads them instead of guessing. #larafoundry #AI
Built a whole warehouse module on Kohana and the engine under it didn't change by one line. Products, stock, attributes, an importer, all my domain. A record goes company-private the moment I add use BelongsToTenant. The rest was already there. #larafoundry #BuildInPublic #Kohana
The real test of a reusable core isn't the app you built it for. I dropped my Laravel SaaS core into a second product (Comentor app - real users, a mobile API, a year-old DB). The seams fought back: package migrations failed on MySQL while SQLite tests stayed green and hid it. #larafoundry #Comentor
Building a reusable SaaS core and a real host app at the same time. The host's quiet bugs (a scaffold shadowing a core contract, a prop wrapped in data) keep pushing fixes back into the core: config-driven OAuth, per-user dates, a killed testbench trap. #larafoundry
Adding a second country to a CRM usually means if-country checks everywhere. My fix: a Country Profile per country - tax fields, banking, carriers, messengers, currency. Turn one on, the user picks what they use. Core stays neutral, host tightens it. #larafoundry #Laravel
Kohana is a CRM I built. I pulled its foundations into a Laravel package. Now I'm rebuilding Kohana on top of that package, and that is the whole point. #Kohana #LaraFoundry
I built a CRM, pulled its core into a Laravel package, then rebuilt the CRM on that package, the real test before it ships. Day one: a full SaaS shell. Then profile saves dropped every field but name and email, a scaffolded Fortify action had shadowed my package's. #larafoundry #Laravel
Most apps hardcode the "admin account under attack" alert to one channel, token in the code. In LaraFoundry it's an event. The core fires one signal for a failed admin password, OTP or PIN and ships email. Any other channel is a host listener. Zero core changes. 774 Pest tests. #larafoundry
In LaraFoundry, the right to access and the right to be forgotten are the same shape: every module registers one exporter and one purger, and the flows never learn the modules. Erasure is a reversible soft-delete plus an idempotent cron, not a hard DELETE. Built in public. #larafoundry #Laravel
I let the super-admin edit email templates straight from the database. The renderer never touches Blade or eval, just a single-pass {{token}} replace, so a stored template cannot execute code. No SSTI, no RCE by construction. New in LaraFoundry, built in public. #larafoundry #Laravel
I shipped a support desk for LaraFoundry by deleting a dependency. The core used to lean on a third-party ticket package. Wrong for a reusable core, so I cut it and wrote the model myself. Less code, the status is derived from who replied, not a dropdown you forget to set. #larafoundry #Laravel
You probably don't need WebSockets for in-app notifications. A full notification centre in LaraFoundry: a bell, a paginated inbox, super-admin broadcasts. No Redis, no daemon, just polling and a database queue. Broadcasts queue and fan out in chunks, idempotent on retry. #larafoundry #Laravel
Building a big project solo, I almost wasted weeks on the most "professional" thing: writing the giant upfront doc. Every route, method, test, rule. One map so nothing collides. That is Big Design Up Front. Teams dropped it on purpose. Here is what they do instead.
Added QR cross-device login to the LaraFoundry core. Pulled it from a production app. It worked, and it had 11 security holes. Plaintext token in the DB. A scanner that fetched any decoded URL. Session fixation. No rate limit. Closed all 11 before merge. v0.13.0. #Laravel #BuildInPublic
tagged v0.10.0 of LaraFoundry: the admin companies console. second screen of the operator panel. headline feature: an operator can suspend a whole tenant now. the hard part wasn't blocking it. it was not locking out members who belong to OTHER companies 👇
tagged v0.9.0 of LaraFoundry: billing. honest headline: i shipped the billing SEAM, not billing. the free core now has the whole shape of a subscription system, gateway contract, driver manager, real access gate, and it cannot take a single cent. on purpose 👇
Did you know? On GitHub, a repo named exactly like your username becomes your profile page. Its README is what people see when they open your account. Then: archived repos still show (go private or delete), and you can pin your best repos to the top. Link to mine in the replies.
tagged v0.8.0 of LaraFoundry: the file & media layer. that closes phase 2. no dramatic bug this time. just a habit i had to unlearn, one that worked fine in the original CRM and breaks the moment the code has to be reusable: saving files with public_path() 👇
tagged v0.7.0 of LaraFoundry: navigation + the first operator console screen. while rebuilding it i found a hole in the original CRM that had been live the whole time: any admin could log in as any user, with no record of it 👇
tagged v0.6.0 of LaraFoundry: multilanguage. a language switcher and a second language. the most boring thing in the backlog. you have built it a hundred times. it shipped two real bugs, and both lived where two systems meet 👇
tagged v0.5.0 of LaraFoundry: the activity log. i didn't invent an audit log. it's spatie under the hood. what i extracted is the context around it: device, IP, route, geo on every entry, plus a super-admin viewer. then the review caught it logging the wrong thing 👇
tagged v0.4.0 of LaraFoundry: roles & permissions. self-written RBAC (not Spatie), tenant-scoped from the ground up, lifted from my live CRM. roles, per-user grants and revokes, default roles cloned into every new company. then my code review found a privilege-escalation hole I'd have shipped 👇
tagged v0.3.0 of LaraFoundry: multi-tenancy. one db, many tenants, row-level isolation. teams or personal mode behind a config switch. ran my code review, saw "8 of 12 handled", almost shipped. ran it again. the 2nd pass found 2 security holes the 1st missed 👇