25
loading...
This website collects cookies to deliver better user experience
Fauna is at the peak of serverless databases and providing scalable and secure infrastructure to organizations and individuals with easy integration with various frameworks. This article will build a Twitter counter with Fauna, Netlify, and the Nuxt framework. I used Fauna as my serverless database of choice because of its high scalability and consistency.
reaction_counter_database
successfully. To do this, we go to the dashboard and click on the security section to generate the API.YOUR_FAUNA_SECRET_KEY
, so that it cannot be accessed by a third party.npm install --save faunadb
@nuxtjs/axios
plugin in making API request, so keep this in mind. You can manually install it by running:npm install @nuxtjs/axios
export default {
modules: ['@nuxtjs/axios']
}
.env
file created at the root of our application, we set our fauna API keyYOUR_FAUNA_SECRET_KEY = THE_KEY
publicRuntimeConfig: {
axios: {
baseURL: process.env.NODE_ENV === 'production' ? process.env.BASE_URL || 'http://localhost:8000/' : 'http://localhost:8000/',
}
},
8000
, this is to avoid any errors when running our serverless functionconst faunadb = require('faunadb');
exports.handler = async (event) => {
const q = faunadb.query;
const client = new faunadb.Client({
secret: process.env.YOUR_FAUNA_SECRET_KEY,
});
const { slug } = event.queryStringParameters;
if (!slug) {
return {
statusCode: 400,
body: JSON.stringify({
message: 'Blog slug not available',
}),
};
}
const doesDocExist = await client.query(
q.Exists(q.Match(q.Index('reaction_count'), slug))
);
if (!doesDocExist) {
await client.query(
q.Create(q.Collection('reactions'), {
data: { slug: slug, reactions: 1 },
})
);
}
const document = await client.query(
q.Get(q.Match(q.Index('reaction_count'), slug))
);
return {
statusCode: 200,
body: JSON.stringify({
reactions: document.data.reactions,
}),
};
};
1
using our slug as a unique identifier. We send a query for the reaction_count index we created and retrieve our reactions and return the reaction count of the blog.const faunadb = require('faunadb');
exports.handler = async (event) => {
const q = faunadb.query;
const client = new faunadb.Client({
secret: process.env.YOUR_FAUNA_SECRET_KEY,
});
const { slug } = event.queryStringParameters;
if (!slug) {
return {
statusCode: 400,
body: JSON.stringify({
message: 'Blog slug not available',
}),
};
}
const doesDocExist = await client.query(
q.Exists(q.Match(q.Index('reaction_count'), slug))
);
if (!doesDocExist) {
await client.query(
q.Create(q.Collection('reactions'), {
data: { slug: slug, reactions: 1 },
})
);
}
const document = await client.query(
q.Get(q.Match(q.Index('reaction_count'), slug))
);
await client.query(
q.Update(document.ref, {
data: {
reactions: document.data.reactions + 1,
},
})
);
const updatedDocument = await client.query(
q.Get(q.Match(q.Index('reaction_count'), slug))
);
return {
statusCode: 200,
body: JSON.stringify({
reactions: updatedDocument.data.reactions,
}),
};
};
1
by running an update in our database.// TwitterReaction.vue
<template>
<div>
<button @click="addReaction" class="focus:outline-none">
{{ initialReaction }}
<svg
class="w-6 h-6"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M4.318 6.318a4.5 4.5 0 000 6.364L12 20.364l7.682-7.682a4.5 4.5 0 00-6.364-6.364L12 7.636l-1.318-1.318a4.5 4.5 0 00-6.364 0z"
></path>
</svg>
</button>
</div>
</template>
// TwitterReaction.vue
<script>
export default {
data() {
return {
initialReaction: null
}
},
async fetch() {
const { data } = await this.$axios.get(
`/.netlify/functions/fetch_reactions?slug=${this.$route.params.slug}`
)
this.initialReaction = data.reactions
},
fetchOnServer: false,
methods: {
addReaction() {
this.initialReaction++
this.incrementLikes()
},
async incrementLikes() {
await this.$axios.post(
`/.netlify/functions/increment_reactions?slug=${this.$route.params.slug}`
)
}
}
}
</script>
initialReaction
, and using the fetch_reactions functions we fetch the reactions and set it to our initialReaction
. Since we are using static mode, we set fetchOnServer
to false
to ensure the fetch hook is called whenever our component is mounted.addReaction
method, which increments our reaction count.