Home > Web Front-end > JS Tutorial > Enabling Application Downloads in Local bolt.new

Enabling Application Downloads in Local bolt.new

Linda Hamilton
Release: 2024-12-05 09:06:11
Original
374 people have browsed it

In this article, I will modify bolt.new to allow applications created in the tool to be downloaded locally. This feature will facilitate internal deployment of bolt.new applications, making it particularly useful for corporate environments.

Objective

  • Add functionality to download the project files as a ZIP archive.

Steps to Implement

  1. Integrate a download button in the interface
    • Add a download button in the sidebar or toolbar.
  2. Generate a ZIP archive of the project
    • Use a library like JSZip to bundle project files into a ZIP archive.
  3. Download the ZIP archive
    • Trigger the browser's download functionality with the generated ZIP file.
  4. Test the feature
    • Ensure that the downloaded ZIP contains the expected files and directory structure.

In the next article, we will cover how to modify bolt.new to integrate with Azure OpenAI Service, streamlining the application for enterprise-level use cases. Please check it.

Adding a Download Button

To enable the feature for downloading project files as a ZIP, we modify the file bolt.new/app/components/workbench/EditorPanel.tsx. The changes are marked between // Append start and // Append end for clarity.

...  
// Append start  
import JSZip from 'jszip';  
// Append end  
...  

export const EditorPanel = memo(  
  ({  
    files,  
    unsavedFiles,  
    editorDocument,  
    selectedFile,  
    isStreaming,  
    onFileSelect,  
    onEditorChange,  
    onEditorScroll,  
    onFileSave,  
    onFileReset,  
  }: EditorPanelProps) => {  

    ...  

    // Append start  
    const handleDownloadZip = useCallback(async () => {  
      const zip = new JSZip();  
      const files = workbenchStore.files.get();  

      // Check if there are files to download  
      if (Object.keys(files).length === 0) {  
        toast.error('No files to download');  
        return;  
      }  

      try {  
        // Add files to the ZIP, maintaining relative paths from WORK_DIR  
        Object.entries(files).forEach(([path, content]) => {  
          if (content && content.content) {  
            const relativePath = path.startsWith(WORK_DIR)   
              ? path.slice(WORK_DIR.length + 1)   
              : path;  
            zip.file(relativePath, content.content);  
          }  
        });  

        const zipBlob = await zip.generateAsync({ type: 'blob' });  
        const downloadLink = document.createElement('a');  
        downloadLink.href = URL.createObjectURL(zipBlob);  

        // Use the project name from `package.json` if available  
        const projectName = files[`${WORK_DIR}/package.json`]?.content  
          ? JSON.parse(files[`${WORK_DIR}/package.json`].content).name  
          : 'project';  
        downloadLink.download = `${projectName}.zip`;  

        downloadLink.click();  
        URL.revokeObjectURL(downloadLink.href);  
        toast.success('Files downloaded successfully');  
      } catch (error) {  
        toast.error('Failed to create zip file');  
        console.error(error);  
      }  
    }, []);  
    // Append end  

    return (  
      <PanelGroup direction="vertical">  
        <Panel defaultSize={showTerminal ? DEFAULT_EDITOR_SIZE : 100} minSize={20}>  
          <PanelGroup direction="horizontal">  
            <Panel defaultSize={20} minSize={10} collapsible>  
              <div className="flex flex-col border-r border-bolt-elements-borderColor h-full">  
                <PanelHeader>  
                  <div className="i-ph:tree-structure-duotone shrink-0" />  
                  Files  
                  {/* Append start */}  
                  <div className="flex-1" />  
                  <button  
                    className="px-2 py-1 rounded-md text-bolt-elements-item-contentDefault bg-transparent enabled:hover:text-bolt-elements-item-contentActive enabled:hover:bg-bolt-elements-item-backgroundActive"  
                    onClick={handleDownloadZip}  
                    title="Download as ZIP"  
                  >  
                    <div className="i-ph:download-simple text-xl" />  
                  </button>  
                  {/* Append end */}  
                </PanelHeader>  
    ...  
Copy after login
Copy after login

Explanation of Changes

  1. Added JSZip import:

    This library is used to generate the ZIP archive.

  2. handleDownloadZip function:

    • Retrieves files from the workbenchStore.
    • Creates a ZIP file with relative paths from WORK_DIR.
    • Automatically names the ZIP file using the project name from package.json, if available.
  3. Download button in the interface:

    • A button is added to the Files panel header to trigger the ZIP download process.
    • Styled and includes a tooltip for user clarity.

With this change, users can download the project files as a ZIP archive directly from the interface.

Updating package.json

To use the JSZip library for generating ZIP archives, add it to the dependencies in package.json.

{  
  ...  
  "dependencies": {  
    "@ai-sdk/anthropic": "^0.0.39",  
    // Append start  
    "jszip": "^3.10.1",  
    // Append end  
  },  
  ...  
}  
Copy after login

Steps to Apply the Update

  1. Open the package.json file.
  2. Add "jszip": "^3.10.1" under the "dependencies" section as shown above.
  3. Run the following command to install the library:
pnpm install  
Copy after login

This ensures that the required library is available in your project for the ZIP generation functionality.

Testing the Download Feature

After completing the modifications, follow these steps to verify the new functionality:

Start the Application

Run the following commands to build and start bolt.new:

...  
// Append start  
import JSZip from 'jszip';  
// Append end  
...  

export const EditorPanel = memo(  
  ({  
    files,  
    unsavedFiles,  
    editorDocument,  
    selectedFile,  
    isStreaming,  
    onFileSelect,  
    onEditorChange,  
    onEditorScroll,  
    onFileSave,  
    onFileReset,  
  }: EditorPanelProps) => {  

    ...  

    // Append start  
    const handleDownloadZip = useCallback(async () => {  
      const zip = new JSZip();  
      const files = workbenchStore.files.get();  

      // Check if there are files to download  
      if (Object.keys(files).length === 0) {  
        toast.error('No files to download');  
        return;  
      }  

      try {  
        // Add files to the ZIP, maintaining relative paths from WORK_DIR  
        Object.entries(files).forEach(([path, content]) => {  
          if (content && content.content) {  
            const relativePath = path.startsWith(WORK_DIR)   
              ? path.slice(WORK_DIR.length + 1)   
              : path;  
            zip.file(relativePath, content.content);  
          }  
        });  

        const zipBlob = await zip.generateAsync({ type: 'blob' });  
        const downloadLink = document.createElement('a');  
        downloadLink.href = URL.createObjectURL(zipBlob);  

        // Use the project name from `package.json` if available  
        const projectName = files[`${WORK_DIR}/package.json`]?.content  
          ? JSON.parse(files[`${WORK_DIR}/package.json`].content).name  
          : 'project';  
        downloadLink.download = `${projectName}.zip`;  

        downloadLink.click();  
        URL.revokeObjectURL(downloadLink.href);  
        toast.success('Files downloaded successfully');  
      } catch (error) {  
        toast.error('Failed to create zip file');  
        console.error(error);  
      }  
    }, []);  
    // Append end  

    return (  
      <PanelGroup direction="vertical">  
        <Panel defaultSize={showTerminal ? DEFAULT_EDITOR_SIZE : 100} minSize={20}>  
          <PanelGroup direction="horizontal">  
            <Panel defaultSize={20} minSize={10} collapsible>  
              <div className="flex flex-col border-r border-bolt-elements-borderColor h-full">  
                <PanelHeader>  
                  <div className="i-ph:tree-structure-duotone shrink-0" />  
                  Files  
                  {/* Append start */}  
                  <div className="flex-1" />  
                  <button  
                    className="px-2 py-1 rounded-md text-bolt-elements-item-contentDefault bg-transparent enabled:hover:text-bolt-elements-item-contentActive enabled:hover:bg-bolt-elements-item-backgroundActive"  
                    onClick={handleDownloadZip}  
                    title="Download as ZIP"  
                  >  
                    <div className="i-ph:download-simple text-xl" />  
                  </button>  
                  {/* Append end */}  
                </PanelHeader>  
    ...  
Copy after login
Copy after login
  1. Open the Application in a Browser and navigate to the "Code" tab of the application interface.

  2. Confirm that a download button is visible in the "Files" section, as shown below:

Enabling Application Downloads in Local bolt.new

  1. Download the Project Files: Click the download button and download the ZIP file.

The above is the detailed content of Enabling Application Downloads in Local bolt.new. For more information, please follow other related articles on the PHP Chinese website!

source:dev.to
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Latest Articles by Author
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template