- TypeScript 91.7%
- CSS 3.8%
- JavaScript 3.5%
- HTML 1%
| public | ||
| scripts | ||
| src | ||
| .gitignore | ||
| index.html | ||
| package.json | ||
| pnpm-lock.yaml | ||
| pnpm-workspace.yaml | ||
| README.md | ||
| tsconfig.app.json | ||
| tsconfig.json | ||
| tsconfig.node.json | ||
| vite.config.ts | ||
Newman Report Viewer
Interactive web interface to visualize Newman/Postman test results.
🚀 Features
- Dynamic loading: JSON reports are loaded at runtime instead of build time
- React Router navigation: Clean URLs for each report (e.g.
/report/go-fiber-sqlc-postgres) - Multilingual (i18n): English/French support with automatic browser language detection
- Dark/light mode: Persistent theme with system preference support
- Filtering: By suite (PHP, Node, Java, etc.) and database (SQLite, Postgres, MySQL)
- Detailed insights: View every request, assertion, response time, request/response body
- URL copy: Button to copy a request URL to the clipboard
- PWA Ready: Manifest and icons for installable app support
📦 Installation
cd Newman/report-viewer
pnpm install
🔧 Development
# Generate the reports index (automatic during dev/build)
pnpm generate-index
# Start the development server
pnpm dev
# The viewer will be available at http://localhost:5173
The generate-index.mjs script automatically creates a public/reports-index.json file that lists all available JSON files. This file is used by the application to load reports dynamically.
You can override the JSON source directory with either:
- CLI argument:
pnpm generate-index -- --json-dir ../my-json-folder - Environment variable:
REPORT_VIEWER_JSON_DIR=../my-json-folder pnpm dev - pnpm config flag:
pnpm dev --json-dir ../my-json-folder
Both generate-index.mjs and the Vite copy step use REPORT_VIEWER_JSON_DIR, NEWMAN_JSON_DIR, or pnpm --json-dir.
🏗️ Build
pnpm build
The build:
- Generates the reports index (
reports-index.json) - Copies all JSON files from the configured JSON source directory (default:
../json) topublic/json - Compiles the React application
- Produces a
distfolder ready to deploy
📂 Structure
report-viewer/
├── public/ # Static files
│ ├── reports-index.json # Automatically generated index
│ ├── json/ # JSON reports (copied at build time)
│ ├── favicon.svg # Application icon
│ └── manifest.json # PWA configuration
├── scripts/
│ └── generate-index.mjs # Script to generate the index
├── src/
│ ├── components/ # React components
│ ├── contexts/ # React contexts (ReportsContext)
│ ├── hooks/ # Custom hooks (useReports, useTheme)
│ ├── i18n/ # Multilingual configuration
│ │ ├── locales/
│ │ │ ├── en.json # English translations
│ │ │ └── fr.json # French translations
│ │ └── config.ts # i18next configuration
│ ├── lib/ # Utilities and parsers
│ ├── pages/ # Pages (HomePage, ReportPage)
│ └── App.tsx # Root component with routing
└── package.json
🔄 Adding new reports
Thanks to dynamic loading, you only need to:
- Run Newman tests (which generate JSON files in
Newman/json/) - Regenerate the index:
pnpm generate-index - Refresh the browser (in dev) or rebuild (in prod)
No full rebuild needed during development! The Vite server will automatically serve new JSON files.
🌐 Deployment
The generated dist folder can be deployed to any static web server:
- GitHub Pages: Configure workflow to build and push to
gh-pages - Netlify / Vercel: Point to
Newman/report-viewerwith thepnpm buildcommand - Apache/Nginx server: Copy
distcontents into your web root
⚠️ Important: For React routing, configure the server to serve index.html on all routes (SPA fallback).
Nginx example
location / {
try_files $uri $uri/ /index.html;
}
Apache example (.htaccess)
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.html$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.html [L]
</IfModule>
🎨 Customization
Languages
The app automatically detects the browser language and switches between English and French. The preference is saved in localStorage.
Pluralization:
Translation keys with counters use _one and _other suffixes for pluralization:
{
"reportsCount_one": "{{count}} report",
"reportsCount_other": "{{count}} reports"
}
Usage in code:
t("header.reportsCount", { count: reports.length });
// count = 0 → "0 report" (French) / "0 reports" (English)
// count = 1 → "1 report"
// count = 2+ → "2 reports"
Add a new language:
-
Create a file
src/i18n/locales/[code].json(e.g.es.jsonfor Spanish) -
Copy the
en.jsonstructure and translate values -
Create the SVG flag component in
src/components/flags/FlagES.tsx:export function FlagES({ className = "w-5 h-4" }: { className?: string }) { return ( <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 750 500" className={className}> {/* Spanish flag SVG */} </svg> ) } -
Export the flag in
src/components/flags/index.ts:export { FlagES } from "./FlagES"; -
Add the language in
src/i18n/config.ts:import es from "./locales/es.json"; const resources = { en: { translation: en }, fr: { translation: fr }, es: { translation: es }, // New language }; -
Add the language in
src/components/LanguageToggle.tsx:import { FlagUK, FlagFR, FlagES } from "@/components/flags"; const languages = [ { code: "en", flag: FlagUK, label: "English" }, { code: "fr", flag: FlagFR, label: "Français" }, { code: "es", flag: FlagES, label: "Español" }, ];
Theme and colors
- Colors: Edit colors in
src/lib/parse.ts(SUITE_COLORS,DB_COLORS,METHOD_COLORS) - Theme: Adjust Tailwind classes in
src/index.css - Layout: Edit
src/components/Layout.tsxfor header/footer
📝 Technologies
- React 19 with TypeScript
- React Router 7 for navigation
- i18next / react-i18next for internationalization
- Tailwind CSS 4 for styling
- Lucide React for icons
- Vite 6 as bundler