My first merged pull requests into laravel/framework were two missing @throws annotations. Not glamorous. They taught me the process, and the process is most of the work.
Start smaller than feels worthwhile. The maintainers review hundreds of PRs. A tiny, obviously-correct change gets merged in hours and teaches you the conventions: which branch, what the tests look like, how Taylor phrases a request for changes. My next batch was four fixes for flaky tests in the session and cache array stores. Flaky tests are a gift to a new contributor: they annoy everyone, the fix is self-contained, and nobody has to debate the API.
Target the right branch. Bug fixes go to the current release branch (12.x, then 13.x). New methods and behaviour go to the next minor, and anything that changes existing behaviour goes to master for the next major. Getting this wrong is the fastest way to a closed PR with a one-line comment.
One concern per pull request. Adding enum support to BroadcastManager and to PasswordBrokerManager was two pull requests, not one, even though the diff was nearly identical. Each could be reviewed in a minute and reverted alone.
Write the test the maintainer would write. For digits_between throwing a TypeError on non-string input, the PR is one cast and one test that passes an integer. The test is the argument; the description just points at it.
Find the gaps by using the framework at the edges. Uri had no withoutFragment() or isNotEmpty(). Mailable had assertHasAttachment() but not assertHasNoAttachments(). Stringable::initials() was missing a parameter its sibling had. Nobody files issues for these. You find them by reaching for a method and noticing it is not there.
Performance fixes need a before and after. PendingDispatch was resolving the cache store for every dispatched job; DatabaseQueue was recomputing a lock it could cache. Both PRs described what was being called, how often, and what changed. Numbers are optional; a clear account of the extra work is not.
Thirty-seven merged so far, and a credit on the Laravel 13 release. The advice compresses to this: be small, be correct, be on the right branch, and let the test do the talking.