@jaredef/lovable-export
v1.0.5
Published
A React component library for exporting Lovable.dev pages as static HTML and uploading them to a proxy server.
Readme
@jaredef/lovable-export
A React component library for exporting Lovable.dev pages as static HTML and uploading them to a proxy server.
Installation
npm install @jaredef/lovable-exportor
pnpm add @jaredef/lovable-exportQuick Start
There are three ways to configure the export functionality:
Option 1: Direct Props (Simplest)
Pass configuration directly to the ExportButton component:
import { Toaster } from "@/components/ui/toaster";
import { Toaster as Sonner } from "@/components/ui/sonner";
import { TooltipProvider } from "@/components/ui/tooltip";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { BrowserRouter, Routes, Route } from "react-router-dom";
import { ExportButton } from '@jaredef/lovable-export'
import '@jaredef/lovable-export/styles.css'
import Index from "./pages/Index";
import NotFound from "./pages/NotFound";
const queryClient = new QueryClient();
const App = () => (
<QueryClientProvider client={queryClient}>
<TooltipProvider>
<Toaster />
<Sonner />
<BrowserRouter>
<Routes>
<Route path="/" element={<Index />} />
<Route path="*" element={<NotFound />} />
</Routes>
</BrowserRouter>
<ExportButton
proxyUrl="https://your-proxy.com"
authPassword="your-admin-password"
defaultSlug="my-page"
/>
</TooltipProvider>
</QueryClientProvider>
);
export default App;Option 2: Environment Variables
Configure via Vite environment variables:
# .env or .env.local
VITE_PROXY_URL=https://your-proxy.com
VITE_ADMIN_PASSWORD=your-admin-passwordimport { Toaster } from "@/components/ui/toaster";
import { Toaster as Sonner } from "@/components/ui/sonner";
import { TooltipProvider } from "@/components/ui/tooltip";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { BrowserRouter, Routes, Route } from "react-router-dom";
import { ExportButton } from '@jaredef/lovable-export'
import '@jaredef/lovable-export/styles.css'
import Index from "./pages/Index";
import NotFound from "./pages/NotFound";
const queryClient = new QueryClient();
const App = () => (
<QueryClientProvider client={queryClient}>
<TooltipProvider>
<Toaster />
<Sonner />
<BrowserRouter>
<Routes>
<Route path="/" element={<Index />} />
<Route path="*" element={<NotFound />} />
</Routes>
</BrowserRouter>
{/* No props needed - reads from env vars */}
<ExportButton defaultSlug="my-page" />
</TooltipProvider>
</QueryClientProvider>
);
export default App;Option 3: React Context Provider
Wrap your app with ExportProvider for centralized configuration:
import { Toaster } from "@/components/ui/toaster";
import { Toaster as Sonner } from "@/components/ui/sonner";
import { TooltipProvider } from "@/components/ui/tooltip";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { BrowserRouter, Routes, Route } from "react-router-dom";
import { ExportProvider, ExportButton } from '@jaredef/lovable-export'
import '@jaredef/lovable-export/styles.css'
import Index from "./pages/Index";
import NotFound from "./pages/NotFound";
const queryClient = new QueryClient();
const App = () => (
<QueryClientProvider client={queryClient}>
<ExportProvider
proxyUrl="https://your-proxy.com"
authPassword="your-admin-password"
>
<TooltipProvider>
<Toaster />
<Sonner />
<BrowserRouter>
<Routes>
<Route path="/" element={<Index />} />
<Route path="*" element={<NotFound />} />
</Routes>
</BrowserRouter>
<ExportButton defaultSlug="my-page" />
</TooltipProvider>
</ExportProvider>
</QueryClientProvider>
);
export default App;API Reference
ExportButton
A floating button component that opens an export modal.
Props
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| defaultSlug | string | '' | Pre-filled slug for the export |
| defaultTitle | string | '' | Pre-filled title (falls back to document.title) |
| defaultDescription | string | '' | Pre-filled description for SEO |
| position | 'bottom-right' \| 'bottom-left' \| 'top-right' \| 'top-left' | 'bottom-right' | Button position |
| proxyUrl | string | From context or env | URL of the proxy server |
| authPassword | string | From context or env | Admin password for uploads |
ExportProvider
React context provider for centralized configuration.
Props
| Prop | Type | Required | Description |
|------|------|----------|-------------|
| proxyUrl | string | Yes | URL of the proxy server |
| authPassword | string | Yes | Admin password for uploads |
| children | ReactNode | Yes | Child components |
useExport Hook
For building custom export UIs.
import { useExport } from '@jaredef/lovable-export'
function CustomExporter() {
const {
status, // 'idle' | 'exporting' | 'uploading' | 'success' | 'error'
message, // Status message string
handleDownload, // (slug, title?, description?) => Promise<void>
handleUpload, // (slug, title?, description?) => Promise<void>
createExportZip // (options?) => Promise<Blob>
} = useExport({
proxyUrl: 'https://your-proxy.com',
authPassword: 'your-password'
})
return (
<button onClick={() => handleDownload('my-slug')}>
Export to ZIP
</button>
)
}useConfig Hook
Get resolved configuration (props > context > env vars).
import { useConfig } from '@jaredef/lovable-export'
function MyComponent() {
const config = useConfig({
proxyUrl: 'optional-override',
authPassword: 'optional-override'
})
console.log(config.proxyUrl, config.authPassword)
}Utility Functions
createExportZip
Create a ZIP blob from the current page.
import { createExportZip } from '@jaredef/lovable-export'
const zipBlob = await createExportZip({
title: 'My Page Title',
description: 'Page description for SEO'
})uploadExport
Upload a ZIP to the proxy server.
import { uploadExport } from '@jaredef/lovable-export'
const result = await uploadExport({
zipBlob,
slug: 'my-page',
title: 'My Page',
description: 'Description',
config: { proxyUrl: '...', authPassword: '...' },
replace: true
})Environment Variables
| Variable | Description |
|----------|-------------|
| VITE_PROXY_URL | URL of your proxy server (e.g., https://your-domain.com) |
| VITE_ADMIN_PASSWORD | Admin password for authenticated uploads |
Configuration Priority
The library resolves configuration in this order (highest priority first):
- Props - Values passed directly to components
- Context - Values from
ExportProvider - Environment Variables -
VITE_PROXY_URLandVITE_ADMIN_PASSWORD - Defaults -
http://localhost:3000for proxy URL, empty string for password
Styling
Import the CSS file in your application:
import '@jaredef/lovable-export/styles.css'CSS Custom Properties
Customize the appearance using CSS custom properties:
:root {
--lovable-export-primary: #2563eb;
--lovable-export-primary-hover: #1d4ed8;
--lovable-export-bg: #ffffff;
--lovable-export-text: #1f2937;
--lovable-export-border: #e5e7eb;
/* See input.css for all available properties */
}TypeScript Types
import type {
ExportButtonProps,
ExportConfig,
ExportResult,
UploadResult,
ExportStatus
} from '@jaredef/lovable-export'Troubleshooting
Export button not appearing
Make sure you've imported the CSS file:
import '@jaredef/lovable-export/styles.css'Upload fails with 401 error
Check that your authPassword matches the ADMIN_PASSWORD configured on your proxy server.
Assets not loading in exported page
The export utility automatically converts absolute paths to relative paths. However, external CDN resources are preserved. Ensure all local assets use relative paths (./assets/... not /assets/...).
Page validation warnings
The export utility checks for:
- Absolute paths that may not work after export
- Missing
<title>tag
Address these warnings to ensure the exported page works correctly.
Peer Dependencies
This package requires:
react>= 18.0.0react-dom>= 18.0.0
License
MIT
