Skip to content

Commit

Permalink
feat: improve blog page and add scaffolding post
Browse files Browse the repository at this point in the history
  • Loading branch information
pablosirera committed Jun 28, 2020
1 parent 6a6fe68 commit 4bfa70c
Show file tree
Hide file tree
Showing 21 changed files with 279 additions and 16 deletions.
1 change: 1 addition & 0 deletions assets/css/main.css
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
@import url('./global.css');
@import url('./animations.css');
@import url('./variables.css');
@import url('./posts.css');
38 changes: 38 additions & 0 deletions assets/css/posts.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
article > .nuxt-content h2 {
margin-top: 30px;
margin-bottom: 10px;
font-size: 1.125rem;
font-weight: bold;
}

article > .nuxt-content .vue {
background-color: theme('colors.green-main.400');
color: white;
padding: 0 3px;
}

article > .nuxt-content .code {
background-color: theme('colors.blue-main.750');
color: theme('colors.gray-main.950');
padding: 0 3px;
}

article > .nuxt-content a {
/* TODO: integrate tailwind */
text-decoration: none;
color: #1f8ed5;
font-weight: bold;
opacity: 1;
border-bottom: solid 1px transparent;
-webkit-transition: opacity 0.2s ease-out, border-bottom-color 0.4s ease-out;
-moz-transition: opacity 0.2s ease-out, border-bottom-color 0.4s ease-out;
-ms-transition: opacity 0.2s ease-out, border-bottom-color 0.4s ease-out;
-o-transition: opacity 0.2s ease-out, border-bottom-color 0.4s ease-out;
transition: opacity 0.2s ease-out, border-bottom-color 0.4s ease-out;
}

article > .nuxt-content a:hover {
/* TODO: integrate tailwind */
opacity: 0.8;
border-bottom: solid 1px #1f8ed5;
}
33 changes: 33 additions & 0 deletions components/blog/CustomImage.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<template>
<span class="image">
<img v-bind="$attrs" loading="lazy" />
</span>
</template>

<script>
export default {
name: 'CustomImage',
}
</script>

