Flow: enter email → magic link → verified → Stripe checkout → dashboard - SessionsController: new/create (send magic link), sent, verify, destroy - Customer model: generate_magic_token!, magic_token_valid?, verify_email! - Migration: magic_token, magic_token_expires_at, email_verified_at + unique indexes - CustomerMailer + mailer layout with magic link email (html + text) - CheckoutController: GET /checkout/start requires auth, passes customer_id as Stripe metadata; webhook finds customer by metadata and updates record - DashboardController: requires auth, uses current_customer from session - ApplicationController: current_customer, require_auth, redirect_after_auth (stores return_to so verify sends user back to where they were headed) - Resend gem + initializer; production uses :resend delivery method - Dev logs magic link URL to Rails logger instead of sending email - Pricing page: simple link to /checkout/start (no more JS fetch) - Layout: Sign in / Dashboard / Sign out nav links Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
34 lines
1.2 KiB
Text
34 lines
1.2 KiB
Text
<% content_for :title, "Sign in — Crimata" %>
|
|
|
|
<style>
|
|
.auth-wrap { max-width: 400px; margin: 0 auto; padding-top: 2rem; }
|
|
.auth-wrap h1 { font-size: 1.75rem; font-weight: 700; letter-spacing: -0.5px; margin-bottom: 0.5rem; }
|
|
.auth-wrap p { color: #555; margin-bottom: 2rem; font-size: 0.95rem; }
|
|
.auth-wrap input[type=email] {
|
|
width: 100%; padding: 0.875rem 1rem;
|
|
border: 1px solid #ddd; border-radius: 8px;
|
|
font-size: 1rem; margin-bottom: 1rem; outline: none;
|
|
transition: border-color 0.15s;
|
|
}
|
|
.auth-wrap input[type=email]:focus { border-color: #111; }
|
|
.auth-wrap .btn { width: 100%; text-align: center; }
|
|
.alert { color: #c0392b; font-size: 0.875rem; margin-bottom: 1rem; }
|
|
</style>
|
|
|
|
<div class="auth-wrap">
|
|
<h1>Create your account</h1>
|
|
<p>Enter your email and we'll send you a sign-in link — no password needed.</p>
|
|
|
|
<% if flash[:alert] %>
|
|
<p class="alert"><%= flash[:alert] %></p>
|
|
<% end %>
|
|
|
|
<%= form_with url: login_path, method: :post do |f| %>
|
|
<%= f.email_field :email,
|
|
placeholder: "you@example.com",
|
|
autofocus: true,
|
|
autocomplete: "email",
|
|
required: true %>
|
|
<%= f.submit "Send sign-in link", class: "btn" %>
|
|
<% end %>
|
|
</div>
|