Enhancing Images with AI: Building a Free Photo Extender Using Next.js and Tailwind CSS
Enhancing Images with AI: Building a Free Photo Extender Using Next.js and Tailwind CSS In today's digital age, the demand for high-quality images is ever-increasing. Whether you're a developer, designer, or content creator, extending and enhancing images can be a valuable skill. In this tutorial, we'll walk through how to build a photo extender free application using Next.js and Tailwind CSS. We'll also leverage an AI service to perform the image extension, similar to the one found on Spark AI's AI Image Extender. Introduction Image outpainting, or extending the edges of an image, allows us to generate new content beyond the original boundaries of a photo. This can be incredibly useful for creating wallpapers, adapting images to different aspect ratios, or enhancing compositions. In this guide, we'll build a simple web application that lets users upload an image and extends it using AI. We'll focus on: Setting up a Next.js project Styling with Tailwind CSS Integrating with an AI image extension API Handling file uploads and displaying results Deploying the application Prerequisites Basic understanding of React and Next.js Node.js installed on your machine Familiarity with Tailwind CSS is a plus Setting Up the Next.js Project First, let's create a new Next.js application: npx create-next-app photo-extender-free cd photo-extender-free Installing Tailwind CSS We'll use Tailwind CSS for styling. Install Tailwind and its dependencies: npm install tailwindcss postcss autoprefixer npx tailwindcss init -p Configure tailwind.config.js: module.exports = { content: ['./pages/**/*.{js,ts,jsx,tsx}', './components/**/*.{js,ts,jsx,tsx}'], theme: { extend: {}, }, plugins: [], }; Add Tailwind directives to your styles/globals.css: @tailwind base; @tailwind components; @tailwind utilities; Building the Upload Component Create a new component at components/UploadImage.js: import { useState } from 'react'; export default function UploadImage({ onImageUpload }) { const [preview, setPreview] = useState(null); const handleChange = (e) => { const file = e.target.files[0]; if (!file) return; setPreview(URL.createObjectURL(file)); onImageUpload(file); }; return ( {preview && ( )} ); } This component handles the file selection, creates a preview URL, and invokes a callback onImageUpload with the selected file. Creating the Main Page Next, update pages/index.js to include the upload component, call the API, and display the result: import { useState } from 'react'; import UploadImage from '../components/UploadImage'; export default function Home() { const [file, setFile] = useState(null); const [extendedUrl, setExtendedUrl] = useState(''); const [loading, setLoading] = useState(false); const handleUpload = (file) => { setFile(file); setExtendedUrl(''); }; const extendImage = async () => { if (!file) return; setLoading(true); const formData = new FormData(); formData.append('image', file); const res = await fetch('/api/extend', { method: 'POST', body: formData, }); const data = await res.json(); setExtendedUrl(data.extendedImageUrl); setLoading(false); }; return ( Photo Extender Free {loading ? 'Extending...' : 'Extend Image'} {extendedUrl && ( Extended Image )} ); } Implementing the API Route Create an API route at pages/api/extend.js. This route will receive the uploaded file, forward it to the AI service, and return the extended image URL. import formidable from 'formidable'; import fs from 'fs'; export const config = { api: { bodyParser: false, }, }; export default async function handler(req, res) { const form = new formidable.IncomingForm(); form.parse(req, async (err, fields, files) => { if (err) return res.status(500).json({ error: 'Form parse error' }); const imageFile = files.image; const buffer = fs.readFileSync(imageFile.filepath); // Call the AI API (replace with real endpoint and key) const apiRes = await fetch('https://api.sparkaipro.com/v1/image-extender', { method: 'POST', headers: { 'Content-Type': 'application/octet-stream', 'Authorization': `Bearer ${process.env.SPARKAI_API_KEY}`, }, body: buffer, }); if (!apiRes.ok) { const errMsg = await apiRes.text(); return res.status(500).json({ error: errMsg }); } const result = await apiRes.json(); // Assuming the API returns { extendedImageUrl: string } res.status(200).json({ extendedImageUrl: result.extendedImageUrl }); }); } Be sure to set your SPARKAI_API_KEY in a .env.local file: SPARKAI_API_KEY=your_api_key_here Styling with Tailw

