Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

5 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

🎨 Concept Art Trainer

A free training tool for concept artists to practice breaking down client briefs into actionable design questions.

Live site: https://concept-art-training.vercel.app/

License Coverage

Features

  • AI-Generated Client Briefs - Realistic briefs with configurable difficulty, genre, design type, and more
  • Question Breakdown Workspace - Organize your analysis into categories (silhouette, color, materials, etc.)
  • Client Q&A Simulator - Chat with simulated clients who have different personalities
  • Research Suggestions - AI-generated research topics based on the brief
  • Reveal Mode - Compare your breakdown with an AI-generated ideal after submission
  • Progress Dashboard - Track which design types and difficulties you've practiced
  • Brief Sharing - Share briefs with other artists via URL
  • Terminology Glossary - Learn industry terms as you practice

Bring Your Own API Key

This app requires users to provide their own AI API key. Supported providers:

  • Anthropic (Claude)
  • OpenAI (GPT-4, GPT-3.5)
  • Google AI (Gemini)
  • OpenRouter (Multiple models)
  • Groq (Fast & cheap Llama, Mixtral)

API keys are stored locally in the browser and never sent to any server except the user's chosen AI provider.

Local Development

# Install dependencies
npm install

# Start dev server
npm run dev

# Build for production
npm run build

# Preview production build
npm run preview

Deployment

Option 1: Vercel (Recommended - Easiest)

  1. Push this code to a GitHub repository
  2. Go to vercel.com and sign in with GitHub
  3. Click "New Project" and import your repository
  4. Click "Deploy" - that's it!

Vercel will automatically detect it's a Vite project and configure everything.

Option 2: Netlify

  1. Push this code to a GitHub repository
  2. Go to netlify.com and sign in with GitHub
  3. Click "New site from Git" and select your repository
  4. Build settings (should auto-detect):
    • Build command: npm run build
    • Publish directory: dist
  5. Click "Deploy site"

Option 3: GitHub Pages

  1. Install gh-pages: npm install -D gh-pages

  2. Add to package.json scripts:

    "predeploy": "npm run build",
    "deploy": "gh-pages -d dist"
  3. Add to vite.config.js:

    base: '/your-repo-name/',
  4. Run: npm run deploy

Option 4: Cloudflare Pages

  1. Push to GitHub
  2. Go to pages.cloudflare.com
  3. Connect your repository
  4. Build settings:
    • Framework preset: Vite
    • Build command: npm run build
    • Build output: dist

Option 5: Docker (Local or Any Container Platform)

# Build the image
docker build -t concept-art-trainer .

# Run locally
docker run -p 8080:80 concept-art-trainer

# Or use docker-compose
docker-compose up

Then open http://localhost:8080


Cloud Container Deployment

AWS (Multiple Options)

Option A: AWS App Runner (Easiest)

  1. Push your image to Amazon ECR:
# Login to ECR
aws ecr get-login-password --region us-east-1 | docker login --username AWS --password-stdin YOUR_ACCOUNT_ID.dkr.ecr.us-east-1.amazonaws.com

# Create repository
aws ecr create-repository --repository-name concept-art-trainer

# Tag and push
docker tag concept-art-trainer:latest YOUR_ACCOUNT_ID.dkr.ecr.us-east-1.amazonaws.com/concept-art-trainer:latest
docker push YOUR_ACCOUNT_ID.dkr.ecr.us-east-1.amazonaws.com/concept-art-trainer:latest
  1. Go to AWS App Runner Console
  2. Click "Create service"
  3. Select "Container registry" → "Amazon ECR"
  4. Select your image
  5. Configure:
    • Port: 80
    • CPU: 0.25 vCPU (plenty for static site)
    • Memory: 0.5 GB
  6. Deploy

Cost: ~$5-15/month for minimal traffic

Option B: AWS ECS with Fargate

  1. Push image to ECR (same as above)
  2. Create an ECS Cluster (Fargate)
  3. Create a Task Definition:
{
  "family": "concept-art-trainer",
  "networkMode": "awsvpc",
  "requiresCompatibilities": ["FARGATE"],
  "cpu": "256",
  "memory": "512",
  "containerDefinitions": [
    {
      "name": "concept-art-trainer",
      "image": "YOUR_ACCOUNT_ID.dkr.ecr.us-east-1.amazonaws.com/concept-art-trainer:latest",
      "portMappings": [
        {
          "containerPort": 80,
          "protocol": "tcp"
        }
      ],
      "healthCheck": {
        "command": [
          "CMD-SHELL",
          "wget --quiet --tries=1 --spider http://localhost:80/health || exit 1"
        ],
        "interval": 30,
        "timeout": 5,
        "retries": 3
      }
    }
  ]
}
  1. Create a Service with an Application Load Balancer

Option C: AWS Lightsail Containers (Simplest AWS Option)

  1. Go to Lightsail Console
  2. Click "Containers" → "Create container service"
  3. Choose the $7/month nano plan
  4. Deploy from local image
  5. Configure public endpoint on port 80
# Install Lightsail plugin
aws lightsailctl

# Push image
aws lightsail push-container-image \
  --service-name concept-art-trainer \
  --label latest \
  --image concept-art-trainer:latest

Azure (Multiple Options)

Option A: Azure Container Apps (Recommended)

  1. Push image to Azure Container Registry:
# Login to Azure
az login

# Create resource group
az group create --name concept-art-rg --location eastus

# Create container registry
az acr create --resource-group concept-art-rg --name conceptarttrainer --sku Basic

# Login to ACR
az acr login --name conceptarttrainer

# Tag and push
docker tag concept-art-trainer conceptarttrainer.azurecr.io/concept-art-trainer:latest
docker push conceptarttrainer.azurecr.io/concept-art-trainer:latest
  1. Deploy to Container Apps:
