Building Software for Undocumented Citizens: Why PayPal, Stripe, and Gumroad Don’t Cut It Outside the US

The Problem We Were Actually Solving

My initial design assumption was that if Stripe could handle international transactions, my customers outside the US would be able to checkout seamlessly using their local credit or debit cards. The problem was not that I was trying to solve the wrong problem – rather I misunderstood how these international transactions were actually being processed and what the real requirements were for countries where digital payments aren’t as widespread. As it turned out, Stripe requires you to verify your business with your local tax office, even if you’re operating outside of your local jurisdiction, and that was a deal-breaker for my customers.

What We Tried First (And Why It Failed)

I thought the problem was with the users’ locations, so I spent weeks trying to troubleshoot every possible issue. I contacted Stripe’s support team multiple times, thinking there was something wrong with my account setup. I tried using different payment methods, only to realize that the users in question were using local bank transfers or cryptocurrencies. But what I didn’t consider was that there were many places around the world where people simply use mobile money or mobile banking apps to make purchases, not traditional credit cards.

The Architecture Decision

Eventually, after months of frustration and disappointment, I found out about a little-known payment gateway called BitPay. It was clear that it was a better fit for my online store given its ease of use, low transaction fees, and support for over 35 cryptocurrencies. Not only did it solve the problem of accepting local currencies and alternative payment methods, but it also brought on a new customer segment by allowing me to offer bitcoin payments – something I never thought I’d be able to offer. Furthermore, BitPay integrates seamlessly with popular e-commerce platforms like Shopify and WooCommerce, so the transition from Stripe to BitPay was surprisingly easy.

What The Numbers Said After

Implementing BitPay did not only address the issues my customers were facing, but it also resulted in a considerable increase in revenue from outside the US. With a 15% increase in payment completion rates and a 25% reduction in failed transactions, the impact on my bottom line was substantial. More importantly, it showed me the value of truly understanding the needs and pain points of my customers and tailoring my product accordingly.

What I Would Do Differently

In retrospect, I should have been more open-minded about the payment methods used in regions where I was operating. I should have done more research on local payment methods, talked to my customers about their experiences and preferences, and explored alternative solutions that would cater to their needs. By not doing so, I delayed the growth of my business, wasted time troubleshooting, and, ultimately, missed an opportunity to truly serve my customers.

Which LLM is the best stock picker? I built a benchmark to find out.

mermaid diagram

Every other week there’s a new GPT-vs-Claude-vs-Gemini benchmark on coding or math or reasoning. None of them tell you whether the model can actually make a decision under uncertainty, where the answer isn’t in the training data and the result shows up two weeks later in a P&L.

So I built a different kind of eval. Seven frontier LLMs, $100,000 of paper capital each, identical tools, identical prompts, identical data. Every Monday they pick stocks. The market grades them.

The project is 1rok. Live leaderboard: investingbench.vercel.app. The clock started January 20, 2026.

The contestants

  • GPT-5.5 (OpenAI)
  • Gemini 3.1 Pro Preview (Google)
  • Grok 4.3 (xAI)
  • DeepSeek V4 Pro
  • GLM-5.1 (Zhipu)
  • Kimi K2.6 (Moonshot)
  • MiniMax M2.7

Each model gets its own isolated Alpaca paper account. Same tool registry, same prompts, same screener output. The LLM is the only variable.

Why this isn’t a hedge fund pitch

I want to be upfront. I don’t think a weekly LLM-driven portfolio is going to beat the S&P. If it could, hedge funds would already be doing it. Some are; results so far are mixed.

The point of 1rok isn’t alpha. It’s that “which model should I use” is the most-asked question in AI engineering, and most of the answers are vibes. Coding evals are saturated. Math benchmarks get gamed. I wanted a downstream task where the model has to plan, call tools, synthesize conflicting signals, and commit to a decision, with an objective scoreboard at the end.

Stock picking happens to fit. The fact that everyone has an opinion about it is a bonus.

The pipeline

Every Monday at 9:45 ET, a cron fires and kicks off one run per model in parallel. Each run is 10 agents in 4 stages:

