{"id":47976570,"url":"https://github.com/owieth/multi-docs-demo","last_synced_at":"2026-04-04T10:56:17.216Z","repository":{"id":346313247,"uuid":"1137779943","full_name":"owieth/multi-docs-demo","owner":"owieth","description":"A Next.js proof-of-concept application that converts Markdown documents to both PDF and DOCX formats with identical custom styling. Users can customize fonts (via Google Fonts API), heading colors, and embed images.","archived":false,"fork":false,"pushed_at":"2026-03-31T07:44:37.000Z","size":1042,"stargazers_count":0,"open_issues_count":47,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-04-04T10:56:14.810Z","etag":null,"topics":["document-conversion","docx","google-fonts","markdown","nextjs","pdf","proof-of-concept","typescript"],"latest_commit_sha":null,"homepage":"https://owieth.github.io/multi-docs-demo/","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/owieth.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-01-19T20:33:45.000Z","updated_at":"2026-03-31T07:44:38.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/owieth/multi-docs-demo","commit_stats":null,"previous_names":["owieth/multi-docs-demo"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/owieth/multi-docs-demo","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/owieth%2Fmulti-docs-demo","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/owieth%2Fmulti-docs-demo/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/owieth%2Fmulti-docs-demo/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/owieth%2Fmulti-docs-demo/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/owieth","download_url":"https://codeload.github.com/owieth/multi-docs-demo/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/owieth%2Fmulti-docs-demo/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31397056,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-04T10:20:44.708Z","status":"ssl_error","status_checked_at":"2026-04-04T10:20:06.846Z","response_time":60,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["document-conversion","docx","google-fonts","markdown","nextjs","pdf","proof-of-concept","typescript"],"created_at":"2026-04-04T10:56:16.523Z","updated_at":"2026-04-04T10:56:17.189Z","avatar_url":"https://github.com/owieth.png","language":"TypeScript","readme":"# Markdown to PDF/DOCX Converter\n\nA Next.js proof-of-concept application that converts Markdown documents to both PDF and DOCX formats with **identical custom styling**. Users can customize fonts (via Google Fonts API), heading colors, and embed images.\n\n\u003cdiv align=\"center\"\u003e\n\n![Showcase](/public/showcase.png 'Showcase')\n\n\u003c/div\u003e\n\n## Features\n\n- Markdown editor with live preview\n- Export to PDF and DOCX with matching styles\n- Google Fonts integration (10 popular fonts)\n- Custom colors for H1 (primary) and H2 (secondary) headings\n- Image upload with placeholder system\n- Server-side conversion\n\n## Architecture\n\n### System Overview\n\n```mermaid\nflowchart TB\n    subgraph Frontend[\"Frontend (Next.js)\"]\n        subgraph UI[\"page.tsx\"]\n            Editor[\"Markdown Editor\u003cbr/\u003e(textarea)\"]\n            Styles[\"Style Controls\u003cbr/\u003e• Font Select\u003cbr/\u003e• Color Pickers\"]\n            Image[\"Image Upload\u003cbr/\u003e(base64 encode)\"]\n        end\n        Buttons[\"Export Buttons\u003cbr/\u003e[PDF] [DOCX]\"]\n    end\n\n    subgraph Backend[\"API Route (route.ts)\"]\n        subgraph Converter[\"converter.ts\"]\n            PDF[\"convertToPdf()\"]\n            DOCX[\"convertToDocx()\"]\n        end\n    end\n\n    subgraph PDFPipeline[\"PDF Pipeline\"]\n        FetchFont[\"Fetch Google Font CSS\"]\n        GenHTML[\"Generate HTML + CSS\"]\n        Pandoc[\"Pandoc + wkhtmltopdf\"]\n    end\n\n    subgraph DOCXPipeline[\"DOCX Pipeline\"]\n        ParseMD[\"Parse Markdown\u003cbr/\u003e(marked.js)\"]\n        BuildDoc[\"Build Document\u003cbr/\u003e(docx library)\"]\n        Pack[\"Packer.toBuffer()\"]\n    end\n\n    Download[\"Browser Download\"]\n\n    Editor --\u003e Buttons\n    Styles --\u003e Buttons\n    Image --\u003e Buttons\n    Buttons --\u003e|\"POST /api/convert\u003cbr/\u003e{markdown, format, styles, image?}\"| Backend\n\n    PDF --\u003e FetchFont --\u003e GenHTML --\u003e Pandoc\n    DOCX --\u003e ParseMD --\u003e BuildDoc --\u003e Pack\n\n    Pandoc --\u003e|\"Binary (PDF)\"| Download\n    Pack --\u003e|\"Binary (DOCX)\"| Download\n```\n\n### Conversion Flow\n\n```mermaid\nsequenceDiagram\n    participant User\n    participant UI as Frontend (page.tsx)\n    participant API as API Route\n    participant Conv as Converter\n    participant Ext as External Tools\n\n    User-\u003e\u003eUI: Enter markdown + styles\n    User-\u003e\u003eUI: Click Export (PDF/DOCX)\n    UI-\u003e\u003eAPI: POST /api/convert\n\n    alt PDF Format\n        API-\u003e\u003eConv: convertToPdf(options)\n        Conv-\u003e\u003eExt: Fetch Google Font CSS\n        Ext--\u003e\u003eConv: Font CSS\n        Conv-\u003e\u003eConv: Generate HTML template\n        Conv-\u003e\u003eExt: pandoc + wkhtmltopdf\n        Ext--\u003e\u003eConv: PDF Buffer\n    else DOCX Format\n        API-\u003e\u003eConv: convertToDocx(options)\n        Conv-\u003e\u003eConv: marked.lexer(markdown)\n        Conv-\u003e\u003eConv: Build Document (docx lib)\n        Conv-\u003e\u003eConv: Packer.toBuffer()\n    end\n\n    Conv--\u003e\u003eAPI: Buffer\n    API--\u003e\u003eUI: Binary Response\n    UI--\u003e\u003eUser: File Download\n```\n\n## How It Works\n\n### PDF Generation\n\n1. **Fetch Google Font CSS** - The selected font's CSS is fetched from Google Fonts API with font weights 400-700\n2. **Generate HTML Template** - A complete HTML document is generated with embedded CSS styles:\n   - Font family applied to all text elements\n   - Primary color for H1 headings\n   - Secondary color for H2/H3 headings\n   - Code blocks, blockquotes, tables styling\n3. **Process Markdown** - Image placeholders are replaced with base64 data URIs\n4. **Convert with Pandoc** - Uses wkhtmltopdf as the PDF engine with options:\n   - `--enable-local-file-access` for local resources\n   - `--no-stop-slow-scripts` for font loading\n   - `--javascript-delay 1000` to wait for fonts\n   - Custom margins (25mm all sides)\n\n### DOCX Generation\n\n1. **Parse Markdown** - Uses `marked.js` to tokenize markdown into AST\n2. **Build Document Programmatically** - Uses `docx` library to create:\n   - Paragraphs with font family and size\n   - Headings with custom colors (primary/secondary)\n   - Lists with bullets\n   - Code blocks with monospace font and shading\n   - Blockquotes with italic styling\n   - Images with base64 data\n3. **Pack to Buffer** - Uses `Packer.toBuffer()` to generate the DOCX binary\n\n## Tech Stack\n\n| Component       | Technology              |\n| --------------- | ----------------------- |\n| Framework       | Next.js 15 (App Router) |\n| Language        | TypeScript              |\n| Styling         | Tailwind CSS            |\n| PDF Engine      | Pandoc + wkhtmltopdf    |\n| DOCX Engine     | docx (npm)              |\n| Markdown Parser | marked                  |\n| Fonts           | Google Fonts API        |\n\n## Prerequisites\n\n### System Dependencies\n\n**macOS:**\n\n```bash\nbrew install pandoc wkhtmltopdf\n```\n\n**Ubuntu/Debian:**\n\n```bash\nsudo apt-get install pandoc wkhtmltopdf\n```\n\n**Windows:**\n\n```powershell\nchoco install pandoc wkhtmltopdf\n```\n\nVerify installation:\n\n```bash\npandoc --version\nwkhtmltopdf --version\n```\n\n## Installation\n\n```bash\n# Clone the repository\ngit clone \u003crepository-url\u003e\ncd multi-docs-demo\n\n# Install dependencies\npnpm install\n\n# Start development server\npnpm dev\n```\n\nOpen [http://localhost:3000](http://localhost:3000)\n\n## Project Structure\n\n```\nmulti-docs-demo/\n├── src/\n│   ├── app/\n│   │   ├── api/\n│   │   │   └── convert/\n│   │   │       └── route.ts      # POST endpoint for conversion\n│   │   ├── layout.tsx            # Root layout\n│   │   ├── page.tsx              # Main UI with editor\n│   │   └── globals.css           # Global styles\n│   └── lib/\n│       └── converter.ts          # PDF/DOCX conversion logic\n├── templates/\n│   └── pdf-template.html         # Legacy PDF template\n├── package.json\n└── README.md\n```\n\n## API Reference\n\n### POST `/api/convert`\n\nConverts markdown to PDF or DOCX format.\n\n**Request Body:**\n\n```typescript\n{\n  markdown: string;           // Markdown content\n  format: 'pdf' | 'docx';     // Output format\n  styles: {\n    fontFamily: string;       // Google Font name (e.g., \"Inter\")\n    primaryColor: string;     // H1 color in hex (e.g., \"#1e3a5f\")\n    secondaryColor: string;   // H2 color in hex (e.g., \"#2d5a87\")\n  };\n  image?: {                   // Optional image\n    base64: string;           // Base64-encoded image data\n    mimeType: string;         // MIME type (e.g., \"image/png\")\n  };\n}\n```\n\n**Response:**\n\n- `200 OK` - Binary file (PDF or DOCX)\n- `400 Bad Request` - Missing required fields\n- `500 Internal Server Error` - Conversion failed\n\n**Headers:**\n\n```\nContent-Type: application/pdf\n           or application/vnd.openxmlformats-officedocument.wordprocessingml.document\nContent-Disposition: attachment; filename=\"document.pdf\" (or .docx)\n```\n\n## Available Fonts\n\nThe following Google Fonts are available:\n\n| Font             | Style                          |\n| ---------------- | ------------------------------ |\n| Inter            | Sans-serif, modern             |\n| Roboto           | Sans-serif, Google's signature |\n| Open Sans        | Sans-serif, highly readable    |\n| Lato             | Sans-serif, warm               |\n| Montserrat       | Sans-serif, geometric          |\n| Poppins          | Sans-serif, geometric          |\n| Source Sans 3    | Sans-serif, Adobe              |\n| Nunito           | Sans-serif, rounded            |\n| Playfair Display | Serif, elegant                 |\n| Merriweather     | Serif, traditional             |\n\n## Image Placeholder\n\nTo include an image in your document, add this placeholder in your markdown:\n\n```markdown\n[IMAGE_PLACEHOLDER]\n```\n\nThen upload an image using the UI. The placeholder will be replaced with the uploaded image in both PDF and DOCX outputs.\n\nIf no image is uploaded, the placeholder is automatically removed from the output.\n\n## Usage Example\n\n1. Enter or paste your markdown content in the editor\n2. Select a font from the dropdown\n3. Choose colors for H1 and H2 headings using the color pickers\n4. (Optional) Upload an image and add `[IMAGE_PLACEHOLDER]` where you want it\n5. Click **Export PDF** or **Export DOCX**\n6. The file downloads automatically\n\n## Limitations\n\n- **Font Rendering**: Some complex fonts may not render identically between PDF and DOCX\n- **Tables**: Basic table support in DOCX; complex tables may need adjustment\n- **Code Highlighting**: Syntax highlighting not included (monospace only)\n- **Page Breaks**: No explicit page break control\n- **Headers/Footers**: Not implemented in this POC\n- **Nested Lists**: Single-level lists only in DOCX\n\n## Docker Deployment\n\n```dockerfile\nFROM node:20-alpine\n\n# Install system dependencies\nRUN apk add --no-cache \\\n    pandoc \\\n    wkhtmltopdf \\\n    fontconfig \\\n    ttf-freefont\n\nWORKDIR /app\n\nCOPY package.json pnpm-lock.yaml ./\nRUN npm install -g pnpm \u0026\u0026 pnpm install --frozen-lockfile\n\nCOPY . .\nRUN pnpm build\n\nEXPOSE 3000\nCMD [\"pnpm\", \"start\"]\n```\n\n## Troubleshooting\n\n### \"pandoc: command not found\"\n\nInstall Pandoc using your system's package manager (see Prerequisites).\n\n### \"wkhtmltopdf: command not found\"\n\nInstall wkhtmltopdf using your system's package manager (see Prerequisites).\n\n### Fonts not rendering in PDF\n\n- Ensure wkhtmltopdf has network access to fetch Google Fonts\n- Check that `--javascript-delay` is sufficient (increase if needed)\n- Verify the font name matches exactly (case-sensitive)\n\n### DOCX colors not applying\n\n- Ensure hex colors include the `#` prefix in the UI\n- The converter strips `#` internally for the docx library\n\n### Images not appearing\n\n- Verify the image is properly base64-encoded\n- Check the `[IMAGE_PLACEHOLDER]` text is exactly as shown (case-insensitive)\n- Supported formats: PNG, JPEG, GIF, WebP\n\n## Future Improvements\n\n- [ ] Add more Google Fonts options\n- [ ] Custom font upload support\n- [ ] Multiple image placeholders\n- [ ] Table of contents generation\n- [ ] Page headers and footers\n- [ ] Syntax highlighting for code blocks\n- [ ] Custom page sizes (A4, Letter, etc.)\n- [ ] Watermark support\n- [ ] Batch conversion API\n\n## License\n\nMIT\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fowieth%2Fmulti-docs-demo","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fowieth%2Fmulti-docs-demo","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fowieth%2Fmulti-docs-demo/lists"}