Warm the pot: Heat the olive oil in a large pot over medium heat. Add onion, carrots, and celery.
Cook for 6–8 minutes, stirring occasionally, until softened and lightly golden.
Add aromatics: Stir in garlic, salt, pepper, rosemary, thyme, oregano, and red pepper flakes (if using). Cook for 1 minute until fragrant.
Build the base: Add the cannellini beans, broth, and bay leaf. If using, drop in the Parmesan rind.
Bring to a gentle simmer.
Simmer: Cook uncovered for 15 minutes to let the flavors meld. If the soup looks too thick, add up to 1 cup water.
Blend for creaminess: Use an immersion blender to blend the soup briefly, 3–5 pulses, leaving plenty of whole beans and veggies. Alternatively, scoop out 2 cups of soup, blend until smooth, and return to the pot.
Add greens: Stir in kale or spinach and simmer 3–4 minutes until wilted and tender.
Finish: Remove bay leaf and Parmesan rind.
Stir in lemon zest and juice. Taste and adjust seasoning with more salt and pepper as needed.
Serve: Ladle into bowls. Top with a drizzle of olive oil, grated Parmesan, and parsley.
Add crusty bread on the side.