Start with scoped CSS. Copy view templates into your app when you need to change the markup.
Use the included styles
The default stylesheet uses latchkey-* classes and --latchkey-* custom properties without a global reset. The gem serves its browser assets from same-origin routes, including in hosts without an asset pipeline.
Use your own classes
Point to your compiled same-origin stylesheet, then map semantic class names. For example, with Bootstrap already installed in your host:
config.stylesheet = "/stylesheets/authentication.css"
config.css_classes = {
body: "bg-body-tertiary p-3",
panel: "container bg-white p-4",
field: "mb-3",
input: "form-control",
button: "btn btn-primary w-100",
notice: "alert alert-danger",
muted: "text-body-secondary",
link: "link-primary"
}Latchkey does not install a CSS framework. Tailwind uses the same mapping; include the initializer and any copied views in its class detection. Set config.stylesheet = nil to render without a stylesheet.
Copy the views
bin/rails generate latchkey:views --only=email_link
bin/rails generate latchkey:views --only=sessionsThe generator preserves existing files. Customize the copied partials and relevant layout, keeping form actions, CSRF fields, cache directives and same-origin assets intact. Token pages use a minimal layout; keep analytics and third-party assets out of it.
The development generator records original template versions and hashes in config/latchkey-ejections.json. Run bin/rails latchkey:doctor after a gem update to review changed upstream templates; repeated generation preserves your files. Commit that manifest with your host’s customizations.
Verify the new presentation
Exercise successful sign-in, validation failures, expired links and sign-out. Check narrow screens, keyboard focus and both Turbo and plain no-JavaScript navigation where allowed by policy. Keep submit controls usable in the initial HTML; provider checks must still be enforced server-side.