This file documents the technical decisions, challenges, and solutions implemented during the development of the Ramadan Bag Invitation Generator.
A web application for generating Ramadan food basket ("قفة رمضان") distribution invitations from Excel files with full Arabic/RTL support.
- Excel file upload and parsing
- Column mapping for flexible data binding
- Live preview of invitations
- Print directly from browser (no PDF download)
- Goal: Create a tool for generating Arabic invitations.
- Tech: Hono + Bun.
- Challenge: RTL support and Arabic fonts.
- Solution: Integrated 'Tajawal' (Google Fonts) and 'Samir.Khouaja.Maghribi' (custom) fonts. Applied
dir="rtl"globally.
- Problem: Arabic headers were appearing as "gibberish" when reading Excel files.
- Solution: Switched from
readAsBinaryStringtoreadAsArrayBufferand usedXLSX.read(data, { type: 'array' }).
- Problem: Dates like
01/01/1947were being parsed as1/1/47and then misinterpreted bynew Date()as2047. - Solution:
- Configured
XLSX.readwithcellDates: true. - Used
XLSX.SSF.parse_date_code()for raw numbers. - Implemented a custom
formatValuehelper with a safeguard for 2-digit years (y < 100). - Final fix: Ensure
YYYY-MM-DDstrict formatting.
- Configured
- Requirement: One invitation per A4 page, properly formatted for printing.
- Solutions:
- Set exact A4 dimensions (210mm x 297mm)
- Configured @media print styles for clean output
- Card height: 90mm per page
- Proper RTL alignment throughout
- Requirement: Use a premium Arabic font for titles.
- Implementation:
- 'Tajawal' font from Google Fonts for body text
- 'Samir.Khouaja.Maghribi' font for invitation titles
- Hono serves the custom .ttf file
- Initial: Used server-side PDF generation with Puppeteer
- Current: Browser-based print using
@media print- simpler and matches preview exactly - Flow: Preview HTML → Browser Print → PDF/Print
├── src/
│ ├── index.ts # Main server (Hono)
│ └── client.js # Client-side logic
├── ui/
│ └── omniversify.ts # UI layout and styles
├── fonts/
│ └── Samir.Khouaja.Maghribi.ttf
├── template.html # Invitation template
├── package.json
└── README.md
- Print: Uses browser's native
@media printfor exact preview matching - Fonts: Tajawal (body) + Samir.Khouaja.Maghribi (titles)
- RTL: Full right-to-left support with
dir="rtl" - Excel: SheetJS (xlsx) for parsing with proper date handling
If adding new fields:
- Update
columnMappingobject inclient.js - Update
template.htmlplaceholders - Update the mapping section in
index.ts
- The
formatValuefunction inclient.jshandles all data formatting - Puppeteer is still available in dependencies but not actively used
- Print directly from browser - no PDF download button