<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Mike</title>
    <description>The latest articles on Forem by Mike (@michael_81be8af).</description>
    <link>https://forem.com/michael_81be8af</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3602493%2F38c46d83-54f8-419e-98d4-2bf6616cd2b0.png</url>
      <title>Forem: Mike</title>
      <link>https://forem.com/michael_81be8af</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/michael_81be8af"/>
    <language>en</language>
    <item>
      <title>HTML to PDF Documents with BoltonSea API</title>
      <dc:creator>Mike</dc:creator>
      <pubDate>Tue, 20 Jan 2026 19:21:52 +0000</pubDate>
      <link>https://forem.com/michael_81be8af/html-to-pdf-documents-with-boltonsea-api-3dn9</link>
      <guid>https://forem.com/michael_81be8af/html-to-pdf-documents-with-boltonsea-api-3dn9</guid>
      <description>&lt;p&gt;An overview regarding HTML-to-PDF document conversion and form creation capabilities.&lt;/p&gt;

&lt;p&gt;While Microsoft Word serves as a primary word processor, its PDF export functionality often fails to preserve complex fillable form fields. While Adobe Acrobat Pro remains the industry standard for creating interactive PDFs, these features require a premium subscription.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Original article here&lt;/strong&gt; 👉 &lt;a href="https://boltonsea.com/blog/html_to_pdf_documents" rel="noopener noreferrer"&gt;[Link Here]&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  HTML Document
&lt;/h2&gt;

&lt;p&gt;As an alternative, website forms can be built using HTML and CSS. Furthermore, the BoltonSea file management system (version 4.0) now supports the conversion of HTML code into both standard and interactive PDF documents.&lt;/p&gt;

&lt;h2&gt;
  
  
  HTML to PDF Creation - Example Scenario
&lt;/h2&gt;

&lt;p&gt;This article's example is based on the scenario to create a rental agreement. By utilizing HTML to PDF conversion, you can create professional, fillable documents suitable for notarization and legal use. Please find the drafted agreement in HTML below for your review.&lt;/p&gt;

&lt;h2&gt;
  
  
  Test HTML to PDF Creation via BoltonSea API
&lt;/h2&gt;

&lt;p&gt;You can also refer to the quick Docker Image installer guide available at &lt;a href="https://boltonsea.com/download" rel="noopener noreferrer"&gt;[Link to Guide]&lt;/a&gt; for additional details.&lt;/p&gt;

&lt;h3&gt;
  
  
  HTML to PDF
&lt;/h3&gt;

