A modern, clean document viewer with embed-ready links. View PDFs, HTML, Markdown, Jupyter notebooks, and moreβall in one place.
- Multi-format Support: PDF, HTML, Markdown, Jupyter Notebooks (.ipynb), Plain Text
- Embed Anywhere: Generate iframe code for any public document
- Zero Setup: Drag & drop files or paste URLsβno installation required
- Dark Mode: Automatic system theme detection with seamless switching
- Responsive Design: Works beautifully on desktop, tablet, and mobile
- Local File Support: Upload and view files with IndexedDB persistence
- Tagged Sources: Direct integration with arXiv and Hitomi
- Download Options: Export to PDF, images (PNG/JPG/WebP/AVIF), or original format
- Search & Navigate: Full-text search in PDFs with keyboard shortcuts
- Proxy Support: Bypass CORS restrictions for remote resources
- Real-time Feedback: Toast notifications for all user actions
- Private Network Protection: Blocks access to private IPs and localhost
- Content Security Policy: Strict CSP headers to prevent XSS
- Input Sanitization: All user inputs are escaped and validated
- HTTPS Enforcement: Upgrade insecure requests automatically
- No Tracking: Privacy-focused with no analytics or cookies
- Node.js 18+ and npm/pnpm/yarn
- Modern browser (Chrome, Firefox, Safari, Edge)
# Clone the repository
git clone https://github.com/gaon12/EasyDocs.git
cd easydocs
# Install dependencies
npm install
# Run development server
npm run devOpen http://localhost:3000 and start viewing documents!
# Build for production
npm run build
# Start production server
npm startSimply drag and drop any supported file onto the home page.
- Go to the home page
- Paste a document URL
- Click "Open"
Use shortcuts for popular sources:
arxiv:2301.12345 # arXiv papers
hitomi:123456 # Hitomi galleries
- Open any document in the viewer
- Click the "Embed Code" button
- Copy the generated iframe code
- Paste into your website
Example embed code:
<iframe
src="https://yourdomain.com/embed/..."
style="width: 100%; height: 600px; border: 0;"
loading="lazy"
title="Embedded document">
</iframe>Click the "Download" button to see available options:
- PDF: Download original or print to PDF
- Images (Hitomi only): Export as PNG, JPG, WebP, or AVIF
- Single files or ZIP bundle
- Combine pages into one image
- Automatic splitting for large images
| Shortcut | Action |
|---|---|
PageDown / PageUp |
Navigate PDF pages |
Ctrl+Shift+F |
Focus search |
Ctrl+Shift+T |
Toggle thumbnails |
Ctrl+Shift+D |
Download PDF |
easydocs/
βββ app/
β βββ api/ # API routes
β β βββ proxy/ # CORS proxy
β β βββ arxiv-pdf/ # arXiv PDF proxy
β β βββ hitomi-image/ # Hitomi image proxy
β βββ components/ # React components
β β βββ modals/ # Modal components
β β β βββ info-modal.tsx
β β β βββ embed-modal.tsx
β β β βββ download-modal.tsx
β β βββ pdf-viewer.tsx # PDF viewer
β β βββ hitomi-viewer.tsx # Gallery viewer
β β βββ toast-container.tsx
β β βββ ...
β βββ lib/ # Utilities & helpers
β β βββ file-type.ts # File type detection
β β βββ download.ts # Download utilities
β β βββ toast.ts # Toast system
β β βββ theme.ts # Theme management
β β βββ ui-utils.ts # UI helpers
β β βββ ...
β βββ viewer/[...doc]/ # Main viewer route
β βββ embed/[...doc]/ # Embed route
β βββ embed-builder/ # Embed code generator
β βββ open/ # Document opener
β βββ layout.tsx # Root layout
βββ public/ # Static assets
βββ next.config.ts # Next.js configuration
βββ tailwind.config.ts # Tailwind CSS config
βββ package.json
Create a .env.local file:
# Optional: Custom domain for embed URLs
NEXT_PUBLIC_BASE_URL=https://yourdomain.comSecurity headers are configured in next.config.ts:
- Content Security Policy (CSP)
- HSTS
- X-Frame-Options
- Access-Control-Allow-Private-Network
The proxy API (app/api/proxy/route.ts) has the following limits:
- Max content size: 150 MB
- Timeout: 30 seconds
- Cache: 5 minutes
Edit tailwind.config.ts and app/globals.css:
/* Change primary color */
.bg-emerald-600 {
--tw-bg-opacity: 1;
background-color: rgb(5 150 105 / var(--tw-bg-opacity));
}- Update
app/lib/file-type.ts:
export type FileType = 'pdf' | 'html' | 'markdown' | 'text' | 'ipynb' | 'yournewtype';-
Create a viewer component in
app/components/ -
Add to viewer page routing in
app/viewer/[...doc]/page.tsx
# Run type checking
npm run type-check
# Lint code
npm run lint
# Format code
npm run formatKey dependencies:
- Next.js 16: React framework
- @embedpdf/react-pdf-viewer: PDF viewing
- React Markdown: Markdown rendering
- fflate: Fast ZIP compression
- Tailwind CSS: Utility-first CSS
- Push to GitHub
- Import to Vercel
- Deploy!
# Build Docker image
docker build -t easydocs .
# Run container
docker run -p 3000:3000 easydocsnpm run build
npm startDeploy the .next folder to any Node.js hosting platform.
Endpoint: /api/proxy?url={encodedUrl}
Methods: GET, HEAD, OPTIONS
Features:
- CORS headers included
- Private IP blocking
- Range request support
- 150MB size limit
Example:
fetch('/api/proxy?url=' + encodeURIComponent('https://example.com/doc.pdf'))
.then(res => res.blob())
.then(blob => console.log(blob));arXiv: /viewer/arxiv:{paper_id}
- Automatically fetches PDF from arXiv
- Shows metadata (authors, abstract, etc.)
Hitomi: /viewer/hitomi:{gallery_id}
- Displays gallery viewer
- Image export options
Contributions are welcome! Please follow these steps:
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
- Use TypeScript for type safety
- Follow ESLint rules
- Use Prettier for formatting
- Write meaningful commit messages
When adding features, please:
- Update relevant documentation
- Add JSDoc comments to functions
- Test on multiple browsers
- Ensure accessibility (ARIA labels, keyboard navigation)
Issue: CORS errors when embedding
- Solution: Use the
/embed/route instead of/viewer/
Issue: PDF not loading
- Solution: Check if the URL is publicly accessible and not blocked by firewalls
Issue: Local files not persisting
- Solution: Check browser storage settings and IndexedDB support
Issue: Toast notifications not showing
- Solution: Ensure
<ToastContainer />is in your root layout
| Browser | Minimum Version |
|---|---|
| Chrome | 90+ |
| Firefox | 88+ |
| Safari | 14+ |
| Edge | 90+ |
This project is licensed under the MIT License - see the LICENSE file for details.
- Next.js - The React framework
- EmbedPDF - PDF viewing library
- Tailwind CSS - CSS framework
- fflate - Compression library
- Issues: GitHub Issues
- Discussions: GitHub Discussions
Made with β€οΈ by gaon12