4.9 KiB
Yaltopia Ticket Email Templates
Internal playground to preview and copy email templates that will later be sent via Resend or another email provider.
This project does not send emails. It renders HTML for different scenarios so developers can copy the markup (or a sample JSON payload) into their actual sending system.
Getting started
npm install
npm run dev
Then open the URL shown in the terminal (typically http://localhost:5173).
Templates
Use the left sidebar to switch between templates:
- Invitation
- Proforma invoice
- Payment request
- VAT summary / VAT detailed
- Withholding summary / Withholding detailed
- Newsletter (Yaltopia branded)
- Password reset (company logo + “Powered by Yaltopia Ticket”)
All templates share an orange / black theme with a card-style layout designed to work well inside transactional emails.
Configuring data
The Configuration panel lets you adjust:
- Company name, logo URL, payment link, bank details
- Invitation info (event name, date/time, location)
- Payment amount and currency
- VAT / Withholding report periods and totals
- Password reset link
For payment-related emails:
- If a payment link is provided, the email shows a bright “Pay now” button.
- If no payment link is provided but bank details are filled, the email shows a bank-transfer panel instead.
You can click Update URL to push key values (company, logo, payment link) into the query string so a particular configuration can be bookmarked or shared.
Preview / HTML / Resend JSON
Each template view has three tabs:
- Preview – visual approximation of the email.
- HTML – raw HTML generated from the React template (copy this into Resend or your provider).
- Resend JSON – example payload of the form:
{
"from": "Yaltopia Ticket <no-reply@yaltopia-ticket.test>",
"to": "recipient@example.com",
"subject": "…",
"html": "<!doctype html>…"
}
Use the Copy button to copy the current tab (HTML or JSON) to your clipboard.
Notes
- Templates use a shared
EmailLayoutcomponent with table-based structure and inline-style friendly attributes to behave well in common email clients. - Newsletter uses a fixed Yaltopia-branded layout; only content slots (title/body) are meant to change.
- Password reset always includes “Powered by Yaltopia Ticket” in the footer and uses the company logo/name from the configuration.
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:
- @vitejs/plugin-react uses Babel (or oxc when used in rolldown-vite) for Fast Refresh
- @vitejs/plugin-react-swc uses SWC for Fast Refresh
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...
},
},
])