&lt;p&gt;API Endpoint: &lt;code&gt;http://localhost:9200/media/document/html_to_pdf_template&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Request Body&lt;/strong&gt; &lt;br&gt;
&lt;em&gt;The complete HTML body is present at the bottom of this article.&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
"media_group_id":"1",
"file_name":"rent_renewal",
"html_content":"&amp;lt;div&amp;gt;Empty WebPage HTML .... &amp;lt;/div&amp;gt;"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Response Body&lt;/strong&gt; Response with the URL of the created 'PDF document'.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
    "id": 1,
    "width": 0,
    "height": 0,
    "maintain_aspect_ratio": false,
    "is_parent_file": false,
    "mime_type": "application/pdf",
    "private_url": "http://localhost:9200/media/file/1/2026/01/pviucoc525r9i4ro176893530770996561.pdf",
    "public_url": "http://localhost:9200/media/file/1/2026/01/pviucoc525r9i4ro176893530770996561.pdf",
    "original_file_name": "rent_renewal.pdf",
    "file_size": 5818,
    "created_on": "2026-01-20T18:55:07.707+00:00"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  PDF File Preview
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff2f8gzgg5rgkj22x4d63.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff2f8gzgg5rgkj22x4d63.png" alt="HTML to PDF File" width="756" height="864"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Renewal Service Agreement - HTML Content
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;!DOCTYPE html&amp;gt;\n&amp;lt;html lang=\"en\"&amp;gt;\n\n&amp;lt;head&amp;gt;\n    &amp;lt;meta charset=\"UTF-8\" /&amp;gt;\n    &amp;lt;style&amp;gt;\n        @page land {\n            size: landscape;\n        }\n\n        @page port {\n            size: portrait;\n        }\n\n        body {\n            page: port;\n        }\n\n        .header {\n            text-align: center;\n        }\n\n        .brand a {\n            text-decoration: none;\n        }\n\n        h1 {\n            font-weight: 500;\n        }\n\n        .main_container {\n            page: port;\n            font-family: sans-serif;\n            width: 17.06cm;\n\n            padding: 16px;\n            margin: 0 auto;\n\n            margin-top: 32px;\n        }\n\n        .content-container {\n            margin-top: 32px;\n            gap: 10px;\n        }\n\n        .content {\n            margin-top: 5px;\n            border: 1px solid #e4e4e4;\n            border-radius: 3px;\n        }\n\n        .content-title {\n            width: auto;\n            color: whitesmoke;\n            font-weight: 200;\n            background-color: #3e6667;\n            padding: 10px;\n        }\n\n        .form-group {\n            padding: 5px;\n        }\n\n        td {\n            padding: 5px;\n        }\n\n        input[type=\"text\"],\n        input[type=\"number\"] {\n            width: 200px;\n            padding: 3.5px;\n            border: 1px solid green;\n            border-radius: 5px;\n        }\n\n        .signature_line {\n            height: 60px;\n            border: 1px solid black;\n            border-radius: 3px;\n        }\n\n        .signature_line,\n        #signature_label {\n            width: 360px;\n            margin-top: 15px;\n            margin-left: auto;\n            /* justify-self: right; */\n        }\n\n        #signature_label {\n            color: #5d5d5d;\n            font-style: italic;\n            text-align: center;\n            font-size: 14px;\n            padding: 5px;\n            width: calc(360px - 5px);\n        }\n    &amp;lt;/style&amp;gt;\n&amp;lt;/head&amp;gt;\n\n&amp;lt;body&amp;gt;\n    &amp;lt;div class=\"main_container\"&amp;gt;\n        &amp;lt;div class=\"header\"&amp;gt;\n            &amp;lt;div&amp;gt;\n                &amp;lt;div class=\"brand\" style=\"align-content: center\"&amp;gt;\n                    &amp;lt;a href=\"https://boltonsea.com\"&amp;gt;\n                        &amp;lt;img src=\"https://s3.us-east-1.amazonaws.com/io.boltonsea.com/dev/logo/2025/boltonsea_logo2.png\" style=\"width: 250px; margin: 0 auto\" /&amp;gt;\n                    &amp;lt;/a&amp;gt;\n                &amp;lt;/div&amp;gt;\n\n                &amp;lt;div&amp;gt;\n                    &amp;lt;h1&amp;gt;Renewal Service Agreement&amp;lt;/h1&amp;gt;\n                &amp;lt;/div&amp;gt;\n            &amp;lt;/div&amp;gt;\n\n            &amp;lt;div style=\"text-align: left\"&amp;gt;\n                &amp;lt;span&amp;gt;Agreement Date: January 6, 2025&amp;lt;/span&amp;gt;\n            &amp;lt;/div&amp;gt;\n        &amp;lt;/div&amp;gt;\n\n        &amp;lt;div class=\"content-container\"&amp;gt;\n            &amp;lt;div class=\"content\"&amp;gt;\n                &amp;lt;div class=\"content-title\"&amp;gt;\n                    &amp;lt;strong&amp;gt;Business Center Address:&amp;lt;/strong&amp;gt;\n                &amp;lt;/div&amp;gt;\n\n                &amp;lt;table&amp;gt;\n                    &amp;lt;tr&amp;gt;\n                        &amp;lt;td&amp;gt;180 Northfield Drive West&amp;lt;/td&amp;gt;\n                    &amp;lt;/tr&amp;gt;\n                    &amp;lt;tr&amp;gt;\n                        &amp;lt;td&amp;gt;(Unit 4)&amp;lt;/td&amp;gt;\n                    &amp;lt;/tr&amp;gt;\n                    &amp;lt;tr&amp;gt;\n                        &amp;lt;td&amp;gt;Waterloo, Ontario&amp;lt;/td&amp;gt;\n                    &amp;lt;/tr&amp;gt;\n                    &amp;lt;tr&amp;gt;\n                        &amp;lt;td&amp;gt;Canada&amp;lt;/td&amp;gt;\n                    &amp;lt;/tr&amp;gt;\n                &amp;lt;/table&amp;gt;\n            &amp;lt;/div&amp;gt;\n\n            &amp;lt;div class=\"content\"&amp;gt;\n                &amp;lt;div class=\"content-title\"&amp;gt;\n                    &amp;lt;strong&amp;gt;Client Address &amp;lt;/strong&amp;gt;\n                &amp;lt;/div&amp;gt;\n\n                &amp;lt;form&amp;gt;\n                    &amp;lt;table&amp;gt;\n                        &amp;lt;tr&amp;gt;\n                            &amp;lt;td&amp;gt;Company Name&amp;lt;/td&amp;gt;\n                            &amp;lt;td&amp;gt;\n                                &amp;lt;input type=\"text\" class=\"form-control\" id=\"company_name\" /&amp;gt;\n                            &amp;lt;/td&amp;gt;\n                        &amp;lt;/tr&amp;gt;\n                        &amp;lt;tr&amp;gt;\n                            &amp;lt;td&amp;gt;Contact Name&amp;lt;/td&amp;gt;\n                            &amp;lt;td&amp;gt;\n                                &amp;lt;input type=\"text\" class=\"form-control\" id=\"contact_name\" /&amp;gt;\n                            &amp;lt;/td&amp;gt;\n                        &amp;lt;/tr&amp;gt;\n                        &amp;lt;tr&amp;gt;\n                            &amp;lt;td&amp;gt;Address&amp;lt;/td&amp;gt;\n                            &amp;lt;td&amp;gt;\n                                &amp;lt;input type=\"text\" class=\"form-control\" id=\"address\" /&amp;gt;\n                            &amp;lt;/td&amp;gt;\n                        &amp;lt;/tr&amp;gt;\n                        &amp;lt;tr&amp;gt;\n                            &amp;lt;td&amp;gt;Phone Number&amp;lt;/td&amp;gt;\n                            &amp;lt;td&amp;gt;\n                                &amp;lt;input type=\"number\" class=\"form-control\" id=\"phone\" /&amp;gt;\n                            &amp;lt;/td&amp;gt;\n                        &amp;lt;/tr&amp;gt;\n                        &amp;lt;tr&amp;gt;\n                            &amp;lt;td&amp;gt;Email&amp;lt;/td&amp;gt;\n                            &amp;lt;td&amp;gt;\n                                &amp;lt;input type=\"text\" class=\"form-control\" id=\"email\" /&amp;gt;\n                            &amp;lt;/td&amp;gt;\n                        &amp;lt;/tr&amp;gt;\n                    &amp;lt;/table&amp;gt;\n                &amp;lt;/form&amp;gt;\n            &amp;lt;/div&amp;gt;\n        &amp;lt;/div&amp;gt;\n\n        &amp;lt;div&amp;gt;\n            &amp;lt;div class=\"content-title\"&amp;gt;\n                &amp;lt;strong&amp;gt;Renewal Payment Details&amp;lt;/strong&amp;gt;\n            &amp;lt;/div&amp;gt;\n\n            &amp;lt;div class=\"content-container\"&amp;gt;\n                &amp;lt;div&amp;gt;\n                    &amp;lt;table&amp;gt;\n                        &amp;lt;tr&amp;gt;\n                            &amp;lt;td&amp;gt;Type of Service:&amp;lt;/td&amp;gt;\n                            &amp;lt;td&amp;gt;Rent&amp;lt;/td&amp;gt;\n                        &amp;lt;/tr&amp;gt;\n                        &amp;lt;tr&amp;gt;\n                            &amp;lt;td&amp;gt;Service Discount:&amp;lt;/td&amp;gt;\n                            &amp;lt;td&amp;gt;50%&amp;lt;/td&amp;gt;\n                        &amp;lt;/tr&amp;gt;\n                        &amp;lt;tr&amp;gt;\n                            &amp;lt;td&amp;gt;Monthly Price:&amp;lt;/td&amp;gt;\n                            &amp;lt;td&amp;gt;$0.5&amp;lt;/td&amp;gt;\n                        &amp;lt;/tr&amp;gt;\n                    &amp;lt;/table&amp;gt;\n                &amp;lt;/div&amp;gt;\n\n                &amp;lt;div class=\"signature_line\"&amp;gt;&amp;lt;/div&amp;gt;\n                &amp;lt;div id=\"signature_label\"&amp;gt;Client Signature and Date (dd/mm/yyyy)&amp;lt;/div&amp;gt;\n            &amp;lt;/div&amp;gt;\n        &amp;lt;/div&amp;gt;\n    &amp;lt;/div&amp;gt;\n&amp;lt;/body&amp;gt;\n\n&amp;lt;/html&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Tools
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt; Docker File Server (&lt;a href="https://boltonsea.com/download" rel="noopener noreferrer"&gt;BoltonSea - Community Plan&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>programming</category>
      <category>dam</category>
      <category>pdf</category>
      <category>devops</category>
    </item>
    <item>
      <title>Video Streaming for Multi-Screen Size Responsive Performance</title>
      <dc:creator>Mike</dc:creator>
      <pubDate>Mon, 22 Dec 2025 13:39:23 +0000</pubDate>
      <link>https://forem.com/michael_81be8af/video-streaming-for-multi-screen-size-responsive-performance-2017</link>
      <guid>https://forem.com/michael_81be8af/video-streaming-for-multi-screen-size-responsive-performance-2017</guid>
      <description>&lt;p&gt;I write to share a strategy for optimizing website video streaming performance, particularly on mobile devices and variable screen sizes.&lt;/p&gt;

&lt;p&gt;The goal is to improve user experience, reduce data consumption, and minimize performance bottlenecks.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Original article here&lt;/strong&gt; 👉 &lt;a href="https://boltonsea.com/blog/video_streaming_optimization" rel="noopener noreferrer"&gt;[Link Here]&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem
&lt;/h2&gt;

&lt;p&gt;High-quality, large video files (e.g., a 30-minute, &lt;code&gt;300mb&lt;/code&gt; video) create several issues:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;High Data Consumption:&lt;/strong&gt; Browsers must fully download the large file, which quickly depletes a user's mobile data plan.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Slow Playback Initiation:&lt;/strong&gt; Users experience a delay while the entire file downloads before the video can begin to stream.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Performance Bottlenecks:&lt;/strong&gt; Processing large media files requires significant memory, which can slow down the performance of the user's device.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F256wtmq9w8ruk8yt1r8j.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F256wtmq9w8ruk8yt1r8j.jpeg" alt="Video Streaming Optimization for Responsive Performance" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Solutions
&lt;/h2&gt;

&lt;p&gt;An approach that combines responsive video compression with file segmentation.&lt;/p&gt;

&lt;h3&gt;
  
  
  Versioned Video Responsive Compression
&lt;/h3&gt;

&lt;p&gt;This strategy involves generating multiple compressed versions of a video, each optimized for different screen sizes (e.g., mobile, tablet, and desktop). This ensures the device only downloads the resolution appropriate for its display, directly addressing the performance issues associated with non-optimized, high-quality files.&lt;/p&gt;

&lt;h3&gt;
  
  
  Segmentation of Large Video Files
&lt;/h3&gt;

&lt;p&gt;Videos should be broken down into small, manageable segments (chunks), with a corresponding playlist file to manage them.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Playlist File&lt;/strong&gt;: This is a file that lists multiple media files (or segments) for playback by a media player.&lt;br&gt;
For a 30-minute (1,800-seconds) video, using 10-second segments would result in 180 segments. If the total file size is &lt;code&gt;300mb&lt;/code&gt;, each segment would be approximately &lt;code&gt;1.67mb&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example&lt;/strong&gt; of an MPEG (.m3u8) Playlist File with segment (&lt;em&gt;.ts) media files&lt;br&gt;
**File Name:&lt;/em&gt;* &lt;code&gt;playlist_1280x720p.m3u8&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#EXTM3U
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:4
#EXT-X-MEDIA-SEQUENCE:1
#EXT-X-PLAYLIST-TYPE:VOD
#EXTINF:3,
video_track_1280x720p_6_00001.ts
#EXTINF:3,
video_track_1280x720p_6_00002.ts
#EXTINF:3,
video_track_1280x720p_6_00003.ts
#EXTINF:3,
video_track_1280x720p_6_00004.ts
#EXTINF:3,
video_track_1280x720p_6_00005.ts
#EXTINF:3,
video_track_1280x720p_6_00006.ts
#EXTINF:3,
video_track_1280x720p_6_00007.ts
#EXTINF:3,
video_track_1280x720p_6_00008.ts
#EXTINF:1,
video_track_1280x720p_6_00009.ts
#EXT-X-ENDLIST
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The web browser would sequentially download each small segment only as needed while playing. This method allows for immediate playback and significantly reduces initial download time and data consumption.&lt;/p&gt;

&lt;h3&gt;
  
  
  Advanced Responsiveness
&lt;/h3&gt;

&lt;p&gt;The most comprehensive and optimized solution is to combine these two strategies: Generate a &lt;code&gt;master playlist&lt;/code&gt; of Compressed, Segmented Videos.&lt;/p&gt;

&lt;p&gt;This involves creating separate segmented playlists for each screen size (e.g., a segmented playlist for mobile, one for tablet, and one for desktop). These individual playlists are then aggregated into a single &lt;code&gt;master playlist&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This system allows the browser on any device to play the &lt;code&gt;master playlist&lt;/code&gt; and automatically select the most suitable resolution and segment based on the device type, screen size, and Internet (network) speed, ensuring the fastest, most optimal viewing experience for every device type.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example of a &lt;code&gt;Master Playlist&lt;/code&gt; File with screen-size specific playlists&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;File Name:&lt;/strong&gt; &lt;code&gt;master_playlist.m3u8&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#EXTM3U
#EXT-X-VERSION:3
#EXT-X-INDEPENDENT-SEGMENTS
#EXT-X-STREAM-INF:BANDWIDTH=667612,AVERAGE-BANDWIDTH=508186,CODECS="avc1.64001e,mp4a.40.5",RESOLUTION=480x270,FRAME-RATE=59.940
playlist_480x270p.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=2183596,AVERAGE-BANDWIDTH=1099733,CODECS="avc1.64001f,mp4a.40.5",RESOLUTION=640x360,FRAME-RATE=59.940
playlist_640x360p.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=4853046,AVERAGE-BANDWIDTH=2730357,CODECS="avc1.640020,mp4a.40.5",RESOLUTION=960x540,FRAME-RATE=59.940
playlist_960x540p.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=7945434,AVERAGE-BANDWIDTH=4125547,CODECS="avc1.640020,mp4a.40.5",RESOLUTION=1280x720,FRAME-RATE=59.940
playlist_1280x720p.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=11649009,AVERAGE-BANDWIDTH=7825004,CODECS="avc1.64002a,mp4a.40.2",RESOLUTION=1920x1080,FRAME-RATE=59.940
playlist_1920x1080p.m3u8
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Should you have any inquiries or have questions, post your comments below.&lt;/p&gt;

</description>
      <category>ffmpeg</category>
      <category>programming</category>
      <category>webdev</category>
      <category>startup</category>
    </item>
    <item>
      <title>AI to Match Qualified Candidates with Job Postings</title>
      <dc:creator>Mike</dc:creator>
      <pubDate>Fri, 14 Nov 2025 15:55:02 +0000</pubDate>
      <link>https://forem.com/michael_81be8af/ai-to-match-qualified-candidates-with-job-postings-107e</link>
      <guid>https://forem.com/michael_81be8af/ai-to-match-qualified-candidates-with-job-postings-107e</guid>
      <description>&lt;p&gt;Our current hiring process involves manually reviewing resumes from various platforms to match candidates with job descriptions. This is inefficient given the high volume of applications.&lt;/p&gt;

&lt;h2&gt;
  
  
  My Proposal
&lt;/h2&gt;

&lt;p&gt;I propose developing an AI workflow to automate this initial screening. The system would match candidates' experience, education, and skills against job requirements, providing hiring managers with a pre-vetted list of qualified candidates. This would streamline the hiring process significantly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Workflow Components:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Job Board&lt;/strong&gt;: A full-stack application designed to serve both job seekers (users) and hiring managers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Content Management System&lt;/strong&gt;: A system, such as &lt;a href="https://boltonsea.com" rel="noopener noreferrer"&gt;Boltonsea&lt;/a&gt;, to effectively manage and organize candidate resumes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AI Engine&lt;/strong&gt;: An integration with a large language model provider (e.g., &lt;a href="https://www.deepseek.com/en" rel="noopener noreferrer"&gt;DeepSeek&lt;/a&gt;, &lt;a href="https://openai.com/" rel="noopener noreferrer"&gt;OpenAI&lt;/a&gt;) for intelligent features.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwfbyifg8zl52elkqhzhk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwfbyifg8zl52elkqhzhk.png" alt="AI Powered Job Board WorkFlow" width="800" height="792"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This outlines the process an applicant undergoes when applying for a position on our job board. Upon submitting their resume, which details their experience, education, and skills, a candidate record is created within our database. The original resume document, whether in MS Word or PDF format, is then securely stored in our Content Management System (CMS) for convenient access.&lt;/p&gt;

&lt;p&gt;Furthermore, each candidate's resume link (resume URL) is forwarded to our AI engine layer to train or retrain our existing AI model. For optimal efficiency, every resume is first converted into a Markdown format, from which only the essential information is extracted and utilized for training purposes.&lt;/p&gt;

&lt;p&gt;This streamlined system is designed to benefit the Hiring Manager by optimizing the job application review process and identifying only the most qualified candidates.&lt;/p&gt;

&lt;h2&gt;
  
  
  AI Training Script (Python Snippet)
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Convert PDF to Markdown&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Processing resume: self.file_path
docling_doc = self.converter.convert(self.file_path).document

# 🔄 Converting to markdown format
text = docling_doc.export_to_markdown()

# ✅ Conversion complete
metadata = {
    "source": self.file_path,
    "format": "resume",
}

yield LCDocument(page_content=text, metadata=metadata)

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Train AI Model&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
def train_resume(resume_url: str):
    OPENAI_API_URL = "https//OPEN_URL"
    index_path = f"{resume_url}_faiss_index"

    # 🔤 Initializing embedding model
    embeddings = HuggingFaceEmbeddings(
        model_name="sentence-transformers/all-MiniLM-L6-v2"
    )

    # ✅ Embedding model initialized
    if os.path.exists(index_path):
        print("📦 Loading existing vector store...")
        vectorstore = FAISS.load_local(
            index_path, embeddings, allow_dangerous_deserialization=True
        )
        # ✅ Vector store loaded
    else:
        # 💫 No existing index found. Creating new one...

        loader = DoclingResumeLoader(resume_url)
        documents = loader.load()

        print("\n📄 Splitting document into chunks...")
        text_splitter = RecursiveCharacterTextSplitter(
            chunk_size=1000, chunk_overlap=200, separators=["\n\n", "\n", " ", ""]
        )
        splits = text_splitter.split_documents(documents)
        print(f"✅ Created {len(splits)} chunks")

        print("\n📦 Building vector store and creating embeddings...")
        vectorstore_start = time.time()
        vectorstore = FAISS.from_documents(splits, embeddings)
        vectorstore_time = time.time() - vectorstore_start
        print(f"✅ Vector store built in {vectorstore_time:.2f} seconds")

        print(f"💾 Saving vector store to {index_path}")
        save_start = time.time()
        vectorstore.save_local(index_path)
        save_time = time.time() - save_start
        print(f"✅ Vector store saved in {save_time:.2f} seconds")

    retriever = vectorstore.as_retriever(search_type="mmr", search_kwargs={"k": 5})
    print("✅ Vector store ready")

    print("\n🤖 Connecting to local language model...")

    llm = ChatOpenAI(
        model="local-model",
        openai_api_base=OPENAI_API_URL,
        openai_api_key="not-needed",
        temperature=0,
    )

    template = """You are a helpful assistant answering questions about the resume: {book_name}.
    Use the following context to answer the question: {context}
    Question: {question}
    Answer the question accurately and concisely based on the context provided."""

    prompt = PromptTemplate(
        input_variables=["book_name", "context", "question"], template=template
    )

    # ✨ System ready! Total setup took
    return ConversationalRetrievalChain.from_llm(
        llm=llm,
        retriever=retriever,
        return_source_documents=True,
        combine_docs_chain_kwargs={
            "prompt": prompt,
            "document_variable_name": "context",
        },
    )

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Ask A.I. "The Question"&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Question: &lt;code&gt;Who qualifies for this job with {{description}}&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;trained_model = train_resume(args.url)
chat_history = []

print("\n Ready to answer questions \n")
print("Type 'quit!' to exit")

while True:
    question = input("\n Ask a question: ")
    if question.lower() == "quit!":
        break

    print("\n ... Processing ... \n")
    result = trained_model.invoke(
        {
            "question": question,
            "chat_history": chat_history,
            "book_name": os.path.basename(args.resume_path),
        }
    )

    print_result(result)
    chat_history.append((question, result["answer"]))
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Tools &amp;amp; Dependency
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;requirements.txt&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  langchain-core==0.3.28
  langchain-text-splitters==0.3.4
  langchain_huggingface==0.1.2
  docling==2.14.0
  langchain_community==0.3.13
  langchain_openai==0.2.14
  langchain==0.3.13
  faiss-cpu==1.9.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Installation&lt;/strong&gt;: &lt;code&gt;pip install -r requirements.txt&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;Job Portal (NextJS)&lt;/code&gt;: &lt;a href="https://themeforest.net/item/superio-job-board-react-nextjs-template/42719363" rel="noopener noreferrer"&gt;Superio&lt;/a&gt; is suitable for you to show professional job board websites that require high advanced features to powerful functions and useful services for users&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;BoltonSea (CMS)&lt;/code&gt;: &lt;a href="https://boltonsea.com" rel="noopener noreferrer"&gt;BoltonSea&lt;/a&gt; is a content management system that offers services related to files, media management and streaming with an APIs and a dashboard UI&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;Docling (Open Source Document Processing for AI)&lt;/code&gt;: &lt;a href="https://www.docling.ai/" rel="noopener noreferrer"&gt;Docling&lt;/a&gt; simplifies document processing with advanced PDF understanding, OCR support, and seamless AI integrations. Parse PDFs, DOCX, PPTX, images &amp;amp; more&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  References:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://dev.to/michael_81be8af/guide-integrate-a-self-hosted-file-server-with-your-web-page-2hdp"&gt;Integrate a Self-Hosted File Server in your Website&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.dataengineerthings.org/how-to-extract-data-from-documents-with-python-a-step-by-step-guide-using-docling-8360264f1e87" rel="noopener noreferrer"&gt;How to Extract Data from Documents with Python (Docling)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/AI-Engineer-Skool/booktutor-ai" rel="noopener noreferrer"&gt;Convert Any Book into an AI Tutor&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/docling-project/docling" rel="noopener noreferrer"&gt;https://github.com/docling-project/docling&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=GTidrAiojbg" rel="noopener noreferrer"&gt;Create AI teachers from ANY book using Docling&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>ai</category>
      <category>tooling</category>
      <category>datascience</category>
      <category>boltonsea</category>
    </item>
    <item>
      <title>Guide: Integrate a Self-Hosted File Server with Your Web Page</title>
      <dc:creator>Mike</dc:creator>
      <pubDate>Sat, 08 Nov 2025 18:00:37 +0000</pubDate>
      <link>https://forem.com/michael_81be8af/guide-integrate-a-self-hosted-file-server-with-your-web-page-2hdp</link>
      <guid>https://forem.com/michael_81be8af/guide-integrate-a-self-hosted-file-server-with-your-web-page-2hdp</guid>
      <description>&lt;p&gt;When building an application (frontend or backend) that requires file management, developers typically face two choices: build a custom feature or purchase an enterprise management service.&lt;/p&gt;

&lt;p&gt;Building a complete file management system or Content Management System (CMS) can be a significant time investment, especially when several robust, premium enterprise solutions already exist. However, while paying for an existing enterprise solution seems easier, the pricing tiers often become a major consideration.&lt;/p&gt;

&lt;p&gt;This tutorial guide will offer developers an alternative by walking through how to quickly integrate a self-hosted file management application with a ReactJS application.&lt;/p&gt;

&lt;p&gt;To follow along with this tutorial, you should have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Docker Engine installed&lt;/li&gt;
&lt;li&gt;Working knowledge of JavaScript and ReactJS&lt;/li&gt;
&lt;li&gt;General web development experience&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Download Self-Hosted File Server (Free)
&lt;/h2&gt;

&lt;p&gt;Here are the steps for setting up your self-hosted, Docker-based file server using the free &lt;strong&gt;BoltonSea Community Service&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Please follow these steps to deploy the service. You can also refer to the quick installer guide available at &lt;a href="https://boltonsea.com/download" rel="noopener noreferrer"&gt;[Link to Guide]&lt;/a&gt; for additional details.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Pull/download the BoltonSea Community Service Image from DockerHub&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;docker pull boltonsea/cms_api:latest&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Verify the Image Download&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;docker images boltonsea/cms_api&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Run the container, exposing the service on port 9080 of your host machine (mapping to port 9200 on the container).&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;docker run -d --name myBoltonSeaCMS -p 9080:9200 boltonsea/cms_api&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Our File Service now Live
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The file service is available here: &lt;code&gt;http://localhost:9080&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Test an endpoint (via Chrome Browser): &lt;code&gt;http://localhost:9080/organizations/1&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2de75z3emrb8mro5qoe1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2de75z3emrb8mro5qoe1.png" alt="Testing https://boltonsea.com Live Server" width="768" height="220"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Create the React Application
&lt;/h2&gt;

&lt;p&gt;We will begin by creating the base React application using the following commands:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx create-react-app my-app
cd my-app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Install Dependencies and Start the UI&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install ajv --save-dev
npm start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The command terminal should display the following output, confirming successful compilation and providing the local access details:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Compiled successfully!

You can now view file-upload-app in the browser.

 Local:            http://localhost:3000
 On Your Network:  http://192.168.4.31:3000

Note that the development build is not optimized.
To create a production build, use npm run build.

webpack compiled successfully
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, let's test our react UI. It should look like this&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7vpmm2yqc65df5c6iygt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7vpmm2yqc65df5c6iygt.png" alt="ReactJS Default UI" width="800" height="493"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Integrate with File Service API
&lt;/h3&gt;

&lt;p&gt;To begin the UI integration process, please set up the necessary files:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Navigate to the &lt;code&gt;my-app/src&lt;/code&gt; folder.&lt;/li&gt;
&lt;li&gt;Create the file named &lt;code&gt;lib.js&lt;/code&gt; within that directory.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This is the template of the &lt;code&gt;lib.js&lt;/code&gt; file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// ---------------- DEFAULT CONSTANT DECLARATIONs  ----------------

const organizationId = 1;
const mediaGroupId = 1;

// ------ Endpoint to our docker-based BoltonSea File Server ------

const FILE_SERVER_ENDPOINT = "http://localhost:9080";
const UPLOAD_ENDPOINT = `${FILE_SERVER_ENDPOINT}/media`;
const MEDIA_GROUP_ENDPOINT = `${FILE_SERVER_ENDPOINT}/mediagroup/${mediaGroupId}/content`;

// ----------------------------------
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// function to upload files into the filer_server
export async function uploadFile(file) {
… …
}

// function to get files from the filer_server
export async function fetchData() {
… …
}

const mediaGroupContent = (content) =&amp;gt; {
… …
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can see that there are three helper method function definitions here.&lt;/p&gt;

&lt;p&gt;This method helps upload files to the file-server&lt;br&gt;
&lt;code&gt;function uploadFile(file)&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This method helps fetch the list of files from the file-server&lt;br&gt;
&lt;code&gt;function fetchData()&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This is a helper method to extract an API requests output&lt;br&gt;
&lt;code&gt;const mediaGroupContent = (content)&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Copy the full content of the &lt;code&gt;lib.js&lt;/code&gt; file.&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// ---------------- DEFAULT CONSTANT DECLARATIONs  ----------------

const organizationId = 1;
const mediaGroupId = 1;

// ---------------- Endpoint to our docker-based BoltonSea File Server ----------------

const FILE_SERVER_ENDPOINT = "http://localhost:9080";
const UPLOAD_ENDPOINT = `${FILE_SERVER_ENDPOINT}/media`;
const MEDIA_GROUP_ENDPOINT = `${FILE_SERVER_ENDPOINT}/mediagroup/${mediaGroupId}/content`;

// --------------------------------------------------------------------

export async function uploadFile(file) {
  // Create an object of formData
  const formData = new FormData();

  // Update the formData object
  formData.append("media_group_id", mediaGroupId);
  formData.append("account_id", organizationId);
  formData.append("file", file);

  try {
    const response = await fetch(UPLOAD_ENDPOINT, {
      method: "POST",
      body: formData,
    });

    if (response.ok) {
      alert("File uploaded successfully!");
      window.location.reload();
    } else {
      console.error("File upload failed:", response.statusText);
      alert("File upload failed!");
    }
  } catch (error) {
    console.error("Error during file upload:", error);
    alert("An error occurred during file upload.");
  }
}

export async function fetchData() {
  let result = [];
  try {
    const response = await fetch(MEDIA_GROUP_ENDPOINT); // Replace with your API URL
    if (!response.ok) {
      throw new Error(`HTTP error! status: ${response.status}`);
    }
    result = await response.json();
    result = mediaGroupContent(result.content);
  } catch (error) {
    console.error("Error Getting Response");
  }

  return result;
}

const mediaGroupContent = (content) =&amp;gt; {
  content = content.filter((item) =&amp;gt; item != null);
  return content.map((mediaItem) =&amp;gt; {
    let type = "document";

    if (mediaItem?.mime_type?.includes("image")) {
      type = "image";
    }
    mediaItem["type"] = type;

    return mediaItem;
  });
};

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Please follow these steps to update the application files:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Navigate to &lt;code&gt;App.js&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Update &lt;code&gt;App.js&lt;/code&gt;:

&lt;ul&gt;
&lt;li&gt;Copy the contents.&lt;/li&gt;
&lt;li&gt;Navigate to the &lt;code&gt;App.js&lt;/code&gt; file and &lt;strong&gt;paste&lt;/strong&gt; the copied contents into the file.&lt;/li&gt;
&lt;li&gt;Refresh the user interface (UI).&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Refresh the UI&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { useEffect, useState } from "react";
import { uploadFile, fetchData } from "./lib";

import logo from "./logo.svg";
import "./App.css";

let file_ = null;

function App() {
  const [mediaList, setMediaList] = useState([]);

  useEffect(() =&amp;gt; {
    fetchData()
      .then(setMediaList)
      .catch((e) =&amp;gt; console.error("An error occured!", e));
  }, []);

  const handleChange = async (e) =&amp;gt; {
    file_ = e.target.files[0];
  };

  const uploadAction = async (e) =&amp;gt; {
    e.preventDefault();

    if (file_) {
      await uploadFile(file_);
      file_ = null;
    }
  };

  return (
    &amp;lt;div className="App"&amp;gt;
      &amp;lt;div id="page_title"&amp;gt;
        &amp;lt;img src={logo} className="App-logo" alt="logo" height={100} /&amp;gt;
        &amp;lt;h1&amp;gt;Document Management Dashboard&amp;lt;/h1&amp;gt;
      &amp;lt;/div&amp;gt;

      &amp;lt;div id="upload-component" className="container"&amp;gt;
        &amp;lt;div className="input-group"&amp;gt;
          &amp;lt;input
            type="file"
            onChange={handleChange}
            className="form-control"
            id="fileInput"
            aria-describedby="uploadButton"
            aria-label="Upload"
          /&amp;gt;
          &amp;lt;button
            className="btn btn-outline-primary"
            type="button"
            id="uploadButton"
            onClick={uploadAction}
          &amp;gt;
            Upload
          &amp;lt;/button&amp;gt;
        &amp;lt;/div&amp;gt;
      &amp;lt;/div&amp;gt;

      &amp;lt;div id="media_list" className="container text-center"&amp;gt;
        &amp;lt;div className="row"&amp;gt;
          {mediaList?.map((item, i) =&amp;gt; (
            &amp;lt;div key={i} className="col-12 col-sm-6 col-lg-4"&amp;gt;
              &amp;lt;div className="media_item"&amp;gt;
                {item.type === "image" &amp;amp;&amp;amp; (
                  &amp;lt;img src={item.public_url} alt={item.original_file_name} /&amp;gt;
                )}

                &amp;lt;div&amp;gt;
                  &amp;lt;a target="_blank" rel="noreferrer" href={item.public_url}&amp;gt;
                    {item.original_file_name}
                  &amp;lt;/a&amp;gt;
                &amp;lt;/div&amp;gt;
              &amp;lt;/div&amp;gt;
            &amp;lt;/div&amp;gt;
          ))}
        &amp;lt;/div&amp;gt;
      &amp;lt;/div&amp;gt;
    &amp;lt;/div&amp;gt;
  );
}

export default App;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Navigate to &lt;code&gt;App.css&lt;/code&gt; 

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Copy&lt;/strong&gt; the contents of the methods.&lt;/li&gt;
&lt;li&gt;Navigate to the &lt;code&gt;App.css&lt;/code&gt; file and &lt;strong&gt;paste&lt;/strong&gt; the copied contents into the file.&lt;/li&gt;
&lt;li&gt;Refresh the user interface (UI).&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Refresh the UI&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@import url("https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/css/bootstrap.min.css");

body {
  background-color: white;
  font-family: "Roboto", sans-serif;
}
h1 {
  color: #444;
  text-align: center;
}

button {
  background-color: #6161d4;
}

/* ------- Other Components ------- */

#page_title {
  margin: 6rem;
  text-align: center;
}

#upload-component {
  margin: 3rem auto;
  max-width: 50rem;
}

