JAMstack Netlify Workshop

Deploys

simple-html-drop directory in the repo

In the dashboard > Deploys

update here

Let's create a Nuxt site!

And set up CI/CD and deploy

start with install:

$ yarn create nuxt-app <project-name>

Locked Deploys

Deploy sensitive material

Locked Deploys

Deploy sensitive material

Split Testing

Using branched deploys

Nuxt demo

Snippet Injection

ga('send', 'pageview', {
  'Branch': '{{ BRANCH }}'
});

Add to Google Analytics

<!-- Google Analytics -->
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','https://www.google-analytics.com/analytics.js','ga');

ga('create', 'UA-XXXXX-Y', 'auto');
ga('send', 'pageview');
</script>
<!-- End Google Analytics -->

Add to Google Analytics

<!-- Google Analytics -->
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','https://www.google-analytics.com/analytics.js','ga');

ga('create', 'UA-XXXXX-Y', 'auto');
ga('send', 'pageview', {
  'Branch': '{{ BRANCH }}'
});
</script>
<!-- End Google Analytics -->

Add to Google Analytics

Why is this JAMstack?

Served from CDN,
deployed to closest datacenter

What does pre-built mean?

Is this Serverless?

Exercises!

Build a basic site with Nuxt with multiple pages, set it up on github, and deploy! πŸš€

start with global install:

$ yarn create nuxt-app <project-name>

Then, make two branches,

and set up split testing

Forms!

Simple Forms!

<form name="contact" method="POST">
  <p>
    <label>Your Name: <input type="text" name="name" /></label>   
  </p>
  <p>
    <label>Your Email: <input type="email" name="email" /></label>
  </p>
  <p>
    <label>Message: <textarea name="message"></textarea></label>
  </p>
  <p>
    <button type="submit">Send</button>
  </p>
</form>
<form name="contact" method="POST" data-netlify="true">
  <p>
    <label>Your Name: <input type="text" name="name" /></label>   
  </p>
  <p>
    <label>Your Email: <input type="email" name="email" /></label>
  </p>
  <p>
    <label>Message: <textarea name="message"></textarea></label>
  </p>
  <p>
    <button type="submit">Send</button>
  </p>
</form>

πŸŽ‰

<form name="contact" method="POST" data-netlify="true" netlify-honeypot="bot-field">
  <p class="hidden">
    <label>Don’t fill this out if you're human: 
      <input name="bot-field" />
    </label>
  </p>
  <p>
    <label>Your Name: 
      <input type="text" name="name" />
    </label>   
  </p>
  <p>
    <label>Your Email: 
      <input type="email" name="email" />
    </label>
  </p>
  <p>
    <label>Message: 
      <textarea name="message"></textarea>
    </label>
  </p>
  <p>
    <button type="submit">Send</button>
  </p>
</form>
.hidden { visibility: hidden; }
data () {
  return {
    uiState: 'idle',
    form: {
      name: '',
      email: '',
      message: ''
    }
  }
}
  methods: {
    async handleSubmit() {
      this.uiState = "submit clicked";

      try {
        await fetch("/", {
          method: "POST",
          headers: { "Content-Type": "application/x-www-form-urlencoded" },
          body: this.encode({ "form-name": "contact", ...this.form })
        })
        .then(console.log("went through"))
        .then($nuxt._router.push("/thankyou"))
      }
      catch(error => console.log(error));

      this.uiState = "form submitted";
    }
  }

Exercise!

Put in a form, and make it work! πŸš€

Β 

suggestion: make it work in a very plain way first, and then the "Vue" way.

Dynamic Routing

Vuex store, data from mockaroo

import data from '~/static/storedata.json'

export const state = () => ({
 cartUIStatus: 'idle',
 storedata: data,
 cart: []
})

Data looks like this

[
 {
   "id": "9d436e98-1dc9-4f21-9587-76d4c0255e33",
   "color": "Goldenrod",
   "description": "Mauris enim leo, rhoncus sed, vestibulum sit amet, cursus id, turpis. Integer aliquet, massa id lobortis convallis, tortor risus dapibus augue, vel accumsan tellus nisi eu orci. Mauris lacinia sapien quis libero.",
   "gender": "Male",
   "name": "Desi Ada",
   "review": "productize virtual markets",
   "starrating": 3,
   "price": 50.40,
   "img": "1.jpg"
 },
  …
]

In pages/products/_id.vue

data() {
 return {
   id: this.$route.params.id
  }
},

Would return:

id: "9d436e98-1dc9-4f21-9587-76d4c0255e33"

Retrieve the entry from the store using mapState and filter

import { mapState } from "vuex";

computed: {
 ...mapState(["storedata"]),
 product() {
   return this.storedata.find(el => el.id === this.id);
 }
},

Let nuxt.config.js know

This is what it wants,

but we don't have that

export default {
  generate: {
    routes: [
      '/product/1',
      '/product/2',
      '/product/3'
    ]
  }
}

So we make a function:

import data from './static/storedata.json'

let dynamicRoutes = () => {
 return new Promise(resolve => {
   resolve(data.map(el => `product/${el.id}`))
 })
}

And call it in the config:

generate: {
  routes: dynamicRoutes
}

Another example with axios

import axios from 'axios'

let dynamicRoutes = () => {
 return axios.get('https://your-api-here/products').then(res => {
   return res.data.map(product => `/product/${product.id}`)
 })
}

Exercise!

Take the base-jamstack-sample in the repo, and make it your own, deploy and change the sitename πŸŽ‰

Β 

Make the contact form work, and try to call the github API to populate a projects page.

Exercises!

Build a basic site with Nuxt with multiple pages, set it up on github, and deploy! πŸš€

Now, take the base-jamstack-sample in the repo, and make it your own, deploy and change the sitename πŸŽ‰

start with global install:

$ yarn create nuxt-app <project-name>

Then, make two branches,

and set up split testing

JAMstack Netlify Workshop: Deploys

By sdrasner

JAMstack Netlify Workshop: Deploys

  • 134
Loading comments...

More from sdrasner