Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Expose Laravel Package

exposedev/expose

Expose is a Laravel package that replaces dd() with a powerful debugging dashboard. Dump variables, queries, models, emails, and more to a beautiful web UI, inspect them without breaking your app, and share results with your team.

Deep Wiki
Context7

Getting Started

Expose is a CLI tunneling client (plus a self-hostable server), not a Laravel package with a service provider — so the first mental adjustment is that you install it globally or as a dev binary, then run it next to artisan serve / Valet / Herd / Sail.

  1. Install it as a tool, not a dependency.

    composer global require exposedev/expose
    # or, pinned per project so the whole team uses the same version:
    composer require --dev exposedev/expose
    ./vendor/bin/expose --version
    

    Make sure ~/.composer/vendor/bin (or ~/.config/composer/vendor/bin) is on PATH if you go global.

  2. Read expose --help and expose share --help before anything else. Flag names have drifted across releases (subdomain, auth, host, port options). The command help in your installed version is the only reliable reference; treat blog posts and older docs as hints.

  3. Authenticate once. The first expose share run walks you through obtaining/storing a token in your home-directory config. Confirm where that file lands and whether it contains a secret — that determines whether it's safe to copy between machines.

  4. First real use case: share a local Laravel app.

    # terminal 1
    php artisan serve --host=127.0.0.1 --port=8000
    # terminal 2
    expose share http://127.0.0.1:8000
    

    With Valet/Herd it's simply expose share myapp.test. You get a public HTTPS URL that proxies to your local app — useful immediately for client demos, QA on a real phone, and webhook receivers.

  5. Where to look first when something is wrong: the tunnel process output (run with the verbose flag), then the Laravel log — most failures are Laravel rejecting the request (host/CSRF/HTTPS), not the tunnel dropping it.

Implementation Patterns

Webhook receiver loop (Stripe, GitHub, Slack, Shopify). This is the highest-value daily pattern. Keep a tunnel running in a dedicated terminal/tmux pane, point the provider's webhook URL at the tunnel host, and let it hit your local route. Because free/ephemeral subdomains rotate per session, either use a reserved subdomain (if your plan/self-hosted server supports one) or wrap the provider config update into a script so re-pointing is one command.

Two-process dev script. Codify it so nobody forgets the second terminal:

"scripts": {
  "share": "expose share http://127.0.0.1:8000"
}

or a make share / Composer script that starts artisan serve in the background and Expose in the foreground. Prefer foreground for the tunnel so Ctrl-C cleans up the connection.

Project-level config for repeatable flags. If you're always sharing the same host with the same subdomain and basic-auth credentials, put those defaults in Expose's config file (created on first run / via its init command) rather than retyping flags. Keep credentials out of the committed repo; commit only the non-secret defaults.

Protect anything that isn't a throwaway demo. Layer Expose's own basic-auth option in front of the tunnel and keep Laravel's auth on sensitive routes. Before exposing, confirm APP_DEBUG=false if outsiders will hit it, and that /telescope, /horizon, /ignition, and .env are not reachable.

Sail / Docker. Run the Expose client on the host and point it at the published port (expose share http://localhost:80), not at a container hostname it can't resolve. If you must run it inside a container, target host.docker.internal and expect an extra layer of networking to debug.

Self-hosting for a team. The server component lets you run your own relay on a VPS: wildcard DNS for the tunnel domain, ports 80/443 reachable, TLS terminated by the server, then clients configured to talk to your host instead of the default. This is the right answer when an org won't allow a third-party tunnel. Pin client and server to compatible versions — mismatched protocol versions are the classic self-host failure.

Mobile/device QA handoff. Share the tunnel URL plus the basic-auth credentials in one message, with a note that it dies when your laptop sleeps. For longer-lived previews, run the tunnel on a always-on box or under a process supervisor.

OAuth callback testing. Workable only with a stable hostname, because the callback URL is registered at the provider. Use a reserved subdomain, register it once, and accept that you'll juggle providers if you test several.

CI/E2E webhook fixtures. Possible (spin up a tunnel, fire a fixture webhook at it, assert), but treat it as a flaky tier: network-dependent, rate-limited, and slow to fail. Gate it behind a label rather than running it on every push.

Gotchas and Tips

  • It is not config/expose.php. There's no Laravel service provider magic to lean on; integration is process orchestration and HTTP-header correctness. If an Artisan wrapper exists in your version, it's a thin shell around the CLI — still debug at the CLI level.
  • HTTPS termination breaks URL generation. Expose terminates TLS and forwards plain HTTP. If Laravel doesn't trust the forwarding proxy, route(), asset(), redirects, and signed URLs come out as http:// and you get mixed-content or signature mismatches. Ensure TrustProxies covers the tunnel (or * in local dev) so X-Forwarded-Proto is honored.
  • APP_URL versus request host. Laravel often derives URLs from the incoming Host, which is the tunnel domain — usually what you want. But anything using config('app.url') (queued mail, some notification links, ASSET_URL) will still point at myapp.test and be unreachable from the outside. Decide deliberately: leaving APP_URL alone is usually correct for tunnels; forcing it to the tunnel URL creates churn when the subdomain rotates.
  • Cookies and sessions. A SESSION_DOMAIN of .myapp.test won't apply to the tunnel host, so sessions silently reset. Same class of problem for Sanctum stateful domains and CSRF cookie domain on SPA setups.
  • Vite HMR is not tunneled. The tunnel proxies your app port, not 5173. Either run npm run build, or configure server.hmr.host/clientPort to the tunnel host and expose the Vite port too. Otherwise the page loads but assets/hot updates fail in confusing ways.
  • WebSockets need a deliberate check. Laravel Echo/Reverb/Pusher traffic goes to a different port and often a different path; verify the tunnel actually carries the upgrade before blaming your broadcasting config.
  • Long-running responses, SSE, and large uploads are the first things to time out or buffer. If a feature works locally but hangs through the tunnel, test the same route with a plain curl against the tunnel and against localhost to isolate.
  • Rotating subdomains are the #1 recurring annoyance. Every restart invalidates webhook registrations, OAuth callbacks, and links you've shared. Reserve a subdomain or self-host if this is a daily workflow.
  • Verbose mode is your debugging lever. When a request 502s or the connection drops, verbose client logs tell you whether the handshake, the local connect, or the proxy failed. For self-hosted servers, correlate against the server-side log.
  • Keep the process alive. Laptop sleep, shell exit, and tmux kills all look like "the tunnel randomly stopped." Use a supervisor or a dedicated pane, and expect reconnects to change the URL.
  • Watch free-tier limits. Concurrent tunnel caps, connection limits, and rate limiting on rapid reconnects will bite scripts that start/stop tunnels in a loop.
  • PHP runtime requirements. The client needs the usual ReactPHP-ish extensions (openssl, and typically pcntl/sockets depending on platform) and behaves best on Linux/macOS; Windows has historically been the roughest platform. If install succeeds but the binary exits immediately, check extensions and PHP version before anything else.
  • Treat the token as a secret. It lives in a home-directory config file; don't bake it into Docker images, CI artifacts, or a committed expose.* config.
  • Never expose a machine with debug on and real credentials in .env. A tunnel is a public ingress; the same hygiene you'd apply to a staging URL applies here, plus the hostname is guessable.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
robertmarney/lara-hierarchial-collections
simonschaufi/rule-doc-generator
emissaoja/emissaoja
blackbricksoftware/gravityforms-civicrm-form-processor
al-rahabi/fancy-crud
jinas/dhivatar-component
mltstephane/laravel-quality
bernskiold/laravel-talentlms
bernskioldmedia/laravel-form-architect