# Create Container Apps environment
az containerapp env create \
  --name concept-art-env \
  --resource-group concept-art-rg \
  --location eastus

# Deploy the app
az containerapp create \
  --name concept-art-trainer \
  --resource-group concept-art-rg \
  --environment concept-art-env \
  --image conceptarttrainer.azurecr.io/concept-art-trainer:latest \
  --target-port 80 \
  --ingress external \
  --registry-server conceptarttrainer.azurecr.io \
  --cpu 0.25 \
  --memory 0.5Gi \
  --min-replicas 0 \
  --max-replicas 1

Cost: Can scale to zero, pay only for usage (~$0-10/month for low traffic)

Option B: Azure App Service (Container)

  1. Push to ACR (same as above)
  2. Create App Service:
# Create App Service plan
az appservice plan create \
  --name concept-art-plan \
  --resource-group concept-art-rg \
  --is-linux \
  --sku B1

# Create web app
az webapp create \
  --resource-group concept-art-rg \
  --plan concept-art-plan \
  --name concept-art-trainer \
  --deployment-container-image-name conceptarttrainer.azurecr.io/concept-art-trainer:latest

# Configure ACR access
az webapp config container set \
  --name concept-art-trainer \
  --resource-group concept-art-rg \
  --docker-registry-server-url https://conceptarttrainer.azurecr.io

Option C: Azure Container Instances (Simplest)

# One command deployment
az container create \
  --resource-group concept-art-rg \
  --name concept-art-trainer \
  --image conceptarttrainer.azurecr.io/concept-art-trainer:latest \
  --dns-name-label concept-art-trainer \
  --ports 80 \
  --cpu 0.5 \
  --memory 0.5

Access at: http://concept-art-trainer.eastus.azurecontainer.io


Google Cloud Run

# Build and push to Google Container Registry
gcloud builds submit --tag gcr.io/YOUR_PROJECT/concept-art-trainer

# Deploy
gcloud run deploy concept-art-trainer \
  --image gcr.io/YOUR_PROJECT/concept-art-trainer \
  --platform managed \
  --region us-central1 \
  --allow-unauthenticated \
  --port 80 \
  --cpu 1 \
  --memory 256Mi \
  --min-instances 0 \
  --max-instances 1

Cost: Free tier includes 2 million requests/month


DigitalOcean App Platform

  1. Push to Docker Hub or DigitalOcean Container Registry
  2. Create App → Select "Docker Hub" or "DOCR"
  3. Configure:
    • HTTP Port: 80
    • Instance Size: Basic ($5/month)
  4. Deploy

CI/CD with GitHub Actions

Create .github/workflows/deploy.yml:

name: Build and Deploy

on:
  push:
    branches: [main]

env:
  IMAGE_NAME: concept-art-trainer

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Build Docker image
        run: docker build -t $IMAGE_NAME .

      - name: Log in to registry
        run: echo "${{ secrets.REGISTRY_PASSWORD }}" | docker login -u "${{ secrets.REGISTRY_USERNAME }}" --password-stdin ${{ secrets.REGISTRY_URL }}

      - name: Push image
        run: |
          docker tag $IMAGE_NAME ${{ secrets.REGISTRY_URL }}/$IMAGE_NAME:latest
          docker tag $IMAGE_NAME ${{ secrets.REGISTRY_URL }}/$IMAGE_NAME:${{ github.sha }}
          docker push ${{ secrets.REGISTRY_URL }}/$IMAGE_NAME:latest
          docker push ${{ secrets.REGISTRY_URL }}/$IMAGE_NAME:${{ github.sha }}

Add your registry secrets in GitHub → Settings → Secrets.

Testing

This project uses Vitest with React Testing Library for testing.

Test Coverage

Metric Coverage
Statements 99.62%
Branches 93.43%
Functions 100%
Lines 99.62%

Running Tests

# Run tests in watch mode
npm test

# Run tests once
npm run test:run

# Run tests with UI
npm run test:ui

# Run tests with coverage
npm run test:coverage

Test Structure

Tests are co-located with their source files:

  • Component.tsxComponent.test.tsx
  • module.tsmodule.test.ts

Writing Tests

// Example component test
import { describe, it, expect, vi } from 'vitest';
import { render, screen, fireEvent } from '@testing-library/react';
import { Button } from './Button';

describe('Button', () => {
  it('should call onClick when clicked', () => {
    const handleClick = vi.fn();
    render(<Button onClick={handleClick}>Click me</Button>);

    fireEvent.click(screen.getByText('Click me'));
    expect(handleClick).toHaveBeenCalledTimes(1);
  });
});

Customization

Adding More Providers

Edit the API_PROVIDERS object in src/App.tsx:

const API_PROVIDERS = {
  // ... existing providers
  newprovider: {
    name: 'New Provider',
    endpoint: 'https://api.newprovider.com/v1/chat',
    modelsEndpoint: 'https://api.newprovider.com/v1/models',
    keyPlaceholder: 'np-...',
    docsUrl: 'https://newprovider.com/api-keys',
  },
};

Then add the corresponding fetch logic in fetchModels() and API call logic in callLLM().

Adding Design Types

Edit the DESIGN_TYPES array and add corresponding entries in CONDITIONAL_OPTIONS.

Adding Glossary Terms

Edit the GLOSSARY object to add new terms and definitions.

License

MIT License - feel free to use, modify, and distribute.

Credits

Built with:

Inspired by concept art training exercises from the game and film industry.

About

Concept art brief generation tool to help learn concept art ideation

Resources

Contributing

Stars

Watchers

Forks

Releases

Packages

Used by

Contributors

Languages