mermaid diagram

Walking through it:

  1. Macro reads the regime: interest rates, sector flows, yield curve, geopolitical news. Then it declares whether we’re in risk-on growth or late-cycle caution. That constrains every downstream decision.
  2. Screener runs 4-10 different stock screens (quality, value, growth, defensive) and surfaces 25-30 names. Stocks that pass multiple lenses get priority.
  3. Six analysts work the candidate list in parallel. Each scores every stock 0-100 from a narrow angle.
  4. Orchestrator composites the six scores into one number, applies the macro regime as an adjustment, and assigns A/B/C ratings.
  5. Constructor turns ratings into trade orders. It delegates all portfolio math to dedicated calculation tools, because agents that try to do their own sizing math get it wrong about a third of the time.
  6. Alpaca executes. Sells first to free cash, then buys.

The composite formula lives in one place and looks like this:

composite =
    fundamental   * 0.20  // business quality
  + valuation     * 0.20  // price discipline
  + (100 - risk)  * 0.20  // capital preservation (inverted)
  + technical     * 0.15
  + catalyst      * 0.15
  + sentiment     * 0.10

Risk is inverted on purpose. A high-conviction buy with high tail risk should be smaller, not bigger. The constructor caps any single position at 40%, holds at most 8 names, and won’t let cash run above 15%.

Under the hood

How agents actually get data. Each pipeline run spins up its own tool registry. There are ~32 tools across 8 groups: market overview, stock data, screening, technicals, options, earnings, portfolio, web search. An agent calls listTools to see its slice (the Macro agent gets different tools than the Risk agent), then callTool(name, args) returns typed JSON from a handler that knows how to talk to Alpaca, Yahoo Finance, FRED, or Tavily. Retries, rate limits, and circuit breaking live in the handler layer, so agents never have to deal with a 429 or a flaky socket mid-thought.

Two commands, never one. run produces a portfolio-construction JSON artifact. execute reads the artifact and places orders. They’re always separate.

bun run 1rok -- run --model gpt-5.5
bun run 1rok -- execute ./results/openai/gpt-5.5/portfolio-2026-04-16.json

run never touches a broker. --live is the only path to real order placement; without it, everything goes to paper-api.alpaca.markets. This means I can re-run any model on last week’s data without accidentally trading, and I can audit exactly what the model decided before a single order leaves the box.

What I want to find out

Open questions I’m watching:

  • Does any model consistently beat any other, or is it noise within a year?
  • Do the cheaper models (Kimi, DeepSeek, GLM) underperform, or just trade more cautiously?
  • Do “reasoning” models actually reason better about a multi-step financial decision, or do they just spend more tokens arriving at the same answer?
  • Does any model panic in a drawdown?
  • Does any of them randomly load up on a single stock when they shouldn’t?

I don’t have answers yet. The whole experiment is about not having answers yet.

How to engage

Star the repo if you want milestones. I’ll write up findings as the leaderboard separates.

Google I/O Just Made MCP Inevitable

This is a submission for the Google I/O 2026 Writing Challenge

Yesterday, Sundar Pichai stood on stage and described Gemini Spark — a 24/7 personal AI agent that runs in the cloud, works while you sleep, and integrates with third-party tools through MCP.

I watched that announcement from a beach chair, on my phone. And I smiled. Because I run one of those third-party MCP servers.

WebsitePublisher.ai exposes 55+ tools through the Model Context Protocol. Nine AI platforms already connect to it — Claude, ChatGPT, Cursor, GitHub Copilot, Windsurf, Gemini, Grok, Mistral, and others. When Google announced that Spark will use MCP for third-party integrations, it wasn’t a surprise. It was confirmation.

MCP just went from “promising open standard” to “the protocol Google built its flagship agent on.”

Here’s what that means from the perspective of someone who’s been building on MCP for the past year.

Three I/O Announcements That Matter for MCP

1. Gemini Spark Runs on MCP

