Amey Pacharkar

Software developer · Mumbai, India

Amey Pacharkar

I build games and tools that teach.

Computer engineering graduate (BE, May 2026) working with Flutter, full-stack web and AI/ML. I'm open to roles at startups.

About

I'm Amey Pacharkar, a computer engineering graduate (BE, May 2026) from Mumbai. I like building niche, slightly weird software, and I'm interested in psychology and game theory. I've worked on Flutter apps for Android and iOS, full-stack web projects and AI/ML libraries.

My favourite project is Chem Arcade. I teach chemistry for CET and JEE to students in the Ambegaon area, and I wanted them to enjoy it, so I built a set of chemistry games with weekly and all-time leaderboards. Each one is made so a student who stumbles on it can have a good time with friends or on their own.

At work I built ChatLink, an internal Android app that automates bulk messaging. I took it from idea to deployment and have supported it for almost a year. I have also built features and systems for three web projects at my current company.

I'm looking for a chance to contribute to live projects.

Featured projects

Four projects I can explain end to end: what problem they solve, how they are built, what went wrong and what I would change.

Chem Arcade

Browser chemistry games for CET, JEE and board-exam students

Live

Solo project · Private repo · 106 commits

The problem and the idea

Students learn best when they're having fun. I teach CET and JEE chemistry and wanted my students to enjoy it, so I built a set of chemistry games anyone can open and play, alone or with friends. There is a competitive side too, with all-time, daily and weekly leaderboards.

The games

  • Periodic Table Battleship: played locally or online with a room code (no matchmaking yet).
  • Name It: a solo, timed IUPAC naming game with a 25-level Learn mode and a competitive Endless mode (Easy, CET, JEE). Your score rises the higher you climb, the faster you answer and the more you get right.

What I owned

  • The game logic for both games.
  • All the chemistry content and levels.
  • The UI design: my own idea and first draft.

How I checked it

  • The level-scoring formulas started as AI output. I tested them and rebalanced them to make them fairer.
  • The Firestore security rules, which act as the anti-cheat layer, were written with AI. I tested them, along with the app, using Firestore rules tests and Playwright end-to-end tests.

Privacy by design

  • Most players are under 18, so there are no emails and no ads. Players join with a nickname and a PIN, never a real name.
How it fits together (first draft)
  1. Student opens the siteBrowser

    An installable web app (PWA) built with Next.js

  2. Joins with a nickname and PINFirebase

    No email, no real name

  3. Plays a gameNext.js

    Game logic runs in the app

  4. Scores and rooms are savedFirestore

  5. Security rules check every writeFirestore rules

    The anti-cheat layer

  6. LeaderboardsFirestore

    All-time, daily and weekly

What I'd do differently

  • Move Name It's user data out of Firestore into a separate relational database such as Postgres, for tighter control over where student data lives.
  • Next.js (App Router)
  • React
  • TypeScript
  • Tailwind
  • Firebase (Firestore + Auth)
  • PWA
  • Playwright
  • Vercel
Periodic Table Battleship, mid-game
Name It: typing the answer
Name It, short clip
Leaderboard (sample data, not real students)
Phone layout (installable web app)

WatchDog

Website change monitoring: get emailed a diff when a page changes

Demo offline

Solo project · Private repo · 38 commits

The hosted demo is offline, so screenshots and a recording will be shown here instead.

The problem and the idea

You add a web page to watch. WatchDog checks it on a schedule and, when the visible content changes, emails you a colour-coded diff of exactly what changed. The idea was to keep an eye on a rival's website, a stock page or any other page. I built it as a subscription product but never marketed it, so it has no customers.

What I built

  • The whole stack: React dashboard, Express API, scheduler, scraper, diffing and email alerts.
  • Subscription plans with Lemon Squeezy: Free (1 monitor, daily checks), Basic $9 (10 monitors), Pro $19 (30 monitors, hourly checks) and Agency $49 (unlimited monitors, hourly, 6-hourly or daily checks).
  • Users are identified by email only, with no passwords or sessions.

Problems I solved

  • Cooldown bug: SQLite stores UTC times with no timezone marker, and JavaScript read them as local time. In India that made a 5.5-hour error, bigger than the Pro and Agency cooldowns, so users could bypass them. Fixed by forcing UTC when parsing.
  • Email outage on Railway: Node's IPv6-first DNS resolution caused ENETUNREACH errors when sending mail. Fixed by resolving the mail server to IPv4 and keeping the TLS server name intact.
  • Webhook signatures failing: express.json() re-formatted the body, which invalidated the HMAC signature. Fixed by reading the raw body on the webhook route only, and comparing signatures in constant time.
  • Noisy pages: the scraper strips scripts, styles, SVGs and meta tags so a diff only shows text a person would read, and it sends browser-like headers to get past basic bot blocks.
How a change becomes an email
  1. Hourly job finds due monitorsnode-cron

    Based on each plan's check frequency

  2. Fetch the pageAxios

    Browser-like headers, 15-second timeout

  3. Clean the textCheerio

    Strip hidden and non-visible content

  4. Hash and compareSQLite

    First check saves a baseline; later checks compare hashes

  5. Diff the changesdiff

    First 10 changed lines saved to the alerts table

  6. Save, then emailNodemailer

    Database updated first; the email sends in the background

What I'd do differently

  • Email-only access means anyone who types another person's email can see that person's monitors. I'd add magic-link authentication.
  • Scraping runs inside the API process, so a restart or a slow scan can miss checks. I'd move it to a job queue with a separate worker, and PostgreSQL.
  • Cheerio only sees static HTML, so client-rendered single-page apps come back empty. I'd add a headless-browser fallback and CSS-selector targeting.
  • React (Vite)
  • Tailwind v4
  • Node.js
  • Express
  • node-cron
  • SQLite
  • Axios
  • Cheerio
  • Nodemailer
  • Lemon Squeezy
  • Railway
Monitor with change history and colour-coded diffs
Empty dashboard
Add-monitor dialog
Pricing cards
Recorded demo (hosted version is offline)

GhostFS

Ephemeral encrypted file transfer that hides data in video frames

Live demo (relay sleeps when idle)

Solo project · Public repo · 11 commits

The relay server sleeps when nobody is using it, and waking it takes long enough that the first connection can time out. If that happens, wait a minute and try again. A recording of a full transfer is shown below.

The problem and the idea

A for-fun project. After learning about bits, bytes and the least significant bit (LSB) in my third-year computer networks course, I wanted to see if I could hide data inside pictures and video. It grew step by step: text to bits drawn as black and white pixels, then bits hidden in an image's LSB, then the same in video frames, then a live transfer system on top.

What I built

  • The byte-to-pixel encoding and the LSB hiding, written by me.
  • The relay and channel system were built with AI help, and I can explain how they work.

Design decisions

  • Encryption (AES-256-GCM, WebCrypto) runs in the browser, so the relay never handles plaintext.
  • The key sits in the part of the link after the #, which browsers never send to a server. The relay only ever sees the channel name.
  • The relay is stateless: nothing is stored in a database. A channel holds two people, waits 15 seconds after the transfer for the download, then destroys everything.
  • Frames travel as raw uncompressed pixels over WebSocket. Lossy video compression would destroy the hidden bits, so I avoided it, and TCP delivers them intact.
How one transfer works
  1. Sender picks a fileBrowser

    Encrypted with AES-256-GCM in the browser

  2. Bits hidden in framesCanvas

    One payload bit in the lowest red bit of each pixel of a 1280×720 decoy video frame

  3. Link is createdBrowser

    #channel=…&key=… The key never leaves the link's # part

  4. Raw frames stream through the relayElixir/Phoenix

    Forwarded unchanged, nothing stored

  5. Receiver joinsBrowser

    Reads the lowest red bit of every pixel, rebuilds and decrypts

  6. Channel destroyedRelay

    15 seconds after the transfer ends

What I'd do differently

  • Cold start: the free-tier Render relay sleeps when idle and takes too long to wake, so the first connection times out. I'd keep one relay machine always on, or make the frontend show a 'waking the relay' status and retry.
  • Bandwidth: raw 720p frames are about 2.8 MB each, over a gigabit per second at full frame rate. That is fine on localhost but not on a real network. I'd send smaller or fewer frames and compress the payload first.
  • No backpressure: the sender never checks how much is queued, so a slow connection piles frames up in browser memory. I'd check bufferedAmount before sending.
  • Detectability: a raw RGB stream isn't a normal video stream, so traffic analysis would spot it. The real protection is the encryption and the key staying out of the server's reach. The LSB hiding is the technique I wanted to explore.
  • Vanilla JS
  • Canvas API
  • WebCrypto
  • Elixir/Phoenix (WebSocket relay)
  • Vercel
  • Render
Recording: a full transfer
Sender view (link and key blurred)
Receiver view, waiting for the sender

multi-agent-experiment

Multi-agent LLM games built from raw HTTP calls, with no frameworks

Learning project

Solo project · Public repo · Python + local llama3.2 (Ollama)

The problem and the idea

I wanted to learn how multi-agent LLM systems work by building them from raw HTTP calls upward, one concept per game. It was a learning project, not a controlled study, so I only claim what I directly observed.

