<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/"
    xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
    <channel>
        
        <title>
            <![CDATA[ publishing - freeCodeCamp.org ]]>
        </title>
        <description>
            <![CDATA[ Browse thousands of programming tutorials written by experts. Learn Web Development, Data Science, DevOps, Security, and get developer career advice. ]]>
        </description>
        <link>https://www.freecodecamp.org/news/</link>
        <image>
            <url>https://cdn.freecodecamp.org/universal/favicons/favicon.png</url>
            <title>
                <![CDATA[ publishing - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Tue, 26 May 2026 04:44:31 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/news/tag/publishing/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ How to Add a Table of Contents to Your Blog Post or Article ]]>
                </title>
                <description>
                    <![CDATA[ Providing a table of contents helps preview and prioritize content when writing lengthier articles. But not every platform makes it easy to add one. How can we implement one when we lack first class t ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-add-a-table-of-contents-to-your-blog-post-or-article/</link>
                <guid isPermaLink="false">66b8e331684cb75ad7f76d16</guid>
                
                    <category>
                        <![CDATA[ blog ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Blogger ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Blogging ]]>
                    </category>
                
                    <category>
                        <![CDATA[ publishing ]]>
                    </category>
                
                    <category>
                        <![CDATA[ technical writing ]]>
                    </category>
                
                    <category>
                        <![CDATA[ writing ]]>
                    </category>
                
                    <category>
                        <![CDATA[ writing tips ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Colby Fayock ]]>
                </dc:creator>
                <pubDate>Wed, 12 Feb 2020 15:45:00 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2020/02/table-of-contents.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Providing a <a href="https://en.wikipedia.org/wiki/Table_of_contents">table of contents</a> helps preview and prioritize content when writing lengthier articles. But not every platform makes it easy to add one. How can we implement one when we lack first class tooling?</p>
<p>Want to skip ahead of the “what” and “why”? <a href="#heading-how-can-we-add-a-table-of-contents">Jump to the “how”</a>!</p>
<h2 id="heading-what-were-going-to-create">What we’re going to create</h2>
<img src="https://www.freecodecamp.org/news/content/images/2020/02/table-of-contents-example.jpg" alt="Image" style="display:block;margin:0 auto" width="600" height="400" loading="lazy">

<p><em>Blog post table of contents</em></p>
<p>For the purposes of this article, we’re going to use freeCodeCamp.org's content manager for visual and demonstration purposes. freeCodeCamp/news uses the blogging platform <a href="https://ghost.org/">Ghost</a> at the time of writing this, but this method can really apply to any article you write.</p>
<h2 id="heading-why-is-this-helpful">Why is this helpful?</h2>
<p>Providing a table of contents helps improve the experience that the people reading your article will have.</p>
<h3 id="heading-it-gives-readers-a-preview-of-the-article">It gives readers a preview of the article</h3>
<p>Jumping into an article, at least a lengthy one, can be a big time commitment. No one wants to spend 20 minutes of their morning only to figure out a post they dove into hasn’t actually answered their questions. Or that it's a rehash of something they’re already an expert on (although differing perspectives can still be helpful).</p>
<p>By providing this preview, you can help people get a sense of what to expect as they start to read. It allows them to prioritize their time with the other list of articles they have to read.</p>
<h3 id="heading-it-provides-anchor-points-to-jump-down-to-specific-content">It provides anchor points to jump down to specific content</h3>
<p>Similar to providing a preview, maybe someone wants to read a specific portion of the page. Maybe it’s because they can skip the first few bits of a tutorial or they are coming in from a link a coworker shared in <a href="https://slack.com/">Slack</a>.</p>
<p>The point is, people can use the table of contents to jump down to the parts that are more important to them.</p>
<h3 id="heading-bonus-it-helps-you-as-an-author">Bonus: it helps you as an author</h3>
<p>Providing a table of contents might not help for many practical reasons, but it's an additional tool for you to prioritize and understand the content of your post. It serves as a high level outline that you can refer to when making sure the flow of your story actually makes sense.</p>
<h2 id="heading-what-it-doesnt-do">What it doesn’t do</h2>
<p>Unfortunately, this is a manual process. This table of contents isn’t going to magically update any time you tweak your content. So make sure to be vigilant during the editing process and update any broken links or add and remove any changes before you publish.</p>
<h2 id="heading-how-can-we-add-a-table-of-contents">How can we add a table of contents?</h2>
<h3 id="heading-content-headers-and-anchor-links">Content headers and anchor links</h3>
<p>The key to this solution is to utilize the built in <code>id</code> attributes applied to content headers in the HTML when building a post page. Using these attributes allows us to create an <a href="https://www.w3.org/TR/REC-html40/struct/links.html#h-12.2.3">anchor link</a> that will jump the browser’s scroll position down to the location of the element with that <code>id</code>.</p>
<p>A basic example of the HTML looks like this:</p>
<pre><code class="language-html">&lt;ul&gt;
  &lt;li&gt;&lt;a href=“#my-id”&gt;Link to My ID&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;article&gt;
  &lt;p&gt;Super long content&lt;/p&gt;
  &lt;h2 id=“my-id”&gt;Important Thing&lt;/h2&gt;
  &lt;p&gt;Important content&lt;/p&gt;
&lt;/article&gt;
</code></pre>
<p>In the above, we can see our <code>article</code> contains some basic content (imagine it's much longer than the above) with an <code>h2</code> that follows with our important content.</p>
<p>By providing our <code>h2</code> with the <code>id</code> attribute, we can now create a link by setting the <code>href</code> to the pattern of <code>#[id]</code> that will jump to that element in the page.</p>
<p>Now, when creating this in our blogging platform, we don’t necessarily need to worry about writing this HTML. But we do need to understand how to find the <code>id</code> in order to create our links.</p>
<h3 id="heading-finding-our-header-id">Finding our header ID</h3>
<p>We can use our browser’s developer tools (<a href="https://developers.google.com/web/tools/chrome-devtools">Chrome</a>, <a href="https://developer.mozilla.org/en-US/docs/Tools">Firefox</a>) to pretty easily find our precious <code>id</code> attributes to create our links.</p>
<p>Using your favorite browser, find the headline that you’d like to use, right-click the text, and then select “Inspect” (or “Inspect Element”) from the bottom of the context menu.</p>
<img src="https://www.freecodecamp.org/news/content/images/2020/02/browser-inspect-element-developer-tools.jpg" alt="Image" style="display:block;margin:0 auto" width="600" height="400" loading="lazy">

<p><em>Using Chrome to inspect a page's HTML</em></p>
<p>From there, you’ll notice that a panel pops up from either the bottom of the page or to the side. The placement of this panel doesn’t matter too much – it’s just a <a href="https://developers.google.com/web/tools/chrome-devtools/customize/placement">user setting</a>. But we can now see the HTML of the page we’re looking at with our header element highlighted.</p>
<img src="https://www.freecodecamp.org/news/content/images/2020/02/developer-tools-highlight-element.jpg" alt="Image" style="display:block;margin:0 auto" width="600" height="400" loading="lazy">

<p><em>Previewing a page's HTML using Chrome developer tools</em></p>
<p>After finding our header in the HTML, find the <code>id</code> attribute. Double click the contents of it, and copy the value which we’ll use in a little bit.</p>
<img src="https://www.freecodecamp.org/news/content/images/2020/02/developer-tools-select-id.jpg" alt="Image" style="display:block;margin:0 auto" width="600" height="400" loading="lazy">

<p><em>Selecting the id attribute using Chrome developer tools</em></p>
<h3 id="heading-creating-a-link-to-our-header">Creating a link to our header</h3>
<p>Since we’re going to create a table of contents, let’s open our post’s editor page and scroll to the top of the page.</p>
<p>The first thing we want to do is start a list, which we can do by typing an asterisk <code>*</code> followed by a space when starting a new content section.</p>
<img src="https://www.freecodecamp.org/news/content/images/2020/02/post-editor-add-list-ghost.gif" alt="Image" style="display:block;margin:0 auto" width="600" height="400" loading="lazy">

<p><em>Adding a new list using Markdown in Ghost</em></p>
<p>Next, write what you want your link to say. Most commonly in table of contents, the link is exactly the same text as the header itself.</p>
<p>After it says what you want, highlight the entire line, and a little context menu will appear above your selection.</p>
<img src="https://www.freecodecamp.org/news/content/images/2020/02/post-rich-text-formatting-editing.jpg" alt="Image" style="display:block;margin:0 auto" width="600" height="400" loading="lazy">

<p><em>Opening the rich text formatting menu</em></p>
<p>Select the little link icon and the context menu will turn into a text field. Type into the text field a hashtag <code>#</code> followed by the contents of the <code>id</code> attribute that you found on your header above.</p>
<img src="https://www.freecodecamp.org/news/content/images/2020/02/post-edit-add-link.jpg" alt="Image" style="display:block;margin:0 auto" width="600" height="400" loading="lazy">

<p><em>Adding or editing a link</em></p>
<p>Hit the Enter key and success! We have a link.</p>
<img src="https://www.freecodecamp.org/news/content/images/2020/02/post-list-with-link.jpg" alt="Image" style="display:block;margin:0 auto" width="600" height="400" loading="lazy">

<p><em>List with link</em></p>
<p>Repeat the steps above and create 1 link for each top level header that you'd like to link to.</p>
<p>Don’t feel like you need to go overboard, though. Typically you’ll see blog posts include only the top level headers of the page, so don’t feel like you need to include every sub header. Ultimately – do what you’re comfortable with.</p>
<h2 id="heading-testing-and-previewing-your-table-of-contents">Testing and previewing your table of contents</h2>
<p>Once we’re done adding all of our links, we can preview or view our post and test that our links work.</p>
<img src="https://www.freecodecamp.org/news/content/images/2020/02/preview-post-freecodecamp-ghost.jpg" alt="Image" style="display:block;margin:0 auto" width="600" height="400" loading="lazy">

<p><em>Previewing or viewing post in Ghost on freecodecamp.org/news</em></p>
<p>After opening your preview or page, scroll to your table of contents or link and click it to test.</p>
<img src="https://www.freecodecamp.org/news/content/images/2020/02/table-of-contents-clicking-link.gif" alt="Image" style="display:block;margin:0 auto" width="600" height="400" loading="lazy">

<p><em>Using a table of contents</em></p>
<p>Success!</p>
<h2 id="heading-more-tools-for-authoring">More tools for authoring</h2>
<p>A table of contents is just one way to help readers enjoy your hard work. What other tools do you use that are important to your workflow? Are there any others you’ve seen but maybe not sure how to implement on your own?</p>
<p>Share with us on Twitter at <a href="https://twitter.com/colbyfayock">@colbyfayock</a> and <a href="https://twitter.com/freecodecamp">@freecodecamp</a>!</p>
<p><a href="https://twitter.com/colbyfayock"><img src="https://res.cloudinary.com/fay/image/upload/w_2000,h_400,c_fill,q_auto,f_auto/w_1020,c_fit,co_rgb:007079,g_north_west,x_635,y_70,l_text:Source%20Sans%20Pro_64_line_spacing_-10_bold:Colby%20Fayock/w_1020,c_fit,co_rgb:383f43,g_west,x_635,y_6,l_text:Source%20Sans%20Pro_44_line_spacing_0_normal:Follow%20me%20for%20more%20JavaScript%252c%20UX%252c%20and%20other%20interesting%20things!/w_1020,c_fit,co_rgb:007079,g_south_west,x_635,y_70,l_text:Source%20Sans%20Pro_40_line_spacing_-10_semibold:colbyfayock.com/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_68,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_145,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_222,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/w_300,c_fit,co_rgb:7c848a,g_north_west,x_1725,y_295,l_text:Source%20Sans%20Pro_40_line_spacing_-10_normal:colbyfayock/v1/social-footer-card" alt="Follow me for more Javascript, UX, and other interesting things!" style="display:block;margin:0 auto" width="2000" height="400" loading="lazy"></a></p>
<ul>
<li><p><a href="https://twitter.com/colbyfayock">? Follow Me On Twitter</a></p>
</li>
<li><p><a href="https://youtube.com/colbyfayock">?️ Subscribe To My Youtube</a></p>
</li>
<li><p><a href="https://www.colbyfayock.com/newsletter/">✉️ Sign Up For My Newsletter</a></p>
</li>
</ul>
<p>You can see how to create a table of contents with the help of JavaScript and browser DevTools <a href="https://www.freecodecamp.org/news/how-to-create-a-table-of-contents-for-your-article/">here</a>.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to deploy a complete video publishing pipeline for web and ecommerce ]]>
                </title>
                <description>
                    <![CDATA[ By Anton Garcia Diaz From ffmpeg and cloud video transcoding to HLS, delivery, players, Video.js, and analytics. After the conquest of social networks, video is spreading through web businesses. As a media consultant working for several of the larges... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/short-videos-in-web-and-ecommerce-workflows/</link>
                <guid isPermaLink="false">66d45d9f3a8352b6c5a2aa03</guid>
                
                    <category>
                        <![CDATA[ ecommerce ]]>
                    </category>
                
                    <category>
                        <![CDATA[ hls ]]>
                    </category>
                
                    <category>
                        <![CDATA[ publishing ]]>
                    </category>
                
                    <category>
                        <![CDATA[ technology ]]>
                    </category>
                
                    <category>
                        <![CDATA[  #Transcoding  ]]>
                    </category>
                
                    <category>
                        <![CDATA[ video ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Video.js ]]>
                    </category>
                
                    <category>
                        <![CDATA[ VideoJS ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Wed, 13 Nov 2019 08:00:00 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2019/11/Video-Publishing-Demo.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Anton Garcia Diaz</p>
<p><em>From ffmpeg and cloud video transcoding to HLS, delivery, players, Video.js, and analytics.</em></p>
<p>After the conquest of social networks, video is spreading through web businesses. As a media consultant working for several of the <a target="_blank" href="https://www.similarweb.com/top-websites/category/lifestyle/fashion-and-apparel">largest fashion ecommerce sites</a> in the world, I feel safe saying the video-everywhere trend is all but unstoppable.  </p>
<p>In this post, I review the main aspects to consider when publishing short-format videos in a web workflow. I comment about open source resources that make an in-house solution possible for each step, like ffmpeg or Video.js. Besides, I use an example with <a target="_blank" href="https://abraia.me/video/">Abraia's video optimization and publishing demo</a> - specially tailored to short videos for fashion ecommerce. </p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://store.abraia.me/05bf471cbb3f9fa9ed785718e6f60e28/Short-Video-Publishing-Demo/Workflow/index.html">https://store.abraia.me/05bf471cbb3f9fa9ed785718e6f60e28/Short-Video-Publishing-Demo/Workflow/index.html</a></div>
<p>It gives full access to the resources created: chunks, playlists, and html code for the video player. This brings quick insights on the inner workings of a complete pipeline. </p>
<p>The content should be helpful either to pursue an in-house processing and publishing pipeline or to sort out the best combination of services. </p>
<h2 id="heading-quality-of-experience-qoe-and-other-business-related-concerns">Quality of experience (QoE) and other business related concerns.</h2>
<p>There are two main concerns that are closely linked. The fear of bloating the bandwidth of users, which damages UX and engagement, and the fear of delivering poor visual quality, which potentially damages brand image. </p>
<p>The balance between these two antagonising factors is what determines the QoE. Keeping a <strong>high QoE</strong> requires delivering nearly the <strong>best possible quality, without rebuffering or stalling</strong> effects or noticeable drops of page speed.  </p>
<p>Of course, there are other issues that matter</p>
<ul>
<li>the customisation of the viewing experience to match the branding of the business</li>
<li>the cost increase of delivering higher bandwidth content </li>
<li>and the additional burden in terms of devops</li>
</ul>
<p>...just to name a few.</p>
<h2 id="heading-a-first-choice-progressive-vs-adaptive-bitrate-abr">A first choice: progressive vs adaptive bitrate (ABR).</h2>
<p>Regarding <a target="_blank" href="https://www.freecodecamp.org/news/video-formats-for-the-web/">video format selection</a>, there are two main options with important implications: progressive video and ABR.</p>
<p>Progressive videos may be delivered and consumed like images, using plain HTML5 code. Moreover, progressive mp4 videos with H264 encoding have universal support across browsers and systems. So, they're the straightforward approach.</p>
<p>However, in the likely event that QoE is a main concern we should go for ABR. More specifically for HLS -again with H264 encoding – which is a broadly supported option. </p>
<p>With <strong>HLS</strong> we'll be able, in most cases, to keep the <strong>bits per second - the bitrate - of the video within the connection capacity limits</strong>. This avoids rebuffering, stalling, or blocking other content. In HLS, the video is available at different bitrates and is split in pieces. This allows the client to request the best quality affordable, based on the network speed at any time. The only caveat is that we'll need to use a player in our front-end (basically a piece of JavaScript). In apps, it's easier because both iOS and Android feature native support for the protocol. </p>
<h2 id="heading-the-pipeline-and-the-workflow">The pipeline and the workflow</h2>
<p>That said, let's see what a video optimization and delivery pipeline for web entails. The pipeline is supposed to process a master or pristine video with a high quality and make it suited to the web. It's also supposed to meet brand requirements on visualization, and to integrate the video events in the analytics of the site. </p>
<p>In sum, our pipeline should address the following problems:</p>
<ul>
<li>Content management</li>
<li>Transcoding and optimization</li>
<li>Delivery</li>
<li>Visualization</li>
<li>Analytics</li>
</ul>
<p>In the end, the pipeline should allow a workflow similar to that of social video platforms - where you upload a video and get a <a target="_blank" href="https://store.abraia.me/05bf471cbb3f9fa9ed785718e6f60e28/Short-Video-Publishing-Demo/Video-Freecodecamp/index.html">link like this</a> to embed or share elsewhere - but under all the custom requirements of our business.</p>
<p>To keep this post short and focused, I'll skip the content management issue, which is basically the way we handle all the resources, including the collaborative media editing and approval workflows. Next, I go through the main optimization and delivery ingredients found in a video publishing pipeline.</p>
<h2 id="heading-transcoding-and-optimization">Transcoding and optimization</h2>
<p>For progressive videos to be responsive, we can create versions with different resolution and quality to be consumed based on breakpoints, similar to images. </p>
<p>In an in-house scheme this operation can be <a target="_blank" href="https://medium.com/abraia/video-transcoding-and-optimization-for-web-with-ffmpeg-made-easy-511635214df0">easily accomplished with ffmpeg</a>. It's an open source tool that performs resizing, compression, and many other operations very efficiently. For instance, to scale a 4K video to fullHD with good visual quality you may simply use:</p>
<pre><code>ffmpeg -y -i input.mp4 -vf scale=<span class="hljs-number">1920</span>:<span class="hljs-number">-2</span> -c:v libx264 -crf <span class="hljs-number">22</span> -profile:v high -pix_fmt yuv420p -color_primaries <span class="hljs-number">1</span> -color_trc <span class="hljs-number">1</span> -colorspace <span class="hljs-number">1</span> -movflags +faststart -an output.mp4
</code></pre><p>Alternatively, with a cloud platform the operation should be a no brainer, although in many cases we loose effective control of the quality settings and possible breakpoints.</p>
<p>Encoding for <strong>HLS</strong> is a bit trickier. First, <strong>we have to define a coding ladder</strong>. Each step of the ladder will feature a different bitrate, from a maximum to a minimum. They set respectively the maximum and minimum quality. </p>
<p>For each bitrate in the ladder, we also have to set the resolution, again from maximum to minimum. Ideally, we should use bitrates specifically tuned to the video content to optimize the use of bandwidth. When done automatically, <strong>on a per video basis</strong>, this is called <strong>per title encoding</strong>. </p>
<p>We have to code the video with the resolutions and bitrates defined and then cut each rendition in chunks. We also have to decide the duration of the chunk. That is, how frequently is HLS renegotiating the quality to request, based on the current network speed. We can do all of the encoding with ffmpeg or with a cloud service.</p>
<p>Let's see the files generated for our example. We have a folder containing all the chunks (.ts extension), and the playlists ( .m3u8 extension). </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/11/imaxe-7.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>The playlists contain all the information about the renditions available. Next, we can see the content of the master playlist: the ladder - bitrates and resolutions - and the relative route to the renditions.</p>
<pre><code>#EXTM3U
#EXT-X-VERSION:<span class="hljs-number">3</span>
#EXT-X-STREAM-INF:BANDWIDTH=<span class="hljs-number">3374012</span>,RESOLUTION=<span class="hljs-number">1920</span>x1080
<span class="hljs-number">1080</span>p.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=<span class="hljs-number">1836580</span>,RESOLUTION=<span class="hljs-number">1280</span>x720
<span class="hljs-number">720</span>p.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=<span class="hljs-number">1002050</span>,RESOLUTION=<span class="hljs-number">856</span>x480
<span class="hljs-number">480</span>p.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=<span class="hljs-number">649329</span>,RESOLUTION=<span class="hljs-number">640</span>x360
<span class="hljs-number">360</span>p.m3u8
</code></pre><p>That is, for each rendition we have an additional playlist containing the information about the duration and route to the corresponding chunks. We also need a poster to use as thumbnail and get covered in the event of a very slow connection or HLS compatibility issues. In our example, all the resources are in the same folder so the route to each resource is simply the name.</p>
<h2 id="heading-delivery">Delivery</h2>
<p><strong>Videos should be delivered through a CDN</strong>. If you make a poor transcoding, many users may suffer slow page loads. But at least if you use a CDN you won't take your site down because the server is unable to handle the load. I've seen big sites that more than doubled their peak traffic the day they decided to use videos in their home page. So videos, whether progressive or HLS, should be delivered as static files cached and delivered by a CDN.</p>
<p>If you are using a cloud platform for video publishing, you should be covered. Any decent one offers video delivery through at least one CDN. If you need coverage in some countries like China, you need to look into each specific platform and the CDN used, since some of them do not work there.</p>
<h2 id="heading-visualization">Visualization</h2>
<p>While for progressive videos HTML5 is enough to ensure visualization, in the case of HLS we need a <strong>JavaScript player with HLS support</strong>. </p>
<p>There are many commercial options, but there are also open source alternatives with very high quality. A good example is <strong>Video.js</strong>. It has a wide support among browsers, only limited by the dependency on the <a target="_blank" href="https://caniuse.com/#search=media%20source">Media Source Extensions API</a>. It brings a high degree of customization using skins and a flexible configuration, for instance allowing you to use autoplay or different video controls.</p>
<p>The player may be inserted in the page code, or it can be in an html static that is embedded as an iframe. </p>
<p>Going back to our example, when we publish the video we create an <a target="_blank" href="https://store.abraia.me/05bf471cbb3f9fa9ed785718e6f60e28/Tests/PexelsVideos2795392/index.html">html resource</a> that has a Video.js player with default settings. The content url should point to the master playlist and the thumbnail to the poster image extracted from the video.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/11/imaxe-3.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>In this case, the html resource also adds <strong>oembed compatibility</strong>. Besides directly access in the browser this html - or a different one in which we copy/paste the player's code - to play <a target="_blank" href="https://store.abraia.me/05bf471cbb3f9fa9ed785718e6f60e28/Tests/PexelsVideos2795392/index.html">the video</a>, we can embed it in a content management system (CMS). For instance, when writing this post for freeCodeCamp.</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://store.abraia.me/05bf471cbb3f9fa9ed785718e6f60e28/Short-Video-Publishing-Demo/Embedding/index.html">https://store.abraia.me/05bf471cbb3f9fa9ed785718e6f60e28/Short-Video-Publishing-Demo/Embedding/index.html</a></div>
<h2 id="heading-analytics">Analytics</h2>
<p>In short videos, typical analytics of interest are the <strong>ratio of users that play the video, the ratio of those who view it in full, or the ratio of playback failures</strong>. </p>
<p>Again, there are many commercial options available. However in many cases a widespread free option like Google Analytics (GA) may be enough. If we are using Video.js, we only have to instrument the html resource with GA, like for any other web page. Going back to our example, we can see it in the editable HTML created.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/11/imaxe-5.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>To track the video use in GA, we just have to track the video events in the player. For instance:</p>
<pre><code>    player.analytics({
      <span class="hljs-attr">defaultVideoCategory</span>: <span class="hljs-string">'Video'</span>,
      <span class="hljs-attr">events</span>: [{
        <span class="hljs-attr">name</span>: <span class="hljs-string">'play'</span>,
        <span class="hljs-attr">label</span>: <span class="hljs-string">'Video-Freecodecamp'</span>,
        <span class="hljs-attr">action</span>: <span class="hljs-string">'play'</span>,
      }, {
        <span class="hljs-attr">name</span>: <span class="hljs-string">'pause'</span>,
        <span class="hljs-attr">label</span>: <span class="hljs-string">'Video-Freecodecamp'</span>,
        <span class="hljs-attr">action</span>: <span class="hljs-string">'pause'</span>,
      }, {
        <span class="hljs-attr">name</span>: <span class="hljs-string">'ended'</span>,
        <span class="hljs-attr">label</span>: <span class="hljs-string">'Video-Freecodecamp'</span>,
        <span class="hljs-attr">action</span>: <span class="hljs-string">'ended'</span>,
      }, {
        <span class="hljs-attr">name</span>: <span class="hljs-string">'error'</span>,
        <span class="hljs-attr">label</span>: <span class="hljs-string">'Video-Freecodecamp'</span>,
        <span class="hljs-attr">action</span>: <span class="hljs-string">'error'</span>,
      }]
    });
</code></pre><p>Then, in GA we can see the events taking place. This screenshot shows my own real-time activity - with two devices and browsers - on the video example created for this post.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/11/imaxe-4.png" alt="Image" width="600" height="400" loading="lazy"></p>
<h2 id="heading-summary">Summary</h2>
<p>I have reviewed the main aspects involved in a video publishing pipeline, from transcoding, to delivery, visualization, and analytics. I have made reference to potential use of different resources, including two prominent open source initiatives like ffmpeg and Video.js.</p>
<p>I have supported the explanation with a simple example using our <a target="_blank" href="https://abraia.me/video/">video publishing demo</a>. It gives full access to the resources created. You'll be able to download, modify, and use the resources in your tests. You can freely use it to repeat the process with a short video of your choice. </p>
<p>Remember to start with a high quality video. The example here is based on a 9 seconds 4k video from <a target="_blank" href="https://www.pexels.com/@cottonbro">@cottonbro</a>. Overall, I expect the post to bring a bird's eye view of what a custom deployment for video publishing entails.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Create and Publish a Chrome Extension in 20 minutes ]]>
                </title>
                <description>
                    <![CDATA[ By Jake Prins Ever wondered what it would be like to create a Chrome extension? Well, I’m here to tell you just how easy it is. Follow these steps and your idea will turn into reality and you’ll be able to publish a real extension in the Chrome Web S... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-create-and-publish-a-chrome-extension-in-20-minutes-6dc8395d7153/</link>
                <guid isPermaLink="false">66c35133a1d481faeda49bb6</guid>
                
                    <category>
                        <![CDATA[ coding ]]>
                    </category>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ publishing ]]>
                    </category>
                
                    <category>
                        <![CDATA[ software development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ tech  ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Sat, 24 Feb 2018 20:04:46 +0000</pubDate>
                <media:content url="https://cdn-media-1.freecodecamp.org/images/1*2eZjMzwZoO2zThFwJ2CuoQ.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Jake Prins</p>
<p>Ever wondered what it would be like to create a Chrome extension? Well, I’m here to tell you just how easy it is. Follow these steps and your idea will turn into reality and you’ll be able to publish a real extension in the <a target="_blank" href="https://chrome.google.com/webstore/category/extensions">Chrome Web Store</a> in no time.</p>
<h3 id="heading-what-is-a-chrome-extension">What is a Chrome extension?</h3>
<p>Chrome extensions allow you to add functionality to the Chrome web browser without diving deeply into native code. That’s awesome because you can create new extensions for Chrome with core technologies that web developers are very familiar with - HTML, CSS, and JavaScript. If you’ve ever built a web page, you’ll will be able to create an extension faster than you can have lunch. The only thing you need to learn is how to add some functionality to Chrome through some of the JavaScript APIs that Chrome exposes.</p>
<p>If you’re not experienced yet in building web pages, I recommend you first dive into some free resources to learn how to code, like <a target="_blank" href="https://www.freecodecamp.org/">freeCodeCamp</a>.</p>
<h3 id="heading-what-do-you-want-to-build">What do you want to build?</h3>
<p>Before you start, you should have a rough idea of what you want to build. It doesn’t need to be some new groundbreaking idea, we can just do this for fun. In this article, I’ll be telling you about my idea and how I implemented it into a Chrome extension.</p>
<h3 id="heading-the-plan">The plan</h3>
<p>I’ve used the <a target="_blank" href="https://chrome.google.com/webstore/detail/unsplash-instant/pejkokffkapolfffcgbmdmhdelanoaih">Unsplash</a> Chrome extension for a while which allows me to have nice background images of <a target="_blank" href="https://unsplash.com/">Unsplash</a> in my default tab. I later replaced it with the <a target="_blank" href="https://muz.li/">Muzli</a> Chrome extension that turns the default tab into a feed of design news and shots from around the web.</p>
<p>Let’s use these two extensions as inspiration to build something new, but this time, for movie lovers. My idea is to show a random background image of a movie every time you open a new tab. On scroll it should turn into a nice feed of popular movies and TV shows. So let’s get started.</p>
<h3 id="heading-step-1-setting-things-up"><strong>Step 1: Setting things up</strong></h3>
<p>The first step is to create a manifest file named <code>manifest.json</code>. This is a metadata file in JSON format that contains properties like your extension’s name, description, version number and so on. In this file we tell Chrome what the extension is going to do, and what permissions it requires.</p>
<p>For the movie extension we need to have permission to control <strong>activeTab</strong>, so our <code>manifest.json</code> file looks something like this:</p>
<pre><code>{ “manifest_version”: <span class="hljs-number">2</span>, “name”: “RaterFox”, “description”: “The most popular movies and TV shows <span class="hljs-keyword">in</span> your   <span class="hljs-keyword">default</span> tab. Includes ratings, summaries and the ability to watch trailers.”, “version”: “<span class="hljs-number">1</span>”, “author”: “Jake Prins”,
</code></pre><pre><code><span class="hljs-string">"browser_action"</span>: {   <span class="hljs-string">"default_icon"</span>: <span class="hljs-string">"tab-icon.png"</span>,   “default_title”: “Have a good day” },
</code></pre><pre><code>“chrome_url_overrides” : {  “newtab”: “newtab.html”},
</code></pre><pre><code> “permissions”: [“activeTab”]}
</code></pre><p>As you can see, we say that <code>newtab.html</code> will be the HTML file that should be rendered every time a new tab gets opened. To do this we need to have permission to control the <strong>activeTab</strong>, so when a user tries to install the extension they will be warned with all the permissions the extension needs.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/4y26iiG0Z4jq3tbBwTgjBlCoksECGWII1LyF" alt="Image" width="467" height="140" loading="lazy"></p>
<p>Another interesting thing inside the <code>manifest.json</code> are the browser actions. In this example we use it to set the title, but there are more options. For instance, to show a popup whenever you click on the app icon inside the address bar, all you have to do is something like this:</p>
<pre><code>“browser_action”: {  “default_popup”: “popup.html”, },
</code></pre><p>Now, <code>popup.html</code> will be rendered inside the popup window that's created in response to a user's click on the browser action. It's a standard HTML file so it’s giving you free reign over what the popup displays. Just put some of your magic inside a file named <code>popup.html</code>.</p>
<h3 id="heading-step-2-test-if-it-works">Step 2: Test if it works</h3>
<p>The next step is to create the <code>newtab.html</code> file and put in a ‘<code>Hello world</code>’:</p>
<pre><code>&lt;!doctype html&gt;<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">html</span>&gt;</span>  <span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span>    <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>Test<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span>  <span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span>  <span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>    <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Hello World!<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>  <span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span></span>
</code></pre><p>To test if it works, visit <code>chrome://extensions</code> in your browser and ensure that the <strong>Developer mode</strong> checkbox in the top right-hand corner is checked.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/hplLksya7cBxpBQdzgbjt6ZjIJG9U8D6whVl" alt="Image" width="800" height="179" loading="lazy">
<em>Chrome Developer mode</em></p>
<p>Click <strong>Load unpacked extension</strong> and select the directory in which your extension files live. If the extension is valid, it will be active straight away so you can open a new tab to see your ‘Hello world’.</p>
<h3 id="heading-step-3-making-things-nice"><strong>Step 3: Making things nice</strong></h3>
<p>Now that we got our first feature working, it’s time to make it nice. We can simply style our new tab by creating a <code>main.css</code> file in our extension directory and load it in our <code>newtab.html</code> file. The same goes when including a JavaScript file for any active functionality that you would like to include. Assuming that you have created a web page before, you can now use your magic to show your users whatever you want.</p>
<h3 id="heading-finishing-up-the-plan"><strong>Finishing up the plan</strong></h3>
<p>All I further needed to finish the movie extension was HTML, CSS and JavaScript, so I don’t think it’s relevant to dive deep into the code, but I’d like to go through it quickly.</p>
<p>Here is what I did:</p>
<p>For my idea I needed some nice background images, so in the JavaScript file I used the <a target="_blank" href="https://www.themoviedb.org/">TMDb API</a> to fetch some popular movies, took their backdrop images and put them in an array. Whenever the page loads it now randomly picks one image from that array and sets it as the background of the page. To make this page a little more interesting I also added the current date in the top right corner. And for more information, it allows users to click the background which leads to visiting the movie’s <a target="_blank" href="http://www.imdb.com/">IMDb</a> page.</p>
<p>I replaced the screen with a nice feed of popular movies when the user tries to scroll down. I used the same API to build cards of movies with an image, title, rating and vote count. Then, on clicking one of those cards, it shows the overview with a button to watch a trailer.</p>
<h3 id="heading-the-result"><strong>The result</strong></h3>
<p>Now with that little <code>manifest.json</code> file and just some HTML, CSS and JavaScript, every new tab that you open looks a lot more interesting:</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/vUPpM1QiRIgV8dcHwBvKsGwJYI1GyJctJaHo" alt="Image" width="640" height="311" loading="lazy">
_View the end result [here](https://chrome.google.com/webstore/detail/raterfox-popular-movies-t/pbmdibcifmempicdafabdakcoamfobik" rel="noopener" target="<em>blank" title=").</em></p>
<h3 id="heading-step-4-publish-your-extension">Step 4: Publish your extension</h3>
<p>When your first Chrome extension looks nice and works like it should, it’s time to publish it to the Chrome Store. Simply follow <a target="_blank" href="https://chrome.google.com/webstore/developer/dashboard">this link</a> to go to your Chrome Web Store dashboard (you’ll be asked to sign in to your Google account if you’re not). Then click the <code>**Add new item**</code> button, accept the terms and you will go to the page where you can upload your extension. Now compress the folder that contains your project and upload that ZIP file.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/9zUs3mIMtnvMDxWsPjVCZ-gNpvIzx3-mPFUe" alt="Image" width="800" height="201" loading="lazy">
<em>Chrome Web Store</em></p>
<p>After successfully uploading your file, you will see a form in which you should add some information about your extension. You can add an icon, a detailed description, upload some screenshots, and so on.</p>
<p>Make sure you provide some nice images to show off your project. The store can use these images to promote your groundbreaking project. The more images you provide, the more prominently your extension will be featured. You can preview how your extension looks inside the web store by clicking the <code>**Preview changes**</code> button. When you’re happy with the result, hit <code>**Publish changes**</code> and that’s it, your done!</p>
<p>Now go to the <a target="_blank" href="https://chrome.google.com/webstore/category/extensions">Chrome Web Store</a> and search for your extension by its title (It might take some time before it’s up there). If you’re interested, you can find mine <a target="_blank" href="https://chrome.google.com/webstore/detail/raterfox-popular-movies-t/pbmdibcifmempicdafabdakcoamfobik">here</a>.</p>
<p>The only thing left to do is get some users. So you might want to share a post about your life changing Chrome extension on social media. Tell your friends to check it out. Add it to <a target="_blank" href="https://www.producthunt.com/posts/raterfox">ProductHunt</a>. And don’t forget to share your project here in the comments. I’m curious to see what you came up with!</p>
<h3 id="heading-conclusion"><strong>Conclusion</strong></h3>
<p>As a web developer, it’s very easy to create a Chrome extension in a short amount of time. All you need is some HTML, CSS, JavaScript and a basic knowledge of how to add functionality through some of the JavaScript APIs that Chrome exposes. Your initial setup can be published inside the Chrome Web Store within just 20 minutes. Building an extension that’s new, worthwhile or looks nice will take some more time. But it’s all up to you!</p>
<p>Use your creativity to come up with something interesting and if you ever get stuck, the excellent Chrome extension <a target="_blank" href="https://developer.chrome.com/extensions">documentation</a> can probably help you out.</p>
<p>So what are you waiting for? It’s time to start working on your own Chrome extension and turning your idea into reality.</p>
<p>Don’t forget to share your project in the comments and hit the clap button if this article was any useful to you. If you got some time and want to be a hero, give <a target="_blank" href="https://chrome.google.com/webstore/detail/raterfox-popular-movies-t/pbmdibcifmempicdafabdakcoamfobik">my extension</a> a positive rating. That would be highly appreciated!</p>
<p>Got questions or feedback? Let me know in the comments!</p>
<p>Thanks for reading! Hope the information was helpfull. Follow me on Medium for more tech related articles or on Twitter and Instagram @jakeprins_nl.</p>
 ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
