Skip to content
Simone Cuomo

AUTHOR

Simone Cuomo

Software Architect

Software Architect, Mentor, Speaker and Writer. Passionate about all aspect of web development, with a special love for VueJs

Select...
Select...
How to add Dark Mode in your Web Application  cover image

How to add Dark Mode in your Web Application

Learn how to enable persistent Light / Dark Theme toggling on your website using CSS and Vanilla JS....

Getting started with Vitepress cover image

Getting started with Vitepress

Create your static blog site using Vitepress. Setup and configure your site in minutes by following this step-by-step tutorial....

Ticket Management for a Successful Project Delivery cover image

Ticket Management for a Successful Project Delivery

Introduction It is very common to assume that when a project fails to deliver on time, it is either the client's fault for changing scope during development, or the development team's technical inability to deliver the scoped milestone in time. Even if the above assumption may at times be partly correct, in this article, we will cover techniques and management tricks that are aimed at removing or minimizing the risk of failure. I am a strong believer that the way the project is managed is key to a project's success, no matter its scope-creep or difficulties. This article will focus on a specific area of project management: Ticket Management. The article will cover multiple areas of Ticket Management, from "Project Breakdown", to the definition of MVP, until exploring the very fine art of ticket writing. Disclaimer Before we jump into the main content of the article, I want to clarify that what I am about to share in the article below has helped me for years on multiple projects, but it is not a rule, and things may be adapted and work differently for different people and management styles. Break the Project Down There is no better way to start our little journey into project management technique than by discussing project breakdown. There are multiple videos, books, and posts that cover this topic and mostly all of them will refer to the definition of MVP (minimum viable product) as the starting point and first delivery milestone for a project: > A minimum viable product (MVP) is a version of a product with just enough features to be usable by early customers who can then provide feedback for future product development. > https://en.wikipedia.org/wiki/Minimum_viable_product As a project manager (or a tech lead taking over PM responsibility) you will be asked to work with the client to define the first milestone for a given product. This as defined above, will include the minimum amount of features to make the product "usable". On multiple occasions in my career, the client's expectation of an MVP has included more than a real MVP should. This is normal, since the client always wants to make a good first impression, and removing features may, at times, be seen negatively for the product. As I mentioned at the start, this post is going to focus on what YOU can do to make sure it is delivered successfully, and it will not focus on how to deal with difficult clients as that is outside the scope of this post. You may probably be wondering how, if we are not going to discuss MVP definition, are we going to change MVP delivery? Your MVP May Not Be the Client's MVP Well, this is actually where the magic begins. I call it magic, but as you will read in a few sentences, the method I use is pretty simple, but I can guarantee you to be very effective. The first step that we are going to take is to sit down with our team and define what you really would expect to see in a real barebone MVP. I usually find it simpler to address this by calling it *Alpha*. The idea of this exercise is to start from a very basic workable product, and then add small features to it as you and the team may seem fit as the MVP. > NOTE: Instead of starting from MVP requirements and trying to remove things, start from the basic technical implementation and build it up to the client MVP. The expectation of this exercise is a set of milestones that are smaller than the client MVP. This should not only be achieved by removing features that may not be seen as required (for example a newsletter integration), but also by proposing a basic version of agreed components (eg. Removing complex shadow from a card, or removing animation on client interaction). A reduced scope should also be associated with a quicker delivery. It is important to understand that this MVP does not have to be shared with the client, but should be visible within the team and actively used as the first and more important delivery milestone. The client (and all communication to them), will still work toward the MVP feature set and timeline. But internally, the team is working toward a faster delivery and a smaller feature set. You may be asking yourself, what are the reasons to add extra work on your shoulder and how can this help the delivery of a project? An effective breakup of MVP and Alpha will produce the following results: - It will provide early insight into project delivery: If you fail delivery of Alpha, you will quite probably fail overall MVP. - Reduce the complexity of the first iteration: As we will see later, removing unneeded complexity helps the team to focus. - Remove the stress from the team and you: Working on your deadline helps manage internal team stress and work with them. - Prioritizes what is needed: A successful Alpha delivery will deliver the client's working version very early on, and will also reduce the "consequences of failure". Failsafe for Missing Delivery Before we move forward to the next topic, I want to share a few more words about the "Alpha MVP" and its benefits. We are going to focus on missing deadlines and how the above methods, can act as a failsafe. As we all know, projects never go to plan. Many things can happen in a project that could affect its delivery. This could be a team member being sick, a delay in hardware delivery, a slow client, a change of scope, and more. Knowing that missing q deadline is more possible than actually hitting them due to unforeseen circumstances, it is just expected to create some guardrails to support our project. The first thing that comes to mind is probably adding a buffer to your project, and this is amazing if possible. But as experience shows us, extra time means extra features and scope creep from the client (Of course there are techniques to avoid this, but this blog post is focusing on what you can do without involving the client). I am not proposing anything extra for you to do to ensure you have an emergency exit in case of late delivery. All you need to know has already been shared above in the previous section! I have delivered many projects on time, but I have also failed others. What needs to be learned from the failure is that even if we "missed the full delivery" in many cases, we still went to production and the client was still happy. via GIPHY Defining an MVP that focuses on what is needed and not what is nice to have, not only speeds up development, but it will also mean that the tasks left at the end of the project are just nice to have, and issues that can easily go live after a few days and do not require immediate intervention. Just to provide more context, these are a few examples of things that have "bleed" outside of the project delivery, and the client was ok with it as we were still able to go to production. - Progress bars attached to client scrolling of the page - Renewal emails and cron for an e-commerce website - Complex page transition - Image zooming - Past event page The ones above are just simple tasks that we sometimes add to our tickets, without realizing the complexity and extra time that they may bring. Let's analyze the first point "Progress bar". This was initially expected to be developed as part of the main navbar ticket. As much as the feature seems simple, it takes time to test and develop, so we moved it out and delivered it later in the project. This allowed us to use those extra hours for actual changes to the data that happened right before the deadline. Creating an environment within your team where "saving a couple of hours" is seen as something important at every stage of the project, will eventually help you deliver faster. > Sometimes we think of a simple few hours of saving as superfluous, but it just takes a few of these changes to make a difference between delivery and failure. Write Just a Few Tickets In the previous section, we defined our MVP and Alpha milestones, and it is now time to write the tickets to achieve this delivery. My second suggestion is: Just write enough tickets to fulfil a couple of days of work and no more. As you may be aware, writing a ticket is a complicated matter and it can take quite some time- time that can be very valuable at the start of a project. Let's assume two different scenarios. The first is where the PM will focus on writing all the tickets, and the second is where we just write a few to get the team going and then analyze the key differences. Write All the Tickets This is a very common scenario. The PM has been given a project and asked to start it asap. At this stage, the PM will spend his first few days writing all the tickets that have been defined as the MVP and will share them with the rest of the team. He will probably join an onboarding meeting, but most of his time for the first few days will be in writing tickets. The backlog at the end of this exercise is going to be nice and full and the PM is going to feel ready to start. Write Just a Few Tickets Also in this case, the PM has been asked to task a new project, but instead of writing lots of tickets, the PM will just write enough for a couple of days. The Backlog looks empty with just a few tickets. Many Tickets vs Just a Few I know that you are probably thinking that I am mad to suggest writing fewer tickets, but I suggest you read below and probably even ask your team and you will be surprised about the answers. Let's compare the two above by using a few metrics: PM, Team, and Project. PM Time The first is PM. In the case of many tickets, the PM will have to spend a few hours writing tickets. Want or not, this is a lengthy operation that takes time. I usually take around 5-10 min per ticket to write them well with all the acceptance criteria and links required. So writing 20, 30 or even 50 of them can take days. In the case of a few tickets, the PM will regain valuable hours at the start of the project. This can be spent on many important tasks such as defining MVP, client communication, setting up procedures within the team, and actively spending time with the team to ensure they have a full understanding of the project and the product to be delivered. WIN: Write just a few tickets Team We are now changing perspectives and looking at this from the team side. As we have seen before, we have two possible examples. In the first one, the time will come in the morning, and have an onboarding meeting with the PM. After this meeting, they will have the ability to start a project. The backlog is nice and defined, and they have lots of tickets to work on, so they can put their heads down, and get on with the work. In the second, the PM is going to introduce the project and share a few tickets that they should accomplish within the next couple of days. The PM is going to be actively involved, and can get the team feedback on the tickets. For example, the team may prefer a Figma screenshot instead that the link or the team mentioned that would be nice to define Accessibility requirements within each ticket. Even if you would probably think that active cooperation can be achieved also from the first iteration (lots of tickets), I have learned from experience that this is not always the case. When the team has lots of tickets available, they just go on with the work and do not think of changing things as they are already set. Making fewer tickets forces the PM and the team to cooperate, they will all know what they are working toward and make adjustments very easy. WIN: Write just a few tickets Project In this last point, we are going to analyze the advantages and disadvantages that the above methodology would produce for our project. In the first method, the project is going to be fully scoped. The PM is going to be able to easily track the burndown and see the progress of the project. This can also be useful for the client as it will have clean visibility on its "MVP". In the second scenario, the PM has surely lots of extra work to do to maintain the project. She will have to be able to track projects using her milestones and not tickets, and she will have to fill the communication gap produced by the missing tickets. At this stage, you probably think that having more tickets is going to be better, but here comes the best part. Even if having fewer tickets will require the PM to work harder, it will produce a more flexible environment that can easily adapt and or change. Small changes in the way ticket are written can benefit the team's velocity, defining a small chunk of work help understand velocity and productivity, and having fewer tickets allow the client to change the scope and re-imagine his product without creating many obsolete tickets on the board. I agree that having fewer tickets and a dry backlog can be complicated to manage, but the benefits, in the long run, are massive. WIN: Fewer tickets if managed well! :) > Note: I may have been a little biased in the above comparison :P Conclusion Project Management is an art and it can be accomplished in many different ways. My management technique focuses on flexibility, but most importantly, team engagement. I think the success of every project is not held by the client's ability to stay on course with its initial idea, or by PM micro-managing the team to complete all the tasks to create the perfect burndown. I am a strong believer that the project's success is helped by the team working on it. If they are engaged, and all work together to accomplish the project, the project will have no issue. Please note that I am not saying that, if the team can complete their tickets, the project is going to be a success, but if the team is engaged in all aspects of the project, the project has a big chance of success. If a developer has a forum to help you define the technical flow of MVP, the project will be delivered faster. If a developer has the forum to express his/her idea on different breakdowns and execution of a task, the project will gain speed and momentum. Remember, you are not always able to change the client, but you can change the way you deliver the work to them!...