What I built

  • Four games, each adding one idea, up to a Werewolf game run by a real state machine: Optimist vs Pessimist, Twenty Questions, Spyfall and Werewolf.
  • Every agent runs on the same small local model.

What I observed

  • Memory is a list you resend: a second call without the history knows nothing, and a call with the history remembers. Easy to reproduce with curl.
  • A system prompt sets tone: a pirate prompt changed the output at once.
  • Don't let the model judge what code can check: in Twenty Questions the answering agent said Yes to a wrong guess and the agents slid into fake small talk. Moving the correctness check into Python as a string comparison fixes it by construction.
  • Contradictory prompts cause invented facts: a lone werewolf told both that it had no fellow wolves and to discuss with them invented a second wolf. After I branched the prompt the next run didn't. That's one run before and one after, so it's consistent with the contradiction being the cause, not proof.
  • Position bias, with caveats: in Spyfall voting one agent name got about half the votes regardless of its role (18 of 36 in the first batch). After shuffling it still got about 10 of 24, above the 25% chance level. I tallied this by hand and changed the name order and the speaking order at the same time, so I couldn't tell which mattered.
How a turn works
  1. State machine picks the speakerPython

    And decides what that agent is allowed to see

  2. Prompt is builtPython

    Role, rules and the history so far

  3. HTTP call to the local modelOllama (llama3.2)

  4. Reply is checked by codePython

    For example, is the guess correct?

  5. State updates, next turnPython

What I'd do differently

  • Count results with a script instead of by eye.
  • Change one variable at a time, so I can tell which change moved the result.
  • Run enough games to tell a real effect from chance.
  • Python
  • Ollama (llama3.2)
  • requests
  • State machines

Other projects

Backend and tools

  • zorvyn-finance-engine — A zero-trust ledger API with an immutable ledger, RS256 JWT auth and a test suite (TypeScript, Express, Prisma, PostgreSQL, Redis). Built as an internship assignment.
  • git-guard — A GitHub bot that scans pushes for leaked secrets and outdated dependencies, and opens an issue automatically (Python, FastAPI).
  • Pythia — A watched-folder tool: rename an empty file to a prompt and Gemini writes the code into it, with RAG over project files (ChromaDB), automatic backups and generated flowcharts (Python).

Apps and team projects

  • Bookstore — A full-stack store on Supabase: a Flutter shopping app with catalog, cart and checkout, and a React admin dashboard for product management.
  • Path to Balance — A Flutter mental-health screening app with adaptive questionnaires and AI-generated reports, built with a teammate who wrote the Node.js backend.
  • SmartDispatch — A team project for a person-to-person delivery platform in Mumbai (Flutter app, Node backend, ML pricing service). I made small contributions.
  • interactive_data_sandbox — A Flutter desktop app for exploring machine-learning algorithms on your own data, with a FastAPI and scikit-learn backend.

Games

  • Wumpus World — An AI puzzle game built with Flutter and the Flame engine.
  • Terminal game in C — A game for the terminal, in progress.

Learning repos: Flutter_Projects, Full-Stack-Web-Development, AIML, AiAgent, edunet-training and a few Flutter starter apps.

I use AI tools as part of my workflow, but I design the systems, review the code and test the results.

Skills

Mobile
  • Flutter
  • Dart
  • BLoC
  • Kotlin (Android accessibility service)
Web
  • React
  • Next.js
  • TypeScript
  • Tailwind CSS
  • Node.js
  • Express
Data and backend
  • PostgreSQL
  • SQLite
  • Firebase (Firestore, Auth)
  • Supabase
  • REST APIs
  • JWT auth
AI / ML
  • Python
  • scikit-learn
  • pandas
  • FastAPI
  • Local LLMs (Ollama)
  • Gemini API
Tools and testing
  • Git and GitHub
  • Docker
  • Playwright
  • Vercel
  • Railway

Experience

Software Intern · CRoad Solutions (remote)

Aug 2025 to present

  • Built ChatLink, an internal Android app that automates bulk messaging (see below). Developed it alone and have supported it after deployment for about a year.
  • Built backend features for an organisation-management platform (Node.js, Express, TypeScript, PostgreSQL, AWS S3 and SQS).
  • Contributed to a TypeScript monorepo for a multi-role office platform (React, Express, Drizzle, OpenAPI).

Chemistry teacher, CET and JEE · Ambegaon area, near Pune (part-time)

Second year

  • Teaching alongside my mentor of four years at the coaching centre he started. I've learned to run a classroom, plan chapters and manage time while teaching with other teachers.
  • It's also what led me to build Chem Arcade.

Education: BE in Computer Engineering, graduated May 2026

Contact

The quickest way to reach me is email. If you'd rather talk first, book a short intro call.

hello@ameypacharkar.com · GitHub