Activity Indicator
AvailableShow that work is in progress when there is no completion value to report.
For NativePHP and Laravel Boost
composer require firstlightui/nativephp and Laravel Boost give you, or your coding agent, what a standard forms app needs: lists and detail, search, forms with Laravel validation, settings, sheets and dialogs, and feedback.
Every control is genuine SwiftUI on iOS and Jetpack Compose on Android. It runs on the SuperNative foundation created by Shane Rosenthal and Simon Hamp.
Android showcase: coming soon.
Start with a recipe
Each recipe is a complete screen you can copy, or hand to your coding agent. Each one runs unchanged in the showcase app, whose Pest tests exercise it.
Recipe 01
List and detail flow
The app shell: native title bars and back navigation, a list, and a detail screen it pushes. The other recipes run inside it.
Read the recipe →Recipe 02
Searchable list
Native search, a paginated list, pull-to-refresh, row navigation, and swipe-to-delete behind a native confirmation.
Read the recipe →Recipe 03
Form screen
A Form Request, errors on each native field, a form-level error, a loading Save button, and success feedback.
Read the recipe →Recipe 04
Settings screen
Grouped native sections with switches and pickers that save as soon as they change.
Read the recipe →Built for coding agents
Firstlight ships a Laravel Boost guideline and two skills. Install Boost and your agent learns the rules every Firstlight screen follows, which recipe fits the screen you ask for, and which control fits each value.
llms-full.txt too, matching the installed version.Terminal
$ composer require firstlightui/nativephp
$ composer require laravel/boost --dev
$ php artisan boost:install
“Set up this app with Firstlight. The main record is a job. I want a searchable list of jobs, a form to create one, and a settings screen.”
An agent writes the screens and runs their Pest tests. Both skills end by asking you to check the app on an iOS simulator and an Android emulator.
Genuine native controls
Every Firstlight control is a real SwiftUI control on iOS and a Jetpack Compose Material 3 control on Android. Nothing is drawn to imitate a platform control, and there is no WebView. You write one Blade tag; each platform shows its own pattern.
usesNativeChrome(). Firstlight works inside it and does not replace it.
Feels like Laravel
NativePHP EDGE has no screen-level validate(). Without it, errors appear as sibling @nativeError text or the generic error overlay. Firstlight adds ValidatesFields, SubmitsForms, AuthorizesActions, and list pagination and deletion as concerns on NativeComponent, so each message lands in the field’s native error slot.
$rules or a Form Request. Each field shows its first message natively, and <firstlight:callout error-for="form" /> shows errors that belong to the whole form.
$this->validate(
StorePostRequest::class,
);
submit() validates, runs the action once, and sends success Feedback. authorize() hides, disables, or guards actions with your Policies instead of the error overlay.
$this->submit(
action: fn () => $post->save(),
successMessage: 'Saved',
);
ScreenAssertions adds field-error, list, dialog, and Feedback checks to NativePHP’s Native::test(). make:firstlight-screen --test scaffolds a screen and its test.
Native::visit('/posts/create')
->set('title', 'Hi')
->call('save')
->assertFieldError('title');
How-to
Validate fields
validate(), validateOnly(), and Form Requests, with messages on native fields.
Read the guide →How-to
Submit forms
Validate, run a PHP action once, and publish success Feedback.
Read the guide →How-to
Authorize actions
Hide, disable, or guard actions with Laravel Gates and Policies.
Read the guide →How-to
Test screens
Scaffold with make:firstlight-screen and test with Native::test().
Read the guide →Accessible by default
Firstlight never draws its own controls. VoiceOver, TalkBack, Dynamic Type, font scaling, dark mode, Increased Contrast, Reduce Motion, and right-to-left layout reach every control the way they reach the platform’s own apps. Firstlight adds the decisions a native control can’t make on its own.
Where verification stands
This behaviour is covered by contract, XCTest, and Robolectric tests, and VoiceOver was checked on a physical iPhone. Spoken TalkBack output has not yet been recorded on a physical Android device.
Components
Fields, choices, lists, dialogs, sheets, status, and feedback. Every field shares the same value, label, error, disabled, and required behaviour, so a form needs no per-control special cases. Each screenshot below comes from the iOS and Android renderers.
Show that work is in progress when there is no completion value to report.
Run one labelled action with a native button.
Keep an important semantic message visible in the page layout with an optional labelled action.
Publish brief app-level outcomes as queued native feedback that persists across normal screen navigation.
Show a compact, display-only count or short marker.
Toggle one Boolean value in a form or checklist, with the state kept in PHP.
Show a visible list of labelled options for selecting one value or several values.
Ask for one native confirmation with explicit cancellation and destructive action semantics.
Present one native acknowledgement with a single action and server-controlled dismissal.
Present authored content in a full-screen native overlay with server-controlled dismissal.
Present authored content in a native bottom sheet with server-controlled dismissal.
Choose an optional calendar date with each platform’s native, server-authoritative picker.
Choose an optional wall-clock time while keeping the model value exact and server-authoritative.
Trigger one compact, accessible action through native SwiftUI and Material icon buttons.
Present one tappable application row with supporting text, leading identity, and a trailing affordance.
Compose finite vertical collections of List Item rows with optional grouped sections and refresh or pagination hooks.
Group List Item rows with optional headers and footers inside a parent List.
Offer compact, individually shaped options for single or multiple selection.
Communicate determinate completion or indeterminate work with the native platform indicator.
Pick one of a few mutually exclusive choices with a native segmented control.
Enter and submit one query with native search, clear, focus, keyboard, and selection behaviour.
Choose one stable string or integer value from a collapsed native selection field.
Select one value from an exact numeric grid using each platform’s native slider.
Move an accepted numeric value through a bounded range one exact step at a time.
Show short, display-only status text in a coloured native capsule.
Display one labelled value with tabular figures, an optional detail, and a single accessible description.
Capture one image or document into Laravel Storage with camera, library, or file picking and optional crop.
Edit one line of text with each platform’s native keyboard, autofill, selection, and accessibility behaviour.
Edit multiline text with native selection, composition, focus, scrolling, and correction behaviour.
Present one boolean setting through each platform’s familiar native on/off control.
Switch between sections of one object with native tabs, counts, and selection your component controls.
Edit JSON, YAML, env, and plain text with line numbers, native indentation, a key row, and follow mode for live logs.
How it renders
Firstlight uses the same EDGE element tree, renderers, theme, and event lifecycle as NativePHP Mobile UI. Ordinary interaction, such as typing and scrolling, stays on the native UI thread.
Quickstart
Requires NativePHP Mobile ^4.7 and Mobile UI ^0.9.
Build your screens with FirstlightUI\NativeComponent, starting from the list and detail recipe. Add Laravel Boost so your coding agent does the same.
composer require firstlightui/nativephp
Firstlight 1.0.0 is the first stable release. It has been tested on physical iOS and Android devices, including VoiceOver on iOS. Spoken TalkBack output and long-running performance tests have not been recorded yet. Read the compatibility notes.