RK-Lens Engineering Onboarding
One intensive month to become a developer capable of shipping features on the RK-Lens stack: Laravel + Hotwire on the server, Hotwire Native on iOS and Android — with an AI-first mindset throughout.
One system — growing every week
Required reading, videos, and repos — before Week 1
Do not start writing code until you have gone through these resources. They define the mental model behind everything in the RK-Lens stack. The weeks will move fast — this foundation is what makes the difference.
Required reading
- Turbo Laravel Docs — read the entire overview from start to finish: Turbo Drive, Turbo Frames, Turbo Streams, Broadcasting, Hotwire Native. This is the server-side integration of Hotwire that the whole stack is built on.
turbo-laravel.com/docs/overview - Hotwire Native iOS — Getting Started — the official guide for setting up the iOS shell: Navigator, path configuration, and bridge components. Read this before Week 3 iOS work.
native.hotwired.dev/ios/getting-started
Required video course
- Hotwire for Laravel by Tony Messias — the author of
hotwired-laravel/turbo-laravelhimself. Watch this course completely before Week 1. It covers the exact stack used in production at RK-Lens.
tonysm.com/courses/hotwire-laravel
Starter kit repos to clone
These are the base projects you will use. Do not start from scratch — clone these and build on top of them.
- Backend (Laravel + Hotwire) — the official Hotwire starter kit: Turbo Laravel, Stimulus, importmap, Tailwind, DaisyUI pre-configured.
github.com/hotwired-laravel/hotwire-starter-kit - iOS shell — clone
turbo-ios, open theDemo/Demo.xcodeprojin Xcode, and run it on the simulator before Week 3.
github.com/hotwired/turbo-ios - Android shell — the example Android app wrapping the Hotwire starter kit. Open this in Android Studio before Week 3.
github.com/hotwired-laravel/hotwire-starter-kit-android-example
The stack in one sentence: the server renders HTML with Blade and broadcasts Turbo Streams; Turbo intercepts all navigation and form submissions in the browser; Stimulus controllers add behavior without a framework; and Hotwire Native wraps the entire web app in a native iOS and Android shell — no API, no JSON, no separate codebase.
What you will build and who you will become
The entire program revolves around one system: the Store Inventory Tracker. It starts as a bare Laravel + Hotwire project and grows into a full mobile app running natively on iOS and Android through Hotwire Native.
What you will build
- A server-driven inventory CRUD with Turbo Drive, Turbo Frames, and Turbo Streams — zero custom JavaScript required for core features
- A clean layered architecture: Controller → Service → RepositoryInterface → Eloquent, with Stimulus controllers for progressive enhancement
- A real-time UI via Turbo Stream broadcasts — when any user updates a quantity or scans a product, every connected screen updates live with no polling
- The same web app wrapped in a native iOS shell (Swift) and a native Android shell (Kotlin) using Hotwire Native — no separate mobile codebase
- A barcode scanner: native camera reads a barcode via a Strada bridge component, the server looks up the SKU in the database, and the product detail page is displayed with name, description, and quantity
Who you become by the end
- You ship features on the real RK-Lens codebase from day one — the stack you learn is exactly what production runs
- You understand the Hotwire mental model: HTML over the wire, progressive enhancement, and why there is almost no custom JS
- You can open, build, and run the native iOS and Android apps, and understand how the WebView and native shells interact through Hotwire Native bridge components
Golden rule: no new codebases. Each week you extend what you built the week before. The native apps in Week 3 wrap the exact same Laravel app from Weeks 1 and 2. The scanner in Week 4 adds one new endpoint on top of the same backend — the product data it displays was already there since Week 1.
Laravel + Hotwire Foundations
Build the web backend and server-rendered UI from the hotwire-starter-kit base. The architecture is enforced from day one: every request flows through Controller → Service → Repository Interface. Turbo handles all navigation and partial updates — no JSON APIs, no frontend framework.
Required architecture — Controller → Service → Repository
Architecture deliverables
- Define
ProductRepositoryInterfacewithlist(),findById(),create(),update(),delete() - Create
EloquentProductRepositoryimplementing the interface — all Eloquent calls isolated here - Create
ProductServicereceiving the interface via constructor injection - Bind the interface to its implementation in
AppServiceProvider ProductControllerdepends onProductServiceonly — zero direct Eloquent or DB usage in the controller
Feature deliverables
- Clone and run the hotwire-starter-kit locally — Turbo, Stimulus, importmap, Tailwind, DaisyUI all pre-configured
- Migration for
products:name,sku(unique),quantity,category,store_id,updated_at - Products list page with Turbo Drive navigation and DaisyUI table using semantic color tokens only
- Product create/edit forms inside a
<turbo-frame>— inline editing without a full page reload - Stimulus controller for live search with debounce — no page navigation when filtering
- Form validation errors shown inline: controller returns 422 and Turbo re-renders the frame with the error-annotated form
- All colors use DaisyUI semantic tokens only (
bg-base-100,text-base-content,btn-primary, etc.) — no raw Tailwind grays or hardcoded hex - Dark mode works automatically via system preference — no theme toggle code needed
Week 1 deliverable: a working products CRUD with server-driven UI. A user can list, create, edit, and delete products entirely through Turbo — no page reloads, no API endpoints, no frontend framework. The architecture is locked in: Controller never touches Eloquent.
Full Application + Turbo Streams
Extend the app into a complete, multi-feature system. Add authentication, a second entity (stores), real-time updates via Turbo Streams, and the role-based access model that mirrors the real RK-Lens codebase.
Backend deliverables
- Authentication: login, logout, and protected routes via
authmiddleware - Create a new migration
create_stores_tablewithname,code,location; a second migrationadd_store_id_to_products_tableadds the foreign key toproducts— never edit the Week 1 migration StoreRepositoryInterface+EloquentStoreRepository+StoreServicefollowing the exact same pattern as Week 1- Role-based access:
adminrole manages stores;associaterole can only update product quantities PATCH /products/{id}/quantitybroadcasts a<turbo-stream action="replace">when quantity changes — all other connected users see the update live- Pagination on the products list:
pageandper_pageparams working correctly with Turbo Drive - Filtering by
store_id,category, andlow_stockflag via query params
Frontend deliverables
- Dashboard: per-store overview with total SKUs, low-stock count, and last-updated timestamp
- Store selector updates the product list via Turbo Frame — no full page reload
- Real-time row update via Turbo Stream: when another user changes a quantity, the row updates live — no polling, no WebSocket client code
- Stimulus controller for toast notifications triggered by a Turbo Stream
appendto a toast container after mutations - Stimulus controller for the quantity input: optimistic UI update on change, reverts on server error
- Low-stock visual indicator: DaisyUI
badge-warningorbadge-erroron rows below threshold — no custom CSS - Mobile-first layout at 375px viewport — this exact view will be rendered inside the native WebView in Week 3
Week 2 deliverable: a working application a real store associate could use to monitor and update inventory in real time. The UI updates itself when other users make changes — implemented entirely through Turbo Streams, with no polling and no frontend state management.
Hotwire Native
The web app you built in Weeks 1 and 2 becomes a native mobile app this week — without rewriting a single line of server code. Hotwire Native is the framework for both platforms: it wraps your Laravel app in a native shell, renders it in a WebView, and lets you add native UI through bridge components.
How Hotwire Native works
iOS setup & deliverables
- Clone turbo-ios and open
Demo/Demo.xcodeprojin Xcode — run the Demo target on the simulator to understand Session, path configuration, and visit types before writing any custom Swift - Create your own iOS app target (or adapt the Demo); add
turbo-iosvia SPM (Turbopackage) and optionallystrada-ios(Stradapackage) — both resolve on first Xcode open - Configure the base URL to point to your local Laravel dev server
- Path configuration: modal presentation for create/edit routes; standard push for list and detail routes
- In the Blade layout, use
Turbo::isHotwireNativeVisit()(theTurbofacade) to conditionally hide the web nav bar when the request comes from the native shell - Add a Strada bridge toast component: web
data-controller="bridge--toast"triggers a native iOS notification banner - Run the app on the iOS Simulator from Xcode — confirm Turbo Drive navigation, form submissions, and Turbo Stream updates work end-to-end
Android setup & deliverables
- Clone the hotwire-starter-kit-android-example and open it in Android Studio — Gradle dependencies (
dev.hotwire:coreanddev.hotwire:navigation-fragments) sync on first open - Configure the base URL to point to your local Laravel dev server (same server the iOS shell connects to)
- Path configuration JSON: bottom sheet modal for create/edit routes; standard fragment push for list and detail routes
- Set the app user agent to include a recognizable prefix so Laravel can detect native visits server-side
- Add a Strada bridge dropdown menu component: web
data-controller="bridge--dropdown-menu"renders as a native Android popup menu - Run the app on the Android Emulator from Android Studio — confirm Turbo navigation, forms, and real-time Turbo Stream updates work inside the WebView
Week 3 deliverable: the Store Inventory Tracker running as a native app on both the iOS Simulator and the Android Emulator. No new server code was written — the same Laravel app from Weeks 1 and 2 powers both native clients through Hotwire Native.
Scanner Pipeline
The final week connects the backend, the web UI, and the native apps into a real end-to-end feature: a barcode scanner. A store associate opens the native app, taps "Scan", points the camera at a barcode — the scanned text is sent to the server, the matching product is looked up by SKU, and the product detail page is displayed with its name, description, and current quantity.
How the scanner works
Seed data — insert these 3 products for testing
Generate barcodes from these SKUs using any free online barcode generator (e.g. barcode.tec-it.com), print or display them on screen, and scan them with the native app running on a physical device.
| SKU | Name | Description | Qty |
|---|---|---|---|
RK-00101 |
Livestock Feed 50lb | Premium all-stock feed, 50 lb bag | 120 |
RK-00247 |
Steel Fence Post 6ft | T-post galvanized steel, 6 ft | 85 |
RK-00389 |
LED Shop Light 4ft | 5000K daylight LED, 4 ft linkable | 42 |
Backend deliverables
- Create a new migration
add_description_to_products_tablethat adds a nullabledescriptiontext column toproducts— never edit the existing Week 1 migration - Seed the 3 example products above into the database — these are the products you will scan during testing
- Add route
GET /products/scan/{sku}inweb.phpbefore any wildcard/products/{id}route to avoid collision —ScanControllerreads the SKU from the route parameter and returns the product detail Blade view viaProductService - If the SKU is not found, return a 404 page with a clear message — the Stimulus controller handles this gracefully
- Product detail page rendered inside a
<turbo-frame>so it integrates cleanly with both the web layout and the native shell - Web scan page: Stimulus controller with
data-controller="scanner"— on web, shows a text input for manual SKU entry; on native, triggers the Strada bridge camera instead - After a successful scan, the Stimulus controller navigates to
/products/scan/{sku}viaTurbo.visit()— same behavior on web and native - Scheduled job: daily low-stock report email listing products below threshold per store, dispatched via Laravel scheduler
- CSV export:
GET /products/exportrespects active filters; streams the response without loading all rows into memory - DB indexes on
products.sku,products.store_id,products.quantity— measure query time before and after withEXPLAIN - No N+1 queries anywhere in the app — verify with Laravel Debugbar or query log; eager-load all relationships
Mobile deliverables (iOS & Android)
- iOS: implement the
BridgeScannerComponentin Swift — listens for thescanbridge message, opensAVCaptureSessionto read barcodes, posts adid-scanbridge message with the scanned text back to the web controller - iOS: request camera permissions correctly; handle the denied state with a native alert pointing to Settings
- Android: implement the same bridge component in Kotlin using ML Kit Barcode Scanning and CameraX — same
scan/did-scanprotocol as iOS - Android: request
CAMERApermission at runtime; handle denial gracefully with an explanatory dialog - The web Stimulus controller is bridge-aware: when running inside the native shell it sends the bridge message; when running in a browser it falls back to the manual text-input flow — same
Turbo.visit()navigation for both - Generate barcodes for the 3 seed SKUs using a free online generator, print or display them, and scan them from the native app running on a physical device — the product detail page must display with name, description, and quantity
- Document the bridge component protocol: message name (
scan), payload shape, expecteddid-scanresponse — the web Stimulus interface is the contract both platforms must satisfy
Week 4 deliverable: a store associate can open the native app, tap "Scan", point the camera at a product barcode, and immediately see the product detail page with its name, description, and current quantity — all through the same Laravel backend built in Weeks 1 and 2. That is the Hotwire Native model in production.
- Clone and run the hotwire-starter-kit locally — Turbo, Stimulus, importmap, Tailwind, DaisyUI pre-configured
- Define
ProductRepositoryInterfacewithlist(),findById(),create(),update(),delete() - Create
EloquentProductRepositoryimplementing the interface - Create
ProductServicereceiving the interface via constructor injection - Bind the interface to its implementation in
AppServiceProvider ProductControllerdepends onProductServiceonly — zero direct Eloquent in the controller- Migration for
products:name,sku(unique),quantity,category,store_id,updated_at - Products list page with Turbo Drive navigation and DaisyUI table using semantic color tokens
- Product create/edit forms inside a
<turbo-frame>— inline editing without full page reload - Stimulus controller for live search with debounce — no page navigation on filter change
- Form validation errors shown inline via Turbo Frame 422 response (re-rendered form with errors)
- All colors use DaisyUI semantic tokens only — no raw Tailwind grays or hardcoded hex values
- Dark mode works automatically via system preference — no theme toggle code
- Authentication: login, logout, protected routes via
authmiddleware - New migration
create_stores_table; separate migrationadd_store_id_to_products_table— never edit the Week 1 migration StoreRepositoryInterface+EloquentStoreRepository+StoreServicefollowing Week 1 pattern- Role-based access:
adminmanages stores;associatecan only update product quantities PATCH /products/{id}/quantitybroadcasts a<turbo-stream action="replace">to all connected users- Pagination on products list:
pageandper_pageparams working correctly with Turbo Drive - Filtering by
store_id,category, andlow_stockvia query params - Dashboard: per-store overview with total SKUs, low-stock count, last-updated timestamp
- Store selector updates product list via Turbo Frame — no full page reload
- Stimulus toast controller triggered by Turbo Stream
appendto toast container after mutations - Low-stock badge: DaisyUI
badge-warning/badge-erroron rows below threshold — no custom CSS - Mobile-first layout at 375px viewport — the same views rendered inside the native WebView in Week 3
- Clone turbo-ios, open
Demo/Demo.xcodeprojin Xcode, run the Demo on the simulator — understand Session, path configuration, and visit types before writing any custom Swift - Create your own iOS target from the Demo; add
turbo-iosvia SPM and configure the base URL to point to your local Laravel dev server - iOS path configuration: modal for create/edit routes; standard push for list and detail routes
- iOS Strada bridge toast component — web
data-controller="bridge--toast"triggers a native iOS banner - iOS: run on the iOS Simulator and confirm Turbo Drive navigation, form submissions, and Turbo Stream updates work
- Clone the hotwire-starter-kit-android-example and open it in Android Studio; configure the base URL to the same local server
- Android path configuration: bottom sheet modal for create/edit; standard fragment push for list and detail
- Android: set a custom user agent prefix so Laravel can detect native visits via
Turbo::isHotwireNativeVisit() - Android Strada bridge dropdown menu component — web renders as native Android popup menu
- Android: run on the Android Emulator and confirm navigation, forms, and real-time updates work
- Blade layout: use
Turbo::isHotwireNativeVisit()(Turbo facade) to hide the web nav bar when the request comes from the native shell
- Create a new migration
add_description_to_products_table— adds a nullabledescriptiontext column toproducts; never edit the existing Week 1 migration - Seed the 3 example products (RK-00101, RK-00247, RK-00389) into the database
GET /products/scan/{sku}— looks up the product by SKU, returns the product detail view with name, description, quantity, store, and category- SKU not found returns a 404 page with a clear message
- Product detail page inside a
<turbo-frame>— works in web and native shell - Web scan page: Stimulus
scannercontroller — manual text-input on web, Strada bridge trigger on native - After scan, navigate to
/products/scan/{sku}viaTurbo.visit() - iOS:
BridgeScannerComponentin Swift —AVCaptureSession, postsdid-scanwith the scanned text back to the Stimulus controller - iOS: camera permissions — handle denial with native alert pointing to Settings
- Android: same bridge component in Kotlin — ML Kit Barcode Scanning + CameraX, same
scan/did-scanprotocol - Android:
CAMERApermission at runtime; graceful denial dialog - Generate barcodes for the 3 seed SKUs online, scan them from a physical device — product detail page must show name, description, and quantity
- Document bridge protocol: message name, payload shape,
did-scanresponse - Scheduled job: daily low-stock report email per store
- CSV export:
GET /products/exportrespects active filters; streams without loading all rows - DB indexes on
products.sku,products.store_id,products.quantity— measure withEXPLAIN - No N+1 queries — eager-load all relationships; verify with Debugbar or query log
Required — read and watch before Week 1
Turbo Laravel Docs
The complete documentation for the hotwired-laravel/turbo-laravel package. Read all sections: Turbo Drive, Frames, Streams, Broadcasting, Hotwire Native, and Testing. This is the backbone of the entire stack.
turbo-laravel.com/docs/overview CourseHotwire for Laravel — Tony Messias
Video course by the author of turbo-laravel itself. Covers the full Hotwire stack with Laravel: Turbo Drive, Frames, Streams, Stimulus controllers, and Hotwire Native integration. Watch this before starting Week 1.
tonysm.com/courses/hotwire-laravelStarter kit repos — clone before starting
hotwire-starter-kit (backend)
The official Laravel + Hotwire starter kit. Turbo Laravel, Stimulus, importmap, Tailwind, and DaisyUI pre-configured. This is your Week 1 starting point — clone it, do not start from scratch.
github.com/hotwired-laravel/hotwire-starter-kit Docsturbo-ios (iOS base)
The iOS library that powers the Hotwire Native shell. Clone this repo, open Demo/Demo.xcodeproj in Xcode, and run the Demo target on the simulator before Week 3. Your iOS app adds this as an SPM dependency.
github.com/hotwired/turbo-ios Docshotwire-starter-kit-android-example
The official Android example app wrapping the Hotwire starter kit. Uses dev.hotwire:core and dev.hotwire:navigation-fragments. Open in Android Studio to run on the emulator in Week 3.
github.com/hotwired-laravel/hotwire-starter-kit-android-exampleHotwire — Turbo + Stimulus deep dives
Turbo Handbook
Official guide for Turbo Drive, Turbo Frames, and Turbo Streams from the Hotwire team. Read all three sections — this is the mental model that drives the entire stack.
turbo.hotwired.dev/handbook DocsStimulus Handbook
How Stimulus controllers work: targets, actions, values, and lifecycle callbacks. Used for the search filter, toast, quantity, and bridge controllers throughout the program.
stimulus.hotwired.dev/handbook YouTubeSupeRails (Hotwire patterns)
Best YouTube channel for practical Hotwire patterns in Rails/Laravel. Covers Turbo Frames, Turbo Streams, Stimulus, and server-driven UI — all directly applicable to Weeks 1 and 2.
youtube.com/@SupeRailsLaravel — Service Container + Architecture
Service Container & Binding
How to bind ProductRepositoryInterface to EloquentProductRepository in AppServiceProvider. Core to the Week 1 architecture — read before writing the first repository.
laravel.com/docs/container YouTubeLaravel Daily
Practical short videos by Povilas Korop. Strong coverage of the Repository Pattern, service layer, and real-world refactoring — directly applicable to the Week 1 and 2 architecture.
youtube.com/@LaravelDaily YouTubeLaracasts
The reference for Laravel. Start with Laravel From Scratch — covers controllers, services, Eloquent, queues, and testing. Use as a reference throughout all four weeks.
youtube.com/@LaracastsTailwind CSS + DaisyUI
DaisyUI Themes & Semantic Colors
How DaisyUI semantic tokens work: bg-base-100, text-base-content, btn-primary. The enforced convention for the entire RK stack — read before touching any CSS in Week 1.
daisyui.com/docs/themes DocsDaisyUI Components
Reference for all DaisyUI component classes: table, badge, btn, modal, toast, drawer. Use these instead of writing custom CSS — they adapt to light/dark mode automatically.
daisyui.com/componentsHotwire Native — iOS + Android
Hotwire Native iOS — Getting Started
Official guide for the iOS shell: Navigator setup, path configuration, and bridge components. Required reading before Week 3 — covers exactly how the turbo-ios Demo connects to a server and how to extend it.
native.hotwired.dev/ios/getting-started Docsnative.hotwired.dev
Full Hotwire Native documentation covering path configuration, bridge components, and native screens for both iOS and Android. The authoritative reference for Week 3.
native.hotwired.devTesting & DevOps
Pest PHP Docs
Writing tests with Pest's expressive syntax: it(), expect(), and Laravel-specific helpers like actingAs() and assertDatabaseHas(). Useful for testing services, repositories, and the scan endpoint.
pestphp.com/docs DocsPlaywright Docs
Getting started, page object model, fixtures, and the test recorder. Useful for E2E testing of Turbo-driven flows like the scanner page and product detail view.
playwright.dev/docs/intro YouTubeTechWorld with Nana (Docker + CI)
Best free content on Docker, Docker Compose, and CI/CD pipelines. Reference for containerizing the Laravel backend, MySQL, and Redis for local and production environments.
youtube.com/@TechWorldwithNana