#media_list {
  padding: 1rem 2rem;
  background-color: #f8f8f8;
}

.media_item {
  height: 15rem;
  overflow: scroll;
  margin: 1.5rem 1rem;
  border-radius: 5px;
  align-content: center;
  background-color: #fff;
  box-shadow: 0 0 5px #ccc; /* A black shadow, offset, blurred, and semi-transparent */
}

.media_item img {
  max-height: 80%;
  margin-bottom: 1em;
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Live Test Our File-Service UI Dashboard
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjsrlu0z49rvwc1968tyg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjsrlu0z49rvwc1968tyg.png" alt="Web Dashboard to test BoltonSea Content Management System" width="800" height="221"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We need to conduct a test of our File Service using the Dashboard interface.&lt;/p&gt;

&lt;p&gt;Please upload a few test files directly through the Dashboard UI and then verify that they can be successfully retrieved afterward. This will help us confirm that the upload and retrieval processes are functioning correctly.&lt;/p&gt;




&lt;p&gt;Here is what my Dashboard looks like 👇 after my file uploads through the Dashboard.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F98nbst3uixbwkyuahewp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F98nbst3uixbwkyuahewp.png" alt="Final view of the dashboard with BoltonSea File Service" width="800" height="559"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Tools
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt; Docker File Server (&lt;a href="https://boltonsea.com/download" rel="noopener noreferrer"&gt;BoltonSea - Community Plan&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt; DashBoard (React APP)&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;Happy Coding!&lt;/p&gt;

</description>
      <category>docker</category>
      <category>react</category>
      <category>boltonsea</category>
      <category>fullstack</category>
    </item>
  </channel>
</rss>