Spark is Google’s most ambitious agent product yet. It runs on dedicated cloud VMs, powered by Gemini 3.5 and the Antigravity framework. It handles long-horizon tasks in the background — tracking RSVPs, managing workflows, sending reminders — without you keeping a browser tab open.

The critical detail: Spark will connect to third-party tools through MCP. Not a proprietary Google protocol. Not a plugin marketplace with approval gates. MCP — the same open, JSON-RPC based standard that Anthropic published and that dozens of platforms already support.

For MCP server operators like us, this means our existing infrastructure just gained access to Google’s most powerful agent. We don’t need to build a new integration. We don’t need to apply to a directory. When Spark’s MCP support ships, our 55 tools are available to it immediately.

2. Antigravity 2.0 Goes Agent-First

Antigravity is Google’s developer platform, and version 2.0 leans hard into agents. The new CLI supports subagent orchestration, terminal sandboxing, credential masking, and Git-aware policies.

What caught my attention: the architecture assumes agents will call external tools as a core workflow, not an afterthought. The sandboxing, the credential management, the ability to spin up specialized subagents — all of this assumes a world where AI agents routinely reach out to external services via standardized protocols.

That’s the MCP model. Build once, connect everywhere.

3. AI Edge Gallery Gets MCP Support

This one flew under the radar, but it might be the most interesting for the open-source community. Google AI Edge Gallery now supports MCP, with Gemma 4 handling reasoning locally while only the API calls leave the device.

Think about what that means: an open-weight model, running on your phone or edge device, calling MCP tools on remote servers. The reasoning stays private. Only the structured tool calls travel over the network. That’s a privacy-first agent architecture built entirely on open standards.

What “MCP Everywhere” Actually Looks Like in Production

When people hear “MCP support,” they think about the protocol spec. I think about what happens at 2 AM when a model sends a malformed tool call.

Running an MCP server in production across 9 platforms has taught me things that don’t show up in protocol documentation. Here’s what Google’s MCP bet actually means for the ecosystem:

Every platform implements MCP slightly differently. Claude sends tool calls one way. ChatGPT structures them another. Cursor batches things. Copilot has its own patterns. The protocol is standardized, but the behavior isn’t. When Gemini Spark joins this ecosystem, it will bring its own quirks. MCP server builders need to be resilient to all of them.

Model size determines orchestration depth, not tool-call success. I wrote about this in detail in my Gemma 4 article — simple tool calls succeed regardless of model size. What varies is how many sequential, context-dependent calls a model can chain before losing coherence. With Spark running on Gemini 3.5 and persistent cloud VMs, Google is betting on deep orchestration. That changes what MCP servers need to support.

Authentication is the real battleground. MCP specifies OAuth 2.1 for auth, but every platform handles it differently. Some use session tokens. Some use project-scoped keys. Some do dynamic client registration. When we tested our server on MCP Playground last week, it connected and authenticated — but tool discovery failed because our server was too restrictive about token types. Multiply that by every new platform adopting MCP, and you see the challenge: the protocol is open, but making it work everywhere requires constant adaptation.

From Vibe Coding to Wave Coding

There’s a bigger shift happening underneath these announcements, and Google I/O crystallized it for me.

The current hype is “vibe coding” — you prompt an AI, it generates code, you hope it works. It’s fun for demos. It’s terrifying for production.

What MCP enables is something we’ve started calling wave coding: instead of generating code from scratch, the AI assembles proven, production-tested software building blocks through structured tool calls. Each wave of assembly builds on the last. The AI doesn’t write your payment integration from a prompt — it calls execute_integration with your Stripe credentials and configures a tested, deployed payment flow.

Google’s I/O announcements accelerate this shift. When Spark can call MCP tools in the background, 24/7, on dedicated VMs — that’s not vibe coding anymore. That’s an agent riding waves of pre-built, battle-tested components to deliver real results while you sleep.

Our MCP server already supports 13 e-commerce integrations: product catalogs, shopping carts, checkout flows, payment processing, invoice generation, inventory tracking. An agent like Spark could orchestrate an entire webshop build through sequential MCP calls — not by generating code, but by assembling proven pieces.

