How to Build Your First AI App: A Complete Development Guide for 2025

Close-up of a smartphone in hand with AI voice chat bubble and coffee in background.

Part 4 of the “Building Money-Making AI Apps” Series

Hey there! Rock back again. Today we’re getting our hands dirty with actual code. I’m gonna show you exactly how I built my AI writing assistant app that’s now making $3k/month. Whether you’re following our series or just want to learn app development, let’s build something cool together!

Planning Your App’s Features

Before we write any code, here’s how I plan my features:

  1. Core Feature: AI Text Generation
  2. User Management
  3. API Integration
  4. Payment Processing
  5. Usage Tracking

Let’s build these one by one!

Setting Up the Project

First, let’s create our project structure:

# Create project directory
mkdir ai-writer-app
cd ai-writer-app

# Initialize frontend
npx create-next-app@latest frontend
cd frontend
npm install @chakra-ui/react axios jsonwebtoken

# Initialize backend
mkdir backend
cd backend
npm init -y
npm install express mongoose openai dotenv jsonwebtoken

Building the Core Features

1. AI Text Generation Service

Here’s our AI service that actually makes money:

# backend/services/aiService.js
import OpenAI from 'openai';

class AIService {
    constructor() {
        this.client = new OpenAI({
            apiKey: process.env.OPENAI_API_KEY
        });
    }

    async generateContent(prompt, style, length) {
        try {
            const completion = await this.client.chat.completions.create({
                model: "gpt-3.5-turbo",
                messages: [
                    {
                        role: "system",
                        content: `You are a professional writer. Write in a ${style} style.`
                    },
                    {
                        role: "user",
                        content: prompt
                    }
                ],
                max_tokens: length,
                temperature: 0.7
            });

            return {
                success: true,
                content: completion.choices[0].message.content
            };
        } catch (error) {
            console.error('AI Generation Error:', error);
            return {
                success: false,
                error: 'Failed to generate content'
            };
        }
    }
}

export default new AIService();

2. User Interface

Here’s our main content generation component:

// frontend/components/ContentGenerator.js
import React, { useState } from 'react';
import { Box, Button, Textarea, Select, useToast } from '@chakra-ui/react';

export default function ContentGenerator() {
    const [prompt, setPrompt] = useState('');
    const [style, setStyle] = useState('professional');
    const [loading, setLoading] = useState(false);
    const [result, setResult] = useState('');
    const toast = useToast();

    const generateContent = async () => {
        try {
            setLoading(true);
            const response = await fetch('/api/generate', {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                },
                body: JSON.stringify({ prompt, style }),
            });

            const data = await response.json();
            if (data.success) {
                setResult(data.content);
            } else {
                throw new Error(data.error);
            }
        } catch (error) {
            toast({
                title: 'Error',
                description: error.message,
                status: 'error',
                duration: 3000,
            });
        } finally {
            setLoading(false);
        }
    };

    return (
        <Box p={5}>
            <Textarea 
                value={prompt}
                onChange={(e) => setPrompt(e.target.value)}
                placeholder="What would you like me to write about?"
                mb={4}
            />
            <Select 
                value={style}
                onChange={(e) => setStyle(e.target.value)}
                mb={4}
            >
                <option value="professional">Professional</option>
                <option value="casual">Casual</option>
                <option value="creative">Creative</option>
            </Select>
            <Button
                onClick={generateContent}
                isLoading={loading}
                colorScheme="blue"
                mb={4}
            >
                Generate Content
            </Button>
            {result && (
                <Box 
                    p={4} 
                    borderWidth={1} 
                    borderRadius="md"
                    whiteSpace="pre-wrap"
                >
                    {result}
                </Box>
            )}
        </Box>
    );
}

3. User Management

Here’s how we handle user accounts:

// backend/models/User.js
const mongoose = require('mongoose');

const userSchema = new mongoose.Schema({
    email: {
        type: String,
        required: true,
        unique: true
    },
    password: {
        type: String,
        required: true
    },
    credits: {
        type: Number,
        default: 0
    },
    subscription: {
        type: String,
        enum: ['free', 'basic', 'pro'],
        default: 'free'
    },
    usageHistory: [{
        date: Date,
        promptType: String,
        credits: Number
    }]
});

module.exports = mongoose.model('User', userSchema);

4. Payment Integration

Here’s our Stripe integration:

// backend/services/paymentService.js
const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY);

const createSubscription = async (userId, priceId) => {
    try {
        const user = await User.findById(userId);

        const session = await stripe.checkout.sessions.create({
            customer_email: user.email,
            line_items: [{
                price: priceId,
                quantity: 1
            }],
            mode: 'subscription',
            success_url: `${process.env.FRONTEND_URL}/success?session_id={CHECKOUT_SESSION_ID}`,
            cancel_url: `${process.env.FRONTEND_URL}/pricing`,
        });

        return session;
    } catch (error) {
        console.error('Subscription Error:', error);
        throw error;
    }
};

5. Usage Tracking

Here’s how we track API usage:

// backend/middleware/usageTracker.js
const trackUsage = async (req, res, next) => {
    const startTime = Date.now();

    res.on('finish', async () => {
        try {
            const duration = Date.now() - startTime;
            await Usage.create({
                userId: req.user.id,
                endpoint: req.path,
                duration,
                status: res.statusCode,
                timestamp: new Date()
            });
        } catch (error) {
            console.error('Usage Tracking Error:', error);
        }
    });

    next();
};

Testing Your App

Here’s my testing setup:

// tests/ai.test.js
describe('AI Content Generation', () => {
    it('should generate content successfully', async () => {
        const result = await aiService.generateContent(
            'Write about AI',
            'professional',
            500
        );
        expect(result.success).toBe(true);
        expect(result.content).toBeTruthy();
    });

    it('should handle errors gracefully', async () => {
        const result = await aiService.generateContent(
            '',
            'professional',
            500
        );
        expect(result.success).toBe(false);
    });
});

Common Development Challenges

  1. Rate Limiting
const rateLimit = require('express-rate-limit');

const apiLimiter = rateLimit({
    windowMs: 15 * 60 * 1000, // 15 minutes
    max: 100 // limit each IP to 100 requests per windowMs
});

app.use('/api/', apiLimiter);
  1. Error Handling
// backend/middleware/errorHandler.js
const errorHandler = (err, req, res, next) => {
    console.error(err.stack);

    res.status(err.status || 500).json({
        success: false,
        error: err.message || 'Something went wrong!'
    });
};

app.use(errorHandler);

What’s Next?

In our next post, we’ll cover how to launch your app and get your first users. I’ll share the exact steps I took to launch my app and get paying customers within the first week!

Pro Tip: Start with a simple MVP and add features based on user feedback. My first version only had the AI text generation – everything else came from user requests!

This post is Part 4 of our “Building Money-Making AI Apps” series. Just joining us? Check out:

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top