<?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>DEV Community: Francesco Esposito</title>
    <description>The latest articles on DEV Community by Francesco Esposito (@phoinixi).</description>
    <link>https://dev.to/phoinixi</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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F120114%2F9fd5769e-8023-44e3-a7a7-bac37d2207f2.png</url>
      <title>DEV Community: Francesco Esposito</title>
      <link>https://dev.to/phoinixi</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/phoinixi"/>
    <language>en</language>
    <item>
      <title>Resuml has a web app now, and nothing leaves your browser</title>
      <dc:creator>Francesco Esposito</dc:creator>
      <pubDate>Wed, 24 Jun 2026 13:03:56 +0000</pubDate>
      <link>https://dev.to/phoinixi/resuml-has-a-web-app-now-and-nothing-leaves-your-browser-2m6l</link>
      <guid>https://dev.to/phoinixi/resuml-has-a-web-app-now-and-nothing-leaves-your-browser-2m6l</guid>
      <description>&lt;p&gt;I've written about &lt;a href="https://dev.to/blog/introducing-resuml/"&gt;resuml&lt;/a&gt; twice already. Once when it was just a CLI, and once when it &lt;a href="https://dev.to/blog/resuml-mcp-claude-code/"&gt;grew an MCP server&lt;/a&gt; so Claude Code could drive it from a chat. Both of those quietly assume you're fine installing a global npm package and living in a terminal. I am. Most people aren't, and honestly they shouldn't have to be just to fix their resume on a Sunday.&lt;/p&gt;

&lt;p&gt;So now there's a hosted version at &lt;a href="https://resuml.app" rel="noopener noreferrer"&gt;resuml.app&lt;/a&gt;. Same engine underneath, nothing to install, and the part I care about most: nothing you type ever leaves your browser.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it actually is
&lt;/h2&gt;

&lt;p&gt;It's the CLI's brain wrapped in a web page. You write your resume in YAML, or use the form editor if you'd rather not look at YAML at all, paste in a job description, and the ATS score updates while you type. Pick a theme from the 300 or so available. Export a PDF when it looks right. That's the whole thing.&lt;/p&gt;

&lt;p&gt;One point I want to be loud about. There's no signup. No account. No analytics quietly tailing you around the site. Your resume lives in your browser's local storage and nowhere else. I don't run a database with your work history in it because I never wanted to be the guy responsible for one. Close the tab and your draft is still there when you come back. Clear your browser data and it's gone, and yeah, that part's on you. I made that trade on purpose.&lt;/p&gt;

&lt;h2&gt;
  
  
  The score is the whole point
&lt;/h2&gt;

&lt;p&gt;Most "AI resume" tools do one of two annoying things. They either rewrite your resume into smooth, weightless mush, or they hand it to an LLM that grades it and cheerfully tells you it's wonderful. resuml does neither. The score runs on a fixed set of rules. Eleven checks, three buckets:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Contact.&lt;/strong&gt; Is the basic stuff there and actually parseable.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Content.&lt;/strong&gt; Summary length, at least two highlights per role, real verbs instead of passive filler, numbers that prove impact, and no sentences that start with the word I.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Structure.&lt;/strong&gt; Dates that line up, at least three skill groups, education that isn't half filled in.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You land in a band. 90 to 100 is excellent, 75 to 89 good, 60 to 74 needs work, under 60 is rough. Paste in a job description and the math tilts to 60% those general checks and 40% how well your wording matches the posting. Because none of it is an LLM guessing, the number won't budge unless the resume genuinely got better. You can't flatter it. To move the score you have to do the dull, real work: add the skills you actually have, turn "was responsible for" into a sentence with a verb and a number in it, fix the gap between two jobs.&lt;/p&gt;

&lt;h2&gt;
  
  
  The bit that's new even if you use the CLI
&lt;/h2&gt;

&lt;p&gt;This didn't exist last time I wrote anything. resuml can pull job postings now, from a handful of free job boards, all at once, and rank them with that same scoring engine. So the question flips. It stops being "is my resume any good" and becomes "which of these openings is my resume already good for." Roles way outside your lane get capped so they don't sneak to the top, and there's a cutoff so you're not scrolling through junk. It's &lt;code&gt;resuml jobs search&lt;/code&gt; on the command line, and the web app shows you the same thing.&lt;/p&gt;

&lt;p&gt;Small change, but it turned out to matter. Nearly every resume tool tunes one document against one job at a time. This one points your document at a whole pile of jobs and tells you where to aim first.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why bother with a web app at all
&lt;/h2&gt;

&lt;p&gt;The plain truth is I kept telling friends to try resuml and then watching them hit &lt;code&gt;npm install -g&lt;/code&gt; and quietly give up. The CLI and the MCP server are the right call if you live in a terminal or inside Claude Code. But "resume as code" is a nice idea that shouldn't make you set up a whole Node toolchain just to poke at it. The web app is the easy way in. Open a link, watch your resume restyle itself across 300 templates, get a score that isn't lying to you, leave. Same YAML, same engine, whichever door you walk in through.&lt;/p&gt;

&lt;p&gt;Go try it at &lt;a href="https://resuml.app" rel="noopener noreferrer"&gt;resuml.app&lt;/a&gt;. It's free to use right now.&lt;/p&gt;

</description>
      <category>resume</category>
      <category>ats</category>
      <category>yaml</category>
      <category>career</category>
    </item>
    <item>
      <title>Resuml - YAML to resume</title>
      <dc:creator>Francesco Esposito</dc:creator>
      <pubDate>Thu, 19 Jun 2025 20:28:38 +0000</pubDate>
      <link>https://dev.to/phoinixi/resuml-yaml-to-resume-ba7</link>
      <guid>https://dev.to/phoinixi/resuml-yaml-to-resume-ba7</guid>
      <description>&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%2Fq3848qmsu9el9gl4umv3.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%2Fq3848qmsu9el9gl4umv3.png" alt="resuml" width="800" height="534"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Introducing Resuml: YAML-powered Resume Builder
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/phoinixi/resuml" rel="noopener noreferrer"&gt;Resuml&lt;/a&gt; is an open-source CLI tool that helps you manage your resume as code. Write your resume in YAML, validate it, and export to JSON or HTML using professional themes.&lt;/p&gt;

&lt;h3&gt;
  
  
  Key Features
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;YAML-first&lt;/strong&gt;: Author your resume in a simple, human-readable YAML format.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Validation&lt;/strong&gt;: Ensure your resume data is correct with built-in validation against the JSON Resume schema.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Export Options&lt;/strong&gt;: Convert your YAML to JSON or render it as HTML using themes like Stack Overflow or React.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Theme Support&lt;/strong&gt;: Choose from available themes for a professional look, or create your own.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CLI &amp;amp; API&lt;/strong&gt;: Use Resuml from the command line or integrate it into Node.js projects.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Quick Start
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Install: &lt;code&gt;npm install -g resuml&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Write your resume in &lt;code&gt;resume.yaml&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Validate: &lt;code&gt;resuml validate --resume resume.yaml&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Export to JSON: &lt;code&gt;resuml tojson --resume resume.yaml --output resume.json&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Render HTML: &lt;code&gt;resuml render --resume resume.yaml --theme stackoverflow --output resume.html&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Example YAML
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;basics&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;John Doe&lt;/span&gt;
  &lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Software Engineer&lt;/span&gt;
  &lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;john@example.com&lt;/span&gt;
  &lt;span class="na"&gt;summary&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Experienced software engineer...&lt;/span&gt;
  &lt;span class="na"&gt;location&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;city&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;San Francisco&lt;/span&gt;
    &lt;span class="na"&gt;countryCode&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;US&lt;/span&gt;
  &lt;span class="na"&gt;profiles&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;network&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;GitHub&lt;/span&gt;
      &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;https://github.com/johndoe&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Why Resuml?
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Keep your resume versioned and editable as code&lt;/li&gt;
&lt;li&gt;Easily switch between formats and themes&lt;/li&gt;
&lt;li&gt;Open-source and privacy-friendly&lt;/li&gt;
&lt;li&gt;Find out more and contribute at &lt;a href="https://github.com/phoinixi/resuml" rel="noopener noreferrer"&gt;https://github.com/phoinixi/resuml&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>career</category>
      <category>webdev</category>
      <category>javascript</category>
      <category>programming</category>
    </item>
    <item>
      <title>I Built a Modern React Theme for JSON Resume</title>
      <dc:creator>Francesco Esposito</dc:creator>
      <pubDate>Sat, 12 Apr 2025 15:55:47 +0000</pubDate>
      <link>https://dev.to/phoinixi/i-built-a-modern-react-theme-for-json-resume-d4h</link>
      <guid>https://dev.to/phoinixi/i-built-a-modern-react-theme-for-json-resume-d4h</guid>
      <description>&lt;h2&gt;
  
  
  Creating a Better Resume Experience with React
&lt;/h2&gt;

&lt;p&gt;Over the past few weeks, I've been working on a project that combines my love for clean design and React development – a modern theme for JSON Resume called &lt;strong&gt;jsonresume-theme-react&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Another Resume Theme?
&lt;/h2&gt;

&lt;p&gt;If you're not familiar with &lt;a href="https://jsonresume.org/" rel="noopener noreferrer"&gt;JSON Resume&lt;/a&gt;, it's a fantastic initiative that lets you manage your resume as a JSON file. The ecosystem has several themes, but I found most of them were either outdated or missing features I wanted.&lt;/p&gt;

&lt;p&gt;I needed something that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Used modern React&lt;/li&gt;
&lt;li&gt;Supported multiple languages&lt;/li&gt;
&lt;li&gt;Rendered markdown in descriptions&lt;/li&gt;
&lt;li&gt;Looked good both on screen and in print&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So I decided to build my own, and I'm pretty happy with how it turned out!&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%2Fcn5li52lhwldwi5vmrom.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%2Fcn5li52lhwldwi5vmrom.png" alt="Resume Screenshot" width="800" height="583"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What Makes This Theme Different
&lt;/h2&gt;

&lt;p&gt;I've focused on creating a balance between professional appearance and modern functionality:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;React 18 &amp;amp; TypeScript&lt;/strong&gt; - Built on current tech for better maintainability&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Multi-language Support&lt;/strong&gt; - Create different versions of your resume for different languages&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Markdown in Descriptions&lt;/strong&gt; - Format your job descriptions with proper lists and emphasis&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Print-Optimized&lt;/strong&gt; - Carefully designed to look great when printed to PDF&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Responsive Design&lt;/strong&gt; - Looks good on everything from phones to desktops&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The theme uses Tailwind CSS for styling, which made it much easier to create a responsive layout that prints well.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Look Inside
&lt;/h2&gt;

&lt;p&gt;The theme renders all standard sections from the JSON Resume schema:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Basic information with optional profile photo&lt;/li&gt;
&lt;li&gt;Work experience with properly formatted date ranges&lt;/li&gt;
&lt;li&gt;Education history&lt;/li&gt;
&lt;li&gt;Skills with optional proficiency levels&lt;/li&gt;
&lt;li&gt;Projects and volunteer work&lt;/li&gt;
&lt;li&gt;Languages and interests&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here's a small example of how work experience renders with markdown support:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"work"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Company Name"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"position"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Senior Developer"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"startDate"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2020-01-01"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"endDate"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2022-12-31"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"summary"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Led development of key products"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"- Rebuilt the authentication system&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;- Improved performance by 40%&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;- Mentored junior developers"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This renders as properly formatted bullets in the final resume, making it much more readable than plain text.&lt;/p&gt;

&lt;h2&gt;
  
  
  Supporting Multiple Languages
&lt;/h2&gt;

&lt;p&gt;One feature I'm particularly proud of is the multilingual support. The theme detects the language from the "language" property in your resume JSON:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"basics"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"John Doe"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"label"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Programmer"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"language"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"en"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"work"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;work&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;history&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can create versions for different languages:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"basics"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Jean Dupont"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"label"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Développeur"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"language"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"fr"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"work"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;work&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;history&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;French&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is perfect if you're applying for jobs internationally or in bilingual markets.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Development Process
&lt;/h2&gt;

&lt;p&gt;Building this theme taught me a lot about:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Optimizing for print media&lt;/strong&gt; - CSS for print is surprisingly tricky&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Component organization&lt;/strong&gt; - Breaking down a resume into logical React components&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Handling internationalization&lt;/strong&gt; - Working with dates and text in multiple languages&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Balancing design and function&lt;/strong&gt; - Creating something that looks good but prioritizes content&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The most challenging part was ensuring the theme remained faithful to the JSON Resume schema while adding extra features. I wanted to make sure it would work with existing resume data without modification.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try It Yourself
&lt;/h2&gt;

&lt;p&gt;If you want to give it a spin, the theme is available on npm and GitHub. I've created detailed documentation in the repository about installation and configuration options.&lt;/p&gt;

&lt;p&gt;I'd love to hear what you think or see examples if you use it for your own resume! I'm still actively developing it and plan to add more customization options in the future.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's Next?
&lt;/h2&gt;

&lt;p&gt;I'm planning several improvements:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Theme customization through configuration&lt;/li&gt;
&lt;li&gt;More layout variants&lt;/li&gt;
&lt;li&gt;Custom sections support&lt;/li&gt;
&lt;li&gt;More export options&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Have you used JSON Resume before? What features would you want in a resume theme? Let me know in the comments!&lt;/p&gt;




&lt;p&gt;The project is open source and available at &lt;a href="https://github.com/phoinixi/jsonresume-theme-react" rel="noopener noreferrer"&gt;github.com/phoinixi/jsonresume-theme-react&lt;/a&gt;&lt;/p&gt;

</description>
      <category>discuss</category>
      <category>react</category>
      <category>resume</category>
      <category>typescript</category>
    </item>
    <item>
      <title>Two-way data binding in vanilla JS (POC)</title>
      <dc:creator>Francesco Esposito</dc:creator>
      <pubDate>Sat, 02 Feb 2019 14:44:02 +0000</pubDate>
      <link>https://dev.to/phoinixi/two-way-data-binding-in-vanilla-js-poc-4e06</link>
      <guid>https://dev.to/phoinixi/two-way-data-binding-in-vanilla-js-poc-4e06</guid>
      <description>&lt;p&gt;As Front-end Engineers we mostly use libraries and/or frameworks to develop and maintain complex web apps, but what there is under the hood? Do you ask yourself that question? You don't!? Well, You should! 🙃&lt;/p&gt;

&lt;p&gt;In this post, I would like to extend the previous example to two-way data binding. 🕺&lt;/p&gt;

&lt;p&gt;Two-way data binding 🤓&lt;br&gt;
If you are not familiar with that concept, two-way data binding means that every change to the state is immediately propagated to the view (and vice-versa). &lt;/p&gt;

&lt;p&gt;Check out the demo below for a quick example:&lt;/p&gt;
&lt;h3&gt;
  
  
  DEMO
&lt;/h3&gt;

&lt;p&gt;&lt;a href="//thepracticaldev.s3.amazonaws.com/i/xax8qjn8qubpijnv2c3o.gif" class="article-body-image-wrapper"&gt;&lt;img src="//thepracticaldev.s3.amazonaws.com/i/xax8qjn8qubpijnv2c3o.gif" alt="demo"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Let's break it down
&lt;/h3&gt;

&lt;p&gt;What do we need to have two-way data binding?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A &lt;strong&gt;view&lt;/strong&gt;, in our example HTML.&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;state&lt;/strong&gt;, kept in memory with JavaScript.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The Key feature is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Every time the &lt;strong&gt;state&lt;/strong&gt; changes, the &lt;strong&gt;view&lt;/strong&gt; needs to be updated (one-way data binding) &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;but also&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Every time the view changes, the state needs to be updated&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So let's assume we have an HTML &lt;strong&gt;view&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"field"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;label&lt;/span&gt; &lt;span class="na"&gt;for=&lt;/span&gt;&lt;span class="s"&gt;"name"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Enter your name:&lt;span class="nt"&gt;&amp;lt;/label&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"name"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"name"&lt;/span&gt;  &lt;span class="na"&gt;data-model=&lt;/span&gt;&lt;span class="s"&gt;"name"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;

      &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"field"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;label&lt;/span&gt; &lt;span class="na"&gt;for=&lt;/span&gt;&lt;span class="s"&gt;"title"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Enter your title:&lt;span class="nt"&gt;&amp;lt;/label&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"title"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"title"&lt;/span&gt; &lt;span class="na"&gt;data-model=&lt;/span&gt;&lt;span class="s"&gt;"title"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;

      &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"results"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;h1&lt;/span&gt; &lt;span class="na"&gt;data-binding=&lt;/span&gt;&lt;span class="s"&gt;"name"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;h2&lt;/span&gt; &lt;span class="na"&gt;data-binding=&lt;/span&gt;&lt;span class="s"&gt;"title"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/h2&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and a &lt;strong&gt;state&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Francesco&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Front-end Developer&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can easily set the &lt;strong&gt;view&lt;/strong&gt; the first time:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;    &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;[data-binding="name"]&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;innerHTML&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;
    &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;[data-binding="title"]&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;innerHTML&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;
    &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;[data-model="name"]&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;
    &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;[data-model="title"]&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But we want some magic, so that when we update the state:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;    &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Richard&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
    &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Technical Lead&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;the &lt;strong&gt;view&lt;/strong&gt; should update too.&lt;/p&gt;

&lt;p&gt;To achieve this, we could modify the default behaviour of the &lt;code&gt;set&lt;/code&gt; property for the &lt;code&gt;state&lt;/code&gt; object, so that other than update the &lt;strong&gt;state&lt;/strong&gt;, it would also update our &lt;strong&gt;view&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;One way to do that in JavaScript is using the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy" rel="noopener noreferrer"&gt;Proxy Object&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;createState&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Proxy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;property&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;property&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// default set behaviour&lt;/span&gt;
          &lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// updates the view every time the state changes&lt;/span&gt;
          &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createState&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Francesco&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
      &lt;span class="nx"&gt;title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Front-end Engineer&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With the power of the Proxy every time we update our &lt;code&gt;state&lt;/code&gt;, the &lt;code&gt;render&lt;/code&gt; function will be called.&lt;br&gt;
A possible implementation of &lt;code&gt;render&lt;/code&gt; can be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;render&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;[data-binding="name"]&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;innerHTML&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
     &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;[data-binding="title"]&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;innerHTML&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
     &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;[data-model="name"]&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
     &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;[data-model="title"]&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We just miss the last little piece. Every time we modify the &lt;strong&gt;view&lt;/strong&gt;, the &lt;strong&gt;state&lt;/strong&gt; should change accordingly. We can obtain that adding an event listener to the inputs: 😎&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;listener&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dataset&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;model&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

   &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;[data-model="name"]&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;keyup&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;listener&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  
   &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;[data-model="title"]&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;keyup&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;listener&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;And &lt;em&gt;Voilá&lt;/em&gt;! Now the trick is complete! 👨‍💻&lt;/p&gt;

&lt;h3&gt;
  
  
  More generic implementation (POC) 🌟
&lt;/h3&gt;

&lt;p&gt;&lt;iframe src="https://stackblitz.com/edit/two-way-data-binding-poc?" width="100%" height="500"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

</description>
      <category>showdev</category>
      <category>javascript</category>
      <category>webdev</category>
      <category>databinding</category>
    </item>
    <item>
      <title>Resume in JSON: jsonresume-theme-stackoverflow</title>
      <dc:creator>Francesco Esposito</dc:creator>
      <pubDate>Mon, 28 Jan 2019 22:43:48 +0000</pubDate>
      <link>https://dev.to/phoinixi/resume-in-json-jsonresume-theme-stackoverflow-4hi8</link>
      <guid>https://dev.to/phoinixi/resume-in-json-jsonresume-theme-stackoverflow-4hi8</guid>
      <description>&lt;h3&gt;
  
  
  Resume in JSON 🤓
&lt;/h3&gt;

&lt;p&gt;A few years ago I discovered &lt;a href="http://jsonresume.org" rel="noopener noreferrer"&gt;jsonresume&lt;/a&gt;, a very promising project aimed to provide a json-schema to write a resume.&lt;/p&gt;

&lt;p&gt;I immediately got excited and I wrote 2 templates for that: 👨🏼‍💻&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;jsonresume-stackoverflow-theme&lt;/strong&gt;: &lt;a href="https://github.com/phoinixi/jsonresume-theme-stackoverflow" rel="noopener noreferrer"&gt;code&lt;/a&gt; and &lt;a href="https://phoinixi.github.io/website/resume/stackoverflow" rel="noopener noreferrer"&gt;demo&lt;/a&gt; which I am proud of 🕺&lt;/li&gt;
&lt;li&gt;another one that I actually don't like anymore 😆&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  My first handcrafted resume template 🌟
&lt;/h3&gt;

&lt;p&gt;The &lt;strong&gt;StackOverflow&lt;/strong&gt; template was my first resume written using web technologies and it has some popularity, I got contributions and features requests. I use it myself as my resume and a bunch of my friends use it too. However, the schema is not very flexible and the last iteration was done 5 years ago &lt;a href="https://github.com/jsonresume/resume-schema" rel="noopener noreferrer"&gt;json-resume-schema&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The current stack to write a template for &lt;strong&gt;json-resume&lt;/strong&gt; is quite old too: &lt;strong&gt;Handlebars.js&lt;/strong&gt;. &lt;/p&gt;

&lt;h3&gt;
  
  
  Need for a rewrite 😎
&lt;/h3&gt;

&lt;p&gt;My idea is to fully rewrite my StackOverflow template, (maybe the json-schema too, but this is another story) using different technologies, the most reasonable that come to my mind are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;React&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_custom_elements" rel="noopener noreferrer"&gt;Custom Elements&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  HELP ❤️
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Is anyone interested in that project?&lt;/li&gt;
&lt;li&gt;Which technologies to do you advice me to choose and why?&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>discuss</category>
      <category>opensource</category>
      <category>webdev</category>
      <category>showdev</category>
    </item>
    <item>
      <title>One-way data binding in vanilla JS (POC)</title>
      <dc:creator>Francesco Esposito</dc:creator>
      <pubDate>Fri, 25 Jan 2019 11:05:33 +0000</pubDate>
      <link>https://dev.to/phoinixi/one-way-data-binding-in-vanilla-js-poc-4dj7</link>
      <guid>https://dev.to/phoinixi/one-way-data-binding-in-vanilla-js-poc-4dj7</guid>
      <description>&lt;p&gt;&lt;strong&gt;Code and Demo&lt;/strong&gt;&lt;br&gt;
&lt;iframe src="https://stackblitz.com/edit/one-way-data-binding?" width="100%" height="500"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h3&gt;
  
  
  Let's break it down in small pieces
&lt;/h3&gt;

&lt;p&gt;I assume you are already familiar with &lt;a href="https://www.quora.com/What-is-data-binding" rel="noopener noreferrer"&gt;data-binding&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Most of the modern front-end frameworks offer data-binding out of the box, just ready to use, but what there is under the hood?&lt;/p&gt;

&lt;p&gt;I tried to implement a basic version of one-way data binding and it was really fun :)&lt;/p&gt;

&lt;p&gt;So, what do we need to have one-way data binding?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A &lt;strong&gt;view&lt;/strong&gt;, in our example HTML.&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;state&lt;/strong&gt;, kept in memory with JavaScript.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The Key feature is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Everytime the state changes, the view need to be updated&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So let's assume we have an HTML &lt;strong&gt;view&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;data-binding=&lt;/span&gt;&lt;span class="s"&gt;"quote"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and a &lt;strong&gt;state&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;quote&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Either you run the day, or the day runs you.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can easily set the view the first time:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;    &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;[data-binding="quote"]&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;innerHTML&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;quote&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We want some magic, so that when we update the state:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;    &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;quote&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;We become what we think about&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;the view should magically change. To achieve this, we could modify the default behaviour of the &lt;code&gt;set&lt;/code&gt; property for the &lt;code&gt;state&lt;/code&gt; object, so that other than update the model, it would also update our &lt;strong&gt;view&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;One way to do that in JavaScript is using the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy" rel="noopener noreferrer"&gt;Proxy Object&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;createState&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Proxy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;property&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;property&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// default set behaviour&lt;/span&gt;
          &lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// updates the view everytime the state changes&lt;/span&gt;
          &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createState&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;quote&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Either you run the day, or the day runs you.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="c1"&gt;// creates initial state&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With the power of the Proxy everytime we update our &lt;code&gt;state&lt;/code&gt;, the &lt;code&gt;render&lt;/code&gt; function will be called.&lt;br&gt;
A possible implementation of &lt;code&gt;render&lt;/code&gt; can be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;render&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;[data-binding="quote"]&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;innerHTML&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;quote&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now if we modify the state with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;    &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;quote&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;We become what we think about.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;render&lt;/code&gt; function will be called and the view will update! &lt;em&gt;MAGIC&lt;/em&gt;! 👨‍💻&lt;/p&gt;

</description>
      <category>showdev</category>
      <category>javascript</category>
      <category>webdev</category>
      <category>databinding</category>
    </item>
  </channel>
</rss>
