BOLT 12 offers an attempt to achieve some of the core functionality that LNURL provides without requiring the use of a web server. An offer encodes the data necessary to reach a node to request an invoice to make a payment, either a node_id, or a blinded path (the last few hops in an onion route, pre-computed and encrypted) to that node using onion messages. It also can encode a minimum amount for a payment, the currency being paid in, an expiry time and minimum/maximum quantity numbers (for purchasing multiple items).
This is all of the information necessary to fetch an actual invoice from the node that issued the offer. Someone who wants to pay an invoice does so over onion messages, one of the core features of BOLT 12. It allows nodes to make a direct, end-to-end-encrypted connection between each other that does not involve a Lightning channel. Just like Lightning payments, these can be used to onion route messages. After obtaining an offer, a payer will use the information encoded in it to send an invoice_request message. The creator of the offer will then respond back with an actual invoice.
There is also support for generating unique per user offers that allow the receiver to request a payment from the creator of the offer, similar to LNURL's withdrawal request feature. BOLT 12 invoices commit to a unique payer key — this can be used in the case of issuing refunds to prove you are the person who actually paid the invoice. This can also be used in combination with the withdrawal offer to guarantee that only the correct person can succeed in getting an invoice paid by the creator, as opposed to whoever is able to get a copy of the offer.
LNURL works just fine, and is already very widely adopted in the Lightning ecosystem, it is just not a realistic solution for users other than businesses or services. BOLT 12 as it is adopted can fill that gap, and provide the same streamlined user experience for end users at home who are not businesses.