Build Advanced Components in Vue 3 using $attrs cover image

Build Advanced Components in Vue 3 using $attrs

In the third major release of Vue js, we have seen many new features and improvements land on our remote working computers. In this article, we are going to cover the $attrs attribute. We will explain what it is used for, how its implementation differs from Vue 2's (former $attrs, class, @listener), and build a code example to help understand its power. Understanding this feature can really support your skills in developing easy to use and scalable components advanced components. What is $attrs? The definition of $attrs, varies between the two major versions of the framework, but in this article, we are going to mainly cover Vue 3, where @attrs can be seen as: > A component property that holds all of the attribute, property, and custom events that are not currently defined within the component. $attrs can also be seen as a safety net, that captures anything that you may not have declared within a component. Let's consider a component that has just a single property and event handler, like the following example: `` If we would instantiate our component like so: `` Our example component would have access to a $attrs property with the following information: `` If the above is not yet making sense, it is absolutely fine. In the next few sections, we will cover, in more granular details, how to actually make use of this feature. $attrs V3 vs $attrs V2 Even if I do not want this article to be a comparison between V2 and V3, it is essential that we touch base on the differences that the $attrs feature offers betweent the two major versions. If you have used VueJs in the past (version 2), there is a significant chance that you have already used $attrs before. The main reason is that almost all the attributes included in the $attrs property were already present in the previous version of the framework. Just split it into different properties. If we take into consideration the example proposed above, the $attrs object is going to appear as follows: Main differences to notice in V2 are: - custom events go into a @listerner bucket - the class is not available (using class in this way requires you to set a property). Most of the content provided in the following chapter can still be applied in V2, as long as we adhere to the above differences and define the extra properties ($listners and a class property). Real Life example As with most of my content, I like to always cover a real life example. Building something from the bottom up, can really help in understanding the reason beind a feature, and help you introduce its usage within your codebase. In the following sections, we are going to build a nice slider (or more precisely a few of them). The complete code can be found on Stackblitz following the following link (stackblitz-vue-example). Let's start from scratch The first step requires us to create a simple component. This is going to be plain Vue and will have nothing to do with the $attrs feature (yet). `` The above code will create a slider that includes single HTML element at the root, and a simple two way binding for a property called value. To use the above component we would do something like this: `` The result should be something like this: Let's add some attributes The above "hello world" example, would never stand the real web development industry. As we know, our components are always full of requirements and specifications, and are never this simple. So to make it a bit more realistic, let's add a couple of attributes (min, max, class, id, data-cy, @keydown and aria-label). `` If we would run the app with the above changes, we would see that all changes take effect. In fact, analysing the app will show the following UI and HTML: As we can notice, all the information has already been applied to our HTML. WAIT A SECOND... Why did I make such a big introduction to $attrs, when all the "non property/event" attributes are already automatically applied to the inner HTML element? Do not worry, I have not wasted your time.. In the next section, we will shake things a bit, because as we know, requirements always change.. :) Change request: Add a title and value In this section we are going to apply some further changes to our component. More precisely, our product owner has assigned us the following ticket: > As a user of the slider, I would like to be able to see a title, and its value in numerical form being shown on screen. The modified component will look like this: `` At first glance, everthing seemed to work, but if we look closely, we can see that something is not right. First, the slider is not blue. Second, the value is going way over 50, and lastly if we look at the html, we'll notice that all of our extra attributes (min, max, data-cy) are assigned to the root element, and not our input element anymore! The best way to solve the above problem would be to find a way to "apply" all the properties, classes, arguments, and events directly to the input field, without them needing to manually declare them- something like a "bucket" of data.. !$ATTRS! Let's jump in the next section and see how we can use $atts to accomplish our goals. $attrs to the rescue At the start of this article, we introduced $attrs as a bucket of information. It is a place that holds all the "undeclared" properties and events, and this is precisely what we need to solve our issue. To use this feature, we can just apply the $attrs property to one or more HTML element, using the v-bind operator: `` As we can see, the above change will make things much better. The use of attrs in our component will act as bridge that copies all out attributes (class, attribute, property and custom events) to one or more elements: The slider thumb is back to being blue. The max value is set to 100, and our extra attributes are set correctly... almost. There is only one problem- our extra attributes have not only been assigned to the input element, but also to the root element! In this case, there is no visual change to show us this issue (and usually there isn't one in real life either. That is why I have not created any). But these extra variables can really create some side effects. Let's fix this. inheritAttrs: false By default, any extra argument being passed to a component is automatically applied to the root element (and to all elements that have the $attrs binding). To switch this feature off, and get control of what elements receive this extra attribute, we can use a flag called inheritAttrs, and set it to false. Our script tag will look like this: `` After this change, our HTML is nice and clean. All the extra properties are applied to the Input element only. Conclusion Before we wrap up, there are a couple of extra points that I want to share, so that you can make furhter use of this feature and understand it more deeply. 1) I prefer not to use the v-model so that I can actually also omit the update:modelValue event (you can see at the file name Slider.vue in the stackblitz code) 2) You can access, and play with the individual properties of the $attrs. So for example, you could apply the $attrs.class to one element, and the $attrs['aria-label]' to another. 3) It is always best to declare property and events, and just use this when you have an element that emits a native event and/or accepts many attributes (like video tag, or all Input fields). Time to say goodbye I have personally taken some time to fully understand this feature, but I really hope that this article may help you in understanding this feature, and helps you define complex but very readable components....

History of Mobile Web Development and the rise of PWA cover image

History of Mobile Web Development and the rise of PWA

In this post, we are going to cover the history of Mobile Development, provide insightful details of current trends and uses of Progressive Web App development...

How to automatically post from your Gatsby site to dev.to cover image

How to automatically post from your Gatsby site to dev.to

Learn how to automatically post your article from your Gatsby site to Dev.to using RSS feed....

Apply SVG filters on HTML using Vue.js cover image

Apply SVG filters on HTML using Vue.js

SVG is a powerful format, based on XML and is well known for its scalability. This image format is usually known for its application on logos, icons and graphs, but in this article, we are going to use it with the help of VueJs to create a dynamic styled HTML container. Prologue The idea of this project occurred to me while listening to Syntax FM podcast with Sara Soueidan. I never had a chance to use SVG before and I was astonished to hear the countless possibilities that lie within this image format, and I wanted to see it with my own eyes. The article is going to walk through all the steps necessary to produce a full working component. A full version of the code can be found in this codepen: vuejs-svg-component-with-filter-and-html-slot-bnejy The CSS filter property already offers us the possibility to apply a great set of filters to our elements, and even load SVG filter directly with the use of the URL filter function. But in this article we are going to use plain SVGs. The component Our first step requires the creation of a Vue component: ` Next, we will add a very simple SVG within our Template tags. Our object will include four main parts: basic structure, shape, filter and foreignObject. Basic structure First we will create the structure of the SVG. For the purpose of our example we are going to create a simple SVG with a fixed size ViewBox: ` Shape SVGs are well known for the multitude of simple shape elements available within its standards. If you have worked with HTML before, SVG elements will look quite familiar, as they exhibit the same features of a normal HTML element, with the addition of specific XML attributes. In our example we are going to create a simple Polygon. This shape is described as: Polygons are made of straight lines, and the shape is "closed" (all the lines connect up). https://www.w3schools.com/graphics/svg_polygon.asp The next code will define a polygon made of 4 lines and filled with the colour blue: ` Filter There are a great number of filter primitives that can be used within an SVG document. Their power comes from the possibility to merge multiple primitives together, to create very complex results, and the ability for the filters to be applied to a single shape/ object within an SVG document. The actual definition of filters is: > The filter SVG element defines a custom filter effect by grouping atomic filter primitives. It is never rendered itself, but must be used by the filter attribute on SVG elements, or the filter CSS property for SVG/HTML elements. https://developer.mozilla.org/en-US/docs/Web/SVG/Element/filter In our example we are going to apply two different filters: feTurbulence and feDisplacementMap. This will provide a distorted effect to all elements in which it is applied. ` As described above, the filter needs to be used within another object with the use of the filter attribute. In our case, we will have to apply the ID of turbulence to our polygon: ` A rendered version of our component will look like this: HTML object Our SVG is finally getting shape. The last step required involves the use of the foreignObject element. This element will allow us to include normal HTML elements within our SVG. Our first step requires us to add the element within the SVG. This is going to be added alongside the shape, but it is going to be completely independent to it. This means that the filter that we have applied to the polygon will bleed into this SVG element. ` Now that we have defined our element, we are able to add any HTML we want within its tags. It is important to note that this approach may produce unwanted behaviour across different browsers, and on site performance. Because of the nature of SVG, all elements within foreignObject element are going to be readable by a screen reader and can be used for accessibility purposes. For the purpose of our example, we are going to add a few simple elements within our SVG: ` > TIPS: We are able to use any CSS declaration within the SVG itself and we can even use an existing declaration. For example, we would have defined the to be green globally, this declaration would have been applied to our element too. Our component will render like this: Make it dynamic The component above works perfectly, but it is still static. In the following section we are going to make it more dynamic by using features available within the VueJs framework. Slot First, we are going to modify the code, so that the content of the foreignObject is actually going to be a slot. These are very useful when you want to provide the flexibility of passing any HTML to the component. ` Then we are going to pass some HTML in the parent component that is using our newly introduced slot: ` Running this code in the browser will produce the following design: Summary Our fully working VueJs SVG component is now completed. The code can be found at the following codesandbox: vueJs Svg component with HTML slot Using SVG within a framework, could be a bit tricky, as reactivity and virtual DOM, produce unwanted results, and this example may not be used in production, without the right set of tests. The article just covers a couple of examples and introduces a few topics, but the possibilities are endless. We could provide a set of shapes as props, introduce SVG animations and finally create a set of filters that can easily be applied to the passed HTML. I hope this proof of concept turns out to be helpful, and I look forward to seeing different permutations and applications of this approach online. References SyntaxFM: https://syntax.fm/show/154/svgs-with-sara-soueidan SVG definition: https://en.wikipedia.org/wiki/Scalable_Vector_Graphics CSS filters: https://css-tricks.com/almanac/properties/f/filter/ SVG filters explained: https://tympanus.net/codrops/2019/01/15/svg-filters-101/ SVG filters: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/filter VUE slots: https://vuejs.org/v2/guide/components-slots.html...