Enhancing Images with AI: Building a Free Photo Extender Using Next.js and Tailwind CSS
In today's digital age, the demand for high-quality images is ever-increasing. Whether you're a developer, designer, or content creator, extending and enhancing images can be a valuable skill. In this tutorial, we'll walk through how to build a photo extender free application using Next.js and Tailwind CSS. We'll also leverage an AI service to perform the image extension, similar to the one found on Spark AI's AI Image Extender.
Introduction
Image outpainting, or extending the edges of an image, allows us to generate new content beyond the original boundaries of a photo. This can be incredibly useful for creating wallpapers, adapting images to different aspect ratios, or enhancing compositions.
In this guide, we'll build a simple web application that lets users upload an image and extends it using AI. We'll focus on:
- Setting up a Next.js project
- Styling with Tailwind CSS
- Integrating with an AI image extension API
- Handling file uploads and displaying results
- Deploying the application
Prerequisites
- Basic understanding of React and Next.js
- Node.js installed on your machine
- Familiarity with Tailwind CSS is a plus
Setting Up the Next.js Project
First, let's create a new Next.js application:
npx create-next-app photo-extender-free
cd photo-extender-free
Installing Tailwind CSS
We'll use Tailwind CSS for styling. Install Tailwind and its dependencies:
npm install tailwindcss postcss autoprefixer
npx tailwindcss init -p
Configure tailwind.config.js
:
module.exports = {
content: ['./pages/**/*.{js,ts,jsx,tsx}', './components/**/*.{js,ts,jsx,tsx}'],
theme: {
extend: {},
},
plugins: [],
};
Add Tailwind directives to your styles/globals.css
:
@tailwind base;
@tailwind components;
@tailwind utilities;
Building the Upload Component
Create a new component at components/UploadImage.js
:
import { useState } from 'react';
export default function UploadImage({ onImageUpload }) {
const [preview, setPreview] = useState(null);
const handleChange = (e) => {
const file = e.target.files[0];
if (!file) return;
setPreview(URL.createObjectURL(file));
onImageUpload(file);
};
return (
<div className="flex flex-col items-center justify-center p-4 border-2 border-dashed rounded-lg">
<input
type="file"
accept="image/*"
onChange={handleChange}
className="mb-4"
/>
{preview && (
<img
src={preview}
alt="Preview"
className="max-w-xs max-h-64 object-contain"
/>
)}
div>
);
}
This component handles the file selection, creates a preview URL, and invokes a callback onImageUpload
with the selected file.
Creating the Main Page
Next, update pages/index.js
to include the upload component, call the API, and display the result:
import { useState } from 'react';
import UploadImage from '../components/UploadImage';
export default function Home() {
const [file, setFile] = useState(null);
const [extendedUrl, setExtendedUrl] = useState('');
const [loading, setLoading] = useState(false);
const handleUpload = (file) => {
setFile(file);
setExtendedUrl('');
};
const extendImage = async () => {
if (!file) return;
setLoading(true);
const formData = new FormData();
formData.append('image', file);
const res = await fetch('/api/extend', {
method: 'POST',
body: formData,
});
const data = await res.json();
setExtendedUrl(data.extendedImageUrl);
setLoading(false);
};
return (
<div className="min-h-screen flex flex-col items-center justify-center bg-gray-100">
<h1 className="text-3xl font-bold mb-6">Photo Extender Freeh1>
<UploadImage onImageUpload={handleUpload} />
<button
onClick={extendImage}
disabled={!file || loading}
className="mt-4 px-6 py-2 bg-blue-600 text-white rounded-lg disabled:opacity-50"
>
{loading ? 'Extending...' : 'Extend Image'}
button>
{extendedUrl && (
<div className="mt-6">
<h2 className="text-2xl font-semibold mb-2">Extended Imageh2>
<img
src={extendedUrl}
alt="Extended Result"
className="max-w-md rounded-lg shadow-lg"
/>
div>
)}
div>
);
}
Implementing the API Route
Create an API route at pages/api/extend.js
. This route will receive the uploaded file, forward it to the AI service, and return the extended image URL.
import formidable from 'formidable';
import fs from 'fs';
export const config = {
api: {
bodyParser: false,
},
};
export default async function handler(req, res) {
const form = new formidable.IncomingForm();
form.parse(req, async (err, fields, files) => {
if (err) return res.status(500).json({ error: 'Form parse error' });
const imageFile = files.image;
const buffer = fs.readFileSync(imageFile.filepath);
// Call the AI API (replace with real endpoint and key)
const apiRes = await fetch('https://api.sparkaipro.com/v1/image-extender', {
method: 'POST',
headers: {
'Content-Type': 'application/octet-stream',
'Authorization': `Bearer ${process.env.SPARKAI_API_KEY}`,
},
body: buffer,
});
if (!apiRes.ok) {
const errMsg = await apiRes.text();
return res.status(500).json({ error: errMsg });
}
const result = await apiRes.json();
// Assuming the API returns { extendedImageUrl: string }
res.status(200).json({ extendedImageUrl: result.extendedImageUrl });
});
}
Be sure to set your SPARKAI_API_KEY
in a .env.local
file:
SPARKAI_API_KEY=your_api_key_here
Styling with Tailwind CSS
We've already used Tailwind utility classes throughout our components. Feel free to customize the design by:
- Adjusting the color palette in
tailwind.config.js
- Adding custom spacing, fonts, or shadows
- Using plugins like
@tailwindcss/forms
for better form controls
Testing the Application
Run the development server:
npm run dev
Navigate to http://localhost:3000
. Upload an image, click Extend Image, and see the magic happen!
Deploying to Vercel
To share your application:
- Push your code to a GitHub repository.
- Log in to Vercel and import your repo.
- Add the
SPARKAI_API_KEY
environment variable in Vercel’s dashboard. - Deploy — Vercel will handle building and hosting.
Your photo extender will be live at a Vercel subdomain, ready for users to enhance images for free.
Conclusion
We’ve built a fully functional photo extender free application using Next.js and Tailwind CSS, powered by an AI image extension API. You can now extend images beyond their original borders, perfect for creative projects, design mockups, and more. Feel free to enhance this base with additional features like:
- Batch processing multiple images
- Custom aspect ratio controls
- User authentication and history tracking
Happy coding and image extending!