You shouldn't use ChatGPT to generate code... Use this other AI instead!

You shouldn't use ChatGPT to generate code... Use this other AI instead!

ChatGPT is one of the most popular AI tools for generating code, but is it really the best option? 🤔

I decided to test three AI models — ChatGPT-4o, Deepseek R1, and Claude Sonnet 3.7 — by asking each one to generate a weather forecast card using HTML, CSS, and JavaScript.

The result? ChatGPT followed the request but delivered a basic code. Meanwhile, another AI surprised me with a much more beautiful and functional design:

Next, we will analyze the results of each tool and see which one truly stood out. But before we reveal which tool did the best job, check out the prompt that was used:

I want the code for an animated card that shows the weather in São Paulo. The card needs to have a theme matching the current weather in the city.

You should return the code using only JS, HTML, and CSS, without any external libraries or anything like that.
You must query the OpenMeteo Forecast API to get the current weather and temperature, as well as the Geolocation API to obtain São Paulo’s coordinates.

---
Context:

I am creating an HTML, CSS, and JS application to display the weather forecast by querying the current forecast from the OpenMeteo API.
I need this card to intuitively show the current weather.

Now, let's analyze the results generated by each of the tested tools.

ChatGPT 4o

Starting with ChatGPT, which followed the request but in a very basic way. It generated a functional card but static with no special visual effects. The code structure was correct, but there was no design differentiation, making the result simple and unimpressive.

Code generated by GPT-4o:

<!DOCTYPE html>
<html lang="pt-BR">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Clima em São Paulo</title>
    <style>
        body {
            display: flex;
            justify-content: center;
            align-items: center;
            height: 100vh;
            margin: 0;
            font-family: Arial, sans-serif;
            background-color: #f0f0f0;
        }
        .weather-card {
            background-color: #ffffff;
            border-radius: 10px;
            box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
            padding: 20px;
            text-align: center;
            width: 300px;
            animation: fadeIn 1s ease-in-out;
        }
        .weather-icon {
            font-size: 48px;
            margin-bottom: 10px;
        }
        .temperature {
            font-size: 36px;
            font-weight: bold;
            margin-bottom: 5px;
        }
        .description {
            font-size: 18px;
            color: #666666;
            margin-bottom: 20px;
        }
        @keyframes fadeIn {
            from { opacity: 0; }
            to { opacity: 1; }
        }
    </style>
</head>
<body>
    <div class="weather-card">
        <div class="weather-icon" id="weather-icon">☀️</div>
        <div class="temperature" id="temperature">--°C</div>
        <div class="description" id="description">Carregando...</div>
    </div>

    <script>
        document.addEventListener('DOMContentLoaded', function() {
            const weatherIcon = document.getElementById('weather-icon');
            const temperature = document.getElementById('temperature');
            const description = document.getElementById('description');

            const latitude = -23.5505;
            const longitude = -46.6333;

            const apiUrl = `https://api.open-meteo.com/v1/forecast?latitude=${latitude}&longitude=${longitude}&current_weather=true`;

            function getWeatherEmoji(code) {
                if (code >= 0 && code <= 3) return '☀️';
                if (code >= 45 && code <= 48) return '🌫️';
                if (code >= 51 && code <= 67) return '🌧️';
                if (code >= 71 && code <= 77) return '❄️';
                if (code >= 80 && code <= 82) return '🌦️';
                if (code >= 95 && code <= 99) return '⛈️';
                return '❓';
            }

            function getWeatherDescription(code) {
                const descriptions = {
                    0: 'Céu limpo',
                    1: 'Principalmente limpo',
                    2: 'Parcialmente nublado',
                    3: 'Nublado',
                    45: 'Nevoeiro',
                    48: 'Nevoeiro com geada',
                    51: 'Chuvisco leve',
                    53: 'Chuvisco moderado',
                    55: 'Chuvisco intenso',
                    56: 'Chuvisco congelante leve',
                    57: 'Chuvisco congelante intenso',
                    61: 'Chuva leve',
                    63: 'Chuva moderada',
                    65: 'Chuva intensa',
                    66: 'Chuva congelante leve',
                    67: 'Chuva congelante intensa',
                    71: 'Neve leve',
                    73: 'Neve moderada',
                    75: 'Neve intensa',
                    77: 'Grãos de neve',
                    80: 'Pancadas de chuva leve',
                    81: 'Pancadas de chuva moderada',
                    82: 'Pancadas de chuva violenta',
                    85: 'Pancadas de neve leve',
                    86: 'Pancadas de neve intensa',
                    95: 'Tempestade leve',
                    96: 'Tempestade com granizo leve',
                    99: 'Tempestade com granizo intenso'
                };
                return descriptions[code] || 'Condição desconhecida';
            }

            function updateWeatherCard(data) {
                const weatherCode = data.current_weather.weathercode;
                const temp = data.current_weather.temperature;

                weatherIcon.textContent = getWeatherEmoji(weatherCode);
                temperature.textContent = `${temp}°C`;
                description.textContent = getWeatherDescription(weatherCode);
            }

            fetch(apiUrl)
                .then(response => response.json())
                .then(data => {
                    updateWeatherCard(data);
                })
                .catch(error => {
                    console.error('Erro ao obter os dados do clima:', error);
                    description.textContent = 'Não foi possível carregar os dados do clima.';
                });
        });
    </script>