Build a Text Editor in the Browser cover image

Build a Text Editor in the Browser

In the last couple of years, modern browsers have been able to surprise us with many fantastic new features, and it is incredibly hard to keep up to date with all of these new features. I was personally not aware that all major browsers now have access to a powerful Web API object: FileReader. Today I am going to share with you my experience of this browser feature. The FileReader allows user to read file content, directly in the browser, without the need for the file to be uploaded to the server. This feature has been introduced to provide a better user experience, and it should NOT replace server side validation. When I first discovered this feature I was very excited but could not think of any specific user cases, until I started to play with it. Since then I was able to use it in the following user cases: 1. Preview an image before uploading (thumbnail) 2. Read file content to return a quick validation to the user ( For example: read a specific string or regex) 3. Provide support for offline browsing 4. Convert file to data URL 5. Provide Client side, Document creation Today we are going to build a Text editor, directly in the browser. A detailed walk through of all the code necessary will be provided throughout the article, but an understanding of Javascript is required to follow the article. The finished work will provide the following features: 1. Ability to upload a text file 2. Ability to modify the content of the text file 3. Ability to download the modified text file Browser Support As mentioned above, the FileReader support is quite extensive as it is now fully supported on all major browsers, with partial support going back to IE10 as shown by the table provided by caniuse.com. FileReader in Action In the following chapter, we are going to build our first FileReader implementation. The first step involves the initialization of the file reader object using the object constructor function syntax. This will create an instance of the file reader Web API: ` Now that our reader is initialized, we are able to attach to some of its events handlers (Events handlers list). We are going to cover this event in more detail later in the post. ` This can also be achieved by using the addEventListener syntax (Events list): ` It is now time to use the readAsText method provided by the API (list of methods). The aim of this method is to read the content of the file provided. Throughout the process the FileReader API is going to trigger events that will trigger the relevant callbacks (myLoadFunction, myErrorFunction). The reader methods accept one argument that is expected to be a file or a Blob object. ` Finally, we need to declare our _file variable by taking advantage of the File API. Creating a file in Javascript from scratch is not always required, as the FileReader can access files from multiple sources (File Constructor, input of type file, drag and drop, Canvas ,etc..).. ` If successful, our code above is going to trigger our MyLoadFunction event callback.This method has access to the reader result and state as part of its arguments. A successful callback from a readAsText method will include the following properties: ` The table below is going to show all the different events associated state and Value. The code required to produce the following table can be accessed on this codepen: https://codepen.io/zelig880/pen/rEVEpK FileReader event Scenario EventName State Result Simple upload on initialization (new FileReader()) 0 (Empty) empty onloadstart 1 (Loading) empty onprogress 1 (Loading) My newly created text file onload 2 (Done) My newly created text file onloadend 2 (Done) My newly created text file Abort on initialization (new FileReader()) 0 (Empty) empty onloadstart 1 (Loading) empty onabort 2 (Done) empty onloadend 2 (Done) empty Our first implementation of the file reader is completed and the code can be accessed on the following codepen: https://codepen.io/zelig880/pen/EBYwer Browser File Editor In this chapter we are going to expand what we have written so far and turn it into a web browser text file editor. To achieve our goal, we will have to make the following modifications to our existing code, by taking advantage of different methods and feature offered by the API. 1. Change the FileReader output to be of type Data URL 2. Use the Data URL to provide a download functionality 3. Provide input to the client to update some text 4. Use the FileReader to read a file uploaded using an input of type file 5. Dynamically update the text field with the uploaded file content Change the FileReader output to be of type Data URL Our first step requires us to change the method used to read our file. The readAsText is going to be replaced with readAsDataUrl. This method is going to provide us with a DATA URL ( a url with a base64 representation of our file). ` Use the Data URL to provide a download functionality A Data URL on its own is not very useful. So in this section we are going to provide a very simple functionality to allow the download of the newly created file. To achieve our download, we are going to use an anchor element . The element will have our Data URL dynamically set as its href and an attribute of download. This attribute specifies that the target file will be downloaded when the user clicks the link instead of navigating to the file. ` To dynamically set our href, we are going to utilize the onload event triggered by the FileReader, by declaring a callback function: ` Our text editor is starting to take shape. At this point we are able to download a "static" text file. Provide input to the client to update some text It is now time to provide some control to our users, and make things more dynamic. To carry out this task, we are going to create a simple text input, used to dynamically modify the content of our file. The Javascript code will look like this: ` The code above has made our text editor come to life. We are now able to modify the text or our downloaded file. Use the FileReader to read a file uploaded using an input of type file Finally, to expand our knowledge of the FileReader API, we are going to enhance our editor with another feature. We are going to give the user the ability to upload a text file from their computer and modify it with the code written above. To accomplish this, we will create an input of type file, and listen to the change event triggered by this element to initialize our FileReader ( this is the most common use of the file reader api). ` This codepen includes our fully functional code: https://codepen.io/zelig880/pen/XLraXj Conclusion It is incredible how much can be achieved nowadays with javascript directly within the browser. In less than 50 lines, we have been able to write a fully functional text editor, it may not be production ready (it has a couple of bugs), but the thought that we can achieve so much, with so little code, fills me with excitement. TLDR: The complete code for our text editor can be found at the following codepen: https://codepen.io/zelig880/pen/XLraXj *This post was written by Simone Cuomo who is a mentor and senior software engineer at ThisDot.* *You can follow them on Twitter at @zelig880.*...