- Add Google OAuth sign-in alongside magic link authentication - Username onboarding: require username selection after first sign-in - Public profile pages at /u/[username] with social links (GitHub, X) - Settings page for managing username and social links - Viewer header: unified floating card with project name, @username, breadcrumb - Guest CTA on viewer page prompting sign-in - Show owner avatar + username on community project cards - Redesigned project cards (larger preview, avatar + stats row below) - Consistent navbar across hub and profile pages with GitHub link - Footer with links to GitHub repo and npm packages - Borderless design with natural shadows throughout - Apple corner smoothing (squircle) progressive enhancement - cursor:pointer globally on buttons and links - DB migrations: username, github_url, x_url columns on auth_users - Root-level db:generate/migrate/push/studio scripts Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
50 lines
1.8 KiB
TypeScript
50 lines
1.8 KiB
TypeScript
import { createAuth } from '@pascal-app/auth/server'
|
|
import { db } from '@pascal-app/db'
|
|
import { Resend } from 'resend'
|
|
import { BASE_URL } from './utils'
|
|
|
|
// Initialize Resend only if API key is available
|
|
const resendApiKey = process.env.RESEND_API_KEY
|
|
const resend = resendApiKey && resendApiKey.trim() !== '' ? new Resend(resendApiKey) : null
|
|
|
|
export const auth = createAuth({
|
|
db,
|
|
appName: 'Pascal Editor',
|
|
baseURL: BASE_URL,
|
|
secret: process.env.BETTER_AUTH_SECRET!,
|
|
googleClientId: process.env.GOOGLE_CLIENT_ID,
|
|
googleClientSecret: process.env.GOOGLE_CLIENT_SECRET,
|
|
sendMagicLink: async ({ email, url }) => {
|
|
if (!resend) {
|
|
console.log(`[DEV] Magic link for ${email}: ${url}`)
|
|
return
|
|
}
|
|
|
|
try {
|
|
await resend.emails.send({
|
|
from: 'Pascal <noreply@pascal.app>',
|
|
to: email,
|
|
subject: 'Sign in to Pascal Editor',
|
|
html: `
|
|
<div style="font-family: Arial, sans-serif; max-width: 600px; margin: 0 auto;">
|
|
<h2>Sign in to Pascal Editor</h2>
|
|
<p>Click the button below to sign in to your account:</p>
|
|
<a href="${url}" style="display: inline-block; background-color: #000; color: #fff; padding: 12px 24px; text-decoration: none; border-radius: 6px; margin: 20px 0;">
|
|
Sign In
|
|
</a>
|
|
<p style="color: #666; font-size: 14px;">This link will expire in 5 minutes.</p>
|
|
<p style="color: #666; font-size: 14px;">If you didn't request this email, you can safely ignore it.</p>
|
|
</div>
|
|
`,
|
|
})
|
|
console.log(`✓ Magic link email sent to ${email}`)
|
|
} catch (error) {
|
|
console.error('Failed to send magic link email:', error)
|
|
throw error
|
|
}
|
|
},
|
|
})
|
|
|
|
export type Session = typeof auth.$Infer.Session
|
|
export type User = typeof auth.$Infer.Session.user
|