</body>
</html>

Verdict: It met the request but produced a very simple interface.

Deepseek R1

The Chinese AI slightly improved the result. The generated card was more visually appealing and featured a slight animation (moving the card up and down), making the visual experience more interesting. Additionally, the gradient background added a touch of sophistication.

Code generated by Deepseek R1:

<!DOCTYPE html>
<html lang="pt-BR">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Clima em São Paulo</title>
    <style>
        body {
            display: flex;
            justify-content: center;
            align-items: center;
            height: 100vh;
            margin: 0;
            background: linear-gradient(135deg, #6a11cb, #2575fc);
            font-family: 'Arial', sans-serif;
            color: white;
        }

        .card {
            background: rgba(255, 255, 255, 0.1);
            border-radius: 15px;
            padding: 20px;
            width: 300px;
            text-align: center;
            box-shadow: 0 4px 30px rgba(0, 0, 0, 0.1);
            backdrop-filter: blur(10px);
            animation: float 3s ease-in-out infinite;
        }

        @keyframes float {
            0%, 100% {
                transform: translateY(0);
            }
            50% {
                transform: translateY(-10px);
            }
        }

        .weather-icon {
            font-size: 60px;
            margin-bottom: 15px;
        }

        .location {
            font-size: 24px;
            font-weight: bold;
            margin-bottom: 10px;
        }

        .temperature {
            font-size: 48px;
            font-weight: bold;
            margin-bottom: 10px;
        }

        .description {
            font-size: 18px;
            font-style: italic;
        }
    </style>
</head>
<body>
    <div class="card">
        <div class="weather-icon"></div>
        <div class="location">São Paulo, SP</div>
        <div class="temperature">--°C</div>
        <div class="description">--</div>
    </div>

    <script>
        document.addEventListener('DOMContentLoaded', () => {
            const apiUrl = 'https://api.open-meteo.com/v1/forecast';
            const latitude = -23.5505;
            const longitude = -46.6333;

            fetch(`${apiUrl}?latitude=${latitude}&longitude=${longitude}&current_weather=true`)
                .then(response => response.json())
                .then(data => {
                    const weather = data.current_weather;
                    const temperature = weather.temperature;
                    const weatherCode = weather.weathercode;

                    const weatherIcon = document.querySelector('.weather-icon');
                    const temperatureElement = document.querySelector('.temperature');
                    const descriptionElement = document.querySelector('.description');

                    temperatureElement.textContent = `${temperature}°C`;
                    descriptionElement.textContent = getWeatherDescription(weatherCode);
                    weatherIcon.textContent = getWeatherIcon(weatherCode);
                })
                .catch(error => {
                    console.error('Erro ao buscar dados do clima:', error);
                });
        });

        function getWeatherDescription(weatherCode) {
            const weatherDescriptions = {
                0: 'Céu limpo',
                1: 'Principalmente limpo',
                2: 'Parcialmente nublado',
                3: 'Nublado',
                45: 'Nevoeiro',
                48: 'Nevoeiro com geada',
                51: 'Chuvisco leve',
                53: 'Chuvisco moderado',
                55: 'Chuvisco denso',
                56: 'Chuvisco congelante leve',
                57: 'Chuvisco congelante denso',
                61: 'Chuva leve',
                63: 'Chuva moderada',
                65: 'Chuva forte',
                66: 'Chuva congelante leve',
                67: 'Chuva congelante forte',
                71: 'Queda de neve leve',
                73: 'Queda de neve moderada',
                75: 'Queda de neve forte',
                77: 'Grãos de neve',
                80: 'Pancadas de chuva leves',
                81: 'Pancadas de chuva moderadas',
                82: 'Pancadas de chuva violentas',
                85: 'Pancadas de neve leves',
                86: 'Pancadas de neve fortes',
                95: 'Trovoada',
                96: 'Trovoada com chuva leve',
                99: 'Trovoada com chuva forte'
            };

            return weatherDescriptions[weatherCode] || 'Condição desconhecida';
        }

        function getWeatherIcon(weatherCode) {
            const weatherIcons = {
                0: '☀️',
                1: '🌤',
                2: '⛅',
                3: '☁️',
                45: '🌫',
                48: '🌫',
                51: '🌧',
                53: '🌧',
                55: '🌧',
                56: '🌧',
                57: '🌧',
                61: '🌧',
                63: '🌧',
                65: '🌧',
                66: '🌧',
                67: '🌧',
                71: '🌨',
                73: '🌨',
                75: '🌨',
                77: '🌨',
                80: '🌦',
                81: '🌦',
                82: '🌧',
                85: '🌨',
                86: '🌨',
                95: '⛈',
                96: '⛈',
                99: '⛈'
            };

            return weatherIcons[weatherCode] || '❓';
        }
    </script>
</body>
</html>

Verdict: A step up from ChatGPT, with a more refined design and subtle animation.

Claude Sonnet 3.7

Now we have the real champion! Claude Sonnet not only generated a much more beautiful card but also added smoother animations and more useful information, such as humidity, feels-like temperature, and wind speed. The final result looked far more professional and attractive, even though the generated code was significantly larger.

Code generated by Claude Sonnet 3.7:

<!DOCTYPE html>
<html lang="pt-br">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Clima em São Paulo</title>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
        }

        body {
            display: flex;
            justify-content: center;
            align-items: center;
            min-height: 100vh;
            background: linear-gradient(135deg, #4b6cb7, #182848);
        }

        .card {
            width: 300px;
            padding: 25px;
            border-radius: 20px;
            background: rgba(255, 255, 255, 0.1);
            backdrop-filter: blur(10px);
            box-shadow: 0 15px 25px rgba(0, 0, 0, 0.2);
            color: white;
            overflow: hidden;
            position: relative;
            transition: all 0.5s ease;
        }

        .card::before {
            content: '';
            position: absolute;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background: rgba(255, 255, 255, 0.05);
            pointer-events: none;
            transform: translateX(-100%);
        }

        .card:hover::before {
            transform: translateX(0);
            transition: transform 0.5s ease-in-out;
        }

        .card-title {
            text-align: center;
            margin-bottom: 20px;
            font-size: 1.5rem;
        }

        .card-body {
            display: flex;
            flex-direction: column;
            align-items: center;
        }

        .weather-icon {
            font-size: 80px;
            margin-bottom: 15px;
            animation: float 3s ease-in-out infinite;
        }

        .temperature {
            font-size: 2.5rem;
            font-weight: bold;
            margin-bottom: 10px;
        }

        .weather-info {
            text-align: center;
            margin-bottom: 15px;
        }

        .weather-description {
            font-size: 1.2rem;
            margin-bottom: 10px;
        }

        .details {
            display: flex;
            justify-content: space-between;
            width: 100%;
            margin-top: 20px;
        }

        .detail {
            display: flex;
            flex-direction: column;
            align-items: center;
        }

        .detail-icon {
            font-size: 20px;
            margin-bottom: 5px;
        }

        .loading {
            text-align: center;
            font-size: 1.2rem;
        }

        @keyframes float {
            0% {
                transform: translateY(0);
            }
            50% {
                transform: translateY(-10px);
            }
            100% {
                transform: translateY(0);
            }
        }

        .clear-day {
            background: linear-gradient(to bottom right, #4facfe, #00f2fe);
        }

        .clear-night {
            background: linear-gradient(to bottom right, #141e30, #243b55);
        }

        .cloudy, .partly-cloudy-day, .partly-cloudy-night {
            background: linear-gradient(to bottom right, #606c88, #3f4c6b);
        }

        .rain, .showers {
            background: linear-gradient(to bottom right, #373b44, #4286f4);
        }

        .thunderstorm {
            background: linear-gradient(to bottom right, #283048, #859398);
        }

        .snow {
            background: linear-gradient(to bottom right, #e6dada, #274046);
        }

        .fog, .mist {
            background: linear-gradient(to bottom right, #757f9a, #d7dde8);
        }

        .rain-container, .snow-container, .cloud-container, .sun-container {
            position: absolute;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            overflow: hidden;
            pointer-events: none;
            z-index: -1;
        }

        .rain-drop {
            position: absolute;
            width: 2px;
            height: 10px;
            background-color: rgba(255, 255, 255, 0.6);
            border-radius: 0 0 5px 5px;
            animation: rain 1s linear infinite;
        }

        .snowflake {
            position: absolute;
            color: white;
            font-size: 16px;
            animation: snow 5s linear infinite;
        }

        .cloud {
            position: absolute;
            color: rgba(255, 255, 255, 0.8);
            font-size: 40px;
            animation: clouds 15s linear infinite;
        }

        .sun {
            position: absolute;
            color: #FFD700;
            font-size: 35px;
            animation: sun-rotate 20s linear infinite;
        }

        @keyframes rain {
            0% {
                transform: translateY(0) translateX(0);
                opacity: 1;
            }
            100% {
                transform: translateY(100px) translateX(20px);
                opacity: 0;
            }
        }

        @keyframes snow {
            0% {
                transform: translateY(0) rotate(0deg);
                opacity: 0.8;
            }
            100% {
                transform: translateY(100px) rotate(360deg);
                opacity: 0;
            }
        }

        @keyframes clouds {
            0% {
                transform: translateX(-100%);
                opacity: 0;
            }
            10% {
                opacity: 1;
            }
            90% {
                opacity: 1;
            }
            100% {
                transform: translateX(100%);
                opacity: 0;
            }
        }

        @keyframes sun-rotate {
            0% {
                transform: rotate(0deg);
            }
            100% {
                transform: rotate(360deg);
            }
        }

        .wi {
            display: inline-block;
            font-family: 'WeatherIcons';
        }

        @media screen and (max-width: 400px) {
            .card {
                width: 90%;
                padding: 15px;
            }

            .weather-icon {
                font-size: 60px;
            }

            .temperature {
                font-size: 2rem;
            }
        }
    </style>
</head>
<body>
    <div class="card" id="weather-card">
        <div class="loading">Carregando informações do clima...</div>
    </div>

    <script>
        const SAO_PAULO_LAT = -23.5505;
        const SAO_PAULO_LON = -46.6333;

        const weatherCodes = {
            0: { description: "Céu limpo", icon: "☀️", class: "clear-day", animation: "sun" },
            1: { description: "Predominantemente limpo", icon: "🌤️", class: "clear-day", animation: "sun" },
            2: { description: "Parcialmente nublado", icon: "⛅", class: "partly-cloudy-day", animation: "cloud" },
            3: { description: "Nublado", icon: "☁️", class: "cloudy", animation: "cloud" },
            45: { description: "Nevoeiro", icon: "🌫️", class: "fog", animation: "cloud" },
            48: { description: "Nevoeiro com geada", icon: "🌫️", class: "fog", animation: "cloud" },
            51: { description: "Garoa leve", icon: "🌦️", class: "showers", animation: "rain" },
            53: { description: "Garoa moderada", icon: "🌦️", class: "showers", animation: "rain" },
            55: { description: "Garoa intensa", icon: "🌧️", class: "rain", animation: "rain" },
            56: { description: "Garoa congelante leve", icon: "🌨️", class: "snow", animation: "snow" },
            57: { description: "Garoa congelante intensa", icon: "🌨️", class: "snow", animation: "snow" },
            61: { description: "Chuva leve", icon: "🌦️", class: "showers", animation: "rain" },
            63: { description: "Chuva moderada", icon: "🌧️", class: "rain", animation: "rain" },
            65: { description: "Chuva intensa", icon: "🌧️", class: "rain", animation: "rain" },
            66: { description: "Chuva congelante leve", icon: "🌨️", class: "snow", animation: "snow" },
            67: { description: "Chuva congelante intensa", icon: "🌨️", class: "snow", animation: "snow" },
            71: { description: "Neve leve", icon: "🌨️", class: "snow", animation: "snow" },
            73: { description: "Neve moderada", icon: "🌨️", class: "snow", animation: "snow" },
            75: { description: "Neve intensa", icon: "❄️", class: "snow", animation: "snow" },
            77: { description: "Grãos de neve", icon: "❄️", class: "snow", animation: "snow" },
            80: { description: "Pancadas de chuva leves", icon: "🌦️", class: "showers", animation: "rain" },
            81: { description: "Pancadas de chuva moderadas", icon: "🌧️", class: "rain", animation: "rain" },
            82: { description: "Pancadas de chuva violentas", icon: "🌧️", class: "rain", animation: "rain" },
            85: { description: "Pancadas de neve leves", icon: "🌨️", class: "snow", animation: "snow" },
            86: { description: "Pancadas de neve fortes", icon: "❄️", class: "snow", animation: "snow" },
            95: { description: "Tempestade", icon: "⛈️", class: "thunderstorm", animation: "rain" },
            96: { description: "Tempestade com granizo leve", icon: "⛈️", class: "thunderstorm", animation: "rain" },
            99: { description: "Tempestade com granizo forte", icon: "⛈️", class: "thunderstorm", animation: "rain" }
        };

        function formatDate(date) {
            const options = { 
                weekday: 'long', 
                year: 'numeric', 
                month: 'long', 
                day: 'numeric',
                hour: '2-digit',
                minute: '2-digit'
            };
            return date.toLocaleDateString('pt-BR', options);
        }

        function createWeatherAnimation(animationType) {
            const container = document.createElement('div');
            container.className = `${animationType}-container`;

            switch(animationType) {
                case 'rain':
                    for (let i = 0; i < 20; i++) {
                        const drop = document.createElement('div');
                        drop.className = 'rain-drop';
                        drop.style.left = `${Math.random() * 100}%`;
                        drop.style.animationDuration = `${0.7 + Math.random() * 0.3}s`;
                        drop.style.animationDelay = `${Math.random() * 2}s`;
                        container.appendChild(drop);
                    }
                    break;
                case 'snow':
                    for (let i = 0; i < 15; i++) {
                        const snowflake = document.createElement('div');
                        snowflake.className = 'snowflake';
                        snowflake.textContent = '❄';
                        snowflake.style.left = `${Math.random() * 100}%`;
                        snowflake.style.animationDuration = `${5 + Math.random() * 5}s`;
                        snowflake.style.animationDelay = `${Math.random() * 5}s`;
                        container.appendChild(snowflake);
                    }
                    break;
                case 'cloud':
                    for (let i = 0; i < 3; i++) {
                        const cloud = document.createElement('div');
                        cloud.className = 'cloud';
                        cloud.textContent = '☁️';
                        cloud.style.top = `${10 + Math.random() * 40}%`;
                        cloud.style.animationDuration = `${15 + Math.random() * 15}s`;
                        cloud.style.animationDelay = `${Math.random() * 5}s`;
                        container.appendChild(cloud);
                    }
                    break;
                case 'sun':
                    const sun = document.createElement('div');
                    sun.className = 'sun';
                    sun.textContent = '☀️';
                    sun.style.top = '10%';
                    sun.style.right = '10%';
                    container.appendChild(sun);
                    break;
            }

            return container;
        }

        async function fetchWeatherData() {
            try {
                const response = await fetch(`https://api.open-meteo.com/v1/forecast?latitude=${SAO_PAULO_LAT}&longitude=${SAO_PAULO_LON}&current=temperature_2m,relative_humidity_2m,apparent_temperature,precipitation,weather_code,wind_speed_10m&timezone=America%2FSao_Paulo`);

                if (!response.ok) {
                    throw new Error('Falha ao obter dados meteorológicos');
                }

                const data = await response.json();
                return data;
            } catch (error) {
                console.error('Erro ao buscar dados meteorológicos:', error);
                throw error;
            }
        }

        async function renderWeatherCard() {
            const cardElement = document.getElementById('weather-card');

            try {
                const weatherData = await fetchWeatherData();
                const current = weatherData.current;

                const weatherCode = current.weather_code;
                const weatherInfo = weatherCodes[weatherCode] || {
                    description: "Indisponível",
                    icon: "❓",
                    class: "cloudy",
                    animation: "cloud"
                };

                cardElement.className = `card ${weatherInfo.class}`;

                const animation = createWeatherAnimation(weatherInfo.animation);
                cardElement.appendChild(animation);

                const temp = Math.round(current.temperature_2m);
                const humidity = Math.round(current.relative_humidity_2m);
                const windSpeed = Math.round(current.wind_speed_10m);
                const feelsLike = Math.round(current.apparent_temperature);
                const precipitation = current.precipitation;

                const now = new Date();
                const formattedDate = formatDate(now);

                cardElement.innerHTML = `
                    <h2 class="card-title">Clima em São Paulo</h2>
                    <div class="card-body">
                        <div class="weather-icon">${weatherInfo.icon}</div>
                        <div class="temperature">${temp}°C</div>
                        <div class="weather-info">
                            <div class="weather-description">${weatherInfo.description}</div>
                            <div class="date">${formattedDate}</div>
                        </div>
                        <div class="details">
                            <div class="detail">
                                <div class="detail-icon">💧</div>
                                <div>${humidity}%</div>
                                <div>Umidade</div>
                            </div>
                            <div class="detail">
                                <div class="detail-icon">💨</div>
                                <div>${windSpeed} km/h</div>
                                <div>Vento</div>
                            </div>
                            <div class="detail">
                                <div class="detail-icon">🌡️</div>
                                <div>${feelsLike}°C</div>
                                <div>Sensação</div>
                            </div>
                        </div>
                    </div>
                `;

                cardElement.appendChild(animation);

            } catch (error) {
                cardElement.innerHTML = `
                    <div class="error">
                        <h2>Erro ao carregar dados</h2>
                        <p>Não foi possível obter informações sobre o clima em São Paulo.</p>
                        <button onclick="renderWeatherCard()">Tentar novamente</button>
                    </div>
                `;
            }
        }

        document.addEventListener('DOMContentLoaded', renderWeatherCard);
    </script>
</body>
</html>

Verdict: By far the best result! Beautiful design, smooth animations, and more information.

Conclusion

If you're using ChatGPT to generate code, you might be missing out on much better solutions.

While GPT-4o created a static and uninspiring card, Claude Sonnet 3.7 delivered a beautiful, animated design with more useful information.

If you want more efficient, visually appealing, and functional code, Claude Sonnet is the best choice!

So, have you tested any of these tools? Share your experience in the comments!