With Turbolinks, when you click to return to a page (not using the browser back button), Turbolinks will display a cached preview of the page while it attempts to grab the content from the server.

If you have a Stimulus object on the page (data-controller=), then the controller will be initialised twice. It will be called once for the cached page, and then again for the fresh page content.

It took me a while to figure out what was going on here and I’m really surprised that the Stimulus Turbolinks “One Two Punch” doesn’t handle this differently. It’s expected behaviour according to one of the Basecamp devs: