Pen Settings

HTML

CSS

CSS Base

Vendor Prefixing

Add External Stylesheets/Pens

Any URLs added here will be added as <link>s in order, and before the CSS in the editor. You can use the CSS from another Pen by using its URL and the proper URL extension.

+ add another resource

JavaScript

Babel includes JSX processing.

Add External Scripts/Pens

Any URL's added here will be added as <script>s in order, and run before the JavaScript in the editor. You can use the URL of any other Pen and it will include the JavaScript from that Pen.

+ add another resource

Packages

Add Packages

Search for and use JavaScript packages from npm here. By selecting a package, an import statement will be added to the top of the JavaScript editor for this package.

Behavior

Auto Save

If active, Pens will autosave every 30 seconds after being saved once.

Auto-Updating Preview

If enabled, the preview panel updates automatically as you code. If disabled, use the "Run" button to update.

Format on Save

If enabled, your code will be formatted when you actively save your Pen. Note: your code becomes un-folded during formatting.

Editor Settings

Code Indentation

Want to change your Syntax Highlighting theme, Fonts and more?

Visit your global Editor Settings.

HTML

              
                <html lang="en">
  <head>
    <!-- Required meta tags -->
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Resume/CV</title>
    <!-- Bootstrap CSS -->
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.1/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-+0n0xVW2eSR5OomGNYDnhzAbDsOXxcvSN1TPprVMTNDbiYZCxYbOOl7+AMvyTG2x" crossorigin="anonymous">
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.4.0/font/bootstrap-icons.css">
    <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.14/vue.min.js"></script>
    <!-- Add Web Animations Polyfill :) -->
    <script src="https://cdnjs.cloudflare.com/ajax/libs/web-animations/2.3.2/web-animations.min.js"></script>
    <script type="module" src="https://cdn.jsdelivr.net/npm/@proyecto26/animatable-component@1.1.10/dist/animatable-component/animatable-component.esm.js"></script>
  </head>
  <body class="d-none">
    <section id="app" class="container-fluid">
      <header class="header position-relative">
        <animatable-component autoplay animation="fadeInDownBig"  easing="ease-in-out" duration="1200">
          <div class="headLine position-absolute"></div>
        </animatable-component>
        <div class="row">
          <div class="col">
            <animatable-component
              autoplay
              animation="fadeInLeft"
              easing="ease-in-out"
              duration="1200"
            >
              <h1 class="firstName text-break">
                {{ firstName }}
              </h1>
            </animatable-component>
            <animatable-component
              autoplay
              animation="fadeInDown"
              easing="ease-in-out"
              duration="1200"
            >
              <h2 class="lastName text-nowrap">
                {{ lastName }}
              </h2>
            </animatable-component>
            <animatable-component
              autoplay
              animation="fade-in-left"
              easing="ease-in-out"
              duration="1200"
            >
              <p class="jobTitle">
                <i class="bi bi-circle-fill"></i>
                <span class="text-break">
                  {{ jobTitle }}
                </span>
              </p>
             </animatable-component>
          </div>
          <div v-if="!!photo" class="col-auto d-none d-lg-block d-print-block">
            <animatable-component autoplay animation="rotateIn" easing="ease-in" duration="1200">
              <img v-bind:src.prop="photo" class="photo border border-2 border-dark rounded-circle img-fluid float-end img-thumbnail">
            </animatable-component>
          </div>
        </div>
        <animatable-component autoplay animation="fadeInUpBig"  easing="ease-in-out" duration="1200">
          <div class="middleLine position-absolute"></div>
        </animatable-component>
      </header>
      <section class="content">
        <div class="row">
          <div class="col personal-details me-4">
            <div class="row list-item me-5">
              <div class="col-auto">
                <animatable-component autoplay animation="heartBeat" easing="ease-in" duration="1200">
                  <div class="icon d-flex justify-content-center">
                    <i class="bi bi-geo-alt-fill" role="img" aria-label="Location"></i>
                  </div>
                </animatable-component>
              </div>
              <div class="col" style="white-space: pre-line;">
                <p class="mt-3">{{ address }}</p>
              </div>
            </div>
            <div v-if="!!phone" class="row list-item me-5">
              <div class="col-auto align-self-center">
                <animatable-component autoplay animation="swing" easing="ease-in" duration="1200">
                  <div class="icon d-flex justify-content-center">
                    <i class="bi bi-telephone-fill" role="img" aria-label="Telephone"></i>
                  </div>
                </animatable-component>
              </div>
              <div class="col">
                <a v-bind:href="'tel:'+ phone" class="text-decoration-none">
                  <p class="mt-3">{{ phone }}</p>
                </a>
              </div>
            </div>
            <div class="row list-item me-5">
              <div class="col-auto align-self-center">
                <animatable-component autoplay animation="flip" easing="ease-in" duration="1200">
                  <div class="icon d-flex justify-content-center">
                    <i class="bi bi-envelope-fill" role="img" aria-label="Email"></i>
                  </div>
                </animatable-component>
              </div>
              <div class="col">
                <a v-bind:href="'mailto:'+ email" class="text-decoration-none">
                  <p class="mt-3">{{ email }}</p>
                </a>
              </div>
            </div>
            <div class="row mt-5 me-5">
              <div class="col">
                <p class="title">Education</p>
              </div>
            </div>
            <div class="row record" v-for="e in education">
              <div class="col-auto bullet">
                <i class="bi bi-record-circle"></i>
              </div>
              <div class="col">
                <p class="fw-bold text-uppercase">
                  {{ e.degree }}
                </p>
                <p class="fw-bold text-uppercase">
                  {{ e.school }}, {{ e.graduationDate }}
                </p>
                <p>{{ e.description }}</p>
              </div>
            </div>
            <div class="row mt-5 me-5">
              <div class="col p-0">
                <p class="title">Links</p>
              </div>
            </div>
            <div class="row record me-4" v-for="l in links">
              <div class="col-auto bullet mb-5">
                <i class="bi bi-record-circle"></i>
              </div>
              <div class="col">
                <p>
                  {{ l.label }}:
                  <a class="text-reset" target="_blank" v-bind:href.prop="l.link">
                    {{ l.link }}
                  </a>
                </p>
              </div>
            </div>
            <div class="row mt-5 me-5">
              <div class="col p-0">
                <p class="title">Skills</p>
              </div>
            </div>
            <div class="row">
              <div class="col">
                <ul class="ms-2">
                  <li class="pb-2" v-for="skill in skills">
                    {{ skill }}
                  </li>
                </ul>
              </div>
            </div>
            <div class="row mt-5 me-5">
              <div class="col p-0">
                <p class="title">Languages</p>
              </div>
            </div>
            <div class="row">
              <div class="col">
                <ul class="ms-2">
                  <li class="pb-2" v-for="language in languages">
                    {{ language }}
                  </li>
                </ul>
              </div>
            </div>
          </div>
          <div class="col col-8">
            <animatable-component
              autoplay
              animation="fade-in-right"
              easing="ease-in-out"
              duration="1200"
            >
              <div class="row bullet">
              <div class="col-auto pt-2">
                <i class="bi bi-circle-fill"></i>
              </div>
              <div class="col">
                <p class="title">About Me</p>
              </div>
            </div>
            </animatable-component>
            <animatable-component
              autoplay
              animation="fade-in-right"
              easing="ease-in-out"
              duration="1200"
            >
              <div class="row record bullet">
              <div class="col-auto">
                <i class="bi bi-record-circle"></i>
              </div>
              <div class="col">
                <p style="white-space: pre-line;">{{ professionalSummary }}</p>
              </div>
            </div>
            </animatable-component>
            <div class="row mt-5">
              <div class="col-auto bullet pt-2">
                <i class="bi bi-circle-fill"></i>
              </div>
              <div class="col">
                <p class="title">Work Experience</p>
              </div>
            </div>
            <div class="row record mb-4 bullet" v-for="employment in employmentHistory">
              <div class="col-auto">
                <i class="bi bi-record-circle"></i>
              </div>
              <div class="col">
                <p class="text-uppercase fw-bold position-relative clearfix">
                  {{ employment.jobTitle }}
                  <span class="float-end">&nbsp;|&nbsp;{{ employment.startDate }} - {{ employment.endDate }}</span>
                </p>
                <p class="fst-italic fw-bold">
                  {{ employment.employer }}, {{ employment.city }}
                </p>
                <p class="mb-0" v-for="achievement in employment.achievements">
                  • {{ achievement }}
                </p>
              </div>
            </div>
          </div>
        </div>
      </section>
    </section>
    <div class="btn-group-fab d-print-none">
      <div>
        <button onclick="javascript:window.print()" type="button" class="btn btn-main btn-primary" title="Print">
          <i class="bi bi-printer fs-3"></i>
        </button>
      </div>
    </div>
    
    <!-- Bootstrap Bundle with Popper -->
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.1/dist/js/bootstrap.bundle.min.js" integrity="sha384-gtEjrD/SeCtmISkJkNUaaKMoLD0//ElJ19smozuHV6z3Iehds+3Ulb9Bn9Plx0x4" crossorigin="anonymous"></script>
  </body>
</html>
              
            
!

CSS

              
                @import url('https://fonts.googleapis.com/css2?family=Raleway:wght@300;400;700&display=swap');

:root {
  /* Colors */
  --color-primary: rgb(41, 41, 41);
  --color-secondary: rgb(45, 45, 45);
  --color-text: rgb(51, 51, 51);
  --color-text-dark: rgb(45, 45, 45);
  --color-title: rgb(25, 25, 25);
  --color-border: rgb(35, 31, 32);
  --color-light-text: rgb(68, 68, 68);
  --color-white: white;
  
  /* Font sizes */
  --font-size-base: 2.48262rem;
  --font-size-medium: 2.8806rem;
  --font-size-large: 4rem;
  --font-size-xl: 6.65793rem;
  --font-size-xxl: 9.02771rem;
  --font-size-small: 2.28048rem;
  --font-size-icon: 2.5rem;
  
  /* Spacing */
  --spacing-xs: 1rem;
  --spacing-sm: 2rem;
  --spacing-md: 3rem;
  --spacing-lg: 4rem;
  --spacing-xl: 5rem;
  
  /* Line heights */
  --line-height-normal: 1.33;
  --line-height-large: 1.68;
  --line-height-title: 4.5rem;
  
  /* Border widths */
  --border-width: 0.225693rem;
  
  /* Letter spacing */
  --letter-spacing-small: 0.115103rem;
  --letter-spacing-medium: 0.5rem;
  --letter-spacing-large: 1.01562rem;
  --letter-spacing-xl: 3.89546rem;
  --letter-spacing-xxl: 4.15952rem;
}

* {
  font-family: Raleway;
  box-sizing: border-box;
  -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizelegibility;
  text-size-adjust: 100%;
  outline: none !important;
}

html {
  font-size: 62.5%
}

.container-fluid {
  padding: 0 10% !important;
}

ul {
  list-style: circle;
}

li::marker {
  color: black;
}

p {
  font-size: var(--font-size-base);
  letter-spacing: var(--letter-spacing-small);
  color: var(--color-text);
  word-break: break-all;
  -webkit-box-pack: center;
  justify-content: center;
}

.headLine {
  width: var(--border-width);
  top: 0;
  left: var(--spacing-xs);
  height: 11.9617rem;
  background-color: var(--color-primary);
}

.header {
  padding-top: 17.8297rem;
  padding-bottom: 10rem;
  direction: ltr;
  margin-bottom: var(--spacing-md);
}

.content {
  margin-top: -4rem;
}

.firstName {
  font-weight: lighter;
  text-transform: uppercase;
  word-break: break-all;
  color: var(--color-secondary);
  font-size: var(--font-size-xl);
  line-height: var(--line-height-large);
  letter-spacing: var(--letter-spacing-xl);
  margin-bottom: 1.12846rem;
  direction: ltr;
}

.lastName {
  font-weight: bold;
  font-size: var(--font-size-xxl);
  text-transform: uppercase;
  word-break: break-all;
  padding-right: 5.64232rem;
  color: var(--color-secondary);
  line-height: 1.09;
  letter-spacing: var(--letter-spacing-xxl);
  direction: ltr;
}

.jobTitle {
  padding-right: 0;
  margin-top: 4.51385rem;
  color: var(--color-primary);
  
  span {
    padding-left: var(--spacing-xs);
    letter-spacing: 0.710932rem;
    text-transform: uppercase;
    word-break: break-all;
    direction: ltr;
    color: var(--color-text-dark);
    font-size: 3.04685rem;
  }
}

.photo {
  width: 27.2rem;
  height: 27.2rem;
  max-height: 270px;
  object-fit: contain;
}

.middleLine {
  width: var(--border-width);
  bottom: 3.1597rem;
  left: var(--spacing-xs);
  height: 5.64232rem;
  background-color: var(--color-primary);
}

.icon {
  width: var(--spacing-xl);
  height: var(--spacing-xl);
  font-size: var(--font-size-icon);
  color: var(--color-white);
  background-color: var(--color-secondary);
  border-radius: 50%;
  padding: 0.7rem;
}

a p {
  word-break: break-all;
  color: var(--color-text);
}

.list-item {
  padding-top: 2.03123rem;
  padding-bottom: 2.03123rem;
  margin-right: var(--spacing-xs);
  &:not(:last-child) {
    border-bottom: var(--border-width) solid var(--color-border);
  }
}

.title {
  width: 100%;
  font-weight: bold;
  font-size: var(--font-size-large);
  text-transform: uppercase;
  line-height: var(--line-height-title);
  border-bottom: 1px solid var(--color-border);
  padding-top: 0;
  padding-bottom: 3.8rem;
  color: var(--color-title);
  letter-spacing: var(--letter-spacing-large);
  margin-bottom: 1.8rem;
}

.personal-details {
  .title {
    padding-top: var(--spacing-lg);
  }
}

.bullet {
  position: relative;
  i {
    font-size: 2.6rem;
  }
  &:before {
    content: "";
    position: absolute;
    left: 1.9rem;
    width: 0.3rem;
    height: 70%;
    background-color: var(--color-primary);
    margin-top: 4.2rem;
  }
}

.record {
  padding-top: var(--spacing-sm);
  p {
    width: 100%;
    font-size: 2.7rem;
    line-height: var(--line-height-normal);
    color: var(--color-text);
    word-break: break-word;
    display: block;
  }
}

li {
  font-family: Raleway;
  line-height: var(--line-height-normal);
  font-size: var(--font-size-medium);
  color: var(--color-light-text);
}

span {
  color: var(--color-text);
  font-size: var(--font-size-small);
  line-height: 1.2;
  letter-spacing: var(--letter-spacing-medium);
}

.btn-group-fab {
  position: fixed;
  width: 50px;
  height: auto;
  right: 20px;
  bottom: 20px;
}

.btn-group-fab div {
  position: relative;
  width: 100%;
  height: auto;
}

.btn-group-fab .btn {
  position: absolute;
  bottom: 0;
  border-radius: 50%;
  display: block;
  margin-bottom: 4px;
  width: 40px;
  height: 40px;
  margin: 4px auto;
}

@media print {
  @page {
    size: A4;
    margin: 0mm !important;
  }
  html {
    font-size: 22.5%;
  }
  .header {
    padding-top: 12rem;
    padding-bottom: 9rem;
  }
  
  ul li {
    margin-left: var(--spacing-xs);
  }
}
              
            
!

JS

              
                /**
 * Resume/CV template created with Bootstrap 5 by @vmoratog and @jdnichollsc
 */
const resume = {
  firstName: 'Juan David',
  lastName: 'Nicholls',
  jobTitle: 'Full-Stack Developer, Open Source Contributor',
  city: 'Medellin',
  postalCode: '',
  country: 'Colombia',
  phone: '+573113101122',
  email: 'jdnichollsc@hotmail.com',
  education: [
    {
      school: 'Universidad de Medellín',
      degree: 'Bachelor',
      graduationDate: '2016',
      description: 'Software Engineering'
    }
  ],
  links: [
    {
      label: 'GitHub/Profile',
      link: 'https://bio.link/jdnichollsc'
    },
    {
      label: 'LinkedIn',
      link: 'https://linkedin.com/in/jdnichollsc'
    }
  ],
  skills: [
    // Languages
    'C#',
    'JavaScript/TypeScript',
    'Python',
    // Frontend Frameworks
    'Angular',
    'Ionic/Capacitor',
    'NativeScript',
    'Phaser/PixiJS',
    'ReactJS/RemixJS/NextJS',
    'React Native',
    // Backend Frameworks
    'ASP.NET (MVC/WebAPI)',
    'NodeJS/NestJS',
    // Databases
    'MySQL/PostgreSQL',
    'NoSQL/MongoDB',
    // Technologies/Other Skills
    'Azure/GCP',
    'Blockchain (EVM/Solana)',
    'Expo',
    'Firebase',
    'Microservices',
    'Solidity',
    'Solana',
    'Temporal',
    'Unity',
  ],
  languages: ['English', 'Spanish'],
  professionalSummary: `Full-Stack Developer and Open Source Contributor with over 12 years of expertise in web, mobile, game and blockchain development. Skilled in building scalable architectures, seamless user experiences and driving innovation through Open Source. Proven ability to deliver impactful solutions across industries such as Digital Media, Aviation, Fintech, Healthcare, Delivery, Energy, Retail, E-commerce, Luxury Goods, Blockchain and Information technology.`,
  employmentHistory: [
    {
      jobTitle: 'Founding Full-Stack Web3 Engineer',
      startDate: 'May 2022',
      endDate: 'Nov 2024',
      employer: 'BAXUS',
      city: 'Remote',
      achievements: [
        'Architected the BAXUS marketplace, designing frontend (React/RemixJS) and backend (Node.js/NestJS) monorepos, integrating Solana and Temporal Workflows to support 140k+ users, achieving a 50% increase in conversion rates and boosting user retention by 30%.',
        'Developed key features for the mobile app (React Native), including bottle creation, barcode scanning, and enhanced search, improving user satisfaction by 25% through app store reviews.',
        'Created dApp templates with Angular, NgRx/Signals, Solana, TailwindCSS, etc.'
      ]
    },
    {
      jobTitle: 'Tech Lead / Full-Stack Developer',
      startDate: 'May 2021',
      endDate: 'May 2022',
      employer: 'Zagalabs',
      city: 'Remote',
      achievements: [
        'Led the engineering effort to refactor Angular/NgRx/Ionic codebases, improving reusability across web and mobile platforms, while delivering new features that enhanced UX and functionality',
        'Developed microservices with NestJS/Kafka, improving communication with third-party providers like Uber Eats.'
      ]
    },
    {
      jobTitle: 'Front-End Developer / Tech Lead',
      startDate: 'Mar 2017',
      endDate: 'Apr 2021',
      employer: 'BevyUp (Acquired by Nordstrom) - S4N',
      city: 'Remote',
      achievements: [
        'Led a team of 5 engineers to develop a modular mobile app with React Native and NodeJS, generating over $4M in sales during Nordstrom’s special events through improved performance and UX.',
        'Migrated the mobile stack from Angular/Ionic to React Native (UX).'
      ]
    },
    {
      jobTitle: 'Consultant / Software Architect',
      startDate: 'Nov 2016',
      endDate: 'Mar 2017',
      employer: 'MVM Ingeniería de software',
      city: 'Medellín/Colombia',
      achievements: [
        'Led the design of MVM’s reactive app architecture, leveraging MeteorJS/GraphQL to accelerate prototyping and product delivery in collaboration with the architecture team.',
        'Implemented cloud services (Azure Functions, CI/CD pipelines) for new apps.'
      ]
    },
    {
      jobTitle: 'Senior Developer / Tech Lead',
      startDate: 'Oct 2014',
      endDate: 'Nov 2016',
      employer: 'Yuxi Global',
      city: 'Medellín/Colombia',
      achievements: [
        'Defined the baseline for cross-platform mobile development, enabling the company to become an Ionic Trusted Partner, and developed a course on JavaScript Patterns to enhance company expertise.',
        'Mentored engineers about JavaScript/Ionic/Angular/NodeJS, fostering self-confidence, technical growth, and soft skills through delegation and guidance.'
      ]
    },
    {
      jobTitle: 'Semi-Senior Analyst Developer',
      startDate: 'Feb 2014',
      endDate: 'Jun 2014',
      employer: 'Aerolínea de Antioquia',
      city: 'Medellín/Colombia',
      achievements: [
        `Enhanced the company’s web portal by collaborating with the design team, researching ASP.NET-based CMS platforms to guide migration decisions and training developers in ALM methodologies.`
      ]
    },
    {
      jobTitle: 'Software Developer',
      startDate: 'Jul 2012',
      endDate: 'Jan 2014',
      employer: 'Pacifica Diseño',
      city: 'Medellín/Colombia',
      achievements: [
        'Led the migration of ASP.NET WebForms apps to MVC, optimizing legacy systems and maintaining the in-house CMS to reduce development time by 30% for client platforms and streamline social media app delivery.',
      ]
    }
  ],
  photo: 'https://s3.eu-west-1.amazonaws.com/resumedone-eu-west-1/AxajI58Ph-photo.png',
}

const formatResume = (r) => ({
  ...r,
  address: [
    r.country,
    r.city,
    r.postalCode
  ].filter(Boolean).join(', ')
})

new Vue({
  el: "#app",
  data: formatResume(resume)
});

/**
 * Wait for animatable-component to be loaded (Only for VanillaJS)
 **/
function animatableLoaded() {
  document.querySelector('body').classList.remove('d-none');
}
if (customElements) {
  customElements.whenDefined('animatable-component').then(animatableLoaded);
} else animatableLoaded()
              
            
!
999px

Console