<style scoped lang="scss">
/* TODO: integrate tailwind */
.image {
display: flex;
justify-content: center;
background-color: transparent;
width: 100%;
height: 100%;
margin: 0 auto;
margin-top: 20px;
margin-bottom: 30px;
img {
border-radius: 5px;
max-width: 100%;
box-shadow: rgba(0, 0, 0, 0.15) 0 32px 32px 0,
rgba(0, 0, 0, 0.15) 0 16px 16px 0, rgba(0, 0, 0, 0.15) 0 8px 8px 0,
rgba(0, 0, 0, 0.15) 0 4px 4px 0;
}
}
</style>
4 changes: 2 additions & 2 deletions components/ui/BlogCard.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
{{ title }}
</h1>
<div class="bottom-post">
<span class="date">{{ getDate(date) }}</span>
<span class="date">🗓 {{ getDate(date) }}</span>
<span class="clock-icon flex items-center">
<fa icon="clock" class="icon mr-1" />
{{ getTimeToReadText(timeToRead) }}
Expand Down Expand Up @@ -79,7 +79,7 @@ $mobile: var(--mobile);
transition: box-shadow 0.5s ease, transform 0.5s ease;
padding: 10px;
@apply flex flex-col cursor-pointer mb-4;
@apply flex flex-col cursor-pointer mb-4 border border-gray-main-300 rounded-md;
}
.post:hover {
Expand Down
77 changes: 77 additions & 0 deletions components/ui/CoffeeWidget.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
<template>
<div class="flex justify-center mt-8">
<a
class="coffee-button"
target="_blank"
href="https://www.buymeacoffee.com/VD4nJSu"
>
<img
src="https://cdn.buymeacoffee.com/buttons/bmc-new-btn-logo.svg"
alt="Invítame a un café"
/>
<span class="coffee-text">
<!-- TODO: integrate translations -->
Invítame a un café
</span>
</a>
</div>
</template>

<script>
export default {
name: 'CoffeeWidget',
}
</script>

<style lang="scss" scoped>
// TODO: integrate tailwind
.coffee-button {
line-height: 35px;
height: 51px;
min-width: 217px;
text-decoration: none;
display: inline-flex;
color: #fff;
background-color: #4fc08d;
border-radius: 5px;
border: 1px solid transparent;
padding: 7px 10px 7px 10px;
font-size: 28px;
letter-spacing: 0.6px;
box-shadow: 0 1px 2px rgba(190, 190, 190, 0.5);
-webkit-box-shadow: 0 1px 2px 2px rgba(190, 190, 190, 0.5);
margin: 0 auto;
font-family: 'Cookie', cursive;
-webkit-box-sizing: border-box;
box-sizing: border-box;
-o-transition: 0.3s all linear;
-webkit-transition: 0.3s all linear;
-moz-transition: 0.3s all linear;
-ms-transition: 0.3s all linear;
transition: 0.3s all linear;
img {
height: 34px;
width: 35px;
margin-bottom: 1px;
box-shadow: none;
border: none;
vertical-align: middle;
}
&:hover,
&:active,
&:focus {
-webkit-box-shadow: 0 1px 2px 2px rgba(190, 190, 190, 0.5);
text-decoration: none;
box-shadow: 0 1px 2px 2px rgba(190, 190, 190, 0.5);
opacity: 0.85;
color: #fff;
}
}
.coffee-text {
margin-left: 15px;
font-size: 28px;
}
</style>
10 changes: 10 additions & 0 deletions content/blog/add-i18n-vue.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
title: 'Añadir i18n en una aplicación Vue'
description: 'Cómo traducir tus aplicaciones con Vue e I18n'
date: 2019-02-01
timeToRead: 5
---

# Hello test 2

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam viverra tincidunt ligula in congue. Cras nec sapien a risus varius dictum. Sed rhoncus convallis sapien quis varius. In justo leo, congue et convallis sed, feugiat et orci. Quisque quam elit, venenatis non diam eget, hendrerit posuere ex. Nam condimentum elit aliquam nisl varius, quis luctus massa ullamcorper. Curabitur ac pellentesque arcu. Nulla turpis libero, condimentum vel tempor non, sagittis vitae sem. Etiam aliquet eu nisl vel dictum. Phasellus vitae ornare purus, ut euismod quam. In eget tristique lacus. Duis lectus sem, pretium sit amet mollis vitae, sagittis eu augue.
10 changes: 10 additions & 0 deletions content/blog/deploy-vue-app.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
title: 'Desplegar una aplicación hecha con Vue en GithubPages'
description: 'Tutorial sobre cómo desplegar una aplicación Vue en github pages'
date: 2018-11-01
timeToRead: 2
---

# Hello test 2

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam viverra tincidunt ligula in congue. Cras nec sapien a risus varius dictum. Sed rhoncus convallis sapien quis varius. In justo leo, congue et convallis sed, feugiat et orci. Quisque quam elit, venenatis non diam eget, hendrerit posuere ex. Nam condimentum elit aliquam nisl varius, quis luctus massa ullamcorper. Curabitur ac pellentesque arcu. Nulla turpis libero, condimentum vel tempor non, sagittis vitae sem. Etiam aliquet eu nisl vel dictum. Phasellus vitae ornare purus, ut euismod quam. In eget tristique lacus. Duis lectus sem, pretium sit amet mollis vitae, sagittis eu augue.
1 change: 0 additions & 1 deletion content/blog/event-bus.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ title: 'Bus de Eventos global con Vue'
description: 'Ejemplo de bus de eventos en Vue'
date: 2019-05-01
timeToRead: 3
name: event-bus
---

# Hello test 2
Expand Down
51 changes: 48 additions & 3 deletions content/blog/scaffolding-vue.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,54 @@ title: 'Estructura de carpetas en Vue'
description: 'Ejemplo de estructura de carpetas en Vue'
date: 2020-02-01
timeToRead: 4
name: scaffolding-vue
---

# Hello test
Hace ya un tiempo que empecé a trabajar con <span class='vue'>Vue</span> y, sinceramente, es uno de los frameworks que más me apasiona. Entre muchas razones, me gusta por su sencillez, por su flexibilidad y por su comunidad.

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam viverra tincidunt ligula in congue. Cras nec sapien a risus varius dictum. Sed rhoncus convallis sapien quis varius. In justo leo, congue et convallis sed, feugiat et orci. Quisque quam elit, venenatis non diam eget, hendrerit posuere ex. Nam condimentum elit aliquam nisl varius, quis luctus massa ullamcorper. Curabitur ac pellentesque arcu. Nulla turpis libero, condimentum vel tempor non, sagittis vitae sem. Etiam aliquet eu nisl vel dictum. Phasellus vitae ornare purus, ut euismod quam. In eget tristique lacus. Duis lectus sem, pretium sit amet mollis vitae, sagittis eu augue.
Una vez comienzas a usar <span class='vue'>Vue</span> con asiduidad y realizas varios proyectos, empiezas a darte cuenta de que su base se construye sobre componentes. Con el desarrollo de aplicaciones se hace notar su flexibilidad con respecto a la estructura de carpetas, el framework no te pone prácticamente ningún problema al respecto, pero una vez comienzas a generar vistas (que son componentes), componentes que pertenecen solo a una vista, componentes comunes, etc. ¿qué pasa? ¿cómo organizamos todos esos componentes para verlos día a día y que sea lo menos doloroso posible?

En el post de hoy os enseñaré un ejemplo de scaffolding, el cual he ido adquiriendo con el paso del tiempo tras probar un ejemplo tras otro, finalmente este es, desde mi opinión, el más cómodo.

## Crear estructura base

Para empezar, tendremos que generar un proyecto de <span class='vue'>Vue</span> básico con <span class='code'>vue-cli</span>, ya que la estructura que nos presenta desde un primer momento es la que intentaremos mantener siempre. Yo he generado un proyecto con la configuración lo más real posible a lo que se podría usar en un proyecto relativamente grande.

<custom-image src="/images/posts/scaffolding-vue/options-vue-cli.png" alt="opciones vue cli seleccionadas"></custom-image>

Una vez termine de instalarse todo, esta será la estructura que nos genera <span class='code'>vue-cli</span>.

<custom-image src="/images/posts/scaffolding-vue/scaffolding-base.png" alt="estructura base proyecto vue"></custom-image>

## Crear componentes globales

Cuando desarrollas una aplicación SPA, por ejemplo, con diferentes rutas y diferentes vistas, al final terminas teniendo componentes que se usan solamente en ciertas vistas y otros que se usan por toda la aplicación. En este apartado vamos a organizar los componentes comunes por tipos de componentes. Veamos un ejemplo visual:

<custom-image src="/images/posts/scaffolding-vue/scaffolding-global-components.png" alt="estructura componentes globales vue"></custom-image>

Como veis, dentro de la carpeta <span class='code'>Components</span> hemos generado dos carpetas, una <span class='code'>Layout</span> y otra <span class='code'>Ui</span>. Esto son dos de las diferenciaciones que yo suelo hacer en mis proyectos, pero depende del proyecto o del equipo de desarrollo los tipos de organización pueden variar.

En el caso de tener componentes que no pertenecen a ningún tipo específico, la idea sería generar una carpeta llamada <span class='code'>Common</span> a la misma altura que layout y ui.

## Crear componentes de vista

Una vez que tengamos los componentes globales organizados, continuaremos con los componentes que solamente pertenecen a una vista en concreto. Veamos un ejemplo.

<custom-image src="/images/posts/scaffolding-vue/scaffolding-views-components.png" alt="estructura componentes vista vue"></custom-image>

En este ejemplo vemos como he creado una carpeta por vista y dentro de ella el componente de la vista lo he llamado <span class='code'>index.vue</span>. Dentro de cada carpeta existe una carpeta <span class='code'>components</span> que en este caso pertenecen solamente a los componentes de la vista.

## Resto de ficheros

Una vez tengamos los componentes organizados, vamos a organizar el resto de ficheros de la aplicación. La idea sería crear una carpeta <span class='code'>shared</span> dentro de nuestro <strong>src</strong> y ahí añadir por ejemplo nuestras constantes, los archivos de traducciones, directivas, mixins, constantes, modelos, etc.

<custom-image src="/images/posts/scaffolding-vue/scaffolding-rest-of-files.png" alt="estructura resto de ficheros vue"></custom-image>

La idea de shared es mantener lo nativo de <span class='vue'>Vue</span> en la carpeta raíz (components, store, etc.) y el contenido adicional almacenarlo dentro de este directorio.

## Conclusión

Por último, me gustaría remarcar que aunque para mi este scaffolding es el más útil para trabajar no tiene que ser así para todo el mundo. Así que os animo a todos a probar día a día cual es el que más se adapta a vuestra forma de trabajo.

Espero que pueda serviros de ayuda y cualquier feedback por <a target='_blank' href='https://twitter.com/pablosirera'>twitter</a> será bienvenido ✌️.

Os dejo también el link al repo de <a target='_blank' href='https://github.com/pablosirera/scaffolding-vue'>github</a>, por si os queréis descargar este ejemplo.
27 changes: 25 additions & 2 deletions nuxt.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,24 @@ export default {
content: process.env.npm_package_description || '',
},
],
link: [{ rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }],
link: [
{ rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' },
{
rel: 'stylesheet',
href: 'https://fonts.googleapis.com/css?family=Cookie',
},
],
},
/*
** Global CSS
*/
css: ['~/assets/css/main.css'],
components: true,
/*
** Plugins to load before mounting the App
** https://nuxtjs.org/guide/plugins
*/
plugins: [],
plugins: ['~/plugins/global.js'],
/*
** Nuxt.js dev-modules
*/
Expand Down Expand Up @@ -89,6 +96,22 @@ export default {
langDir: 'locales/',
vueI18n: {
fallbackLocale: 'es',
dateTimeFormats: {
es: {
short: {
year: 'numeric',
month: 'long',
day: 'numeric',
},
},
en: {
short: {
year: 'numeric',
month: 'long',
day: 'numeric',
},
},
},
},
},
/*
Expand Down
6 changes: 3 additions & 3 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
},
"dependencies": {
"@fortawesome/free-solid-svg-icons": "^5.13.1",
"@nuxt/components": "^1.0.6",
"@nuxt/content": "^1.3.2",
"@nuxtjs/pwa": "^3.0.0-beta.20",
"nuxt": "^2.13.0",
Expand Down
18 changes: 17 additions & 1 deletion pages/blog/_slug.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
<template>
<nuxt-content :document="doc" />
<article class="mb-20">
<h1 class="text-4xl">{{ doc.title }}</h1>
<h2>
<span>🗓 {{ $d(new Date(doc.date), 'short') }}</span>
-
<span>⏱ {{ doc.timeToRead }} {{ $tc('posts.minute', 2) }}</span>
</h2>
<div class="divider" />
<nuxt-content :document="doc" />
<CoffeeWidget />
</article>
</template>

<script>
Expand All @@ -10,3 +20,9 @@ export default {
},
}
</script>

<style scoped>
.divider {
@apply border-4 border-blue-main-400 opacity-75 w-16 rounded mt-4 mb-8;
}
</style>
8 changes: 4 additions & 4 deletions pages/blog/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
v-for="(post, index) in posts"
:key="index"
v-bind="post"
@select="goToPost(post.name)"
@select="goToPost(post.path)"
/>
</div>
</div>
Expand All @@ -22,12 +22,12 @@ export default {
BlogCard,
},
async asyncData({ $content }) {
const posts = await $content('blog').fetch()
const posts = await $content('blog').sortBy('date', 'desc').fetch()
return { posts }
},
methods: {
goToPost(name) {
this.$router.push({ path: `/blog/${name}` })
goToPost(path) {
this.$router.push({ path })
},
},
}
Expand Down
4 changes: 4 additions & 0 deletions plugins/global.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import Vue from 'vue'
import CustomImage from '@/components/blog/CustomImage.vue'

Vue.component('custom-image', CustomImage)
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit 4bfa70c

Please sign in to comment.