In this article, you'll know how to build a contact website and contact ways...
First, we'll build a simple page and in it how to contact us like Twitter, Dev, Github...
Nuxtjs
Nuxt is an open-source web application framework built on top of Vue.js, It is well known for its SSR capabilities, but it can also do static.
Instead of having a Node server process each client request - eventually fetching data from an API or database in between, we'll be using Nuxt as a static site generator to do the heavy lifting during the build stage.
FaunaDB
Fauna is a globally distributed, low-latency database, with native GraphQL support, that promises to be always consistent and always secure.
As a serverless database, FaunaDB allows applications to access data through a secure API, in contrast to more "traditional" relational databases that require you to open a connection. In that sense, FaunaDB is βconnectionlessβ and rather behaves like an API, which fits perfectly in a Jamstack architecture. There is also no need to host and manage our own database. It requires zero server configuration and supports seamless scalability out-of-the-box.
Demo
you can try the project (demo)
Pre-requisites
before we move on, you'll need :
Npm, Node & Npx installed.
Let's go
first, you'll need to install create-nuxt-app
$ npm i -g create-nuxt-app
after install let's create our site
$ create-nuxt-app PROJ_NAME && cd PROJ_NAME
now we need three packages :
faunadb: JavaScript driver for FaunaDB
slugify: we'll use this package to generate slugs from con names
$ npm i faunadb slugify dotenv
now let's create graphql schema
$ mkdir graphql && cd graphql && touch schema.gql
data modiling (graphql schema)
structure:
desc: contact description
repoUrl: contact url
brand || solid: check if fontawesome icon is
fab
orfas
faI: contact fontawesome icon
hashtag: if the contact has a hashtag
hashtag_name: hashtag name
inside schema.gql
type Repo {
desc: String! @unique
repoUrl: String! @unique
# if font-awesome icon is brand or solid
brand: Boolean
solid: Boolean
faI: String
# this only for twitter & dev contacts
hashtag: Boolean
hashtag_name: String
}
type Query {
allRepos: [Repo!]!
}
now go to faunaDB dashboard & create new database
go to graphql section and import your schema
now you should have collections
Creating keys
create Admin key
& Server key
ADMIN
Press SAVE
in your project create .env
file
replace ποΈ with your key
SERVER
Also press SAVE
in .env
replace ποΈ with your second key
ok we finish all this
return to graphql
folder and create db-connection.js
$ touch db-connection.js
inside it paste this code
require("dotenv").config();
const faunadb = require("faunadb");
const query = faunadb.query;
function createClient() {
if (!process.env.FAUNA_ADMIN_KEY) {
throw new Error("FAUNA_ADMIN_KEY not found");
}
const client = new faunadb.Client({
secret: process.env.FAUNA_ADMIN_KEY
});
return client;
}
exports.client = createClient();
exports.query = query;
very important step
in nuxt.config.js
in above
require("dotenv").config();
and let's add generate
prop
generate: {
async routes() {
const faunadb = require("faunadb");
const query = faunadb.query;
const slugify = require("slugify");
const q = query;
if (!process.env.FAUNA_SERVER_KEY) {
throw new Error("FAUNA_SERVER_KEY not found.");
}
const client = new faunadb.Client({
secret: process.env.FAUNA_SERVER_KEY
});
const result = await client.query(
q.Map(
q.Paginate(q.Match(q.Index("allRepos"))),
q.Lambda("X", q.Get(q.Var("X")))
)
);
const repos = result.data.map(repo => repo.data);
const routes = repos.map(repo => {
const repoUrlParts = repo.repoUrl.split("/");
const repoOwner = repoUrlParts[repoUrlParts.length - 2];
const repoName = repoUrlParts[repoUrlParts.length - 1];
const slug = slugify(repoName, {
remove: /[*+~.()'"!:@]/g
});
repo.slug = slug;
repo.owner = repoOwner;
repo.name = repoName;
return {
payload: repo
};
});
routes.push({
route: "/",
payload: repos
});
return routes;
}
}
Import collections
return to faunaDB dashboard, collections section to create new collection
press new document
example data
{
"desc": "you can make a github issue",
"repoUrl": "https://github.com/YOUR_REPO/issues",
"brand": true,
"solid": false,
"faI": "github",
"hashtag": false
}
I put dev-x Twitter, GitHub issue, Dev org
now go to pages
before beginning, we need some packages
font-awesome
sass & sass-loader
$ npm i @fortawesome/fontawesome-svg-core @fortawesome/vue-fontawesome @fortawesome/free-brands-svg-icons @fortawesome/free-solid-svg-icons sass sass-loader
now go to nuxt.config.js
in css
section
we going to import font-awesome style
type this
css: [
"@fortawesome/fontawesome-svg-core/styles.css",
...
],
go to pages
and create index.scss
in pages
you should have two files
βββ index.vue
βββ index.scss
in index.vue
template
<template>
<div class="container">
<div>
<Logo />
<h1 class="title">contact.dev-x</h1>
<div>
<div class="card">
<h3>Contacts →</h3>
<ul v-for="repo in repos" :key="repo.desc">
<li>
{{ repo.desc }}
<strong v-if="repo.hashtag">{{ repo.hashtag_name }}</strong>
<a :href="repo.repoUrl">
<a class="btn">
<fai v-if="repo.brand" :icon="['fab', `${repo.faI}`]" />
<fai v-if="repo.solid" :icon="repo.faI" />
</a>
</a>
</li>
</ul>
</div>
</div>
</div>
</div>
</template>
script
<script>
import Vue from "vue";
import { library, config } from "@fortawesome/fontawesome-svg-core";
import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome";
import { fab } from "@fortawesome/free-brands-svg-icons";
import { fas } from "@fortawesome/free-solid-svg-icons";
// This is important, we are going to let Nuxt.js worry about the CSS
config.autoAddCss = false;
// You can add your icons directly in this plugin. See other examples for how you
// can add other styles or just individual icons.
library.add(fab);
library.add(fas);
// Register the component globally
Vue.component("fai", FontAwesomeIcon);
Vue.config.productionTip = false;
export default {
asyncData({ payload }) {
return { repos: payload };
}
};
</script>
style
<style lang="scss">
@import "index.scss";
</style>
index.scss
$color: #121312;
.container {
margin: 0 auto;
min-height: 100vh;
display: flex;
justify-content: center;
align-items: center;
text-align: center;
}
.title {
display: block;
font-weight: 300;
font-size: 100px;
color: #31465e;
letter-spacing: 1px;
}
.subtitle {
font-weight: 300;
font-size: 42px;
color: #526488;
word-spacing: 5px;
padding-bottom: 15px;
}
.links {
padding-top: 15px;
}
.card {
cursor: pointer;
margin: 1rem;
flex-basis: 45%;
padding: 1.5rem;
text-align: left;
color: inherit;
text-decoration: none;
border: 2px solid#000000;
border-radius: 2.5px;
flex-direction: column;
box-shadow: 5px 6px 0px black;
}
.card h3 {
margin: 0 0 1rem 0;
font-size: 1.5rem;
}
.card li {
margin: 0;
font-size: 1.25rem;
line-height: 1.5;
list-style: none;
font-family: DF;
}
a {
color: rgb(0, 119, 255);
}
strong {
color: dodgerblue;
}
.btn {
display: inline-block;
border-radius: 4px;
border: 1px solid $color;
color: $color;
text-decoration: none;
padding: 10px 30px;
margin-left: 15px;
}
.btn:hover {
color: #fff;
background-color: $color;
}
Everything is ok
the step before end
in terminal type...
$ npm run generate
if you see this error
don't worry it's a soft error
after generate
we'll use serve
to serve the output build
$ npx serve dist
# or
$ sudo npm i -g serve
$ serve dist
go to localhost:5000
and see your result
Deploy to firebase (optional)
install firebase globally
if you've windows
npm i -g firebase firebase-tools
mac or linux
$ sudo npm i -g firebase firebase-tools
now go to firebase console
let's create a web app
and create a new project
hosting
final touches
copy "site"
prop
go to the project and type
$ firebase login
it's going to login in browser
initializing
$ firebase init
go to firebase.json
{
"hosting": {
"site": "contactus-x",
"public": "dist",
...
}
}
and the final step
$ firebase deploy --only hosting:contactus-x
that it
$ echo happy coding β¨οΈ
Top comments (0)