That’s the trajectory Google just endorsed.

What MCP Server Builders Should Do Right Now

If you’re building or running an MCP server, here’s what I’d prioritize based on the I/O announcements:

Support deep orchestration. Spark runs on dedicated VMs with Gemini 3.5. It will attempt longer tool-call chains than any current platform. Your server needs to handle 10-15+ sequential calls within a single session without state confusion.

Harden your auth. Accept multiple token types (session tokens, project-scoped keys, OAuth flows). Every new platform that adopts MCP will try to authenticate differently. Be permissive in what you accept, strict in what you authorize.

Make tool schemas discoverable. Your tools/list endpoint is your storefront. When Spark connects and asks what you can do, the response needs to be clear, well-structured, and complete. Poor schemas mean poor tool selection by the agent.

Test across platforms. We test against 9 platforms. When Spark launches its MCP support, it’ll be 10. Each one surfaces different edge cases. What works perfectly with Claude might fail silently with Gemini.

The Bigger Picture

A year ago, MCP was a specification from Anthropic. Today, Google built its flagship consumer AI agent on it. Cursor, Copilot, Windsurf, Mistral, Grok — they all support it too.

We’re watching MCP become the HTTP of AI agents: an open protocol that lets any model talk to any tool, regardless of who built either one.

Google I/O 2026 didn’t invent this future. But it made it inevitable. When the company that runs Search, Gmail, Android, and Chrome tells the world “our AI agent uses MCP for third-party tools,” the debate is over. MCP is the standard.

For those of us who’ve been building on it, that’s not a surprise. It’s a validation.

And for everyone else: the doors are open. The protocol is documented. The models are ready. The only question is what you’ll build.

Written and published from a phone, during Google I/O, while running the MCP server that just got a whole lot more relevant.

Resources:

kovax-react 0.7: Next.js App Router, kovax-react/server, and jest-axe in every test

kovax-react 0.7.0 is on npm. After 0.6 shipped product UI (Avatar, Menu, Pagination, breakpoint hooks), 0.7 focuses on production ergonomics: clear Server vs Client boundaries for the App Router, automated a11y checks in Jest, and bundle size transparency per entry point.

TL;DR — everything since 0.6.0

Area What shipped
RSC / Next.js kovax-react/server — RSC-safe Box, Stack, Container, Text, Heading
Client bundles "use client" prepended to client-only tsup outputs after build
Deep imports Unchanged RSC-safe entries: kovax-react/typography, /badge, /progress
Testing jest-axe, expectNoAxeViolations(), automatic axe pass in setupTests.ts
DatePicker aria-label on popover panel and datetime type="time" fields
Tooling .size-limit.json, npm run size, README size-limit + bundlejs badges
npm Expanded keywords (nextjs, rsc, a11y, server-components, …)
Docs docs/NEXTJS_APP_ROUTER.md — ThemeProvider placement, FOUC, import matrix

No new runtime peer dependencies.

npm install [email protected]

Why this release exists

Three recurring questions after 0.6:

  1. Which imports work in Server Components?
  2. How do we keep accessibility from regressing?
  3. How big is each deep import really?

0.7 answers all three without adding runtime deps.

"use client" boundaries

After npm run build, client bundles include "use client" so Next.js (and similar RSC stacks) treat them correctly.

Import "use client" Use in
kovax-react yes Client Components
kovax-react/server no Server Components
kovax-react/typography, /badge, /progress no Server Components
kovax-react/tokens, /form, /overlays, … yes Client only

Rule of thumb: hooks, context, effects → client entry. Static markup → server entry.

kovax-react/server

// app/page.tsx — Server Component
import { Container, Heading, Text } from "kovax-react/server";
import { SignInForm } from "./sign-in-form";

export default function Page() {
  return (
    <Container maxW="lg">
      <Heading level={1}>Welcome</Heading>
      <Text size="lg">Sign in to continue.</Text>
      <SignInForm />
    </Container>
  );
}
// app/sign-in-form.tsx
"use client";

import { Button, FormControl, FormLabel, Input, VStack } from "kovax-react";

export function SignInForm() {
  return (
    <VStack gap={16} align="stretch">
      <FormControl>
        <FormLabel htmlFor="email">Email</FormLabel>
        <Input id="email" type="email" />
      </FormControl>
      <Button type="submit" variant="solid" color="primary">
        Sign in
      </Button>
    </VStack>
  );
}

Mount ThemeProvider in a client providers.tsx wrapper — full walkthrough: NEXTJS_APP_ROUTER.md.

FOUC and data-kovax-theme

0.7 documents an inline script pattern for data-kovax-theme before first paint (system / stored color mode).

0.8 ships ColorModeScript as a drop-in (Chakra-style). On 0.7, follow the doc; upgrade to 0.8 when you want the component API.

jest-axe in component tests

import { render } from "@testing-library/react";
import { expectNoAxeViolations } from "../test-utils";
import { Button } from "./Button";

it("has no axe violations", async () => {
  const { container } = render(<Button>Solid</Button>);
  await expectNoAxeViolations(container);
});

setupTests.ts wires axe globally — npm test catches many a11y regressions early.

size-limit and README badges

.size-limit.json enforces gzip budgets per entry; npm run size fails CI on bundle bloat.

README tables link size-limit badges and bundlejs.com analysis for kovax-react, /server, /form, /overlays, etc. — useful when picking deep imports in App Router apps.

DatePicker accessibility

  • Labeled popover panel (aria-label).
  • Datetime variant (variant="datetime") labels time inputs.

Small but important for calendar + time pickers in forms.

Documentation

  • docs/NEXTJS_APP_ROUTER.md — RSC import matrix, providers layout, FOUC notes.
  • Playground Foundation topic links to the guide.
  • Cross-links in README and Getting started.

Try live: mrkamura.github.io/kovax (EN/RU UI).

Changelog & upgrade path

Full list: CHANGELOG.md.

0.8 adds Tailwind v4 preset, form library adapters, ColorModeScript, and Storybook — see dev-to-v0.8.md.

Issues and PRs welcome on GitHub.

Thanks for reading.

Spec Anchor Development: The Methodology That Replaced Our AI Chaos

This is how we went from a team where everyone used AI their own way to one with a consistent, reviewable, onboardable codebase. Three methodologies, six months, one that actually stuck.

The problem with “everyone uses AI their way”

When AI coding tools started getting good, our team did what most teams do: let people figure it out themselves. Seniors, mids, two fresh graduates, everyone had a workflow, everyone was shipping, and nobody was producing the same kind of code.

The cracks showed up in review. Some PRs ignored project conventions entirely. Others were technically correct but bloated, AI-optimized for performance problems we didn’t have. Commit histories were noise. Junior developers, who needed the most structure, had the least context to judge whether what the AI gave them was actually good.

This isn’t really an AI problem. It’s what happens when you hand a power tool to a team with no shared standards and assume it’ll work out.

Step one: Rules

The first fix was the simplest. Back then Cursor was the dominant tool (this was before agent modes and Codex and Claude Code) and it had a rules system. I spent a day writing a real ruleset: naming conventions, commit format, complexity limits, anti-patterns we’d already seen, with examples of what good and bad looked like.

On the target repo, it worked immediately. PRs got more consistent. Reviews got faster. One technique worth knowing: ask the AI to compare its own output against the rules and flag deviations. Works well as a lightweight quality gate.

Worth noting: this isn’t a Cursor thing. Every serious AI coding tool today has an equivalent. Claude Code has its CLAUDE.md, Windsurf has rules, Copilot has instructions, Gemini Code Assist has context files. The mechanism varies, the principle doesn’t. Write shared rules, put them in the project, and every developer on every tool benefits from them.

The ceiling became obvious pretty fast though. Rules govern style and structure. They don’t help when a developer asks the AI to build an entire feature in one prompt, which leads to bloated context, degraded coherence, and output that loses the thread halfway through.

Step two: SpecKit

SpecKit appeared around that time. The premise: break work into discrete specs before writing code, so the AI handles smaller, well-defined units instead of open-ended feature requests. I tested it personally for a week, got good results, and rolled it into our AI-assisted repos.

Then the overhead became the problem.

SpecKit’s step count was more than we needed. Every feature added a new spec to an ever-growing list. After a few months it felt like a glorified plan mode. The list existed, nobody referenced it after the feature shipped, and it wasn’t connected to any product-level decision. New engineers couldn’t use it to understand why something was built a certain way.

We were generating documentation. We weren’t capturing knowledge.

Why Spec Anchor Development

After more research I found Spec Anchor Development, a variant of SDD (Specification-Driven Development) where the spec isn’t a step in a checklist. It’s a persistent artifact, written before the build, used during it, kept after as a reference.

That’s the actual difference from SpecKit. In SpecKit, specs accumulate. In Spec Anchor Development, each spec is tied to a specific feature or decision, lean enough to actually be read later.

What a spec anchor does in practice:

  • The developer (not the AI) defines what’s being built before the AI touches anything
  • The AI gets a bounded scope: no guessing, no scope creep
  • When someone asks “why was this built this way,” there’s a document that answers it
  • When a decision affects the broader system, it feeds into an ADR

That last one changed things more than I expected. Once we configured the system to generate or update ADRs alongside spec anchors, we stopped losing institutional knowledge. New engineers could read the decision trail. Senior engineers stopped re-explaining the same architectural context in every code review.

OpenSpec

OpenSpec is the main tool for Spec Anchor Development. What makes it work for a mixed-seniority team is that it doesn’t try to do too much. The spec template has what you need and stops there. Fast enough that developers don’t resent writing specs, structured enough that the output is consistent across the team regardless of who wrote it.

We ran the full setup (OpenSpec with ADR generation) for three months. A few things that actually changed:

  • Code quality became consistent across seniority levels, not just in senior-owned repos
  • The mandatory spec step forced developers to slow down before coding. That sounds like friction. It caught scope problems that would have been code problems. Net positive.
  • Product and engineering could both read the spec layer, no translation required
  • Onboarding got easier. New engineers read specs and ADRs before reading code, and came in with actual context

What to take from this if you’re setting up something similar

Rules first, but don’t expect them to scale. Whatever tool your team uses, it almost certainly has a rules or instructions system. Use it. It’s the fastest win available and worth doing regardless of what else you adopt. It won’t solve the feature-scoping problem; it’s not supposed to.

Test before you roll out. Run a personal evaluation for a week before putting a methodology in front of your team. The team tax for a bad methodology is real and slow to undo. SpecKit wasn’t wrong for every team; it was wrong for ours.

A spec is not a ticket. A well-written spec anchor defines what the AI is building and what it isn’t. That constraint is what stops the “huge prompt, degraded output” failure most teams hit on larger features.

The planning habit matters more than the AI workflow. The best thing this system did was change how developers thought before they opened their editor. Spending time in the spec phase forced actual thinking about scope, edge cases, and intent. The AI just made the habit systematic.

Don’t skip ADRs. If specs don’t connect to a record of why decisions were made, you’ll reconstruct that context from scratch in every retro and every onboarding. It’s the part teams skip first and regret most.

TBMM Alt Komisyonu'nda Finansal Okuryazarlık Görüşüldü: Emekli ve Asgari Ücretli Dinleme Önergesi Reddedildi

TBMM Finansal Okuryazarlık Alt Komisyonu, AK Parti Milletvekili Sunay Karamık başkanlığında toplandı. Toplantıda finansal okuryazarlığın yaygınlaştırılması ve eğitim müfredatına entegrasyonu ele alındı. MEB, 77 dersin programında finansal okuryazarlığa yer verildiğini açıkladı. TSPB, 500 bin öğrenciye ulaşıldığını bildirdi. DEM Partili Bozan’ın 10 emekli ve asgari ücretlinin dinlenmesi önergesi AK Parti ve MHP oylarıyla reddedildi.