# Making of this url shortener
https://u.baldir.fr is a static URL shortener. It means it is generated and
served on a simple HTTP server (in our case NGinx). The links shortened will be
added as yaml files pushed to a Git repo. Then a Gitlab CI will build and deploy
changes on a static http server (for my case through SSH on a Linode)
## Install gridsome cli & setup project
In my setup, I develop and deploy on the same machine. In a more traditional
setup, an artefact would be generated during the build and then deployed
remotely.
Follow https://gridsome.org/docs/#prerequisites
```bash
yarn global add @gridsome/cli
gridsome create u.baldir.fr
cd u.baldir.fr
# Test if it is working
gridsome develop
# go to http://localhost:8080 and http://localhost:8080/___explore (graphql)
```
## Install plugins
We want to add an entry for each url to shorten as a yaml file.
Gridsome wil read all `*.yml` files from `content/links` and convert it as a
GraphQL collection. Then, we will use the collection in our vue components.
We need to install
[`@gridsome/source-filesystem`](https://gridsome.org/plugins/@gridsome/source-filesystem)
plugin.
```bash
yarn add @gridsome/source-filesystem
# or if you ar using npm
npm install @gridsome/source-filesystem
```
We also need to install a yaml transformer:
[`@gridsome/transformer-yaml`](https://gridsome.org/plugins/@gridsome/transformer-yaml)
```bash
yarn add @gridsome/transformer-yaml
# or if you ar using npm
npm install @gridsome/transformer-yaml
```
## Configure plugin
In [`gridsome.config.js`](gridsome.config.js) change to the following
```json
module.exports = {
siteName: 'u.baldir.fr',
siteDescription: 'Baldir.fr url shortener',
plugins: [
{
// Create posts from markdown files
use: '@gridsome/source-filesystem',
options: {
typeName: 'Url',
path: 'content/links/*.yml',
route: '/:tinyUrl'
}
}
]
}
```
This will create a GraphQL collection `allUrl()` and also a vue Route that will
use the property `tinyUrl` as part of the Url.
Create a folder to host the content : `content/links`
Create the file `content/links/google.yml`
```yaml
tinyUrl: "google"
destinationUrl: "https://google.fr"
description: "A famous search engine"
```
Create the file `content/links/yahoo.yml`
```yaml
tinyUrl: "yahoo"
destinationUrl: "https://yahoo.fr"
description: "Another search engine"
```
The route u.baldir.fr/google will lead to 404 page because there is no template yet for the type `Url`.
Though, we can test the graphQL data by going to `localhost:4000/___explore`
Test the following query :
```
query {
allUrl{
totalCount
edges{
node{
id
path
fileInfo{name}
tinyUrl
destinationUrl
}
}
}
url: url(path: "/content/links/google/"){
id
path
fileInfo{name}
tinyUrl
destinationUrl
}
}
```
## Create a template
Now we want a template to be applied to the site for the route we defined.
Create the file `src/templates/Url.vue`. Note that it matches the typeName we
defined earlier.
```xml
Redirecting to {{$page.url.destinationUrl}}...
query Url ($path: String!) {
url: url(path: $path){
tinyUrl
destinationUrl
}
}
```
This template uses the data from graphQL query and redirects to the destination
URL.
Try it : localhost:4000/google
## Cleaning up
remove the files
* src/layouts/README.md
* src/pages/About.vue
* src/pages/README.md
* src/templates/README.md
## Make the index as a list of all short links
Modify `src/pages/index.vue` with the following.
```xml
{
urls: allUrl(sort: [{by: "edges.nodes.tinyUrl", order: ASC}]) {
edges {
node {
tinyUrl
destinationUrl
description
}
}
}
}
```
## Automate deployment with Gitlab
.gitlab-ci.yml
```
image: ubuntu:18.04
before_script:
- 'apt-get update -y && apt-get install openssh-client -y && apt-get install sshpass'
build1:
stage: build
script:
- sshpass -p "$server_ssh_secret" ssh -o StrictHostKeyChecking=no "$server_ssh_user@$server_ssh_url" 'cd /home/marc/sources/u.baldir.fr && git checkout master && git fetch origin && git reset --hard origin/HEAD && git pull && gridsome build'
```
The previous script checkout latest version from github repository and then
builds static content with gridsome CLI.
Set variables in your gitlab project
* $server_ssh_secret : your ssh password
* $server_ssh_user : your ssh user
* $server_ssh_url : url of the server
## Alternative deployment automation
Alternatively, we could create an artifact from generated `dist` folder and
store it as a zip file in an artifact repository. Then the CI can trigger
this artifact to be downloaded (for instance with a ssh command) and deflated
in the appropriate location of the HTTP server.
## Nginx configuration
No need for rewrite configuration in NGinx, it is managed by VueJs. It works
out of the box even if we use HTTPS.
```
server {
server_name u.baldir.fr;
location / {
root /home/marc/sources/u.baldir.fr/dist;
index index.html;
}
error_page 404 /404.html;
location = /50x.html {
root /usr/share/nginx/html;
}
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/u.baldir.fr/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/u.baldir.fr/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}
```