React.js / Next.js and Vue.js / Nuxt.js Syntax Comparison Side by Side
Tags: react, nextjs, vue, nuxt
Published: 2020-04-19 00:31:57

<blockquote>
React.js and Vue.js are both great frameworks. And Next.js and Nuxt.js even bring them to the next level, which helps us to create the application with less configuration and better maintainability. But if you have to switch between those to frameworks frequently. You might easily forget the syntax in another framework after diving into the other one. In this article, I summarize the basic syntax and scenarios for those frameworks and list then side by side. I hope this can help us catch up with the syntax as soon as possible. 
</blockquote>

{% github oahehc/react-vue-comparison no-readme %}

## Agenda
  * React.js vs Vue.js
    * [Render](#render)
    * [Basic-Component](#basic-component)
    * [Prop](#prop)
    * [Event-Binding](#event-binding)
    * [Custom-Event](#custom-event)
    * [State](#state)
    * [Change-State](#change-state)
    * [Two-Way-Binding(Vue.js only)](#two-way-binding)
    * [Compute](#compute)
    * [Watch](#watch)
    * [Children-and-Slot](#children-and-slot)
    * [Render-HTML](#render-html)
    * [Conditional-Rendering](#conditional-rendering)
    * [List-Rendering](#list-rendering)
    * [Render-Props](#render-props)
    * [Lifecycle](#lifecycle)
    * [Error-Handling](#error-handling)
    * [Ref](#ref)
    * [Performance-Optimization](#performance-optimization)
  * Next.js vs Nuxt.js
    * [Assets](#assets)
    * [Basic-Routes](#basic-routes)
    * [Dynamic-Routes](#dynamic-routes)
    * [Link](#link)
    * [Fetch-On-Server](#fetch-on-server)
    * [Layout](#layout)
    * [Error-Page](#error-page)
    * [Meta-Tag](#meta-tag)
    * [Context](#context)
  * Tools
    * [CLI](#cli)


---

### Render <a name="render"></a>

#### React.js

```javascript
ReactDOM.render(<App />, document.getElementById("root"));
```

#### Vue.js

```javascript
new Vue({
  render: (h) => h(App),
}).$mount("#root");
```

### Basic-Component <a name="basic-component">

#### React.js

* Class component

```javascript
class MyReactComponent extends React.Component {
  render() {
    return <h1>Hello world</h1>;
  }
}
```

* Function component

```javascript
function MyReactComponent() {
  return <h1>Hello world</h1>;
}
```

#### Vue.js

```html
<template>
  <h1>Hello World</h1>
</template>
<script>
  export default {
    name: "MyVueComponent",
  };
</script>
```

### Prop <a name="prop">

#### React.js

```javascript
function MyReactComponent(props) {
  const { name, mark } = props;

  return <h1>Hello {name}{mark}</h1>;
}

MyReactComponent.propTypes = {
  name: PropTypes.string.isRequired,
  mark: PropTypes.string,
}
MyReactComponent.defaultProps = {
  mark: '!',
}
...

<MyReactComponent name="world">
```

#### Vue.js

```html
<template>
  <h1>Hello {{ name }}</h1>
</template>
<script>
  export default {
    name: "MyVueComponent",
    props: {
      name: {
        type: String,
        required: true,
      },
      mark: {
        type: String,
        default: "!",
      },
    },
  };
</script>

...

<MyVueComponent name="World" />
```

### Event-Binding <a name="event-binding">

#### React.js

* Class component

```javascript
class MyReactComponent extends React.Component {
  save = () => {
    console.log("save");
  };

  render() {
    return <button onClick={this.save}>Save</button>;
  }
}
```

* Function component

```javascript
function MyReactComponent() {
  const save = () => {
    console.log("save");
  };

  return <button onClick={save}>Save</button>;
}
```

#### Vue.js

```html
<template>
  <button @click="save()">Save</button>
</template>
<script>
  export default {
    methods: {
      save() {
        console.log("save");
      },
    },
  };
</script>
```

### Custom-Event <a name="custom-event">

#### React.js

```javascript
function MyItem({ item, handleDelete }) {
  return <button onClick={() => handleDelete(item)}>{item.name}</button>;

  /*
   * Apply useCallback hook to prevent generate new function every rendering.
   *
   * const handleClick = useCallback(() => handleDelete(item), [item, handleDelete]);
   *
   * return <button onClick={handleClick}>{item.name}</button>;
  */
}

...

function App() {
  const handleDelete = () => { ... }

  return <MyItem item={...} handleDelete={handleDelete} />
}

```

#### Vue.js

```html
<template>
  <button @click="deleteItem()">{{item.name}}</button>
</template>
<script>
  export default {
    name: "my-item",
    props: {
      item: Object,
    },
    methods: {
      deleteItem() {
        this.$emit("delete", this.item);
      },
    },
  };
</script>

...

<template>
  <MyItem :item="item" @delete="handleDelete" />
</template>
<script>
  export default {
    components: {
      MyItem,
    },
    methods: {
      handleDelete(item) { ... }
    },
  };
</script>
```

### State <a name="state">

#### React.js

* Class component

```javascript
class MyReactComponent extends React.Component {
  state = {
    name: 'world,
  }
  render() {
    return <h1>Hello { this.state.name }</h1>;
  }
}
```

* Function component

```javascript
function MyReactComponent() {
  const [name, setName] = useState("world");

  return <h1>Hello {name}</h1>;
}
```

#### Vue.js

```html
<template>
  <h1>Hello {{ name }}</h1>
  <!-- use component state as prop -->
  <my-vue-component :name="name">
</template>
<script>
  export default {
    data() {
      return { name: "world" };
    },
  };
</script>
```

### Change-State <a name="change-state">

#### React.js

* Class component

```javascript
class MyReactComponent extends React.Component {
  state = {
    count: 0,
  };

  increaseCount = () => {
    this.setState({ count: this.state.count + 1 });
    // get current state before update to make sure we didn't use the stale value
    // this.setState(currentState => ({ count: currentState.count + 1 }));
  };

  render() {
    return (
      <div>
        <span>{this.state.count}</span>
        <button onClick={this.increaseCount}>Add</button>
      </div>
    );
  }
}
```

* Function component

```javascript
function MyReactComponent() {
  const [count, setCount] = useState(0);

  const increaseCount = () => {
    setCount(count + 1);
    // setCount(currentCount => currentCount + 1);
  };

  return (
    <div>
      <span>{count}</span>
      <button onClick={increaseCount}>Add</button>
    </div>
  );
}
```

#### Vue.js

```html
<template>
  <div>
    <span>{{count}}</span>
    <button @click="increaseCount()">Add</button>
  </div>
</template>
<script>
  export default {
    data() {
      return { count: 0 };
    },
    methods: {
      increaseCount() {
        this.count = this.count + 1;
      },
    },
  };
</script>
```

### Two-Way-Binding(Vue.js only) <a name="two-way-binding">

#### React.js

_React didn't have two-way binding, so we need to handle the data flow on our own_

```javascript
function MyReactComponent() {
  const [content, setContent] = useState("");

  return (
    <input
      type="text"
      value={content}
      onChange={(e) => setContent(e.target.value)}
    />
  );
}
```

#### Vue.js

```html
<template>
  <input type="text" v-model="content" />
</template>
<script>
  export default {
    data() {
      return { content: "" };
    },
  };
</script>
```

### Compute <a name="compute">

#### React.js

_React.js don't have `compute` property, but we can achieve this through react hook easily_

```javascript
function DisplayName({ firstName, lastName }) {
  const displayName = useMemo(() => {
    return `${firstName} ${lastName}`;
  }, [firstName, lastName]);

  return <div>{displayName}</div>;
}

...

<DisplayName firstName="Hello" lastName="World" />
```

#### Vue.js

```html
<template>
  <div>{{displayName}}</div>
</template>
<script>
  export default {
    name: "display-name",
    props: {
      firstName: String,
      lastName: String,
    },
    computed: {
      displayName: function () {
        return `${this.firstName} ${this.lastName}`;
      },
    },
  };
</script>

...

<DisplayName firstName="Hello" lastName="World" />
```

### Watch <a name="watch">

_React.js don't have `watch` property, but we can achieve this through react hook easily_

```javascript
function MyReactComponent() {
  const [count, setCount] = useState(0);

  const increaseCount = () => {
    setCount((currentCount) => currentCount + 1);
  };

  useEffect(() => {
    localStorage.setItem("my_count", newCount);
  }, [count]);

  return (
    <div>
      <span>{count}</span>
      <button onClick={increaseCount}>Add</button>
    </div>
  );
}
```

#### Vue.js

```html
<template>
  <div>
    <span>{{count}}</span>
    <button @click="increaseCount()">Add</button>
  </div>
</template>
<script>
  export default {
    data() {
      return { count: 0 };
    },
    methods: {
      increaseCount() {
        this.count = this.count + 1;
      },
    },
    watch: {
      count: function (newCount, oldCount) {
        localStorage.setItem("my_count", newCount);
      },
    },
  };
</script>
```

### Children-and-Slot <a name="children-and-slot">

#### React.js

```javascript
function MyReactComponent({ children }) {
  return <div>{children}</div>;
}

...

<MyReactComponent>Hello World</MyReactComponent>
```

#### Vue.js

```html
<template>
  <div>
    <slot />
  </div>
</template>
<script>
  export default {
    name: "my-vue-component",
  };
</script>

...

<MyVueComponent>Hello World</MyVueComponent>
```

### Render-HTML <a name="render-html">

#### React.js

```javascript
function MyReactComponent() {
  return <div dangerouslySetInnerHTML={{ __html: "<pre>...</pre>" }} />;
}
```

#### Vue.js

```html
<template>
  <div v-html="html"></div>
</template>
<script>
  export default {
    data() {
      return {
        html: "<pre>...</pre>",
      };
    },
  };
</script>
```

### Conditional-Rendering <a name="conditional-rendering">

#### React.js

```javascript
function MyReactComponent() {
  const [isLoading, setLoading] = useState(true);

  return (
    <div>
      {isLoading && <span>Loading...</span>}
      {isLoading ? <div>is loading</div> : <div>is loaded</div>}
    </div>
  );
}
```

#### Vue.js

```html
<template>
  <div>
    <!--v-show: always render but change css base on the condition-->
    <span v-show="loading">Loading...</span>
    <div>
      <div v-if="loading">is loading</div>
      <div v-else>is loaded</div>
    </div>
  </div>
</template>
<script>
  export default {
    data() {
      return { loading: true };
    },
  };
</script>
```

### List-Rendering <a name="list-rendering">

#### React.js

```javascript
function MyReactComponent({ items }) {
  return (
    <ul>
      {items.map((item) => (
        <li key={item.id}>
          {item.name}: {item.desc}
        </li>
      ))}
    </ul>
  );
}
```

#### Vue.js

```html
<template>
  <ul>
    <li v-for="item in items" :key="item.id">
      {{item.name}}: {{item.desc}}
    </li>
  </ul>
</template>
<script>
  export default {
    props: {
      items: Array,
    },
  };
</script>
```

### Render-Props <a name="render-props">

#### React.js

```javascript
function Modal({children, isOpen}) {
  const [isModalOpen, toggleModalOpen] = useState(isOpen);

  return (
    <div className={isModalOpen ? 'open' : 'close'}>
      {type children === 'function' ? children(toggleModalOpen) : children}
    </div>)
  ;
}

Modal.propTypes = {
  isOpen: PropTypes.bool,
  children: PropTypes.oneOfType([PropTypes.string, PropTypes.element]).isRequired,
}
Modal.defaultProps = {
  isOpen: false,
}

...

<Modal isOpen>
  {(toggleModalOpen) => {
    <div>
      <div>...</div>
      <button onClick={() => toggleModalOpen(false)}>Cancel</button>
    </div>
  }}
</Modal>
```

#### Vue.js (slot)

```html
<template>
  <div v-show="isModalOpen">
    <slot v-bind:toggleModal="toggleModalOpen" />
  </div>
</template>
<script>
  export default {
    name: "modal",
    props: {
      isOpen: {
        type: Boolean,
        default: false,
      },
    },
    data() {
      return {
        isModalOpen: this.isOpen,
      };
    },
    methods: {
      toggleModalOpen(state) {
        this.isModalOpen = state;
      },
    },
  };
</script>

...

<Modal isOpen>
  <template v-slot="slotProps">
    <div>...</div>
    <button @click="slotProps.toggleModal(false)">Close</button>
  </template>
</Modal>
```

### Lifecycle <a name="lifecycle">

#### React.js

http://projects.wojtekmaj.pl/react-lifecycle-methods-diagram/

* Class component

```javascript
class MyReactComponent extends React.Component {
  static getDerivedStateFromProps(props, state) {}
  componentDidMount() {}
  shouldComponentUpdate(nextProps, nextState) {}
  getSnapshotBeforeUpdate(prevProps, prevState) {}
  componentDidUpdate(prevProps, prevState) {}
  componentWillUnmount() {}

  render() {
    return <div>Hello World</div>;
  }
}
```

* Function component

```javascript
function MyReactComponent() {
  // componentDidMount
  useEffect(() => {}, []);


  // componentDidUpdate + componentDidMount
  useEffect(() => {});

  // componentWillUnmount
  useEffect(() => {
    return () => {...}
  }, []);

  // runs synchronously after a render but before the screen is updated
  useLayoutEffect(() => {}, []);

  return <div>Hello World</div>;
}
```

#### Vue.js

- https://vuejs.org/v2/guide/instance.html#Lifecycle-Diagram

```html
<template>
  <div>Hello World</div>
</template>
<script>
  export default {
    beforeCreate() {},
    created() {},
    beforeMount() {},
    mounted() {},
    beforeUpdate() {},
    updated() {},
    beforeDestroy() {},
    destroyed() {},
  };
</script>
```

### Error-Handling <a name="error-handling">

#### React.js

```javascript
class ErrorBoundary extends React.Component {
  state = { hasError: false };

  static getDerivedStateFromError(error) {
    // Update state so the next render will show the fallback UI.
    return { hasError: true };
  }

  componentDidCatch(error, errorInfo) {}

  render() {
    if (this.state.hasError) return <h1>Something went wrong.</h1>;
    return this.props.children;
  }
}

...

<ErrorBoundary>
  <App />
</ErrorBoundary>
```

#### Vue.js

```javascript
const vm = new Vue({
  data: {
    error: "",
  },
  errorCaptured: function(err, component, details) {
    error = err.toString();
  }
}
```

### Ref <a name="ref">

#### React.js

* Class component

```javascript
class AutofocusInput extends React.Component {
  constructor(props) {
    super(props);
    this.ref = React.createRef();
  }

  state = {
    content: "",
  };

  componentDidMount() {
    this.ref.current.focus();
  }

  setContent = (e) => {
    this.setState({ content: e.target.value });
  };

  render() {
    return (
      <input
        ref={this.ref}
        type="text"
        value={this.state.content}
        onChange={this.setContent}
      />
    );
  }
}
```

* Function component

```javascript
function AutofocusInput() {
  const [content, setContent] = useState("");
  const ref = useRef(null);

  useEffect(() => {
    if (ref && ref.current) {
      ref.current.focus();
    }
  }, []);

  return (
    <input
      ref={ref}
      type="text"
      value={content}
      onChange={(e) => setContent(e.target.value)}
    />
  );
}
```

#### Vue.js

```html
<template>
  <input ref="input" type="text" v-model="content" />
</template>
<script>
  export default {
    name: "autofocus-input",
    data() {
      return { content: "" };
    },
    mounted() {
      this.$refs.input.focus();
    },
  };
</script>
```

### Performance-Optimization <a name="performance-optimization">

#### React.js

* PureComponent

```javascript
class MyReactComponent extends React.PureComponent {
  ...
}
```

* shouldComponentUpdate

```javascript
class MyReactComponent extends React.Component {
  shouldComponentUpdate(nextProps) {...}

  ...
}
```

* React.memo

```javascript
export default React.memo(
  MyReactComponent,
  (prevProps, nextProps) => {
    ...
  }
);
```

* useMemo

```javascript
export default function MyReactComponent() {
  return React.useMemo(() => {
    return <div>...</div>;
  }, []);
}
```

* useCallback

```javascript
function MyItem({ item, handleDelete }) {
  const handleClick = useCallback(() => handleDelete(item), [
    item,
    handleDelete,
  ]);

  return <button onClick={handleClick}>{item.name}</button>;
}
```

#### Vue.js

* v:once

```html
<span v-once>This will never change: {{msg}}</span>
```

* functional component

https://vuejs.org/v2/guide/render-function.html#Functional-Components

```html
<template functional>
  <h1>Hello {{ name }}</h1>
</template>
<script>
  export default {
    name: "MyVueComponent",
    props: {
      name: String,
    },
  };
</script>
```

* keep-alive component

https://vuejs.org/v2/api/#keep-alives

```html
<keep-alive>
  <component :is="view"></component>
</keep-alive>
```

---

### Assets <a name="assets">

#### Next.js

```js
/*
|- public/
|-- my-image.png
*/
function MyImage() {
  return <img src="/my-image.png" alt="my image" />;
}
```

#### Nuxt.js

* assets

_By default, Nuxt uses vue-loader, file-loader and url-loader for strong assets serving._

```html
<!--
|- assets/
  |- image.png
-->
<img src="~/assets/image.png" alt="image" />
```

* static

_automatically served_

```html
<!--
|- static/
  |- image.png
-->
<img src="/image.png" alt="image" />
```

### Basic-Routes <a name="basic-routes">

#### Next.js

```
|- pages/
  |- index.js        → href="/"
  |- blog/index.js   → href="/blog"
```

#### Nuxt.js

```
|- pages/
  |- index.vue       → href="/"
  |- blog/index.vue  → href="/blog"
```

### Dynamic-Routes <a name="dynamic-routes">

#### Next.js

```
|- pages/
  |- blog/[slug].js           → href="/blog/:slug" (eg. /blog/hello-world)
  |- [username]/[option].js   → href="/:username/:option" (eg. /foo/settings)
  |- post/[...all].js         → href="/post/*" (eg. /post/2020/id/title)
```

#### Nuxt.js

```
|- pages/
  |- blog/[slug].vue         → href="/blog/:slug" (eg. /blog/hello-world)
  |- _username/_option.vue   → href="/:username/:option" (eg. /foo/settings)
```

### Link <a name="link">

#### Next.js

```js
import Link from "next/link";

function Home() {
  return (
    <Link href="/">
      <a>Home</a>
    </Link>
  );
}
```

#### Nuxt.js

```html
<template>
  <nuxt-link to="/">Home page</nuxt-link>
</template>
```

### Fetch-On-Server <a name="fetch-on-server">

#### Next.js

_getInitialProps can only be used in the default export of every page_

* < Next.js 9.3 (class component)

```js
import fetch from "isomorphic-unfetch";

export default class Page extends React.Component {
  static async getInitialProps(ctx) {
    const res = await fetch(`https://.../data`);
    const data = await res.json();

    return { props: { data } };
  }

  render() {
    // Render data...
  }
}
```

* < Next.js 9.3 (function component)

```js
import fetch from "isomorphic-unfetch";

function Page({ data }) {
  // Render data...
}

Page.getInitialProps = async (ctx) => {
  const res = await fetch(`https://.../data`);
  const data = await res.json();

  return { props: { data } };
};
```

* >= Next.js 9.3

```js
import fetch from "isomorphic-unfetch";

function Page({ data }) {
  // Render data...
}

export async function getServerSideProps() {
  const res = await fetch(`https://.../data`);
  const data = await res.json();

  return { props: { data } };
}

export default Page;
```

#### Nuxt.js

```html
<template>
  <div v-if="$fetchState.error">Something went wrong 😭</div>
  <div v-if="$fetchState.pending">Loading...</div>
  <div v-else>
    <h1>{{ post.title }}</h1>
    <pre>{{ post.body }}</pre>
    <button @click="$fetch">Refresh</button>
  </div>
</template>

<script>
  import fetch from "node-fetch";

  export default {
    data() {
      return {
        post: {},
      };
    },
    async fetch() {
      this.post = await this.$http.$get("xxx");
    },
    fetchOnServer: true,
  };
</script>
```

### Layout <a name="layout">

#### Next.js

`./pages/_app.js`: automatically apply to all pages

```js
export default function MyApp({ Component, pageProps }) {
  return (
    <React.Fragment>
      <MyHeader />
      <Component {...pageProps} />
      <MyFooter />
    </React.Fragment>
  );
}
```

#### Nuxt.js

`layouts/with-header-footer.vue`: create layout

```html
<template>
  <div>
    <MyHeader />
    <nuxt />
    <MyFooter />
  </div>
</template>
```

`pages/index.vue`: apply layout

```html
<template>
  <!-- Your template -->
</template>
<script>
  export default {
    layout: "with-header-footer",
  };
</script>
```

### Error-Page <a name="error-page">

#### Next.js

`pages/_error.js`

```js
function Error({ statusCode }) {
  return (
    <p>
      {statusCode
        ? `An error ${statusCode} occurred on server`
        : "An error occurred on client"}
    </p>
  );
}

Error.getInitialProps = ({ res, err }) => {
  const statusCode = res ? res.statusCode : err ? err.statusCode : 404;
  return { statusCode };
};

export default Error;
```

#### Nuxt.js

`layouts/error.vue`

```html
<template>
  <div class="container">
    <h1 v-if="error.statusCode === 404">Page not found</h1>
    <h1 v-else>An error occurred</h1>
    <nuxt-link to="/">Home page</nuxt-link>
  </div>
</template>

<script>
  export default {
    props: ["error"],
    layout: "blog", // you can set a custom layout for the error page
  };
</script>
```

### Meta-Tag <a name="meta-tag">

#### Next.js

```js
import Head from "next/head";

function IndexPage() {
  return (
    <div>
      <Head>
        <title>My page title</title>
        <meta name="viewport" content="initial-scale=1.0, width=device-width" />
      </Head>
      <p>Hello world!</p>
    </div>
  );
}
```

#### Nuxt.js

```html
<template>
  <h1>{{ title }}</h1>
</template>

<script>
  export default {
    data() {
      return {
        title: "Hello World!",
      };
    },
    head() {
      return {
        title: this.title,
        meta: [
          // To avoid duplicated meta tags when used in child component, set up an unique identifier with the hid key
          {
            hid: "description",
            name: "description",
            content: "My custom description",
          },
        ],
      };
    },
  };
</script>
```

### Context <a name="context">

#### Next.js

_getInitialProps can only be used in the default export of every page_

```js
function Page({ data }) {
  // Render data...
}

Page.getInitialProps = async (context) => {
  const { pathname, query, asPath, req, res, err } = context;
  // pathname - Current route. That is the path of the page in /pages
  // query - Query string section of URL parsed as an object
  // asPath - String of the actual path (including the query) shown in the browser
  // req - HTTP request object (server only)
  // res - HTTP response object (server only)
  // err - Error object if any error is encountered during the rendering

  return { props: { project: "next" } };
};
```

#### Nuxt.js

```js
export default {
  asyncData(context) {
    // Universal keys
    const {
      app,
      store,
      route,
      params,
      query,
      env,
      isDev,
      isHMR,
      redirect,
      error,
    } = context;
    // Server-side
    if (process.server) {
      const { req, res, beforeNuxtRender } = context;
    }
    // Client-side
    if (process.client) {
      const { from, nuxtState } = context;
    }

    return { project: "nuxt" };
  },
};
```

---

### CLI <a name"cli"></a>

#### React.js: create-react-app

```zsh
npx create-react-app react-template
```

#### Next.js: create-next-app

```zsh
npx create-next-app next-template
```

#### Vue.js: vue-cli

```zsh
yarn global add @vue/cli
vue create vue-template
```

#### Nuxt.js: create-nuxt-app

```zsh
npx create-nuxt-app nuxt-template
```

---

## Reference
  * [React.js](https://reactjs.org/docs/getting-started.html)
  * [Next.js](https://nextjs.org/docs/getting-started)
  * [Vue.js](https://vuejs.org/v2/guide/#Getting-Started)
  * [Nuxt.js](https://nuxtjs.org/guide/installation)
  * [Vue and React Side by Side](https://medium.com/myriatek/vue-and-react-side-by-side-55d02b9fb222)
  * [I created the exact same app in React and Vue. Here are the differences](https://medium.com/javascript-in-plain-english/i-created-the-exact-same-app-in-react-and-vue-here-are-the-differences-2019-edition-42ba2cab9e56)
  * [Few Tips to Optimizing Performance of React Project](https://dev.to/oahehc/few-tips-to-optimizing-performance-of-react-project-5h25)
  * [5 Extremely Easy ways to drastically improve your VueJS app’s speed](https://dev.to/veebuv/5-extremely-easy-ways-to-drastically-improve-your-vuejs-app-s-speed-5k0)
  * [create-react-app](https://create-react-app.dev/docs/getting-started/)
  * [create-next-app](https://nextjs.org/blog/create-next-app)
  * [vue-cli](https://cli.vuejs.org/)
  * [create-nuxt-app](https://github.com/nuxt/create-nuxt-app)