MAKETEK
Build technology from scratch. No frameworks, no magic. Just raw code, step by step, from the most primitive form possible.
Learn the fundamentals that every developer should know before touching a framework.
The Philosophy
Before you can break the rules, you need to know what the rules are. Before you use a framework, understand what it replaces.
Zero Abstraction
No frameworks hiding the logic from you. Every line of code does exactly what it says. You understand everything because you wrote everything.
Copy-Paste Ready
Every code block works as-is. Copy it, paste it, run it. No setup, no configuration, no "npm install" with 300 dependencies.
Primitive First
Start with the browser APIs. fetch() instead of Axios. querySelector() instead of jQuery. Understand what the tools do before using them.
Build to Learn
The goal is understanding, not shipping. Once you understand the primitives, frameworks become tools instead of magic boxes.
Step by Step
Each step builds on the previous one. By the end, you'll have a complete real-time application built with zero dependencies.
The Foundation: Pure HTML
Everything starts with HTML. No build tools, no bundlers. Just a text file that the browser can read. This is the skeleton of any website.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>My First Page</title>
</head>
<body>
<h1>Hello, World</h1>
<p>This is where everything begins.</p>
<button id="btn">Click me</button>
</body>
</html>Styling: Raw CSS
CSS controls how things look. No Tailwind, no SASS. Write it by hand, understand every property. The cascade is your friend.
/* styles.css */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: system-ui, sans-serif;
background: #0a0a0a;
color: #e0e0e0;
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
}
h1 {
font-size: 3rem;
background: linear-gradient(135deg, #00f0ff, #7b61ff);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
button {
padding: 12px 24px;
border: 1px solid rgba(255,255,255,0.1);
border-radius: 8px;
background: transparent;
color: #fff;
cursor: pointer;
transition: all 0.3s;
}
button:hover {
background: rgba(255,255,255,0.05);
border-color: #00f0ff;
}Logic: Vanilla JavaScript
JavaScript makes things interactive. No React, no Vue. Just plain JS manipulating the DOM directly. This is how it all works under the hood.
// app.js - Pure JavaScript, no dependencies
// Select elements
const btn = document.getElementById('btn');
const output = document.createElement('div');
document.body.appendChild(output);
// State - just a variable
let count = 0;
// Event listener
btn.addEventListener('click', () => {
count++;
render();
});
// Render function - manual DOM update
function render() {
output.innerHTML = `
<p>Clicked: ${count} times</p>
<p>Last click: ${new Date().toLocaleTimeString()}</p>
`;
output.style.marginTop = '20px';
output.style.color = count > 10 ? '#00ff88' : '#e0e0e0';
}
// Initial render
render();
console.log('App started - no framework needed');Data: Fetch from an API
Real applications need data. The Fetch API is built into every browser. No Axios needed. Learn to talk to any server.
// Fetching data from a public API
async function loadData() {
const container = document.getElementById('data');
container.innerHTML = '<p>Loading...</p>';
try {
const response = await fetch(
'https://api.coingecko.com/api/v3/simple/price?ids=solana&vs_currencies=usd'
);
const data = await response.json();
container.innerHTML = `
<div style="padding:20px; border:1px solid rgba(255,255,255,0.1); border-radius:12px;">
<h3>Solana Price</h3>
<p style="font-size:2rem; color:#00f0ff;">
$${data.solana.usd.toLocaleString()}
</p>
<small style="color:#888;">
Updated: ${new Date().toLocaleString()}
</small>
</div>
`;
} catch (error) {
container.innerHTML = `<p style="color:#ff3366;">Error: ${error.message}</p>`;
}
}
// Auto-refresh every 30 seconds
loadData();
setInterval(loadData, 30000);WebSocket: Real-Time Connection
HTTP is request-response. WebSocket is a persistent connection that receives data in real-time. This is how live feeds, chats, and trading bots work.
// Real-time WebSocket connection
const ws = new WebSocket('wss://pumpportal.fun/api/data');
ws.onopen = () => {
console.log('Connected to PumpPortal');
// Subscribe to new token launches
ws.send(JSON.stringify({
method: 'subscribeNewToken'
}));
};
ws.onmessage = (event) => {
const msg = JSON.parse(event.data);
// New token created on PumpFun
if (msg.txType === 'create') {
console.log('NEW TOKEN:', {
name: msg.name,
symbol: msg.symbol,
mint: msg.mint,
creator: msg.traderPublicKey
});
// Add to page
const div = document.createElement('div');
div.textContent = `[${msg.symbol}] ${msg.name} - ${msg.mint.slice(0,8)}...`;
document.getElementById('feed').prepend(div);
}
};
ws.onclose = () => {
console.log('Disconnected. Reconnecting in 3s...');
setTimeout(() => location.reload(), 3000);
};Storage: Save Data Locally
Before you need a database, browsers have built-in storage. LocalStorage persists data between page reloads. Simple and effective.
// Simple local storage wrapper
const Store = {
get(key) {
try {
const data = localStorage.getItem(key);
return data ? JSON.parse(data) : null;
} catch {
return null;
}
},
set(key, value) {
localStorage.setItem(key, JSON.stringify(value));
},
remove(key) {
localStorage.removeItem(key);
}
};
// Usage: Save user preferences
Store.set('theme', 'dark');
Store.set('watchlist', ['SOL', 'BTC', 'ETH']);
Store.set('settings', {
notifications: true,
autoRefresh: 30,
currency: 'USD'
});
// Read it back
const watchlist = Store.get('watchlist');
console.log(watchlist); // ['SOL', 'BTC', 'ETH']
// This data survives page refresh and browser restartComponent Pattern: Build UI Without Frameworks
React components? You can build the same pattern with vanilla JS. Create reusable pieces of UI that manage their own state.
// Vanilla JS component pattern
function TokenCard(token) {
const el = document.createElement('div');
el.className = 'token-card';
el.innerHTML = `
<div style="display:flex; gap:12px; padding:16px;
background:#16161f; border:1px solid rgba(255,255,255,0.06);
border-radius:12px; margin-bottom:8px;">
<img src="https://pump.fun/coin/${token.mint}/image"
width="40" height="40"
style="border-radius:50%;"
onerror="this.style.display='none'" />
<div style="flex:1;">
<strong>${token.name}</strong>
<span style="color:#888; margin-left:8px;">$${token.symbol}</span>
<div style="font-size:12px; color:#555; margin-top:4px;">
${token.mint.slice(0,8)}...${token.mint.slice(-4)}
</div>
</div>
<a href="https://pump.fun/coin/${token.mint}"
target="_blank"
style="color:#00f0ff; font-size:13px;">
View
</a>
</div>
`;
return el;
}
// Usage
const feed = document.getElementById('feed');
const token = { name: 'MyCoin', symbol: 'MC', mint: 'ABC123...' };
feed.appendChild(TokenCard(token));Put It All Together
Combine everything into a single working application. HTML structure, CSS styling, JavaScript logic, API calls, WebSocket for real-time, and local storage. No npm install needed.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>My PumpFun Feed</title>
<style>
* { margin:0; padding:0; box-sizing:border-box; }
body { background:#050508; color:#f0f0f5; font-family:system-ui; padding:20px; }
h1 { font-size:2rem; margin-bottom:20px; }
#status { font-size:12px; color:#888; margin-bottom:16px; }
.dot { width:8px; height:8px; border-radius:50%; display:inline-block; margin-right:6px; }
.online { background:#00ff88; }
.offline { background:#ff3366; }
#feed { display:flex; flex-direction:column; gap:8px; }
</style>
</head>
<body>
<h1>PumpFun Live Feed</h1>
<div id="status"><span class="dot offline"></span>Connecting...</div>
<div id="feed"></div>
<script>
const feed = document.getElementById('feed');
const status = document.getElementById('status');
const ws = new WebSocket('wss://pumpportal.fun/api/data');
ws.onopen = () => {
status.innerHTML = '<span class="dot online"></span>Connected';
ws.send(JSON.stringify({ method: 'subscribeNewToken' }));
};
ws.onmessage = (e) => {
const msg = JSON.parse(e.data);
if (msg.txType === 'create' && msg.mint) {
const div = document.createElement('div');
div.style.cssText = 'padding:12px; background:#16161f; border-radius:8px; border:1px solid rgba(255,255,255,0.06);';
div.innerHTML = `<strong>${msg.name || '???'}</strong> <span style="color:#888;">$${msg.symbol || '???'}</span> <a href="https://pump.fun/coin/${msg.mint}" target="_blank" style="color:#00f0ff; float:right;">View</a>`;
feed.prepend(div);
if (feed.children.length > 50) feed.lastChild.remove();
}
};
ws.onclose = () => {
status.innerHTML = '<span class="dot offline"></span>Disconnected';
setTimeout(() => location.reload(), 3000);
};
</script>
</body>
</html>