Users often need to export web pages as PDFs. The browser's window.print() function produces inconsistent results: CSS backgrounds are omitted, page breaks occur mid-element, and layout rendering differs from the screen display.
WebSave as PDF provides a client-side solution for adding PDF export to web applications. It captures the current page state directly in the browser. This guide covers integration for React, Preact, Vue, Angular, Svelte, Astro, and SolidJS.
TL;DR
1. Add the script to your HTML file:
<script src="https://edge.pdfcrowd.com/websave/1.3.0/websave.min.js" async></script>
2. Add a button with configuration:
The data-config attribute references a global configuration object:
<button
class="pdfcrowd-websave pdfcrowd-websave-style"
data-key="demo"
data-config="myConfig">
Download PDF
</button>
<script>
window.myConfig = {
fileName: 'report.pdf',
conversionMode: 'content', // Captures current page state
apiSettings: {
page_size: 'Letter'
}
};
</script>
That's it. The conversionMode: 'content' setting is important for reactive apps - it captures the rendered DOM with all dynamic content, form inputs, and user interactions.
Note for SPAs: If your framework (React, Vue, Svelte, etc.) renders buttons dynamically, you'll need to manually initialize them using window.WebSave.initButton(). See framework-specific examples below for details.
Choose Your Framework
React Integration
Loading WebSave
Recommended: Add to index.html in your React project root:
<script src="https://edge.pdfcrowd.com/websave/1.3.0/websave.min.js" async></script>
Next.js: Use Script component in pages/_app.js:
import Script from 'next/script'
export default function MyApp({ Component, pageProps }) {
return (
<>
<Script
src="https://edge.pdfcrowd.com/websave/1.3.0/websave.min.js"
strategy="lazyOnload"
/>
<Component {...pageProps} />
</>
)
}
Example
// src/App.jsx
import { useEffect, useRef } from 'react'
function App() {
const buttonRef = useRef(null);
useEffect(() => {
// Configure WebSave with settings
window.reportConfig = {
fileName: 'monthly-report.pdf',
conversionMode: 'content',
apiSettings: {
page_size: 'Letter'
}
};
// Initialize the dynamically rendered button
window.WebSave?.initButton(buttonRef.current);
}, []);
return (
<div>
<h1>Monthly Report</h1>
{/* Report content */}
<button
ref={buttonRef}
className="pdfcrowd-websave pdfcrowd-websave-style"
data-key="demo"
data-config="reportConfig">
Download PDF
</button>
</div>
);
}
export default App;
Preact Integration
Loading WebSave
Recommended: Add to src/index.html (Vite) or public/index.html:
<script src="https://edge.pdfcrowd.com/websave/1.3.0/websave.min.js" async></script>
Example
// src/app.jsx
import { useEffect, useRef } from 'preact/hooks'
export function App() {
const buttonRef = useRef(null);
useEffect(() => {
// Configure WebSave with settings
window.reportConfig = {
fileName: 'monthly-report.pdf',
conversionMode: 'content',
apiSettings: {
page_size: 'Letter'
}
};
// Initialize the dynamically rendered button
window.WebSave?.initButton(buttonRef.current);
}, []);
return (
<div>
<h1>Monthly Report</h1>
{/* Report content */}
<button
ref={buttonRef}
class="pdfcrowd-websave pdfcrowd-websave-style"
data-key="demo"
data-config="reportConfig">
Download PDF
</button>
</div>
);
}
Vue Integration
Loading WebSave
Recommended: Add to index.html (Vue 3/Vite):
<script src="https://edge.pdfcrowd.com/websave/1.3.0/websave.min.js" async></script>
Nuxt 3: Add to nuxt.config.ts:
export default defineNuxtConfig({
app: {
head: {
script: [
{
src: 'https://edge.pdfcrowd.com/websave/1.3.0/websave.min.js',
async: true
}
]
}
}
});
Example
<!-- src/App.vue -->
<script setup>
import { onMounted, ref } from 'vue';
const buttonRef = ref(null);
onMounted(() => {
// Configure WebSave with settings
window.reportConfig = {
fileName: 'monthly-report.pdf',
conversionMode: 'content',
apiSettings: {
page_size: 'Letter'
}
};
// Initialize the dynamically rendered button
window.WebSave?.initButton(buttonRef.value);
});
</script>
<template>
<div>
<h1>Monthly Report</h1>
<!-- Report content -->
<button
ref="buttonRef"
class="pdfcrowd-websave pdfcrowd-websave-style"
data-key="demo"
data-config="reportConfig">
Download PDF
</button>
</div>
</template>
Angular Integration
Loading WebSave
Recommended: Add to src/index.html:
<script src="https://edge.pdfcrowd.com/websave/1.3.0/websave.min.js" async></script>
Example
import { Component, OnInit, AfterViewInit, ElementRef, ViewChild } from '@angular/core';
@Component({
selector: 'app-report',
template: `
<div>
<h1>Monthly Report</h1>
<!-- Report content -->
<button
#websaveButton
class="pdfcrowd-websave pdfcrowd-websave-style"
data-key="demo"
data-config="reportConfig">
Download PDF
</button>
</div>
`
})
export class ReportComponent implements OnInit, AfterViewInit {
@ViewChild('websaveButton') websaveButton!: ElementRef;
ngOnInit() {
// Configure WebSave with settings
(window as any).reportConfig = {
fileName: 'monthly-report.pdf',
conversionMode: 'content',
apiSettings: {
page_size: 'Letter'
}
};
}
ngAfterViewInit() {
// Initialize the dynamically rendered button
(window as any).WebSave?.initButton(this.websaveButton.nativeElement);
}
}
Svelte Integration
Loading WebSave
Recommended: Add to public/index.html (Vite) or src/app.html (SvelteKit):
<script src="https://edge.pdfcrowd.com/websave/1.3.0/websave.min.js" async></script>
Example
<!-- src/App.svelte -->
<script>
import { onMount } from 'svelte';
let buttonElement;
onMount(() => {
// Configure WebSave with settings
window.reportConfig = {
fileName: 'monthly-report.pdf',
conversionMode: 'content',
apiSettings: {
page_size: 'Letter'
}
};
// Initialize the dynamically rendered button
window.WebSave?.initButton(buttonElement);
});
</script>
<div>
<h1>Monthly Report</h1>
<!-- Report content -->
<button
bind:this={buttonElement}
class="pdfcrowd-websave pdfcrowd-websave-style"
data-key="demo"
data-config="reportConfig">
Download PDF
</button>
</div>
Astro Integration
Loading WebSave
Recommended: Add to your layout file (e.g., src/layouts/Layout.astro):
---
// src/layouts/Layout.astro
---
<html>
<head>
<script src="https://edge.pdfcrowd.com/websave/1.3.0/websave.min.js" async></script>
</head>
<body>
<slot />
</body>
</html>
Alternative: Add to individual pages in the <head> section.
Example
---
// Report.astro
---
<div>
<h1>Monthly Report</h1>
<!-- Report content -->
<button
class="pdfcrowd-websave pdfcrowd-websave-style"
data-key="demo"
data-config="reportConfig">
Download PDF
</button>
</div>
<script is:inline>
// Configure WebSave with settings
window.reportConfig = {
fileName: 'monthly-report.pdf',
conversionMode: 'content',
apiSettings: {
page_size: 'Letter'
}
};
// Initialize button after DOM and WebSave are ready
document.addEventListener('DOMContentLoaded', function() {
const button = document.querySelector('.pdfcrowd-websave');
window.WebSave?.initButton(button);
});
</script>
SolidJS Integration
Loading WebSave
Recommended: Add to index.html:
<script src="https://edge.pdfcrowd.com/websave/1.3.0/websave.min.js" async></script>
Example
// src/App.jsx
import { onMount } from 'solid-js'
function App() {
let buttonRef;
onMount(() => {
// Configure WebSave with settings
window.reportConfig = {
fileName: 'monthly-report.pdf',
conversionMode: 'content',
apiSettings: {
page_size: 'Letter'
}
};
// Initialize the dynamically rendered button
window.WebSave?.initButton(buttonRef);
});
return (
<div>
<h1>Monthly Report</h1>
{/* Report content */}
<button
ref={buttonRef}
class="pdfcrowd-websave pdfcrowd-websave-style"
data-key="demo"
data-config="reportConfig">
Download PDF
</button>
</div>
);
}
export default App;
Try It Yourself
Click the button below to export this page as a PDF. WebSave captures the current page state including any text you enter.