diff --git a/app/api/email/create-template/route.ts b/app/api/email/create-template/route.ts new file mode 100644 index 0000000..11912c9 --- /dev/null +++ b/app/api/email/create-template/route.ts @@ -0,0 +1,330 @@ +import { NextRequest, NextResponse } from 'next/server'; +import { Resend } from 'resend'; +import fs from 'fs'; +import path from 'path'; + +const resend = new Resend(process.env.RESEND_API_KEY); + +export async function POST(request: NextRequest) { + try { + const body = await request.json(); + + const { + templateName, + subject, + description, + senderName, + senderTitle, + senderEmail, + senderPhone, + variables + } = body; + + // Validate required fields + if (!templateName || !subject || !senderEmail) { + return NextResponse.json( + { error: 'Missing required fields: templateName, subject, senderEmail' }, + { status: 400 } + ); + } + + // Read the React Email component + const templatePath = path.join(process.cwd(), 'emails', 'SchoolWorkshopOutreachEmail.tsx'); + + if (!fs.existsSync(templatePath)) { + return NextResponse.json( + { error: 'Email template file not found' }, + { status: 404 } + ); + } + + const templateContent = fs.readFileSync(templatePath, 'utf8'); + + // Generate HTML for Resend template + const html = generateResendHTML(templateContent, variables || []); + + // Create template in Resend with variables + const templateVariables = variables.map((variable: any) => ({ + key: variable.name, + name: variable.name, + type: 'string', // Resend requires type: "string" or "number" + description: variable.description || `Variable for ${variable.name}` + })); + + const { data, error } = await resend.templates.create({ + name: templateName, + subject: subject, + html: html, + variables: templateVariables, + }); + + if (error) { + console.error('Resend API error:', error); + return NextResponse.json( + { error: error.message }, + { status: 400 } + ); + } + + return NextResponse.json({ + message: 'Template created successfully', + templateId: data.id, + templateName: templateName, + variables: variables || [] + }); + + } catch (error) { + console.error('API route error:', error); + return NextResponse.json( + { error: 'Internal server error' }, + { status: 500 } + ); + } +} + +function generateResendHTML(templateContent: string, variables: any[]) { + // Generate HTML with Resend variable syntax + let html = ` + + + + + ragTech School Workshop Outreach + + + +
+
+ +
+ +
+

{{{contactName ? 'Dear ' + contactName + ',' : 'Dear [Contact Person Name],'}}}

+ +

+ I hope this email finds you well. My name is {{{senderName}}} from ragTech, and I'm reaching out because we believe your students at {{{schoolName}}} would benefit from our hands-on technology workshops delivered by practising software engineers. +

+ +

Who We Are

+

+ ragTech brings real engineers who are actively building technology into classrooms. We're not professional trainers who used to work in tech — we're engineers who are still coding, still learning, and bringing that real-world experience into every session. +

+ +

+ Our Tech Podcast: We host the ragTech Podcast where we explore the topics and questions that matter in tech today — from AI ethics and career growth to responsible innovation and community building. Our podcast reflects our approach: honest conversations, practical insights, and making complex tech topics accessible to everyone. +

+ +

Meet Our Speakers

+ +
+
+
+ Saloni +
+
+
Saloni
+
Senior Software Engineer, Co-Director (WomenDevs SG)
+
+ Engineering leader who turns complex software and AI concepts into practical workflows teams can apply immediately. +
+
+ Expertise: AI 101 for Developers, Tech Concepts for Product Managers, Interview Preparation +
+
+
+
+ +
+
+
+ Victoria +
+
+
Victoria
+
Solutions Architect, GitHub Star, Co-Director (WomenDevs SG)
+
+ Solutions architect and technical communicator known for making advanced topics accessible and actionable. +
+
+ Expertise: System Design, Personal Branding, Technical Writing, GitHub Best Practices +
+
+
+
+ +
+
+
+ Natasha +
+
+
Natasha
+
Software Engineer, Partnerships Lead (WomenDevs SG)
+
+ Builder and facilitator focused on responsible tech adoption, community leadership, and 0 to 1 product execution. +
+
+ Expertise: AI Ethics, Responsible Tech, Community Leadership, Women in Tech Empowerment +
+
+
+
+ +

Our School Workshops

+

+ We offer a range of programmes designed for different age groups and learning objectives: +

+ +
+
šŸ’» Intro to Coding
+
+ Perfect for complete beginners. Students write their first lines of real code and solve mini challenges. +
+
    +
  • Available in Python, JavaScript, or web basics (HTML/CSS)
  • +
  • Duration: 60-90 minutes
  • +
  • Levels: Secondary, JC, and polytechnic/university
  • +
+
+ +
+
šŸ¤– Gen AI & Tech Literacy
+
+ Interactive demos with live AI tools. Covers how AI works, responsible usage, bias, and ethics. +
+
    +
  • Students learn when to trust (and when NOT to trust) AI
  • +
  • Duration: 60-90 minutes
  • +
  • Levels: Secondary, JC, and polytechnic/university
  • +
+
+ +
+
šŸ› ļø Mini Hackathon
+
+ Team-based problem-solving experience. Perfect for innovation days or orientation events. +
+
    +
  • Themes: sustainability tech, community apps, AI for good
  • +
  • Duration: Half-day or full-day
  • +
  • Levels: Secondary school through university
  • +
+
+ +
+
🌱 Tech & Sustainability
+
+ Explores tech's environmental impact (carbon cost of AI, e-waste). Discussion-based activities included. +
+
    +
  • Adaptable for geography, computing, or general science classes
  • +
  • Duration: 45-60 minutes
  • +
  • Levels: Secondary school through university
  • +
+
+ +
+
šŸš€ Breaking Into Tech
+
+ Career guidance from working engineers. Debunks myths about who belongs in tech. +
+
    +
  • Real playbook for getting started in tech careers
  • +
  • Duration: 45-90 minutes
  • +
  • Levels: Upper secondary through university
  • +
+
+ +

Flexible Delivery Formats

+

+ We fit around your timetable and event needs: +

+ + +

Why Schools Choose ragTech

+ + +

See Us in Action

+

+ You can watch our speakers in action: +

+ + +

Let's Tailor Something for {{{schoolName}}}

+

+ I'd love to schedule a brief 15-minute call to discuss: +

+ + +

+ Visit our full workshop catalogue: https://ragtechdev.com/workshops/school +

+ + + +

+ Looking forward to potentially bringing real tech education to your students! +

+ +

+ Best regards,
+ {{{senderName}}}
+ {{{senderTitle}}}
+ ragTech
+ {{{senderEmail}}}
+ {{{senderPhone}}}
+ ragtechdev.com +

+
+
+ +`; + + return html; +} diff --git a/app/components/BusinessCard.tsx b/app/components/BusinessCard.tsx index 652deb4..2d7f302 100644 --- a/app/components/BusinessCard.tsx +++ b/app/components/BusinessCard.tsx @@ -12,11 +12,20 @@ interface BusinessCardProps { onClose: () => void; } -export default function BusinessCard({ - member, - onClose, -}: BusinessCardProps) { - const { name, role, email, linkedInUrl, image, color, roleColor } = member; +export default function BusinessCard({ member, onClose }: BusinessCardProps) { + const { + name, + role, + email, + linkedInUrl, + image, + color, + roleColor, + experienceSummary, + experienceHighlights, + featuredLinks, + } = member; + const [qrModal, setQrModal] = useState<{ isOpen: boolean; value: string; @@ -42,7 +51,6 @@ export default function BusinessCard({ {member && ( <> - {/* Backdrop */} - {/* Business Card */}
e.stopPropagation()} > - {/* Close Button */} - {/* Card Header with Profile */}
- {name} + {name}
-

- {name} -

-

+

{name}

+

{role}

-

- ragTech -

+

ragTech

- {/* Contact Information */}
- {/* Email */} - {/* Quick Connect Section */} + {experienceSummary ? ( +
+

+ {experienceSummary} +

+
+ ) : null} + + {experienceHighlights && experienceHighlights.length > 0 ? ( +
+

+ Workshop and Speaking Experience +

+
    + {experienceHighlights.map((highlight) => ( +
  • + {highlight} +
  • + ))} +
+
+ ) : null} + + {featuredLinks && featuredLinks.length > 0 ? ( +
+ ) : null} +

Quick Connect

- {/* LinkedIn */} {linkedInUrl && ( )} - {/* FutureNet Quiz */} - {/* Techie Taboo */}
- {/* Tagline */}

Building technology that empowers communities @@ -199,7 +207,6 @@ export default function BusinessCard({ )} - {/* QR Modal */} {link.external ? ( {link.label} + ) : link.children ? ( + <> + + {link.label} + + +

+
+ {link.children.map((child) => ( + + {child.label} + + ))} +
+
+ ) : ( ) : ( - setIsMobileMenuOpen(false)} - className="text-brown hover:text-brownDark transition-colors duration-300 font-semibold py-2" - > - {link.label} - +
+ setIsMobileMenuOpen(false)} + className="text-brown hover:text-brownDark transition-colors duration-300 font-semibold py-2 inline-block" + > + {link.label} + + {link.children ? ( +
+ {link.children.map((child) => ( + setIsMobileMenuOpen(false)} + className="text-sm text-brownDark hover:text-brown font-semibold" + > + {child.label} + + ))} +
+ ) : null} +
) ))}
diff --git a/app/components/TeamMemberCard.tsx b/app/components/TeamMemberCard.tsx index a1d8da3..78b612e 100644 --- a/app/components/TeamMemberCard.tsx +++ b/app/components/TeamMemberCard.tsx @@ -6,6 +6,9 @@ export interface TeamMember { name: string; role: string; description: string; + experienceSummary?: string; + experienceHighlights?: string[]; + featuredLinks?: { label: string; href: string }[]; color: string; roleColor: string; image: string; @@ -31,24 +34,40 @@ export default function TeamMemberCard({ member, index, onClick }: TeamMemberCar onClick={() => onClick(member)} >
- {member.name} + {member.name}
-

- {member.name} -

+

{member.name}

{member.role}

-

- {member.description} -

+

{member.description}

+ + {member.experienceSummary ? ( +
+

+ {member.experienceSummary} +

+
+ ) : null} + + {member.experienceHighlights && member.experienceHighlights.length > 0 ? ( +
+

+ Experience Highlights +

+
    + {member.experienceHighlights.slice(0, 2).map((highlight) => ( +
  • + {highlight} +
  • + ))} +
+
+ ) : null} +

- Tap to view business card → + Tap to view business card ->

diff --git a/app/data/team.ts b/app/data/team.ts index adba3f0..ca7df4b 100644 --- a/app/data/team.ts +++ b/app/data/team.ts @@ -3,9 +3,21 @@ import type { TeamMember } from '../components/TeamMemberCard'; export const team: TeamMember[] = [ { name: 'Saloni', - role: 'Software Developer', + role: 'Senior Software Engineer, Co-Director (WomenDevs SG)', description: - 'Software developer who loves breaking down complex concepts into bite-sized, understandable pieces.', + 'Engineering leader who turns complex software and AI concepts into practical workflows teams can apply immediately.', + experienceSummary: + '10+ years in software engineering with workshop leadership across developer and product audiences.', + experienceHighlights: [ + 'Led AI 101 for Software Developers workshop: practical guidance on where AI helps and where engineering judgment still matters.', + 'Teaches concrete AI usage patterns including scoped coding tasks, PR review support, framework explanations, test generation, and repetitive workflow automation.', + 'Demonstrated AI-assisted app building with side-by-side comparisons against traditional implementation approaches.', + 'Delivered Tech Concepts for Product Managers sessions covering CI/CD, LLM fundamentals, and model limitations beyond prompt-only usage.', + 'Created Interview Ready online course content for developers preparing for technical interviews.', + ], + featuredLinks: [ + { label: 'Interview Ready Online Course Series', href: 'https://www.youtube.com/watch?v=WJS2QeE1_-4' }, + ], color: 'from-primary/20 to-primary/5', roleColor: '#fda2a9', image: '/assets/team/saloni.png', @@ -14,9 +26,20 @@ export const team: TeamMember[] = [ }, { name: 'Victoria', - role: 'Solutions Engineer', + role: 'Solutions Architect, GitHub Star, Co-Director (WomenDevs SG)', description: - 'Combines technical expertise with storytelling to make tech topics engaging and relatable.', + 'Solutions architect and technical communicator known for making advanced topics accessible and actionable.', + experienceSummary: + 'One of only two GitHub Stars in Singapore, with startup and large fintech architecture experience.', + experienceHighlights: [ + 'Delivered How to Make Opportunities Find You: Personal Branding 101 at NTU, based on a long-term practical visibility framework.', + 'Runs system design interview prep workshops with concise frameworks, practical examples, and collaborative exercises.', + 'Facilitated hands-on group design sessions, including Netflix-style system design problem solving.', + 'Recognized technical blogger with six years of consistent technical writing and community education.', + ], + featuredLinks: [ + { label: 'Technical Blog by Victoria', href: 'https://lo-victoria.com/' }, + ], color: 'from-secondary/20 to-secondary/5', roleColor: '#a2d4d1', image: '/assets/team/victoria.png', @@ -25,9 +48,33 @@ export const team: TeamMember[] = [ }, { name: 'Natasha', - role: 'Software Engineer', + role: 'Software Engineer, Partnerships Lead (WomenDevs SG)', description: - 'Passionate about making technology inclusive and accessible for everyone, regardless of their background.', + 'Builder and facilitator focused on responsible tech adoption, community leadership, and 0 to 1 product execution.', + experienceSummary: + 'Masters in Computer Information Systems (Boston University), UCLA Global Studies with Digital Humanities minor, plus startup and US venture accelerator experience.', + experienceHighlights: [ + 'Designed and facilitated a 1-hour Intentional AI workshop for STT Global Data Centres using custom cards to evaluate high-impact vs low-impact AI use cases for operations.', + 'Included live demos of generating SVG code for image alternatives in selected scenarios to support more conscious resource usage decisions.', + 'Organized and facilitated the ethics panel Navigating the Ethical Landscape of AI: Causality, Principles and Perspectives.', + 'Hosted multiple women empowerment workshops on speaking up, communication, and confidence in tech spaces.', + 'NTU Women in Tech mentor and facilitator of networking sessions for technologists using technical analogies for collaboration strategy.', + 'Led open source community efforts including month-long Hacktoberfest programming with livestream contribution guides.', + ], + featuredLinks: [ + { + label: 'Navigating the Ethical Landscape of AI Panel', + href: 'https://www.youtube.com/watch?v=BPYt_Xs20q8&t=1400s', + }, + { + label: 'Networking for Techies - JuniorDevSG', + href: 'https://www.youtube.com/watch?v=oE_EWQUYpj8&t=6s', + }, + { + label: 'Website', + href: 'https://natashaannn.com/', + }, + ], color: 'from-accent/20 to-accent/5', roleColor: '#eec08c', image: '/assets/team/natasha.png', diff --git a/app/workshops/corporate/page.tsx b/app/workshops/corporate/page.tsx new file mode 100644 index 0000000..8985ba1 --- /dev/null +++ b/app/workshops/corporate/page.tsx @@ -0,0 +1,414 @@ +'use client'; + +import Link from 'next/link'; +import Image from 'next/image'; +import { useMemo, useState } from 'react'; +import { motion } from 'framer-motion'; +import Hero from '../../components/Hero'; +import BusinessCard from '../../components/BusinessCard'; +import TeamMemberCard, { TeamMember } from '../../components/TeamMemberCard'; +import { team } from '../../data/team'; + +const workshops = [ + { + tag: 'FOR ENGINEERING TEAMS', + title: 'Intentional AI for High-Impact Delivery', + description: + 'A practical workshop for engineering and operations teams to evaluate where AI adds meaningful value and where it introduces unnecessary cost, risk, or resource usage.', + highlights: [ + '60-90 minute format for teams and leadership groups', + 'Custom scenario cards mapped to your business domain', + 'Team exercise: classify high-impact vs low-impact AI use cases', + 'Focus on responsible resource usage, including energy and water awareness', + 'Includes live technical demonstrations for implementation decisions', + ], + image: '/workshop/intentional-ai-corporate-workshop.jpg', + speakerNote: 'Designed and facilitated by Natasha', + }, + { + tag: 'FOR SOFTWARE ENGINEERS', + title: 'AI 101 for Software Developers', + description: + 'A hands-on session for developers who want practical AI workflows they can use immediately in day-to-day engineering work.', + highlights: [ + '60-90 minute workshop with implementation-focused guidance', + 'Covers scoped coding tasks, PR review, framework explainers, and test generation', + 'Discusses where AI improves velocity and where human judgment is critical', + 'Includes live app-building workflow demonstrations', + 'Delivered with real examples from production engineering contexts', + ], + image: '/workshop/saloni-ai-101-for-software-developers.jpg', + speakerNote: 'Delivered by Saloni', + }, + { + tag: 'FOR PRODUCT AND BUSINESS', + title: 'Tech Concepts for Product Managers', + description: + 'Bridge the communication gap between product, engineering, and business stakeholders with practical explanations of modern delivery systems and AI foundations.', + highlights: [ + '60-90 minute workshop for PMs and cross-functional teams', + 'Covers CI/CD, LLM fundamentals, and common misconceptions', + 'Explains limitations, reliability, and risk in AI-enabled product decisions', + 'Analogy-based teaching for non-engineering audiences', + 'Can run standalone or as a companion to AI 101 for engineers', + ], + image: '/workshop/saloni-tech-concepts-for-pm-workshop.jpg', + speakerNote: 'Delivered by Saloni', + }, + { + tag: 'FOR LEADERSHIP AND EVENTS', + title: 'Navigating AI Ethics and Governance', + description: + 'A facilitated panel or keynote format for leaders and practitioners exploring ethics principles, accountability, and practical governance for AI initiatives.', + highlights: [ + '60-90 minute panel, fireside, or keynote options', + 'Topics include bias, accountability, and decision-making tradeoffs', + 'Designed for leadership offsites, innovation forums, and internal summits', + 'Includes moderated Q and A with audience engagement', + 'Can be customized to industry-specific policy and risk concerns', + ], + image: '/workshop/natasha-tech-sustainability-panel.jpg', + speakerNote: 'Organized and facilitated by Natasha', + videoUrl: 'https://www.youtube.com/watch?v=BPYt_Xs20q8&t=1400s', + }, + { + tag: 'FOR INNOVATION PROGRAMS', + title: 'Hackathon Facilitation and Judging', + description: + 'From kickoff design to final judging, we support corporate hackathons with clear challenge framing, mentoring, and evaluation criteria.', + highlights: [ + 'Half-day, full-day, and multi-week innovation formats', + 'Mentor office hours, judging rubrics, and finalist showcase support', + 'Themes available: AI for good, open source, sustainability tech', + 'Hybrid and livestream support for distributed teams', + 'Delivered by facilitators with hands-on hackathon judge experience', + ], + image: '/workshop/natasha-intentional-ai-workshop.jpg', + speakerNote: 'Facilitated by the RagTech team', + }, +]; + +const formats = [ + { label: 'Lunch and Learn', duration: '45-60 min', desc: 'Focused sessions for department-wide upskilling' }, + { label: 'Team Workshops', duration: '60-120 min', desc: 'Hands-on collaborative working sessions' }, + { label: 'Leadership Briefings', duration: '45-90 min', desc: 'Decision-oriented sessions for leads and managers' }, + { label: 'Hackathons', duration: 'Half day to multi-week', desc: 'Innovation programs with mentoring and judging' }, +]; + +const icebreakerFeatures = [ + 'Custom Techie Taboo cards adapted to your team context and vocabulary', + 'Gets technical and non-technical stakeholders aligned quickly', + 'Creates shared language before deeper workshop discussion', + 'Can be included as a standalone team-building activity', +]; + +const featuredVideos = [ + { + title: 'Navigating the Ethical Landscape of AI: Causality, Principles and Perspectives', + speaker: 'Organized and facilitated by Natasha', + src: 'https://www.youtube.com/embed/BPYt_Xs20q8?start=1400', + }, + { + title: 'Networking for Techies - JuniorDevSG', + speaker: 'By Natasha', + src: 'https://www.youtube.com/embed/oE_EWQUYpj8?start=6', + }, + { + title: 'Interview Ready Online Course Series', + speaker: 'By Saloni', + src: 'https://www.youtube.com/embed/WJS2QeE1_-4', + }, +]; + +const audiences = [ + { label: 'Engineering Teams', icon: 'ENG' }, + { label: 'Product and Design', icon: 'PM' }, + { label: 'Data and AI Teams', icon: 'AI' }, + { label: 'Leadership Groups', icon: 'LDR' }, + { label: 'Innovation Programs', icon: 'INN' }, + { label: 'Internal Tech Communities', icon: 'COM' }, +]; + +export default function CorporateWorkshopsPage() { + const [selectedMember, setSelectedMember] = useState(null); + const speakers = useMemo( + () => team.filter((member) => ['Natasha', 'Saloni', 'Victoria'].includes(member.name)), + [] + ); + + return ( +
+ + +
+
+

+ We work with +

+
+ {audiences.map((a) => ( + + {a.icon} {a.label} + + ))} +
+
+
+ +
+
+ +
+ Techie Taboo card front +
+
+

Our Signature Icebreaker

+

+ Techie Taboo for Teams +

+

+ We use our custom Techie Taboo card game to kick off corporate workshops. It quickly creates shared context, + encourages participation, and makes complex topics easier to discuss across functions. +

+
    + {icebreakerFeatures.map((item) => ( +
  • + - + {item} +
  • + ))} +
+
+
+
+
+ +
+
+ +

+ Corporate Programmes +

+

+ Each programme is tailored to your team goals, role mix, and delivery context. +

+
+ +
+ {workshops.map((workshop, index) => ( + +
+ {workshop.title} +
+ +
+

{workshop.tag}

+

{workshop.title}

+

{workshop.description}

+

{workshop.speakerNote}

+

+ Programme Highlights +

+
    + {workshop.highlights.map((item) => ( +
  • + - + {item} +
  • + ))} +
+
+ + Book This Session + + {workshop.videoUrl ? ( + + Watch Recording + + ) : null} +
+
+
+ ))} +
+
+
+ +
+
+ +

+ Delivery Formats +

+

+ We adapt to your team structure, timeline, and operating cadence. +

+
+
+ {formats.map((format, index) => ( + +

{format.label}

+

{format.duration}

+

{format.desc}

+
+ ))} +
+
+
+ +
+
+ +

+ Meet the Speakers +

+

+ Practicing engineers and tech leaders who bring implementation reality into every session. +

+
+
+ {speakers.map((member, index) => ( +
+ +
+ ))} +
+
+
+ +
+
+ +

+ See Us in Action +

+

+ Recordings from talks and sessions led by our facilitators. +

+
+
+ {featuredVideos.map((video, index) => ( + +
+