A Next.js report-generation template for professional biological aging reports with live preview and PDF export.
- ✅ Data entry form with validation
- ✅ Real-time age calculation from DOB
- ✅ Live HTML preview of report
- ✅ Beautiful charts (scatter plot & gauge)
- ✅ PDF generation with Puppeteer
- ✅ Responsive design
- ✅ Professional styling
- Framework: Next.js 14+ (App Router)
- Language: TypeScript
- Styling: Tailwind CSS
- PDF Generation: Puppeteer
- Charts: Recharts
- Icons: Lucide React
- Node.js 18+ installed
- npm or yarn
- Navigate to the project directory:
cd mytrueage-report-generator- Install dependencies (if not already installed):
npm installRun the development server:
npm run devOpen http://localhost:3000 in your browser.
npm run build
npm startmytrueage-report-generator/
├── app/
│ ├── page.tsx # Main page with form/preview toggle
│ ├── preview/page.tsx # Standalone preview page
│ ├── layout.tsx # Root layout
│ ├── globals.css # Global styles
│ └── api/
│ └── generate-pdf/
│ └── route.ts # PDF generation API endpoint
│
├── components/
│ ├── forms/
│ │ └── DataEntryForm.tsx # Main input form
│ │
│ └── report/
│ ├── ReportPreview.tsx # Full report preview wrapper
│ │
│ ├── pages/
│ │ ├── CoverPage.tsx # Page 1: Cover
│ │ ├── PersonalInformationPage.tsx # Page 2: Personal details
│ │ ├── BiologicalAgePage.tsx # Page 3: Bio Age results
│ │ ├── PaceOfAgingPage.tsx # Page 4: Pace of Aging
│ │ ├── UnderstandingYourResultsPage.tsx # Page 5: Results interpretation
│ │ ├── ScienceBehindAgePathPage.tsx # Page 6: Science background
│ │ ├── RecommendationsPage.tsx # Page 7: Recommendations
│ │ ├── ResourcesPage.tsx # Page 8: Resources and links
│ │ ├── FrequentlyAskedQuestionsPage.tsx # Page 9: FAQ
│ │ ├── DisclaimerPage.tsx # Page 10: Disclaimer
│ │ └── ReferencesPage.tsx # Page 11: References
│ │
│ ├── charts/
│ │ ├── BioAgeScatterPlot.tsx # Scatter plot chart
│ │ └── PaceOfAgingGauge.tsx # Speedometer gauge
│ │
│ └── layout/
│ ├── PageHeader.tsx # Reusable page header
│ ├── PageFooter.tsx # Reusable page footer
│ └── PageWrapper.tsx # Standard page container
│
├── lib/
│ ├── calculations.ts # Age & metrics calculations
│ └── formatters.ts # Formatting utilities
│
├── types/
│ └── report.types.ts # TypeScript interfaces
│
├── public/
│ ├── images/ # 📁 DROP YOUR IMAGES HERE
│ │ └── README.md # Instructions for images
│ │
│ └── icons/ # 📁 DROP YOUR ICONS HERE
│ ├── diet/
│ ├── supplements/
│ └── lifestyle/
│
└── styles/
└── report.css # PDF-specific styles
All image assets should be placed in the public/ folder:
Place in public/images/:
cover-graphic.jpg- Cover page hero image (aging stages)dna-methylation.svg- DNA illustrationlogo.svg- GENESSENSE/MEDGENOME logocover.png- Hero background used on the cover (see note below)
Place in respective folders under public/icons/:
Diet icons (public/icons/diet/):
- grain.svg, vegetables.svg, protein.svg, fish.svg, beverage.svg, ketogenic.svg
Supplement icons (public/icons/supplements/):
- omega3.svg, probiotics.svg, vitamins.svg, minerals.svg
Lifestyle icons (public/icons/lifestyle/):
- meditation.svg, sleep.svg, exercise.svg
import Image from 'next/image';
// Example usage
<Image
src="/images/logo.svg"
alt="Logo"
width={200}
height={100}
/>- The cover hero uses a CSS background (
/images/cover.png) to tightly control positioning across desktop/PDF; it intentionally bypasses Next.js<Image />and usesbackground-size: coverplusbackground-position: right center. - Keep cover assets at sufficient resolution; adjust
background-position/background-sizeinstyles/report.css(.cover-hero-image) if swapping in a different aspect ratio.
- Cover Page – Branding, partner logos, hero image
- Personal Information – Patient details with iconography
- Biological Age – Bio age summary plus scatter plot
- Pace of Aging – DunedinPACE gauge and interpretation
- Understanding Your Results – Biological age & pace explainer
- Science Behind AgePath – Epigenetic clock background
- Recommendations – Lifestyle and supplement guidance
- Resources – Links and QR codes
- Frequently Asked Questions
- Disclaimer
- References
To add additional pages or variants:
- Create new page component in
components/report/pages/ - Import and add to
ReportPreview.tsx - Use existing layout components for consistency
Example:
// components/report/pages/IntroductionPage.tsx
import PageWrapper from '../layout/PageWrapper';
import PageHeader from '../layout/PageHeader';
export default function IntroductionPage() {
return (
<PageWrapper pageNumber={5}>
<PageHeader title="Introduction to Biological Age" />
{/* Your content here */}
</PageWrapper>
);
}The app uses Puppeteer to generate PDFs. The process:
- User fills form → clicks "Preview Report"
- Preview renders in browser
- User clicks "Download PDF"
- API route launches Puppeteer
- Puppeteer navigates to preview page
- PDF generated and downloaded
- Default timeout: 60 seconds
- Charts rendered via client-side components
- Background colors/images included
- A4 format (210mm × 297mm)
- Push to GitHub
- Import to Vercel
- Add environment variables if needed
- Deploy
Important for Vercel: Add vercel.json for longer function timeout:
{
"functions": {
"app/api/generate-pdf/route.ts": {
"maxDuration": 60
}
}
}For production, you may need:
VERCEL_URL=your-deployment-url.vercel.appUse these values to test the application:
- Name: John Doe
- Date of Birth: 1953-06-15
- Gender: Male
- Sample Type: EDTA Blood
- Kit ID: KIT123456
- Chronological Age: 70.56
- Biological Age: 67.26
- DunedinPACE: 1.001
Edit CSS variables in styles/report.css:
:root {
--primary-blue: #1e40af;
--light-blue: #3b82f6;
--orange: #f97316;
--green: #22c55e;
/* ... */
}Modify in styles/report.css under the Typography section.
If PDF generation fails:
- Local Development: Ensure Chrome/Chromium is installed
- Production: Use
chrome-aws-lambdafor serverless
npm install chrome-aws-lambda- Ensure
'use client'directive is at top of chart components - Check browser console for errors
- Verify Recharts is installed
Proprietary - GENESSENSE & MEDGENOME
For issues or questions, contact the development team.