As events evolve in the digital landscape, we might have seen some fun, engaging, and personalized event tickets shared on social media. This innovation is fascinating and showcases just how many excellent low-cost services and capabilities exist in web development.
This post will discuss building concert tickets using Cloudinary, Xata, and Next.js. At the end of this tutorial, we will learn how to store images on Cloudinary and explore the rich capabilities of Xata, a serverless database.
Check here for the source code on GitHub and the demo here.
Prerequisites
The knowledge of the following is required:
- Knowledge of JavaScript and React.js
- Node.js and its package manager, npm. We run the command
node -v
&&npm -v
to verify we have them installed or install them from here - Signup for a free Cloudinary account
- A Xata account
- Understanding Next.js would help us quickly follow this tutorial
Creating a Next.js application
To create the Next.js app, we go to our terminal or command line. Using the cd
command, we navigate to the directory we want our to create our app.
cd <directory-name>
Once inside the directory, we create a new project using the command:
npx create-next-app
# or
yarn create next-app
Once that's finished, we navigate into that directory and start a hot-reloading development server for the project on http://localhost:3000 with:
npm run dev
#or
yarn dev
Installing Cloudinary
Cloudinary provides a robust solution to store, transform, optimize and deliver images and videos in software applications.
Install the cloudinary-react package that exposes various media delivery and transformation functions using the command line.
npm i cloudinary-react lodash
Lodash is a dependency of the Cloudinary package.
Installing TailwindCSS
TailwindCSS is a utility-first CSS framework packed with classes to help us style web pages.
We install tailwindcss
and its peer dependencies via npm, which generates tailwind.config.js
and postcss.config.js
.
npm install -D tailwindcss postcss autoprefixer
npx tailwindcss init -p
We need to add the paths to all of our template files in the tailwind.config.js file.
//tailwind.config.js
module.exports = {
content: [
"./pages/**/*.{js,ts,jsx,tsx}",
"./components/**/*.{js,ts,jsx,tsx}",
],
theme: {
extend: {},
},
plugins: [],
}
We should add the @tailwind
directives for Tailwind’s layers to our ./styles/globals.css
file.
//globals.css
@tailwind base;
@tailwind components;
@tailwind utilities;
Setting up the Xata database
Let’s create a new database on our Xata dashboard called concert-ticket
Click on the created database and add a table titled concert
. Next, add concert_name
and artist
column of type String to the table.
Our database should look like this:
Setting up the Xata instance
To set up Xata, we'll need to install the CLI globally:
npm install @xata.io/cli -g
Then, authorize Xata to log us in:
xata auth login
Next, we select Create a new API key in the browser
from the prompts in our terminal. This opens our browser, where we can type in any name we choose. Once successful, we will get a display page indicating that we are all set.
Now, let’s cd
into the Nextjs project created earlier and run xata init
to initialize Xata in our project;
cd <directory-name>
xata init
This is where we select the name of the database created earlier, then select Generate Javascript code with ES modules code
and choose our output source as src/xata.js
which is where the Xata codegen will be generated.
Image Upload to Cloudinary
In our dashboard, we will have access to upload and save the downloaded images in Cloudinary by clicking the Media Library
tab and Upload button, as displayed below.
Next, we need to copy the publicId
for the saved images from our dashboard, which will be necessary to generate the article banner.
Setting up the image collection
We’ll create a utils
folder in the project root directory, where we need to create a ticket.json
file to hold to data of the uploaded images.
Here is the JSON data for the ticket.json
file.
[
{
"id": 1,
"publicId": "photo-1649894221695-45abb718a190_sgjhwd.jpg"
},
{
"id": 2,
"publicId": "photo-1649894222226-056a1a79d9fb_xlv73h.jpg"
},
{
"id": 3,
"publicId": "photo-1648800475313-2bb7fbec8701_ae60yw.jpg"
},
{
"id": 4,
"publicId": "photo-1647067867267-e01d98462f3c_ugtnwe.jpg"
},
{
"id": 5,
"publicId": "photo-1644241687200-eadaf7601290_xcz2kh.jpg"
}
]
Creating the concert ticket
With our project fully set up and configured, we can start building the concert ticket.
First, we need to modify the index.js
file in the pages
folder to the gist below:
From the code snippet in the gist, we:
- Import required dependencies and image collections
- Create state variables to manage selected Image ID, form data, and display the Concert ticket
- A
handleChange()
function to control form inputs - Markups for form elements and conditionally render the list of Images using
cloudinary-react
. The list of images also has anonClick()
function that sets the current imageid
to show the active image, the form object, and theshowCard
property
By now, the application should look like this:
Next, we create a components
folder in the root directory, and create a Concert.js
file with the following snippet:
import { CloudinaryContext, Transformation, Image } from "cloudinary-react";
export const Concert = ({ message, name, publicId }) => {
return (
<div>
<CloudinaryContext cloudName="beswift">
<Image publicId={publicId} alt="image" width={1000} ref={ref}>
<Transformation crop="fit" effect="blur:100" />
<Transformation effect="brightness_hsb:-50" />
<Transformation
color="#FFFFFF"
overlay={{
background: "",
fontFamily: "Neucha",
fontSize: 150,
fontWeight: "bold",
text: message,
textAlign: "center",
}}
width="1300"
crop="fit"
/>
<Transformation flags="layer_apply" />
<Transformation
color="#FFFFFF"
overlay={{
fontFamily: "Dancing Script",
fontSize: 50,
fontWeight: "bold",
text: `Artist: ${name}`,
}}
/>
<Transformation
flags="layer_apply"
gravity="center"
x="450"
y="350"
/>
</Image>
</CloudinaryContext>
</div>
);
};
The snippet above does the following:
- Imports the required dependencies
- The
Concert
component accepts amessage
,name
, andpublicId
props - Configure
CloudinaryContext
,Image
, andTransformation
to render the image, message, and name - We also leverage Cloudinary to apply multiple transformations on the image. We added the following transformations, cropping, blurring, brightening, and adding overlays for text, text position, text properties, and flags to alter the position of the text
Then, we update index.js
to conditionally render the Concert.js
component as shown below:
//imports here
import { Concert } from '../components/Concert'; //add
export default function Home() {
//states here
const handleChange = (e) => {
//handle change codes here
};
//add
const handleSubmit = (e) => {
e.preventDefault();
if (imageId) {
setShowCard(true);
} else {
setFormData({ ...formData, error: true });
}
};
return (
<div className='p-10'>
{/* Head JSX comes here */}
<main className=''>
<h1 className='text-3xl'>Concert ticket</h1>
<header className='flex border-b-2 mt-7 mb-7'>
{/* Header contents JSX comes here */}
</header>
<form onSubmit={handleSubmit} className='lg:w-2/5'> {/* add handleSubmit */}
{/* Form contents JSX comes here */}
</form>
{/* Conditionally render card Components */}
{showCard && (
<div className='mt-10'>
<Concert
message={formData.message}
name={formData.name}
publicId={formData.publicId}
/>
</div>
)}
</main>
</div>
);
}
In the snippet above, we:
- Imported the
Concert
component - Created an
handleSubmit
function that checks if an image is selected and then conditionally renders theConcert
component with necessaryprops
Storing data in the database
Let’s create a new file in the api
folder and name it add-concert.js
. Paste the code below in the file:
import { getXataClient } from "../../src/xata";
const handler = async (req, res) => {
const xata = await getXataClient();
const { concert_name, artist } =
req.body;
await xata.db.concert.create({
concert_name,
artist,
});
res.end();
};
export default handler;
We get the data sent to the API and save it to the Xata database.
Finally, we test our application by starting the development server and creating different event tickets.
We can right-click to copy the URL of the generated image.
Conclusion
This post discussed building a concert tickets generator using Cloudinary’s image transformation and saving data in the Xata database. Explore adding more text information to the image and a copy-to-clipboard function for the image URL.
Resources
We may find these resources helpful: