# Fix Mobile Layout Bugs in a Laravel App

Yes. An agent opens a Laravel site at phone widths, fixes scroll and tap-target bugs, and takes a designer's corrections before the pull request.

[Run this on Rush](https://cloud.getrush.ai/run/fix-mobile-layout/laravel/), in a Project that has your repository.

## What the agent does

The agent learns the breakpoints the stylesheet already has, because a phone bug here is usually a gap between them. BookStack is Laravel ^v13.35.0 on PHP ^8.3.0, with phpunit/phpunit ^12.5.38. composer test runs phpunit, and phpunit.xml sets DB_CONNECTION to mysql_testing and excludes the slow and lang groups. Styles are Sass in resources/sass, compiled by npm run build:css:dev (sass ./resources/sass:./public/dist) into public/dist/styles.css, which layouts/base.blade.php loads. resources/sass/_vars.scss defines $bp-l at 1000px, $bp-m at 880px, $bp-s at 600px, $bp-xs at 400px and $bp-xxs at 360px. The two widths in the request sit on opposite sides of $bp-xs: 375 is under 400 and over 360, and 414 is over 400 and under 600. A fix that only lives inside the xs query will look done at 375 and broken at 414.

The header is the first place that falls over. header.grid is three columns until smaller-than($bp-l), where it becomes one column. Below that width .header-links is display: none until the menu opens. .mobile-menu-toggle sets font-size to 2em, line-height to 1, a 2px border and padding of 0 by $xs, and $xs is 6px, so the hit area is the icon rather than a 44px target. The grid system in _layout.scss collapses .grid.half and the focus grids at $bp-m, .grid.third at $bp-s, and .grid.half.collapse-xs only at $bp-xs. Pages to open, from routes/web.php, are / (HomeController@index), /shelves, a shelf, /books, a book, a page at /books/{book}/page/{page}, search and the settings screens. base.blade.php sets the viewport meta to width=device-width and does not set initial-scale. The html element already toggles dark-mode from the user setting, so this job does not restyle the theme.

In the sandbox browser the agent sets the width to 375 and then 414 and walks those routes. It records horizontal scroll, overlapping header links, clipped page titles and controls whose box is under 44px, including the menu toggle. Fixes stay in the existing Sass partials, using the mixins and the spacing scale ($m is 16px, $s is 12px), then npm run build:css:dev regenerates public/dist. It does not add a new framework. Before and after screenshots of each page, at both widths, are posted on the run.

A designer watching can point at a control the measurement missed, or at a shelf card that still overflows at 414 because the rule stopped at 400. The follow-up names the page and the width. The agent adjusts the partial, rebuilds the CSS and recaptures that page before opening the pull request. PHPUnit is not a layout check. The agent runs it when a Blade change could break a view test, against MySQL on the mysql_testing connection the phpunit file names, and says so in the pull request.

## Start it with one API call

`POST https://api.prix.dev/o/{org}/sessions`

```json
{
  "agent": "codex",
  "input": "Open every main page in the browser at 375 and 414 pixels wide: home, shelves, a shelf, books, a book, a page, search and settings. The Sass breakpoints are in resources/sass/_vars.scss: $bp-xs is 400px and $bp-s is 600px, so these two widths are on different sides of the xs query. Fix horizontal scroll, overlapping or clipped elements and tap targets under 44 pixels, including .mobile-menu-toggle, using the existing partials and mixins. Set initial-scale on the viewport meta in layouts/base.blade.php if it is missing. Do not change the dark-mode behaviour. Rebuild CSS with npm run build:css:dev. Screenshot each page before and after at both widths and open a pull request with them. Apply follow-ups first.",
  "resources": [
    {
      "url": "https://github.com/your-org/your-app"
    }
  ]
}
```

1. **Get an API key.** In the console, open Settings, then API keys, and create a key for your org. Send it in the Authorization header as a Bearer token.
2. **Send the request.** POST the body in request.json to https://api.prix.dev/o/{org}/sessions, with your repository as the resources URL. The run starts in its own cloud sandbox.
3. **Read what came back.** Follow the run on its live stream or wait for the run.completed webhook, then read the result and its trajectory.

## What comes back

What comes back is a pull request whose diff is Sass under resources/sass, the compiled public/dist/styles.css, and the viewport tag in layouts/base.blade.php if it changed. The description pairs before and after shots of each main page at 375 and at 414, and names the breakpoint query that was wrong for one of those widths. The images are also artifacts on the session, each with a download URL that lasts an hour.

A reviewer checks the 414 shots as carefully as the 375 ones, because a rule gated on $bp-xs does not apply at 414. They check the menu toggle's padding against 44px, that header links still open, and that dark-mode on the html element was not removed. They skim the compiled CSS only to see that it matches the Sass, since the layout loads public/dist/styles.css.

The designer's marks arrive as follow-ups while the sandbox still has the browser at those widths. POST /o/{org}/sessions/{id}/messages once the turn is idle. A message during the turn is 409 TURN_ACTIVE. The console queues that message. The parked machine keeps the built CSS and wakes for the correction. It is kept for 7 idle days.

## Run it on every layout report

A layout report starts one session on the repository. The designer watches the before screenshots and sends the misses back as follow-ups. Any org member can read the run. Control of the browser is a five-minute lease held by one person, the starter or an org admin being the ones who steer.

The key's webhook posts run.completed or run.failed at the end of the capture turn and again after the correction turn. session_url is in the payload. Runs beyond max_concurrent, 4 by default, are refused with 429, so a sweep of several properties should be queued rather than fired at once.

## Why run it on Rush?

Phone layout fails at a specific width this stylesheet treats differently, and a desktop browser with the devtools closed will not show it. The sandbox sets 375 and 414, reloads the Blade pages, and keeps both captures. The designer does not need PHP or MySQL installed to point at the shelf grid.

The pull request carries the pictures and the Sass. The transcript carries the css build and any PHPUnit run. The next report is another sandbox, so one experiment at 414 does not block a different fix.

## Frequently asked questions

### Why do 375 and 414 need different checks?

$bp-xs is 400px and $bp-xxs is 360px. 375 falls in the xs band. 414 does not, and the next stop is $bp-s at 600px. A collapse written only inside smaller-than($bp-xs), such as .grid.half.collapse-xs, is inactive at 414. The screenshots have to include both.

### Does it replace the Sass with a new framework?

No. Fixes go in the partials that already own the rule, using the spacing scale in _vars.scss. npm run build:css:dev writes public/dist, which is what base.blade.php loads. A pull request that adds a second CSS pipeline is outside this request.

### Will dark mode be disturbed?

The html class dark-mode comes from the user's setting in base.blade.php, and the prompt leaves that alone. Header colours that already use the lightDark mixin should keep it. The job is width, overflow and target size.

### Does the designer have to wait for the pull request?

No. The before and after shots are posted on the run first. A follow-up can name a page and a width, and the agent recaptures it before opening the pull request. After the sandbox has been idle for 7 days it is gone, and a further change is a new session.
