For new projects it's very nice that Tapestry 5.4 uses and includes Bootstrap. But for existing 5.2 and 5.3 projects not already using Bootstrap (which is probably the vast majority), upgrading to 5.4 requires a burdensome amount of CSS and HTML changes. Even if you go the route of eliminating the Bootstrap CSS file (which for large existing apps may be the only practical option), you still need to come up with all new CSS rules for the built-in Tapestry components -- Grid, BeanEditor, Palette, etc -- on your own.
Back in August, Tapestry 5.4-alpha-18 switched from Bootstrap 2 to Bootstrap 3. Since 2 and 3 are incompatible, this meant Howard had to do another round of disruptive, non-backward-compatible changes to Tapestry components (see his commits between Aug 21 and Sep 3, for TAP5-2151), and all users tracking the alphas had to adapt their apps to use Bootstrap 3. What happens if you wanted to stick with Bootstrap 2? What happens when Bootstrap 4 comes out? As we all know, one of Tapestry's "core principles" is backward compatibility -- which means upgrades should be very easy. It occurred to me that Tapestry already has a built-in means for rendering alternate content for the same components -- the template skinning mechanism (http://blog.tapestry5.de/index.php/2011/06/24/template-skinning/). Could this mechanism be used for the Bootstrap compatibility problem? Could Tapestry use Template Skinning internally to choose between "Bootstrap 2", "Bootstrap 3" and "Tapestry Classic" templates based on a configured symbol? One obstacle is that most of Tapestry's built-in components render the CSS class names and layout directly from the component class (using MarkupWriter) rather than using a template. In the cases I looked at, though, this could be changed. For example, TextField's has this: writer.element("input","type",type,"name", getControlName(),"class", "form-control","id", getClientId(),"value", value,"size", getWidth()); but that could be moved to a TextField.tml file: <input type="${type}" name="${controlName}" class="form-control" id="${clientId}" value="${value}" size="${width}" /> It's not quite that simple, of course. The templates might end up with some "if" statements wrapped around some sections to handle logic that now resides in the component class. But that's okay, because it still allows us to have alternate versions of the templates for different skins/themes. By my count there are 14 components that have Bootstrap-related rendering (Alerts, BeanEditForm, BeanEditor, Checkbox, Checklist, ControlGroup, DateField, Errors, Palette, PasswordField, Radio, Select, TextArea, TextField), and of those, only BeanEditForm/BeanEditor, Checklist use templates.
