Peel and thinly slice the onions into half-moons, about 1/8-inch thick for even cooking.
Heat the butter and olive oil in a heavy-bottomed pot or Dutch oven over medium heat.
Add the onions and a pinch of salt. Cook slowly, stirring every 5-10 minutes, until the onions are golden brown and jammy. This takes about 35-45 minutes.
Pour in the white wine (or 1/2 cup broth if not using wine) to deglaze the pot. Scrape up the browned bits from the bottom with a wooden spoon and let the liquid reduce for 2-3 minutes.
Add the broth, thyme, and bay leaf to the pot. Bring to a gentle simmer, cover partially, and cook for 20-30 minutes to allow the flavors to meld.
Taste and adjust seasoning with salt and pepper as needed. Remove the thyme sprigs and bay leaf before serving.
Preheat the broiler. Arrange the baguette slices on a baking sheet and toast under the broiler for 1-2 minutes per side, until golden.
Grate the Gruyère cheese and set aside.
Ladle the hot soup into oven-safe bowls, leaving room at the top.
Float a toasted baguette slice on each bowl and top generously with grated Gruyère.
Place the bowls on a baking sheet and broil for 2-3 minutes, or until the cheese is melted, bubbly, and golden brown. Watch carefully to prevent burning.
Carefully remove the bowls from the oven (they’ll be hot!) and let them cool for a minute.
Serve immediately and enjoy your delicious French onion soup!