// ============================================================
// pra.veen.in — redesign · 3 variations · tweakable
// ============================================================
const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
"variant": "arcade",
"palette": ["#1a6aff", "#e83040", "#f0a830", "#30d060"],
"accent": "#f0a830",
"fontPair": "vt323-plex",
"density": "regular",
"dark": true
} /*EDITMODE-END*/;
// ── palettes ────────────────────────────────────────────────
const PALETTES = [
["#1a6aff", "#e83040", "#f0a830", "#30d060"], // original SMPTE-leaning
["#ff3d7f", "#3df0c8", "#ffd166", "#7c5cff"], // arcade neon
["#fb5607", "#ffbe0b", "#3a86ff", "#8338ec"], // playful primaries
["#06d6a0", "#ef476f", "#ffd166", "#118ab2"], // soft poppy
["#ff006e", "#fb5607", "#ffbe0b", "#8338ec"] // hot pop
];
const ACCENTS = ["#f0a830", "#ff3d7f", "#3df0c8", "#7c5cff", "#06d6a0", "#fb5607"];
const FONT_PAIRS = {
"vt323-plex": { display: "'VT323', monospace", body: "'IBM Plex Mono', monospace", name: "VT323 + Plex" },
"grotesk-mono": { display: "'Space Grotesk', sans-serif", body: "'JetBrains Mono', monospace", name: "Grotesk + JBMono" },
"fraunces-dm": { display: "'Fraunces', serif", body: "'DM Sans', sans-serif", name: "Fraunces + DM" },
"instrument-plex": { display: "'Instrument Serif', serif", body: "'IBM Plex Mono', monospace", name: "Instrument + Plex" }
};
// ── helpers ─────────────────────────────────────────────────
function useClock() {
const [t, setT] = React.useState(() => new Date());
React.useEffect(() => {
const id = setInterval(() => setT(new Date()), 1000);
return () => clearInterval(id);
}, []);
return t;
}
function useReveal() {
const ref = React.useRef(null);
const [vis, setVis] = React.useState(false);
React.useEffect(() => {
if (!ref.current) return;
const io = new IntersectionObserver(([e]) => {if (e.isIntersecting) setVis(true);}, { threshold: 0.12 });
io.observe(ref.current);
return () => io.disconnect();
}, []);
return [ref, vis];
}
function Reveal({ children, delay = 0, style, ...rest }) {
const [ref, vis] = useReveal();
return (
{children}
);
}
const fmtClock = (d) => `${String(d.getHours()).padStart(2, '0')}:${String(d.getMinutes()).padStart(2, '0')}:${String(d.getSeconds()).padStart(2, '0')}`;
// ── shared data ─────────────────────────────────────────────
const PROJECTS = [
{ tag: "Intelligence", name: "FlowSense", desc: "Real-time options intelligence dashboard. Futures premium, OI dynamics, gap classification, false breakout detection, institutional trap mechanics.", stack: ["Python", "Flask", "SocketIO"] },
{ tag: "Pattern Engine", name: "Kaptrax", desc: "Analog engine over 10 years of Nifty data. 204K rows, cosine similarity + FastDTW, context-filtered by VIX regime, time bucket, and expiry week.", stack: ["Python", "SQLite", "NumPy", "DTW"] },
{ tag: "OI Analysis", name: "OI Bot", desc: "Fetches Nifty option chains every 5 minutes. Computes OI changes across 3 timeframes with Claude-powered institutional flow analysis and WhatsApp alerts.", stack: ["Flask", "APScheduler", "Claude", "Twilio"] },
{ tag: "Training", name: "Scalp Simulator", desc: "Interactive training environment for options scalping. Black-Scholes ATM synthesis, scoring engine mapped to the Option Buyer's Field Manual.", stack: ["Flask", "JS", "Black-Scholes"] },
{ tag: "Paper Trading", name: "Paper Plane", desc: "Complete paper trading app for derivatives. Live option chains, simulated order book, P&L tracking, position sizing, and a journaling layer — practice the entire flow without risking capital.", stack: ["Flask", "JS", "WebSockets", "SQLite"] }];
const FREQS = [
{ icon: "🤖", label: "AI / LLMs /\nTransformers" },
{ icon: "📚", label: "Reading" },
{ icon: "📜", label: "History &\nEconomics" },
{ icon: "🏍️", label: "Motorcycles" },
{ icon: "🎬", label: "Cinema" },
{ icon: "🌍", label: "Geopolitics &\nDefense Tech" }];
// ============================================================
// VARIANT A — WORKSHOP (refined retro, closest to original)
// ============================================================
function VariantWorkshop({ t }) {
const clock = useClock();
const palette = t.palette;
const accent = t.accent;
const isDark = t.dark;
const density = t.density;
const pad = density === 'compact' ? 70 : density === 'comfy' ? 140 : 100;
const bg = isDark ? '#080810' : '#f5f3ec';
const surface = isDark ? '#0e0e1a' : '#ffffff';
const surfaceRaised = isDark ? '#131320' : '#fbf9f4';
const text = isDark ? '#d8d8e0' : '#1a1a26';
const textDim = isDark ? '#6a6a80' : '#75727f';
const textMuted = isDark ? '#333348' : '#bcb9c4';
const borderC = isDark ? 'rgba(255,255,255,.06)' : 'rgba(0,0,0,.08)';
return (
{/* ambient glows */}
{/* tube light */}
{/* PS symbols */}
{['△', '○', '✕', '□'].map((s, i) =>
{s}
)}
{/* HERO */}
{/* monitor stack — now wrapped around the real workspace photo */}
{fmtClock(clock)}
PRAVEEN P. PALA
Praveen P. Pala
{/* ABOUT */}
CH:01 // About
Built for Hostile Terrain.
I build tools for financial markets. Intelligence systems that read
option chains in real time, pattern engines that scan ten years of price data,
flow detectors that try to figure out what the institutions are up to.
If there's a dashboard involved, I probably built that too.
Been at this since I was a kid making Geocities pages in school.
Visitor counters, cursor trails, the whole thing. The internet's changed
a lot since then but the itch to build stuff hasn't. Now I just point it
at markets instead of guestbooks.
{/* PROJECTS — pegboard */}
CH:02 // Projects
Transmissions
{PROJECTS.map((p, i) =>
)}
{/* FREQS */}
CH:03 // Frequencies
Off The Radar
When I'm not reading OI tables or arguing with price action, you'll find me scanning these frequencies.
{FREQS.map((f, i) =>
)}
{/* CONTACT */}
);
}
// ── workshop sub-components ─────────────────────────────────
function CRT({ aspect, palette, accent, wide, idx }) {
// Static SMPTE bars, NO signal-lost overlay, NO flicker animation.
// Small static "ON AIR" lamp + label only.
return (
{/* small lamp */}
CH-{String(idx + 1).padStart(2, '0')}
{/* CRT glass gradient */}
{/* scanlines */}
);
}
function SecLabel({ t, color, children }) {
return (
▋
{children}
);
}
function SecTitle({ t, text, children }) {
return (
{children} );
}
function bodyStyle(textDim, text) {
return { fontSize: 15, lineHeight: 1.8, color: textDim, maxWidth: 580 };
}
function PegCard({ p, t, palette, surfaceRaised, text, textDim, textMuted, borderC, delay }) {
const [hover, setHover] = React.useState(false);
return (
setHover(true)} onMouseLeave={() => setHover(false)}
style={{
background: surfaceRaised, border: `1px solid ${hover ? palette[0] : borderC}`, borderRadius: 4, overflow: 'hidden',
position: 'relative', transition: 'all .3s', transform: hover ? 'translateY(-2px)' : 'translateY(0)',
cursor: 'default'
}}>
{p.tag}
{p.name}
{p.desc}
{p.stack.map((s, i) =>
{s}
)}
);
}
function Gadget({ f, t, palette, surface, textDim, borderC }) {
const [hover, setHover] = React.useState(false);
return (
setHover(true)} onMouseLeave={() => setHover(false)}
style={{
background: surface, border: `1px solid ${hover ? palette[2] + '80' : borderC}`, borderRadius: 4,
padding: '24px 16px', textAlign: 'center', position: 'relative', overflow: 'hidden', transition: 'border-color .3s'
}}>
{f.icon}
{f.label}
);
}
function Terminal({ t, palette, surface, textDim, borderC }) {
return (
);
}
function Nav({ t, text, textDim, accent, red, surface }) {
return (
PRAVEEN. P. PALA
);
}
// ============================================================
// VARIANT B — ARCADE (chunky color blocks, playful)
// ============================================================
function VariantArcade({ t }) {
const clock = useClock();
const palette = t.palette;
const accent = t.accent;
const isDark = t.dark;
const density = t.density;
const gap = density === 'compact' ? 16 : density === 'comfy' ? 36 : 24;
const bg = isDark ? '#0a0a14' : '#fff6e8';
const text = isDark ? '#f8f6ff' : '#0a0a14';
const textDim = isDark ? '#9999b4' : '#5a5870';
const cardBorder = isDark ? '#1a1a2e' : '#0a0a14';
return (
{/* checkerboard ambient */}
{/* sticker bg blobs */}
{/* ticker */}
{Array.from({ length: 2 }).map((_, k) =>
★ NOW BUILDING ● FLOWSENSE LIVE ▲ NIFTY @ {fmtClock(clock)}
◆ OPTIONS DESK OPEN ✕ TRADING IN PRIVATE ★ pr@veen.in
● BUILDING IN PUBLIC
)}
{/* HERO — playful sticker layout */}
BUILDER · ONLINE
Praveen
P. Pala.
Builder of tools for financial markets — pattern engines,
option-chain readers, and real-time dashboards. Geocities kid, all grown up.
See the work ↓
pr@veen.in ↗
{/* workspace photo as the hero sticker */}
LIVE FROM THE DESK
{fmtClock(clock)}
{/* ABOUT — bold split */}
CH.01 — ABOUT
Built for hostile terrain.
I build tools for financial markets. Intelligence systems that read option chains in real time, pattern
engines that scan ten years of price data, flow detectors that try to figure out what the institutions
are up to. If there's a dashboard involved, I probably built that too.
Been at this since I was a kid making Geocities pages in school — visitor counters, cursor trails,
the whole thing. The internet's changed, the itch to build hasn't. Now I point it at markets instead of guestbooks.
{/* PROJECTS — sticker cards */}
{PROJECTS.map((p, i) =>
)}
{/* FREQS — playful chips */}
When I'm not reading OI tables or arguing with price action.
{FREQS.map((f, i) =>
)}
{/* CONTACT */}
);
}
function NavArcade({ t, text, bg, palette, accent, cardBorder }) {
return (
praveen. p. pala
);
}
function Tile({ bg, cardBorder, rot, children, style }) {
return (
{children}
);
}
function BigChip({ color, bg, cardBorder, children, href, t }) {
return (
{e.currentTarget.style.transform = 'translate(-2px,-2px)';e.currentTarget.style.boxShadow = `6px 6px 0 ${cardBorder}`;}}
onMouseLeave={(e) => {e.currentTarget.style.transform = 'translate(0,0)';e.currentTarget.style.boxShadow = `4px 4px 0 ${cardBorder}`;}}>
{children}
);
}
function StickerCard({ p, t, palette, bg, text, textDim, cardBorder, idx, delay }) {
const [hover, setHover] = React.useState(false);
const tilt = idx % 2 === 0 ? -1 : 1;
const cardBg = idx % 4 === 0 ? palette[0] : idx % 4 === 1 ? palette[2] : idx % 4 === 2 ? palette[3] : palette[1];
return (
setHover(true)} onMouseLeave={() => setHover(false)}
style={{
background: cardBg, color: bg, padding: '20px', borderRadius: 16,
border: `2px solid ${cardBorder}`, boxShadow: `6px 6px 0 ${cardBorder}`,
transform: hover ? 'translate(-3px,-3px) rotate(0deg)' : `translate(0,0) rotate(${tilt}deg)`,
boxShadow: hover ? `9px 9px 0 ${cardBorder}` : `6px 6px 0 ${cardBorder}`,
transition: 'transform .2s, box-shadow .2s', position: 'relative', overflow: 'hidden',
cursor: 'default'
}}>
{p.tag}
{p.name}
{p.desc}
{p.stack.map((s, i) =>
{s}
)}
);
}
function FreqChip({ f, t, bg, cardBorder, pageBg }) {
const [hover, setHover] = React.useState(false);
return (
setHover(true)} onMouseLeave={() => setHover(false)}
style={{
display: 'inline-flex', alignItems: 'center', gap: 10, padding: '12px 18px',
background: bg, color: pageBg, borderRadius: 999, border: `2px solid ${cardBorder}`,
boxShadow: `3px 3px 0 ${cardBorder}`, fontFamily: t._font.body, fontSize: 13, fontWeight: 700,
letterSpacing: 1, transition: 'transform .15s',
transform: hover ? 'translate(-2px,-2px) rotate(-2deg)' : 'rotate(0deg)'
}}>
{f.icon}
{f.label.replace(/\n/g, ' ')}
);
}
// ============================================================
// VARIANT C — ZINE (editorial, asymmetric, big type)
// ============================================================
function VariantZine({ t }) {
const clock = useClock();
const palette = t.palette;
const accent = t.accent;
const isDark = t.dark;
const density = t.density;
const gap = density === 'compact' ? 60 : density === 'comfy' ? 140 : 100;
const bg = isDark ? '#0e0d12' : '#efe9dc';
const paper = isDark ? '#1a1820' : '#f7f2e6';
const text = isDark ? '#ece4d4' : '#1a1820';
const textDim = isDark ? '#857d6f' : '#5c5648';
const rule = isDark ? '#3a342c' : '#1a1820';
return (
{/* paper grain */}
")` }} />
{/* MASTHEAD */}
Vol. XXVI · No. 11
The Pala Quarterly
{fmtClock(clock)} IST
{/* HERO — editorial */}
◆ Field Dispatch · Praveen P. Pala
Praveen
P. Pala
.
"If there's a dashboard involved, I probably built that too."
The Builder · Geocities Era
Fig. 01 — The bridge
Two CRTs, one real screen, mechanical keys, plants, and a small army of figurines watching me trade.
{/* ABOUT — multi-column editorial */}
Section I
About the builder.
I build tools for financial markets. Intelligence systems that read option chains in real
time, pattern engines that scan ten years of price data, flow detectors that try to figure out what
the institutions are up to. If there's a dashboard involved, I probably built that too.
Been at this since I was a kid making Geocities pages in school. Visitor counters, cursor trails,
the whole thing. The internet's changed a lot since then but the itch to build stuff hasn't.
Now I just point it at markets instead of guestbooks.
{/* PROJECTS — index list */}
Transmissions, an index.
Section II
{PROJECTS.map((p, i) =>
)}
{/* FREQS — sidebar list */}
Section III
Frequencies received.
When not reading OI tables or arguing with price action.
{FREQS.map((f, i) =>
{String(i + 1).padStart(2, '0')}
{f.icon}
{f.label.replace(/\n/g, ' ')}
)}
{/* CONTACT */}
);
}
function NavZine({ t, text, textDim, bg, accent, rule }) {
return (
Praveen· P· Pala
);
}
function ZineRow({ p, t, palette, text, textDim, rule, idx, delay }) {
const [hover, setHover] = React.useState(false);
return (
setHover(true)} onMouseLeave={() => setHover(false)}
className="m-row-stack"
style={{
display: 'grid', gridTemplateColumns: '60px 1fr 1.4fr 200px', gap: 24, alignItems: 'baseline',
padding: '24px 0', borderBottom: `1px solid ${rule}`, position: 'relative',
transition: 'background .2s', cursor: 'default'
}}>
{String(idx + 1).padStart(2, '0')}.
{p.name}{p.tag.toLowerCase()}
{p.desc}
{p.stack.map((s, i) =>
{s}{i < p.stack.length - 1 ? ' ·' : ''}
)}
);
}
// ============================================================
// ROOT — variant switcher + tweaks panel
// ============================================================
function App() {
const [t, setTweak] = useTweaks(TWEAK_DEFAULTS);
// resolve font pair lazily (don't store object in tweaks JSON)
const _font = FONT_PAIRS[t.fontPair] || FONT_PAIRS["vt323-plex"];
const tx = { ...t, _font };
// sync scanline overlay class on body
React.useEffect(() => {
document.body.classList.toggle('scanlines', t.dark);
document.body.classList.toggle('scanlines-light', !t.dark);
}, [t.dark]);
let view;
if (t.variant === 'arcade') view =
;else
if (t.variant === 'zine') view =
;else
view =
;
return (
<>
{view}
setTweak('dark', !t.dark)}
aria-label={t.dark ? 'Switch to light mode' : 'Switch to dark mode'}
title={t.dark ? 'Switch to light mode' : 'Switch to dark mode'}
style={{
position: 'fixed', left: 16, bottom: 16, zIndex: 99999,
width: 44, height: 44, borderRadius: 999,
background: t.dark ? 'rgba(255,255,255,.08)' : 'rgba(0,0,0,.06)',
color: t.dark ? '#f0e8d0' : '#1a1820',
border: `1px solid ${t.dark ? 'rgba(255,255,255,.18)' : 'rgba(0,0,0,.15)'}`,
backdropFilter: 'blur(12px)', WebkitBackdropFilter: 'blur(12px)',
cursor: 'pointer', display: 'flex', alignItems: 'center', justifyContent: 'center',
fontSize: 18, transition: 'transform .2s, background .2s',
boxShadow: t.dark ? '0 4px 16px rgba(0,0,0,.4)' : '0 4px 16px rgba(0,0,0,.08)',
}}
onMouseEnter={(e) => { e.currentTarget.style.transform = 'scale(1.08) rotate(-12deg)'; }}
onMouseLeave={(e) => { e.currentTarget.style.transform = 'scale(1) rotate(0deg)'; }}>
{t.dark ? '☀️' : '🌙'}
setTweak('variant', v)} />
setTweak('dark', v)} />
setTweak('palette', v)} />
setTweak('accent', v)} />
({ value: k, label: v.name }))}
onChange={(v) => setTweak('fontPair', v)} />
setTweak('density', v)} />
>);
}
ReactDOM.createRoot(document.getElementById('root')).render(
);