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)