Qwen3-Coder-30B-A3B-Instruct is a next-generation code-focused language model built for developers, engineers, and technical creators who need both power and flexibility. With support for massive context windows and advanced tool-calling abilities, it’s designed to handle everything from repository-scale code understanding to real-time coding assistance. Whether you’re exploring code completions, building automations, or interacting with complex functions, Qwen3-Coder-30B-A3B-Instruct delivers fast, efficient results—making it a practical choice for modern coding workflows and experimentation.
Qwen3-Coder-Flash Benchmarks Table
Benchmark | Qwen3-Coder 30B-A3B-Instruct | Qwen3-Coder 480B-A35B-Instruct | Kimi-K2 Instruct | DeepSeek-V3 0324 | Claude Sonnet-4 | OpenAI GPT-4.1 |
---|
Agentic Coding | | | | | | |
Terminal-Bench | 31.3 | 37.5 | 30.0 | 2.5 | 35.5 | 25.3 |
SWE-bench Verified | | | | | | |
w/ OpenHands, 500 turns | 51.6 | 69.6 | – | – | 70.4 | – |
w/ OpenHands, 100 turns | 51.6 | 67.0 | 65.4 | 38.8 | 68.0 | 48.6 |
w/ Private Scaffolding | – | – | 65.8 | 22.3 | 72.7 | 63.8 |
SWE-bench Live | 20.7 | 26.3 | 22.4 | 13.0 | 27.7 | – |
SWE-bench Multilingual | 34.7 | 54.7 | 47.3 | 13.0 | 53.3 | 31.5 |
Multi-SWE-bench mini | 19.5 | 25.8 | 19.8 | 15.6 | 24.8 | – |
Multi-SWE-bench flash | 19.3 | 27.0 | 20.7 | 15.9 | 25.0 | – |
Aider-Polyglot | 33.3 | 61.8 | 56.9 | – | 56.4 | 52.4 |
Spider2 | 21.4 | 31.1 | 25.2 | 17.7 | 31.1 | 25.6 |
Agentic Browser Use | | | | | | |
WebArena | 43.5 | 49.9 | 47.4 | 40.0 | 51.1 | 44.3 |
Mind2Web | 51.0 | 55.8 | 42.7 | 36.0 | 47.4 | 49.6 |
Agentic Tool Use | | | | | | |
BFCL-v3 | 62.2 | 68.7 | 65.2 | 64.7 | 73.3 | 62.9 |
TAU-Bench Retail | 68.7 | 77.5 | 70.7 | 59.1 | 80.5 | – |
TAU-Bench Airline | 48.0 | 60.0 | 53.5 | 40.0 | 60.0 | – |
Qwen3-Coder-30B-A3B-Instruct – Recommended GPU Configuration
Format / Quantization | Min GPU (VRAM) | Recommended GPU | Notes / Use Case |
---|
GGUF Q4 (e.g., Q4_K_S, IQ4_NL) | 16 GB (can run on some 12 GB GPUs) | 24 GB (A6000, 4090, H100, A100) | For llama.cpp, Ollama, LM Studio, local inferencing; single GPU, fastest start |
GGUF Q5/Q6 | 24 GB | 24 GB+ (A6000, 4090, H100, A100) | Slightly higher quality, still fast |
GGUF Q8/FP16 | 48 GB | 48 GB+ (A6000, H100, A100, 3090) | Higher precision, much more RAM needed |
Transformers (float16, bfloat16, no quant) | 48–80 GB | 80 GB (H100, A100) | For maximum quality, context, and multi-GPU parallelism |
4-bit (transformers) | 24 GB | 24 GB+ | For bitsandbytes 4-bit inference |
8-bit (transformers) | 40 GB | 48 GB+ | For 8-bit quantization |
Multi-GPU (Full FP16) | 2×40 GB+ | 2–4×A100 40GB/80GB, H100 | For full context window, large batch, training/finetune |
Most Popular Single-GPU Setups
GPU Model | VRAM | Runs Q4 GGUF? | Runs Q8 GGUF? | Runs Transformers? | Notes |
---|
RTX 4090 | 24 GB | Yes | No | 4-bit, 8-bit only | Good perf, desktop class |
RTX A6000 | 48 GB | Yes | Yes | 8-bit, some FP16 | Ideal for all GGUF |
NVIDIA H100 | 80 GB | Yes | Yes | Yes (all) | Datacenter grade, all workloads |
NVIDIA A100 | 40/80 GB | Yes | Yes | Yes (all) | Datacenter, all workloads |
RTX 3090 | 24 GB | Yes | No | 4-bit, 8-bit only | Marginal for big context |
Tesla T4/L4 | 16 GB | Yes (Q4) | No | No | For minimal GGUF, limited context |
Summary
- For fast chat, code, and web UI on a single GPU, Q4/Q5 GGUF models on a 24GB+ GPU (4090, A6000) are ideal.
- For full-precision or multi-turn, high-context tasks, use H100/A100 80GB.
- 4-bit GGUF will run even on consumer GPUs with 16GB+ VRAM, but for smooth operation and bigger context, 24GB or more is best.
Resources
Link: https://huggingface.co/unsloth/Qwen3-Coder-30B-A3B-Instruct-GGUF
Step-by-Step Process to Install & Run Qwen3-Coder-Flash Locally
For the purpose of this tutorial, we will use a GPU-powered Virtual Machine offered by NodeShift; however, you can replicate the same steps with any other cloud provider of your choice. NodeShift provides the most affordable Virtual Machines at a scale that meets GDPR, SOC2, and ISO27001 requirements.
Step 1: Sign Up and Set Up a NodeShift Cloud Account
Visit the NodeShift Platform and create an account. Once you’ve signed up, log into your account.
Follow the account setup process and provide the necessary details and information.
Step 2: Create a GPU Node (Virtual Machine)
GPU Nodes are NodeShift’s GPU Virtual Machines, on-demand resources equipped with diverse GPUs ranging from H100s to A100s. These GPU-powered VMs provide enhanced environmental control, allowing configuration adjustments for GPUs, CPUs, RAM, and Storage based on specific requirements.
Navigate to the menu on the left side. Select the GPU Nodes option, create a GPU Node in the Dashboard, click the Create GPU Node button, and create your first Virtual Machine deploy
Step 3: Select a Model, Region, and Storage
In the “GPU Nodes” tab, select a GPU Model and Storage according to your needs and the geographical region where you want to launch your model.
We will use 1 x H100 SXM GPU for this tutorial to achieve the fastest performance. However, you can choose a more affordable GPU with less VRAM if that better suits your requirements.
Step 4: Select Authentication Method
There are two authentication methods available: Password and SSH Key. SSH keys are a more secure option. To create them, please refer to our official documentation.
Step 5: Choose an Image
In our previous blogs, we used pre-built images from the Templates tab when creating a Virtual Machine. However, for running Qwen3-Coder-Flash, we need a more customized environment with full CUDA development capabilities. That’s why, in this case, we switched to the Custom Image tab and selected a specific Docker image that meets all runtime and compatibility requirements.
We chose the following image:
nvidia/cuda:12.1.1-devel-ubuntu22.04
This image is essential because it includes:
- Full CUDA toolkit (including
nvcc
)
- Proper support for building and running GPU-based applications like Qwen3-Coder-Flash
- Compatibility with CUDA 12.1.1 required by certain model operations
Launch Mode
We selected:
Interactive shell server
This gives us SSH access and full control over terminal operations — perfect for installing dependencies, running benchmarks, and launching tools like Hunyuan3D World 1.0.
Docker Repository Authentication
We left all fields empty here.
Since the Docker image is publicly available on Docker Hub, no login credentials are required.
Identification
nvidia/cuda:12.1.1-devel-ubuntu22.04
CUDA and cuDNN images from gitlab.com/nvidia/cuda. Devel version contains full cuda toolkit with nvcc.
This setup ensures that the Qwen3-Coder-Flash runs in a GPU-enabled environment with proper CUDA access and high compute performance.
After choosing the image, click the ‘Create’ button, and your Virtual Machine will be deployed.
Step 6: Virtual Machine Successfully Deployed
You will get visual confirmation that your node is up and running.
Step 7: Connect to GPUs using SSH
NodeShift GPUs can be connected to and controlled through a terminal using the SSH key provided during GPU creation.
Once your GPU Node deployment is successfully created and has reached the ‘RUNNING’ status, you can navigate to the page of your GPU Deployment Instance. Then, click the ‘Connect’ button in the top right corner.
Now open your terminal and paste the proxy SSH IP or direct SSH IP.
Next, If you want to check the GPU details, run the command below:
nvidia-smi
Step 8: Install Ollama
After connecting to the terminal via SSH, it’s now time to install Ollama from the official Ollama website.
Website Link: https://ollama.com/
Run the following command to install the Ollama:
curl -fsSL https://ollama.com/install.sh | sh
Step 9: Serve Ollama
Run the following command to host the Ollama so that it can be accessed and utilized efficiently:
ollama serve
Step 10: Open the Model Page and Choose Your GGUF File
- Go to the model’s Hugging Face page for
Qwen3-Coder-30B-A3B-Instruct-GGUF
Link: https://huggingface.co/unsloth/Qwen3-Coder-30B-A3B-Instruct-GGUF
- Switch to the “Files and versions” tab to see all available GGUF files and quantizations.
- Browse the list and choose the quantized GGUF file you want to run (such as
Qwen3-Coder-30B-A3B-Instruct-IQ4_NL.gguf
, Qwen3-Coder-30B-A3B-Instruct-Q4_K_S.gguf
, etc.).
- Note the file name and tag (everything after the last
-
and before .gguf
is usually the tag you’ll use with your Ollama command).
- You are now ready to use this file with your Ollama run command in the next step!
Step 11: Run the Model in Your Terminal
- Open your terminal on the VM or local machine.
- Use the
ollama run
command with your chosen model and quantization.
For example:
ollama run hf.co/unsloth/Qwen3-Coder-30B-A3B-Instruct-GGUF:IQ4_NL
- Ollama will start downloading and preparing the model. You’ll see progress bars as files are pulled (this may take some time depending on the file size and your network speed).
- Once loaded, you’ll get an interactive prompt where you can start chatting with the model right away!
- Try a sample message, like
who are you?
, and confirm you get a response from Qwen3-Coder.
Step 12: Check the Available Python version and Install the new version
Run the following commands to check the available Python version.
If you check the version of the python, system has Python 3.8.1 available by default. To install a higher version of Python, you’ll need to use the deadsnakes
PPA.
Run the following commands to add the deadsnakes
PPA:
sudo apt update
sudo apt install -y software-properties-common
sudo add-apt-repository -y ppa:deadsnakes/ppa
sudo apt update
Step 13: Install Python 3.11
Now, run the following command to install Python 3.11 or another desired version:
sudo apt install -y python3.11 python3.11-venv python3.11-dev
Step 14: Update the Default Python3
Version
Now, run the following command to link the new Python version as the default python3
:
sudo update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.8 1
sudo update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.11 2
sudo update-alternatives --config python3
Then, run the following command to verify that the new Python version is active:
python3 --version
Step 15: Install and Update Pip
Run the following command to install and update the pip:
curl -O https://bootstrap.pypa.io/get-pip.py
python3.11 get-pip.py
Then, run the following command to check the version of pip:
pip --version
Step 16: Created and activated Python 3.11 virtual environment
Run the following commands to created and activated Python 3.11 virtual environment:
apt update && apt install -y python3.11-venv git wget
python3.11 -m venv openwebui
source openwebui/bin/activate
Step 17: Install Open-WebUI
Run the following command to install open-webui:
pip install open-webui
Step 18: Serve Open-WebUI
In your activated Python environment, start the Open-WebUI server by running:
open-webui serve
- Wait for the server to complete all database migrations and set up initial files. You’ll see a series of INFO logs and a large “OPEN WEBUI” banner in the terminal.
- When setup is complete, the WebUI will be available and ready for you to access via your browser.
Step 19: Set up SSH port forwarding from your local machine
On your local machine (Mac/Windows/Linux), open a terminal and run:
ssh -L 8080:localhost:8080 -p 29598 root@115.124.123.238
This forwards:
Local localhost:8000
→ Remote VM 127.0.0.1:8000
Step 20: Access Open-WebUI in Your Browser
Go to:
http://localhost:8080
- You should see the Open-WebUI login or setup page.
- Log in or create a new account if this is your first time.
- You’re now ready to use Open-WebUI to interact with your models!
After signing up or logging in to Open-WebUI, you’ll see your downloaded model automatically listed and ready for use in the model selection panel. This confirms that your setup is complete—just select the model (like hf.co/unsloth/Qwen3-Coder-30B-A3B-Instruct-GGUF:IQ4_NL
) and you can start chatting or running advanced tasks right from the web interface, all powered by your own hardware and local model!
Step 21: Generate and Preview Creative Outputs
- Enter your creative prompt (for example, a request for an interactive HTML/JS project) into the chat panel of Open-WebUI.
- The model will process your prompt and generate a complete code solution—often with a live code preview and a fully rendered output on the right.
- Preview the output:
- If your prompt requests interactive web content, you’ll see a live demo (like the “Matrix Code Rain with Hacked Creatures”) side-by-side with the generated HTML code.
- You can interact directly with the preview to test features such as clicks, effects, and animations.
- If needed, copy or download the code for use in your own projects.
Generated code from model:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Matrix Code Rain - Hacked Creatures</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
background-color: #000;
overflow: hidden;
font-family: 'Courier New', monospace;
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
color: #0f0;
}
canvas {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 1;
}
.container {
position: relative;
width: 100%;
height: 100%;
z-index: 2;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
text-align: center;
padding: 20px;
pointer-events: none;
}
h1 {
font-size: 3rem;
margin-bottom: 20px;
text-shadow: 0 0 10px #0f0;
letter-spacing: 3px;
animation: pulse 2s infinite;
}
.instructions {
background-color: rgba(0, 20, 0, 0.7);
padding: 20px;
border-radius: 10px;
max-width: 600px;
backdrop-filter: blur(5px);
border: 1px solid #0f0;
box-shadow: 0 0 20px rgba(0, 255, 0, 0.3);
}
p {
margin: 10px 0;
font-size: 1.2rem;
line-height: 1.6;
}
.highlight {
color: #0f0;
font-weight: bold;
}
@keyframes pulse {
0% { opacity: 0.7; }
50% { opacity: 1; }
100% { opacity: 0.7; }
}
.glow {
animation: glow 1.5s ease-in-out infinite alternate;
}
@keyframes glow {
from { text-shadow: 0 0 5px #0f0, 0 0 10px #0f0; }
to { text-shadow: 0 0 15px #0f0, 0 0 25px #0f0; }
}
.creature {
position: absolute;
font-size: 24px;
z-index: 3;
pointer-events: none;
animation: fadeOut 3s forwards;
}
@keyframes fadeOut {
0% { opacity: 1; transform: scale(1); }
100% { opacity: 0; transform: scale(0.5); }
}
</style>
</head>
<body>
<canvas id="matrixCanvas"></canvas>
<div class="container">
<h1 class="glow">MATRIX CODE RAIN</h1>
<div class="instructions">
<p>Click anywhere to <span class="highlight">hack the matrix</span> and spawn ASCII creatures!</p>
<p>Watch as they ride the digital streams of code...</p>
<p>Each creature will <span class="highlight">dissolve after a few seconds</span></p>
</div>
</div>
<script>
// Get canvas and context
const canvas = document.getElementById('matrixCanvas');
const ctx = canvas.getContext('2d');
// Set canvas to full window size
function resizeCanvas() {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
}
// Initial resize
resizeCanvas();
window.addEventListener('resize', resizeCanvas);
// Matrix characters - Katakana, Latin, and symbols
const chars = "アァカサタナハマヤャラワガザダバパイィキシチニヒミリヰギジヂビピウゥクスツヌフムユュルグズブヅプエェケセテネヘメレヱゲゼデベペオォコソトノホモヨョロヲゴゾドボポヴッン0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
const charArray = chars.split('');
// Font size and columns
const fontSize = 14;
const columns = canvas.width / fontSize;
// Create drops for each column
const drops = [];
for (let i = 0; i < columns; i++) {
drops[i] = Math.floor(Math.random() * -100);
}
// Matrix rain effect
function drawMatrix() {
// Semi-transparent black overlay to create trail effect
ctx.fillStyle = 'rgba(0, 0, 0, 0.05)';
ctx.fillRect(0, 0, canvas.width, canvas.height);
// Draw characters
ctx.font = `${fontSize}px 'Courier New', monospace`;
for (let i = 0; i < drops.length; i++) {
const char = charArray[Math.floor(Math.random() * charArray.length)];
// Bright green for head of stream, fade to dimmer as it goes down
const brightness = Math.min(255, Math.abs(drops[i]) * 3);
ctx.fillStyle = `rgb(0, ${brightness}, 0)`;
ctx.fillText(char, i * fontSize, drops[i] * fontSize);
// Reset drop if it reaches the bottom or randomly
if (drops[i] * fontSize > canvas.height && Math.random() > 0.975) {
drops[i] = 0;
}
drops[i]++;
}
}
// CRT flicker effect
function drawCRT() {
const time = Date.now();
const flickerIntensity = 0.1 + Math.sin(time * 0.01) * 0.05;
ctx.fillStyle = `rgba(0, 255, 0, ${flickerIntensity})`;
ctx.fillRect(0, 0, canvas.width, canvas.height);
}
// ASCII creatures
const creatures = [
" ╔══╗ \n ║ ║ \n ╚══╝ ",
" ╭─╮ \n │ ││ \n ╰─╯ ",
" ╔═╗ \n ║ ║ \n ╚═╝ ",
" ╭─╮ \n │ ║ \n ╰─╯ ",
" ╔══╗ \n ║ ║ \n ╚══╝ ",
" ╭─╮ \n │ ║ \n ╰─╯ ",
" ╔═╗ \n ║ ║ \n ╚═╝ ",
" ╭─╮ \n │ ││ \n ╰─╯ "
];
// Track active creatures
const activeCreatures = [];
// Create a creature at position
function createCreature(x, y) {
const creature = {
id: Date.now() + Math.random(),
x: x,
y: y,
char: creatures[Math.floor(Math.random() * creatures.length)],
life: 0,
maxLife: 300 // frames before dissolving
};
activeCreatures.push(creature);
}
// Draw creatures
function drawCreatures() {
for (let i = 0; i < activeCreatures.length; i++) {
const creature = activeCreatures[i];
creature.life++;
// Fade out as life progresses
const alpha = Math.max(0, 1 - (creature.life / creature.maxLife));
ctx.fillStyle = `rgba(0, 255, 0, ${alpha})`;
// Split character string into lines and draw them
const lines = creature.char.split('\n');
const charHeight = fontSize;
const startX = Math.floor(creature.x / fontSize) * fontSize;
const startY = Math.floor(creature.y / fontSize) * fontSize;
for (let j = 0; j < lines.length; j++) {
ctx.fillText(lines[j], startX, startY + (j * charHeight));
}
// Remove creature if life is over
if (creature.life > creature.maxLife) {
activeCreatures.splice(i, 1);
i--;
}
}
}
// Mouse click handler to spawn creatures
canvas.addEventListener('click', function(e) {
const rect = canvas.getBoundingClientRect();
const x = e.clientX - rect.left;
const y = e.clientY - rect.top;
createCreature(x, y);
});
// Animation loop
function animate() {
drawMatrix();
drawCRT();
drawCreatures();
requestAnimationFrame(animate);
}
// Start animation
animate();
</script>
</body>
</html>
Step 22: Experiment, Iterate, and Save Your Projects
- Keep exploring! Try new prompts, tweak your ideas, or ask the model to enhance, optimize, or remix your previous outputs.
- Use the “Preview” and “Save” buttons under the generated code to test changes instantly or keep your favorite creations.
- Download or copy the full HTML code to use in your own projects, portfolio, or website—everything is ready to go!
- Don’t hesitate to experiment with both visual and interactive elements—each prompt can generate a unique, dynamic result limited only by your imagination.
- Enjoy your own AI-powered coding playground, where every creative idea comes to life in seconds!
Generated code from model:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>AI City Night Lights</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
background: linear-gradient(to bottom, #0c1445, #1a237e);
height: 100vh;
overflow: hidden;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
color: #fff;
}
.container {
position: relative;
width: 100%;
height: 100%;
max-width: 1200px;
margin: 0 auto;
}
canvas {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
cursor: pointer;
}
.title {
position: absolute;
top: 20px;
left: 0;
width: 100%;
text-align: center;
font-size: 2.5rem;
text-shadow: 0 0 10px rgba(0, 200, 255, 0.7);
z-index: 10;
letter-spacing: 3px;
}
.instructions {
position: absolute;
bottom: 30px;
left: 0;
width: 100%;
text-align: center;
font-size: 1.2rem;
z-index: 10;
background: rgba(0, 0, 0, 0.5);
padding: 10px;
border-radius: 10px;
max-width: 600px;
margin: 0 auto;
}
.firework {
position: absolute;
pointer-events: none;
z-index: 5;
}
.glow {
position: absolute;
border-radius: 50%;
filter: blur(20px);
opacity: 0.7;
}
</style>
</head>
<body>
<div class="container">
<h1 class="title">AI CITY NIGHT LIGHTS</h1>
<canvas id="cityCanvas"></canvas>
<div class="instructions">Click anywhere to launch fireworks • Every 15 seconds a train zooms across the city</div>
</div>
<script>
// Canvas setup
const canvas = document.getElementById('cityCanvas');
const ctx = canvas.getContext('2d');
// Set canvas to full window size
function resizeCanvas() {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
}
window.addEventListener('resize', resizeCanvas);
resizeCanvas();
// City data
const buildings = [];
const fireworks = [];
const particles = [];
const trains = [];
// Building class
class Building {
constructor(x, width, height) {
this.x = x;
this.width = width;
this.height = height;
this.windows = [];
this.color = `hsl(${Math.random() * 30 + 190}, 70%, ${Math.random() * 20 + 40}%)`;
// Create windows
const windowWidth = Math.random() * 10 + 5;
const windowHeight = Math.random() * 8 + 4;
const rows = Math.floor(height / (windowHeight + 3));
const cols = Math.floor(width / (windowWidth + 3));
for (let row = 0; row < rows; row++) {
for (let col = 0; col < cols; col++) {
// Randomly decide if window should be lit
if (Math.random() > 0.3) {
this.windows.push({
x: col * (windowWidth + 3) + 5,
y: row * (windowHeight + 3) + 5,
width: windowWidth,
height: windowHeight,
color: `hsl(${Math.random() * 30 + 40}, 100%, ${Math.random() * 40 + 60}%)`,
pulse: Math.random() * Math.PI * 2,
pulseSpeed: Math.random() * 0.05 + 0.02
});
}
}
}
}
draw() {
// Building body
ctx.fillStyle = this.color;
ctx.fillRect(this.x, canvas.height - this.height, this.width, this.height);
// Building top (roof)
ctx.fillStyle = `hsl(${Math.random() * 30 + 180}, 70%, ${Math.random() * 20 + 30}%)`;
ctx.fillRect(this.x, canvas.height - this.height, this.width, 5);
// Windows with animation
for (let window of this.windows) {
window.pulse += window.pulseSpeed;
// Pulsing effect
const pulse = Math.sin(window.pulse) * 0.3 + 0.7;
const brightness = 100 * pulse;
ctx.fillStyle = `hsl(${window.color.split(',')[0].split('(')[1]}, ${window.color.split(',')[1]}, ${brightness}%)`;
ctx.fillRect(this.x + window.x, canvas.height - this.height + window.y, window.width, window.height);
}
}
}
// Create buildings
function createBuildings() {
buildings.length = 0;
const buildingCount = Math.floor(canvas.width / 100) + 20;
for (let i = 0; i < buildingCount; i++) {
const width = Math.random() * 80 + 40;
const height = Math.random() * 300 + 150;
const x = i * 100 - 100;
buildings.push(new Building(x, width, height));
}
}
// Firework class
class Firework {
constructor(x, y) {
this.x = x;
this.y = y;
this.particles = [];
this.color = `hsl(${Math.random() * 360}, 100%, 60%)`;
this.exploded = false;
// Create particles
for (let i = 0; i < 100; i++) {
this.particles.push({
x: this.x,
y: this.y,
size: Math.random() * 3 + 1,
speedX: Math.random() * 6 - 3,
speedY: Math.random() * 6 - 3,
color: this.color,
life: 1
});
}
}
update() {
if (!this.exploded) {
// Move upward to explode
this.y -= 5;
if (this.y < canvas.height / 2) {
this.explode();
}
} else {
// Update particles
for (let i = 0; i < this.particles.length; i++) {
const p = this.particles[i];
p.x += p.speedX;
p.y += p.speedY;
p.life -= 0.01;
if (p.life <= 0) {
// Remove dead particles
this.particles.splice(i, 1);
i--;
}
}
}
}
explode() {
this.exploded = true;
}
draw() {
if (!this.exploded) {
// Draw firework trail
ctx.beginPath();
ctx.arc(this.x, this.y, 3, 0, Math.PI * 2);
ctx.fillStyle = this.color;
ctx.fill();
} else {
// Draw particles
for (let p of this.particles) {
if (p.life > 0) {
ctx.beginPath();
ctx.arc(p.x, p.y, p.size * p.life, 0, Math.PI * 2);
ctx.fillStyle = `rgba(${parseInt(p.color.split(',')[0].split('(')[1])}, ${parseInt(p.color.split(',')[1])}, ${parseInt(p.color.split(',')[2])}, ${p.life})`;
ctx.fill();
}
}
}
}
}
// Train class
class Train {
constructor() {
this.x = -100;
this.y = canvas.height - 200;
this.width = 150;
this.height = 30;
this.speed = Math.random() * 5 + 3;
this.color = `hsl(${Math.random() * 60 + 200}, 80%, ${Math.random() * 30 + 40}%)`;
this.lights = [];
// Create lights
for (let i = 0; i < 5; i++) {
this.lights.push({
x: 10 + i * 25,
color: `hsl(${Math.random() * 60 + 40}, 100%, ${Math.random() * 40 + 60}%)`
});
}
}
update() {
this.x += this.speed;
}
draw() {
// Train body
ctx.fillStyle = this.color;
ctx.fillRect(this.x, this.y, this.width, this.height);
// Train windows
ctx.fillStyle = '#87CEEB';
for (let i = 0; i < 4; i++) {
ctx.fillRect(this.x + 20 + i * 30, this.y + 5, 20, 15);
}
// Train lights
for (let light of this.lights) {
ctx.beginPath();
ctx.arc(this.x + light.x, this.y + 10, 4, 0, Math.PI * 2);
ctx.fillStyle = light.color;
ctx.fill();
}
}
}
// Create river
function drawRiver() {
const waterHeight = canvas.height * 0.15;
const riverY = canvas.height - waterHeight;
// River surface
ctx.fillStyle = '#003366';
ctx.fillRect(0, riverY, canvas.width, waterHeight);
// Water reflections
ctx.globalAlpha = 0.3;
for (let i = 0; i < 50; i++) {
const x = Math.random() * canvas.width;
const y = riverY + Math.random() * waterHeight;
const width = Math.random() * 200 + 50;
const height = Math.random() * 30 + 10;
ctx.fillStyle = `rgba(255, 255, 255, ${Math.random() * 0.3 + 0.1})`;
ctx.fillRect(x, y, width, height);
}
ctx.globalAlpha = 1;
// River reflections
for (let i = 0; i < 30; i++) {
const x = Math.random() * canvas.width;
const y = riverY + Math.random() * waterHeight;
const width = Math.random() * 50 + 20;
const height = Math.random() * 10 + 5;
ctx.fillStyle = `rgba(100, 200, 255, ${Math.random() * 0.4 + 0.1})`;
ctx.fillRect(x, y, width, height);
}
}
// Draw stars
function drawStars() {
for (let i = 0; i < 200; i++) {
const x = Math.random() * canvas.width;
const y = Math.random() * (canvas.height * 0.5);
const size = Math.random() * 1.5;
const opacity = Math.random() * 0.8 + 0.2;
ctx.beginPath();
ctx.arc(x, y, size, 0, Math.PI * 2);
ctx.fillStyle = `rgba(255, 255, 255, ${opacity})`;
ctx.fill();
}
}
// Draw city skyline
function drawCity() {
// Draw buildings
for (let building of buildings) {
building.draw();
}
// Draw train
for (let train of trains) {
train.update();
train.draw();
}
// Remove trains that are off screen
for (let i = 0; i < trains.length; i++) {
if (trains[i].x > canvas.width + 200) {
trains.splice(i, 1);
i--;
}
}
}
// Draw fireworks
function drawFireworks() {
for (let i = 0; i < fireworks.length; i++) {
fireworks[i].update();
fireworks[i].draw();
if (!fireworks[i].exploded && fireworks[i].y < 0) {
fireworks.splice(i, 1);
i--;
}
}
}
// Handle click events
canvas.addEventListener('click', function(e) {
const rect = canvas.getBoundingClientRect();
const x = e.clientX - rect.left;
const y = e.clientY - rect.top;
// Create firework at click position
fireworks.push(new Firework(x, y));
});
// Initialize
createBuildings();
// Train timer
let trainTimer = 0;
setInterval(() => {
trains.push(new Train());
}, 15000);
// Animation loop
function animate() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
// Draw background elements
drawStars();
drawRiver();
// Draw city
drawCity();
// Draw fireworks
drawFireworks();
requestAnimationFrame(animate);
}
// Start animation
animate();
</script>
</body>
</html>
Conclusion
With Qwen3-Coder-30B-A3B-Instruct, coding at scale becomes smoother, faster, and more creative than ever. By combining high-performance hardware, the flexibility of NodeShift Cloud, and modern tools like Ollama and Open-WebUI, you can experiment with powerful language models, generate interactive applications, and supercharge your workflow—all from your own secure cloud environment. Whether you’re building, exploring, or simply having fun, the path from idea to execution is wide open. Dive in, experiment boldly, and let your projects shine!