Initial commit

This commit is contained in:
Jennie Robinson Faber 2025-08-26 14:17:16 +01:00
parent 6fc1013745
commit 826517a798
18 changed files with 16576 additions and 0 deletions

View file

@ -0,0 +1,32 @@
// server/api/auth/login.post.js
import jwt from 'jsonwebtoken'
import Member from '~/server/models/member'
export default defineEventHandler(async (event) => {
const { email } = await readBody(event)
const member = await Member.findOne({ email })
if (!member) {
throw createError({ statusCode: 404 })
}
// Send magic link via Resend
const token = jwt.sign(
{ memberId: member._id },
process.env.JWT_SECRET,
{ expiresIn: '7d' }
)
await resend.emails.send({
from: 'Ghost Guild <noreply@ghostguild.org>',
to: email,
subject: 'Your Ghost Guild login link',
html: `
<a href="https://ghostguild.org/auth/verify?token=${token}">
Click here to log in
</a>
`
})
return { success: true }
})

View file

@ -0,0 +1,25 @@
// server/models/member.js
import mongoose from 'mongoose'
const memberSchema = new mongoose.Schema({
email: { type: String, required: true, unique: true },
name: { type: String, required: true },
circle: {
type: String,
enum: ['community', 'founder', 'practitioner'],
required: true
},
contributionTier: {
type: String,
enum: ['0', '5', '15', '30', '50'],
required: true
},
helcimCustomerId: String,
helcimSubscriptionId: String,
slackInvited: { type: Boolean, default: false },
createdAt: { type: Date, default: Date.now },
lastLogin: Date
})
export default mongoose.model('Member', memberSchema)

29
server/emails/welcome.js Normal file
View file

@ -0,0 +1,29 @@
// server/emails/welcome.js
export const welcomeEmail = (member) => ({
from: 'Ghost Guild <welcome@ghostguild.org>',
to: member.email,
subject: 'Welcome to Ghost Guild! 👻',
html: `
<div style="font-family: sans-serif; max-width: 600px; margin: 0 auto;">
<h1>Welcome to the community, ${member.name}!</h1>
<p>You've joined the <strong>${member.circle} circle</strong>
with a ${member.contributionTier}/month contribution.</p>
<h2>Your next steps:</h2>
<ol>
<li>Watch for your Slack invite (within 24 hours)</li>
<li>Explore the <a href="https://ghostguild.org/members/resources">resource library</a></li>
<li>Introduce yourself in #introductions</li>
</ol>
<p>Thank you for being part of our solidarity economy!</p>
<hr style="margin: 30px 0; border: 1px solid #eee;">
<p style="color: #666; font-size: 14px;">
Questions? Reply to this email or reach out in Slack.
</p>
</div>
`
})

24
server/models/member.js Normal file
View file

@ -0,0 +1,24 @@
// server/models/member.js
import mongoose from 'mongoose'
const memberSchema = new mongoose.Schema({
email: { type: String, required: true, unique: true },
name: { type: String, required: true },
circle: {
type: String,
enum: ['community', 'founder', 'practitioner'],
required: true
},
contributionTier: {
type: String,
enum: ['0', '5', '15', '30', '50'],
required: true
},
helcimCustomerId: String,
helcimSubscriptionId: String,
slackInvited: { type: Boolean, default: false },
createdAt: { type: Date, default: Date.now },
lastLogin: Date
})
export default mongoose.model('Member', memberSchema)