Vanilla 🍦SPA Parcel Starter
Published: 2020-12-05 19:19:15

# TLDR

Go to [the repo](https://github.com/manavm1990/parcel-starter)

![Use This Template](https://dev-to-uploads.s3.amazonaws.com/i/lmwln7ct043m363hzoqc.gif)

`clone`: [Template repo](https://github.com/manavm1990/parcel-starter)

`cd` into the `clone`d directory

`npm i`

`npm start` to fire up Parcel `localhost` server.

Write your code 👩🏾‍💻 🦄

# What's It All About?

[**Read the README**](https://github.com/manavm1990/parcel-starter/blob/master/README.md)

Summarily, if you are a newer dev, it can be distracting to set up tooling and linting and other 'dev tools 🧰' to have a reductive workflow.

This template is for writing a Vanilla SPA application (good to do as a prerequisite to React, Vue, etc.) using `"parcel-bundler"`. 

So, you can dive right in and have a set of 'battle-tested' tooling helping you learn and develop and be more reductive overall. 🤓

As you progress, you adjust the each and everything as you see fit. It grows/adapts with you. 🚀

It's helped hundreds of my previous 👨🏾‍🎓 in bootcamps 🏕️ and college  🏫 courses.

## VS Code Extensions & Settings

When you 🔥 this up in VS Code, you will be prompted in the bottom right to install some extensions. These are listed in the '.vscode' directory 📁.

**To take full advantage [dl and install 🪁](https://www.kite.com/).**

## Linting/Prettier for CSS & JS

It's using `extends: ["airbnb-base", "prettier"]`. ⚠️ `"airbnb"` linting is very strict! 😖 I _strongly_ encourage you to stick with it and research the linting 'mistakes' b4 just turning them off.

I've already adjusted a few for you:

```javascript
rules: {
    "array-callback-return": "warn",
    "import/extensions": "warn",
    "import/prefer-default-export": "warn",
    "no-plusplus": ["error", { allowForLoopAfterthoughts: true }],
    "no-unused-expressions": ["error", { allowShortCircuit: true }],
    "no-unused-vars": "warn",
  },
```

### [Prettier](https://prettier.io/)

There is some very basic `"prettier"` config stuff in other files, but we just use the default stuff for that one.

```json
"husky": {
    "hooks": {
      "pre-commit": "lint-staged"
    }
  },
  "lint-staged": {
    "*.js": "eslint --cache --fix",
    "*.css": "stylelint --fix",
    "*.{js,css,md}": "prettier --write"
  }
```

We have also activated 'pre-commit 🪝s.' This prevents `commit`ting of code that doesn't pass the linter. It also 'auto-formats' the code for consistent repo code.

### CSS

[Stylelint](https://stylelint.io/) also is riding along. CSS mistakes can be easy to make, and it can get sloppy. This will guide along the way and prevent some common [CSS specificity](https://developer.mozilla.org/en-US/docs/Web/CSS/Specificity) issues.

## Project Entry-Point 🎉

The entry point is: 'index.html'. À la React, we have a `root` that will wrap our _functional components,_ which will come from 'index.js.'

```html
 <!-- TODO: 'render' content here -->
    <div id="root"></div>
    <script src="./index.js"></script>
```

And, in 'index.js,'

```javascript
/**
 * TODO: Import some components
 * U might also need to import 'api' to get your initial data?
 */
import testComponent from "./components";

const root = document.getElementById("root");

const render = () => {
  root.innerHTML = testComponent();
};

// ⚠️ Don't 4get to actually render! 😆
render();

// TODO: Use api to 'fetch' 'initial data?' Maybe 'api.index()'?
```

## Modularity

Each of the other 'module' directories contain 'index.js' files and you can build in other files as needed from there. I've already included some comments and/or starter code in each one. We take a look at each briefly.  

### 'api/index.js'

```javascript
/**
 * TODO: All interactions with external data should be managed from here.
 * You probably need to 'import' stuff from 'db' if using a database.
 * Then you can create methods such as 'index,' 'create(payload),' etc.
 */
```

_As an example,_ this might turn into something like shown below. Specifically, this would apply very closely if you were using Firebase's Firestore for data management - that's not really important for what we are doing here.
The point is to maintain a separation of concerns/services. It's going to 'api's job to manage interacting with external sources.

```javascript
import db from "./db";

export default {
  async index() {
    const querySnapshot = await db.collection("students").get();

    return querySnapshot.docs.map((doc) => ({ id: doc.id, ...doc.data() }));
  },

  // More generically, the PARAMETER might be called 'payload'
  async create(student) {
    db.collection("students").add(student);
  },

  // TODO: Add addl. 'api methods' 👇🏾 if needed
};
```

### 'db'

This 🏠s your connection to an external database service. It is subsequently used by 'api' - in fact, this directory could be 🏠ed inside of 'api'...and in fact I am going to change that! 

Anyway, 'db/config.js' is for any configuration details that you might need to connect to your database. If these are supposed to be 'secret,' you should look into using a '.env,' or, even better, keep that on server-side.

'db/client.js' is for establishing and export whatever database clients are created using your configuration details.

Finally, as always...as always...'db/index.js' is there to simply `export` out whatever 'api' might need to use.

### 'components'

This is what initially renders, and is where most of your work will probably be done. As your app grows, you may even need a 'pages' directory 📁 and a 'layouts' directory 💦.

In this one, we see a simple example of a _functional component:_ `export { default as Main } from "./Main";`. It's nothing but a _function_ that _returns_ some HTML markup, in this case.

Again, this is really where you may end up with a lot of work 💦 depending on your app's needs. This directory could end up looking 👀 something like: ![Components Directory Structure Example](https://dev-to-uploads.s3.amazonaws.com/i/wscsh3sl6tc486b5xqsp.gif)

### 'lib'

This is where we might keep various 'utility functions' that our components might need to `import` to do their respective jobs.

### 'store'

This is to enforce a 'single source of truth' concerning the state of our data at any given time in our app. It's a 'data store' or 'data library.' I don't really like the name 'store,' but that's what the dev community says it is. As _Petey Pablo_ says, "Who am I?" 

There are many strategies for doing this, but I've included the following starter 🌱 code to do with as you see fit:

```javascript
export default {
  data: [],
  setData(newData) {
    // 'concat' is 'non-mutating'
    this.data = this.data.concat(newData);
  },
};
```

**Summarily, any part of your app that either wants to 'get' or 'set' data should do this via the 'store'** - a single source of truth. _This is the foundation upon which Redux/Vuex/Flux,_ etc. are based on.

## There's a Lot! 💦

Well, I hope this helps more than it hurts. There's a lot to consider...but just get started with this and grow into it. You don't **have to** use each part of this! Really, just rendering a few functional components is fine.

If you do want to see a somewhat simple example of making something with this, here's [a project repo](https://github.com/swic-cis-277/student-scores-in-class) of something we worked on in one of my college class.

---

Reach out if you need a bit more guidance. I have other template repos too for other stuff.

---

**Update:** For a more in-depth discussion, join [my GitHub discussion.](https://github.com/manavm1990/parcel-starter/discussions)