Go to file
2026-03-12 00:53:32 +03:00
public feat: white preview bg and html export 2026-03-12 00:23:10 +03:00
src feat: footer social links, cancel appointment button, Resend-ready docs 2026-03-12 00:53:32 +03:00
.gitignore first commit 2026-03-12 00:19:52 +03:00
eslint.config.js first commit 2026-03-12 00:19:52 +03:00
index.html first commit 2026-03-12 00:19:52 +03:00
package-lock.json first commit 2026-03-12 00:19:52 +03:00
package.json first commit 2026-03-12 00:19:52 +03:00
README.md feat: footer social links, cancel appointment button, Resend-ready docs 2026-03-12 00:53:32 +03:00
tsconfig.app.json first commit 2026-03-12 00:19:52 +03:00
tsconfig.json first commit 2026-03-12 00:19:52 +03:00
tsconfig.node.json first commit 2026-03-12 00:19:52 +03:00
vite.config.ts first commit 2026-03-12 00:19:52 +03:00

Yaltopia Home Email Template Studio

This project is a small React app used to preview transactional email templates that will be sent through Resend for Yaltopia Home.

All templates share a white + black theme with a strong card layout and a "Powered by Yaltopia Home" footer, similar to the design references you provided.

Tech stack

  • React + TypeScript (Vite)
  • Plain CSS for layout and email styling (no CSS framework)

Running locally

npm install
npm run dev

Then open the printed URL (usually http://localhost:5173) in your browser.

The left sidebar lets you switch between templates, and the preview panel shows how each email looks on desktop and mobile widths.

Email templates

All templates live in src/email/templates.tsx and are wired with sample data in src/email/sampleData.ts.

  • InvitationTeamMemberEmail invitation for new team members to join a Yaltopia Home workspace.
  • PropertyRequestReceivedEmail confirms a property search request has been received.
  • PropertyFoundRequestEmail notifies when a matching property has been found.
  • BillPaymentReminderEmail reminder for rent, water, security, and electric charges with either a payment link or bank details.
  • NewsletterEmail simple newsletter layout with multiple article cards.
  • OwnerSuccessEmail sent to owners after a successful sale or rental.
  • ListingApprovedEmail confirms that a listing is approved and visible to the public.
  • AppointmentBookedEmail confirms a viewing appointment and provides an "Add to calendar" link.
  • PasswordResetEmail password reset flow with short-lived link copy.

All templates are wrapped with BaseEmailShell, which lives in src/email/BaseEmailShell.tsx and provides the shared header, frame, and footer.

Using with Resend

These templates are ready to use with Resend. They are plain React components that render to static HTML with:

  • Footer: Social links (Instagram, X, YouTube, Facebook, LinkedIn), "Powered by Yaltopia Home", and a verification link. Override links via socialLinks on BaseEmailShell.
  • Logo: Pass logoUrl (absolute URL) when sending so the logo loads in email clients (e.g. https://yaltopia.home/logo.svg).
  • Appointment email: Includes "Add to calendar" and "Cancel appointment" buttons; pass calendarUrl and cancelUrl from your backend.

You can use them in two ways:

  1. React (recommended) Use the react option in resend.emails.send() and pass the template component with props. Resend will render to HTML.
  2. HTML Use the HTML tab in the preview app to copy the full HTML for a template, then use it as a custom template in Resend (replace placeholders with your variables).

When integrating, replace sample props with real data and generate all URLs (payment, calendar, cancel, reset) from your backend.

Example: sending via Resend with React

import { Resend } from 'resend'
import { InvitationTeamMemberEmail, AppointmentBookedEmail } from './src/email/templates'
import { BaseEmailShell } from './src/email/BaseEmailShell'

const resend = new Resend(process.env.RESEND_API_KEY)

// Optional: override footer social links and logo for all emails
const sharedShellProps = {
  socialLinks: {
    instagram: 'https://instagram.com/youraccount',
    twitter: 'https://x.com/youraccount',
    facebook: 'https://facebook.com/youraccount',
  },
  logoUrl: 'https://yaltopia.home/assets/logo.svg',
}

await resend.emails.send({
  from: 'Yaltopia Home <no-reply@yaltopia.home>',
  to: 'user@example.com',
  subject: 'You have been invited to Yaltopia Home',
  react: (
    <InvitationTeamMemberEmail
      recipientName="Jane Doe"
      teamName="Yaltopia Home Ops"
      role="Leasing Manager"
      inviteUrl="https://yaltopia.home/invite/abc123"
    />
  ),
})

// Appointment with calendar + cancel
await resend.emails.send({
  from: 'Yaltopia Home <no-reply@yaltopia.home>',
  to: 'user@example.com',
  subject: 'Your viewing appointment is confirmed',
  react: (
    <AppointmentBookedEmail
      recipientName="Jane Doe"
      date="February 15, 2026"
      time="2:00 PM"
      timezone="EAT"
      location="123 Property St, Gate A"
      agentName="Amara, Yaltopia Home"
      calendarUrl="https://yaltopia.home/calendar/add/apt-123"
      cancelUrl="https://yaltopia.home/appointments/apt-123/cancel"
    />
  ),
})

React + TypeScript + Vite

This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.

Currently, two official plugins are available:

React Compiler

The React Compiler is not enabled on this template because of its impact on dev & build performances. To add it, see this documentation.

Expanding the ESLint configuration

If you are developing a production application, we recommend updating the configuration to enable type-aware lint rules:

export default defineConfig([
  globalIgnores(['dist']),
  {
    files: ['**/*.{ts,tsx}'],
    extends: [
      // Other configs...

      // Remove tseslint.configs.recommended and replace with this
      tseslint.configs.recommendedTypeChecked,
      // Alternatively, use this for stricter rules
      tseslint.configs.strictTypeChecked,
      // Optionally, add this for stylistic rules
      tseslint.configs.stylisticTypeChecked,

      // Other configs...
    ],
    languageOptions: {
      parserOptions: {
        project: ['./tsconfig.node.json', './tsconfig.app.json'],
        tsconfigRootDir: import.meta.dirname,
      },
      // other options...
    },
  },
])

You can also install eslint-plugin-react-x and eslint-plugin-react-dom for React-specific lint rules:

// eslint.config.js
import reactX from 'eslint-plugin-react-x'
import reactDom from 'eslint-plugin-react-dom'

export default defineConfig([
  globalIgnores(['dist']),
  {
    files: ['**/*.{ts,tsx}'],
    extends: [
      // Other configs...
      // Enable lint rules for React
      reactX.configs['recommended-typescript'],
      // Enable lint rules for React DOM
      reactDom.configs.recommended,
    ],
    languageOptions: {
      parserOptions: {
        project: ['./tsconfig.node.json', './tsconfig.app.json'],
        tsconfigRootDir: import.meta.dirname,
      },
      // other options...
    },
  },
])