Elements Kinds

Se você usa arrays no JavaScript, o motor V8 está tomando decisões por trás dos panos que podem deixar seu código MUITO mais rápido… ou MUITO mais lento.

E a maioria das pessoas nem percebe 👇

📌 O segredo: *Elements Kinds*

O V8 classifica seus arrays internamente para otimizar execução.
Mas essa otimização depende totalmente de como você usa o array.

🔑 Tipos que o V8 usa

🟢 SMI (inteiros) → mais otimizado

[1, 2, 3]

🟡 DOUBLE (float)

[1, 2.5]

🔴 GENERIC (misturado) → pior cenário

[1, "a", {}]

⚠️ Armadilha crítica (quase ninguém fala disso)

A evolução é irreversível:

SMI → DOUBLE → GENERIC

const arr = [1, 2, 3];
arr.push(1.5); // já piorou
arr.push("x"); // pior ainda

👉 Depois disso, não tem volta.

📦 PACKED vs HOLEY

🚀 PACKED (rápido) → sem buracos

[1, 2, 3]

🐢 HOLEY (lento) → com buracos

const arr = [1, 2, 3];
arr[10] = 5;

👉 Isso força o V8 a fazer mais checks internos.

⚡ O que destrói sua performance

  • Misturar tipos no mesmo array
  • Criar arrays esparsos (buracos)
  • Mudar o tipo ao longo do tempo

🚀 Como escrever código mais rápido

  • Use arrays homogêneos
  • Evite buracos
  • Seja previsível
  • Não “evolua” o array sem necessidade

🧠 Resumo brutal

  • V8 otimiza arrays agressivamente
  • Você pode quebrar isso facilmente
  • Pequenas decisões → grande impacto em escala

Para saber mais segue o post que fala mais a fundo sobre esse assunto.

From Zero to Shipped: How We Built Indiefy.xyz in a Weekend (With AI as Co-Founder)

We built a full-stack SaaS product – auth, database, payments, integrations, leaderboard, i18n, mobile UI, SEO – in a single sprint using AI as a build partner. Here’s every step, decision, and dead end. By the end of this post, you’ll think “wait, I could actually build that.”

The Idea That Wouldn’t Shut Up

Every indie hacker has the same problem: you want to build in public, but the tools suck.

You’ve got your MRR on a Google Sheet. Your equity is in a Notion doc nobody reads. Your expenses live in three different apps. And when someone asks “how’s the startup going?” you have to piece together a story from six different tabs.

That’s when the idea hit: what if Spotify, but for founders?

Not Spotify the product – Spotify the vibe. The dark design. The stats everywhere. The “Wrapped” that makes you feel like your year actually meant something. A profile page at indiefy.xyz/yourname that tells your whole founder story in one scroll – real MRR, real profit, real equity, real goals.

We called it Indiefy.

Step 0: Write the Spec Before Writing a Single Line of Code

The first thing we did wasn’t open a terminal. We wrote an indiefy.md file – a proper product spec. Not a Notion doc, not a tweet thread. A real, structured document with:

  • The concept in one sentence: “Spotify, but for indie hackers”
  • The target audience (5 different profiles: solo founders, early employees with stock options, angels, advisors, minority partners)
  • Every single feature, grouped into sections
  • The monetization model (Free vs Pro)
  • The tech stack
  • A 5-day build timeline

This step is the one most builders skip. Don’t skip it. When you have a spec, you have prompts. When you have prompts, AI can actually build your product instead of guessing.

Here’s an excerpt from ours:

## Features

### Charges & P&L public
- Real Profit = MRR - project costs - pro-rata fixed costs
- Runway = savings / total monthly costs
- Break-even: at what MRR you cover everything

> First tool that shows REAL project profitability, not just gross MRR.

That last line became our north star for every design decision.

Step 1: The Design System First (Seriously, Do This First)

We started with design tokens, not code. The whole aesthetic was clear from day one: Spotify dark theme. Exactly this palette:

Token Value
Background #0a0a0a
Cards #111111 and #1a1a1a
Accent green #1DB954
Primary text #FFFFFF
Secondary #A3A3A3
Borders #2a2a2a

Two fonts. That’s it. DM Sans for body copy. Syne for numbers and titles – that Syne font on a big MRR number hits different.

The prompt we gave the AI was surgical:

Create the complete design system for Indiefy.
Stack: Next.js 16 App Router, Tailwind CSS v4, TypeScript strict.
Design: Spotify-inspired, dark mode only.
Colors: [exact hex values]
Typography: DM Sans (body) + Syne (stats/titles)
Generate: tailwind.config.ts, globals.css, Layout.tsx with left sidebar,
Card.tsx (variants: default/highlight/glass), Typography.tsx
Rules: NO generic Bootstrap-like styles. Server Components by default.

The AI spit out a complete design system in one shot. Because the prompt was specific. Garbage in, garbage out – and vice versa.

Step 2: The Database Schema – Think Hard Before You Click Enter

The spec: 8 models. User, Project, Expense, Revenue, Goal, Milestone, Badge, Follow.

We wrote out the entire Prisma schema by hand in the spec file before generating it. Every relation, every index, every enum. This took 45 minutes and saved us from three migrations later.

model Project {
  id                 String        @id @default(cuid())
  userId             String
  name               String
  slug               String        @unique
  status             ProjectStatus // ACTIVE | ACQUIRED | DEAD | STEALTH
  equityPercent      Float?
  estimatedValuation Float?
  mrr                Float         @default(0)
  isPublic           Boolean       @default(true)
  showFinancials     Boolean       @default(false)
  // ...
}

The showFinancials boolean was a key product decision: people can share their profile publicly without showing the money. This unlocks a whole segment of users who want visibility but not full transparency.

We also added the Integration model from day one – Stripe, RevenueCat, LemonSqueezy, Paddle – even before building the integration pages. Schema-first means you don’t paint yourself into a corner later.

Step 3: Auth – The Part Everyone Dreads

Supabase Auth with Google + GitHub OAuth. Two provider buttons. That’s it.

The interesting part wasn’t the OAuth flow – it was the sync between Supabase Auth (which handles the JWT and session) and Prisma (which owns the business data). We wrote a route app/api/auth/sync/route.ts that fires after OAuth callback and ensures a User row exists in Postgres.

The middleware was three lines of logic:

// middleware.ts
const isProtectedRoute = matcher.some(path => req.nextUrl.pathname.startsWith(path))
const session = await getSession(req)

if (isProtectedRoute && !session) {
  return NextResponse.redirect(new URL('/login', req.url))
}

Username validation deserves a mention: lowercase, alphanumeric + hyphens, 3-20 chars, unique. We validated this with Zod server-side and debounced API check client-side. Tiny detail, important UX.

Step 4: The Dashboard – Making Numbers Feel Alive

This is where the product really started to look like something.

Four KPI cards at the top:

  1. Total MRR
  2. Net Profit
  3. Total Users
  4. Paper Wealth (equity x valuations)

That last one is what makes Indiefy different from every other dashboard tool. Paper wealth – the sum of all your equity stakes multiplied by estimated valuations – is a number no other tool shows you. It might be zero. It might be fictional. But it’s yours, and it’s there, and it feels good.

The MRRChart component used Recharts AreaChart with a gradient fill. One snippet made the whole chart feel premium:

<defs>
  <linearGradient id="mrrGradient" x1="0" y1="0" x2="0" y2="1">
    <stop offset="5%"  stopColor="#1DB954" stopOpacity={0.3} />
    <stop offset="95%" stopColor="#1DB954" stopOpacity={0} />
  </linearGradient>
</defs>

Step 5: Projects – The Core Loop

The project form was the most complex UI we built. A slider for equity percentage (0-100) with a live calculation beneath it: “Your estimated stake: 47,000”. A tech stack tag input. Status badges that actually looked like badges, not dropdowns.

The killer feature was the acquisition simulator. You type a valuation. The number updates instantly:

const yourShare = (estimatedSale * equityPercent) / 100
// Displayed in real-time as you type

Status colors:

Status Color Vibe
ACTIVE #1DB954 green Go time
ACQUIRED Blue Congrats
DEAD Red RIP
STEALTH Gray We see you

After creating a project, we auto-generated a milestone: "Launch de projet". Small touch. Makes the product feel alive immediately.

Step 6: Expenses & Real P&L

This is the feature that makes Indiefy honest.

Most “MRR dashboards” just show you gross revenue. Indiefy shows you the real number:

Gross Revenue (MRR):           2,400
Project costs (Vercel, etc): -    89
Fixed costs (pro-rata):      -   340
                             --------
Net Profit:                    1,971  
Margin rate:                      82%
Runway:                    14 months
Break-even MRR:                  429

The getPnLSummary() server action ran a single Prisma query that joined revenues, project expenses, and fixed costs pro-rated across all active projects. The math isn’t complex – it’s just honest math nobody else was doing.

Step 7: Integrations – The Part That Made It Real

Instead of just supporting Stripe, we ended up integrating five payment providers:

  • Stripe – OAuth Connect, read-only access
  • RevenueCat – API key, for mobile apps
  • LemonSqueezy – API key
  • Paddle – API key
  • Polar – the new open-source one
  • Dodo Payments – emerging market focus

The git log tells the story:

e98928d Polar
2f675fd leaderboard
7457233 dodo payments
67366a0 paddle
829add8 coming soon integrations

Each integration followed the same pattern:

// lib/integrations/syncEngine.ts
async function syncProjectRevenue(projectId: string): Promise<SyncResult> {
  const integration = await getActiveIntegration(projectId)
  const data = await fetchFromProvider(integration)

  await prisma.project.update({
    where: { id: projectId },
    data: { mrr: data.mrr, arr: data.arr, totalRevenue: data.totalRevenue }
  })

  await createRevenueEntry(projectId, data)
  await checkAndGenerateMilestones(projectId)
  await updateLastSynced(integration.id)

  return { success: true, mrr: data.mrr, lastSyncedAt: new Date() }
}

API keys were stored encrypted with AES-256-GCM. Not optional. You’re handling people’s financial data.

The Vercel cron job synced everything at 6am daily:

// vercel.json
{
  "crons": [{
    "path": "/api/cron/sync-revenues",
    "schedule": "0 6 * * *"
  }]
}

Step 8: Leaderboard – The Viral Loop

The leaderboard was the feature we almost cut. “Do we really need a ranking system?”

Yes. We really did.

2f675fd leaderboard
a2e22b5 explore algo
a17f087 trending algo

Three commits across leaderboard features. The ranking algorithm wasn’t just “sort by MRR” – we built a momentum score: a composite of MRR velocity (month-over-month growth %), user growth, and update frequency.

A 200 MRR project growing 30% monthly ranks higher than a 5k MRR project that hasn’t been updated in three months.

The Explore page had its own trending algorithm. Same logic: recent activity + growth velocity > absolute numbers. This made the platform feel fair for people who are just getting started.

Step 9: Mobile – The Feature You Can’t Skip Anymore

b8ff2e8 mobile ui
b4fc4a6 bottom nav
471fcce bubbles: mobile nav icons, verified-only badges
3a8410b loading pages

Mobile was a late sprint but not an afterthought. We replaced the left sidebar with a bottom navigation bar on mobile. Standard pattern, but the implementation matters: same server components, just conditional layout based on viewport. The Tailwind breakpoints did the heavy lifting.

The “bubble” nav icons made the mobile UI feel native rather than “responsive web.” Five tabs: Dashboard, Explore, Profile, Goals, Settings.

Loading states were added systematically across all pages – skeleton screens, not spinners. The difference between a product that feels fast and one that feels slow is often just skeleton screens.

Step 10: i18n – Because Half Your Users Aren’t English

d2ca272 i18n
ba6d47f i18n
40a060b Goal i18n

We used next-intl for internationalization. The routing structure:

app/
  [locale]/
    dashboard/
    profile/
    ...

Every user-facing string became a key:

const t = useTranslations('dashboard')
// t('kpi.totalMrr') -> "Total MRR" or "MRR Total"

Three commits for i18n because the first one was “we need i18n”, the second was “actually doing i18n”, and the third was “ok goals weren’t translated yet.”

Step 11: Security, Legal, Pricing

b4fc4a6 legals
a78c03e SECU
5023241 pricing page

Security was a dedicated commit because integrations meant we had real sensitive data: OAuth tokens, API keys, payment provider access. We audited every route for:

  • Auth checks on every server action
  • User ownership verification before any data mutation
  • Encrypted storage for all third-party credentials
  • Rate limiting on public API endpoints

Legal pages (Privacy Policy, Terms of Service) were generated but reviewed. You need them. Especially when you’re storing financial data and connecting to payment processors.

The pricing page was the last non-feature piece. Simple: Free (1 project, basic stats) vs Pro (~7/month, everything).

Step 12: SEO – The Long Game Starts at Launch

7928c7b SEO
eb6e47b SEO
2312193 Analytics
6e88960 Remove from sitemap the not public accounts

Dynamic OG images for every public profile (using @vercel/og). Proper <meta> tags. Sitemap generation that excluded private accounts – you don’t want to index profiles people marked private.

Vercel Analytics + Speed Insights went in at the same time. You can’t improve what you don’t measure.

The Final Stack

After 115 commits, here’s what Indiefy runs on:

Layer Technology
Framework Next.js 16 (App Router)
Styling Tailwind CSS v4
Database Supabase (PostgreSQL)
ORM Prisma 7
Auth Supabase Auth (Google + GitHub OAuth)
Payments Stripe (subscriptions)
Integrations Stripe, RevenueCat, LemonSqueezy, Paddle, Polar, Dodo
Charts Recharts
i18n next-intl
Validation Zod v4
Toasts Sonner
Deployment Vercel
OG Images @vercel/og
Analytics Vercel Analytics + Speed Insights

What Made This Possible

The honest answer: structured prompts written by a human who knew exactly what to build.

Every build step was a complete, specific prompt:

  • “Generate X with these exact fields”
  • “Use Zod for validation”
  • “No any types”
  • “Server Components by default, use client only when necessary”
  • “Match this exact design system”

The AI didn’t make product decisions. It executed them. The product thinking – what to build, why, in what order – that was 100% human.

Three things made the AI useful here:

  1. Specificity – vague prompts get vague code
  2. Existing design system – the AI respected our tokens because we defined them first
  3. Step-by-step – small, focused tasks beat “build me an app”

The Numbers

Metric Count
Git commits 115
Major features ~15
Payment integrations 6
Languages at launch 2
Bootstrap CSS used 0

Could You Build This?

Yes. Genuinely, yes.

The technical complexity here isn’t exceptional. Next.js App Router is mature. Supabase handles auth beautifully. Prisma removes the pain from database work. Stripe’s documentation is excellent.

What’s rare isn’t the ability to build it – it’s the discipline to spec it first, prompt it right, and ship before perfecting.

The features we shipped aren’t perfect. Some UI could be cleaner. The mobile experience could be smoother. The analytics could be deeper. But the product exists, it works, and it’s live.

Perfect is the enemy of shipped.

What’s Next for Indiefy

  • Indiefy Wrapped (December): your year as a founder, Spotify-style, shareable card
  • Enjoy life

If you’re an indie hacker who wants to display your real journey – not just a landing page, but actual MRR, real profit, equity you might never cash out but still own – create your profile at indiefy.xyz.

My First Electronics Project – Building a Real-Time Power Outage Monitor with ESP32 and Slack

The moment of realization happened in Singapore. I was thousands of miles away from home, enjoying a trip, when I went to check my home CCTV footage through my phone. The screen stayed black. “Connection Failed.”

The internal monologue of a developer immediately goes to the worst-case scenario: Did the router die? Is there a break-in? Did the server crash?

The reality was much simpler, yet equally frustrating: a power cut. The cameras ran on their internal batteries until they hit 0%, leaving me in a complete information blackout. I didn’t know if the power was out for ten minutes or ten hours.

I promised myself I wouldn’t leave for another trip without a “Heartbeat” from my home in Amritsar.

The Solution

I needed a non-invasive system (no cutting 220V mains wires), resilient to inverter switchover gaps, and capable of sending instant notifications.

I chose the ESP32 for its built-in Wi-Fi and low power consumption. By pairing it with a Slack Webhook, I created a device that “shouts” the second the grid fails.

The Hardware Stack

To keep things modular and “plug-and-play,” I went with:

  • ESP32 DevKit V1: The brain of the operation.

  • USB-TTL Converter: This acts as the sensor. It brings the 5V USB signal down to a safe 3.3V for the ESP32 to read.

  • 1000µF Capacitor: Essential for bridging the 20ms gap during inverter switchover. This prevents the ESP32 from rebooting during the transition.

  • Female-to-Female jumper wires

  • Some USB data cables

Engineering the “Flicker Filter”

One of the biggest hurdles was electrical noise. GPIO 34 on the ESP32 is an input-only pin and can act like an antenna. Without a solid ground reference, the signal “flickered” between ON and OFF.

I solved this with a two-pronged approach:

  1. Grounding Geometry: Moving the ground wires to the same side of the board to stabilize the reference voltage.

  2. Software Debounce: I implemented a 3-second delay in the code. The system verifies that the power is actually out before sending a Slack alert, preventing false alarms from minor grid fluctuations.

Watch the Journey

I documented the entire process—from navigating the local electronics markets in my city to the final “Production” test where I manually tripped the MCB.

Closing Thoughts

Engineering isn’t just about writing code for a Jira ticket; it’s about solving the small, personal anxieties of life through technology. Now, when I’m on vacation, I’ll know exactly what’s happening at home. Not because I’m checking a camera, but because my home is talking to me.

If you’re interested in building this yourself, feel free to reach out or check out the repository!

The Grimoire and Latent Space

For over forty years I have been fascinated by programming, and the fascination has always been rooted in the same thing: the experience of creating something apparently out of nothing, using nothing but my own thoughts.

There is no raw material. No canvas, no clay, no timber. There is only the space between what I intend and what I can express, and the slow, iterative work of closing that gap. I begin with an idea — an imagining, sometimes sharp, sometimes barely a shape — and I start capturing it in code. Each statement is an attempt to say what I mean. Each execution reveals where I didn’t quite say it. A small adjustment here, a rethink there. The thing I am building talks back to me through its failures, and through that conversation, it takes form.

I have always thought of this process as something like discovering a grimoire. Not writing one — discovering one. Each line of code is an incantation that I did not fully understand until I spoke it and saw what it summoned. The completed program is a spell that, once all its clauses are right, produces the solution as if by conjuring. The magic was never in any single line. It was in the accumulation, the patient layering of intent upon intent until the whole thing coheres and something real emerges from something that was, moments before, entirely imaginary.

This is what has kept me coming back. Not the solutions themselves — those are fleetingly satisfying. What keeps me is the act of creation. The journey.

The arrival of AI capable of writing code raises a practical question: can I hand over the cognitive load of creation? Not the typing but the imagining. The imagining-into-existence.

Considering it that way, a question arises.

Where do those ideas live before I reach for them?

When I sit down to solve a problem, the solution does not arrive fully formed. It emerges. I reach for something — a pattern, an approach, a structural intuition — and it is there, available to be grasped. But where was it before I reached? Is it purely the product of my own mind, the accumulated residue of everything I have learned and experienced? My conscious knowledge and my subconscious experience, firing together to produce candidates that I then select from?

I think the answer is yes, but the yes is more interesting than it first appears. Because what I am describing is not retrieval. It is not like opening a filing cabinet. It is more like reaching into a space of possibilities — a vast, high-dimensional space shaped by every problem I have ever encountered, every solution I have ever seen, every conversation, every failure, every late-night debugging session — and plucking from it a candidate that feels right. The conscious mind does the plucking. But the space itself is built from both conscious and subconscious experience, and it contains far more possibilities than I could ever enumerate.

In the world of AI, we talk about latent space. This is the internal, high-dimensional representation that a neural network builds from its training data — a vast landscape of encoded relationships, patterns, and possibilities that the model navigates when generating a response. The model does not retrieve answers from a database. It moves through latent space, and what it produces is shaped by the topology of that space.

If latent space is the product of an AI’s training, is my own accumulated experience not my own latent space?

I believe the answer is yes.

Recently I came across the concept of nāma-rūpa.

Nāma-Rūpa is a Buddhist philosophy, the name is a compound from Pali and Sanskrit: nāma means name, rūpa means form. Having lived in Malaysia, I recognised the words — nama and rupa — and that recognition attracted me.

The philosophy is very deep but what resonated with me were the ideas that to name something is to participate in giving it form and to perceive form is already to have named it. The first direction is intuitive — a programmer names a function and, by naming it, begins to define what it does. The second direction is subtler: when I look at a sprawling piece of code and suddenly see “this is a state machine,” the recognition is itself a naming act. The form was there, latent. Naming it made it available for thought.

This viewpoint enabled me to express everything I have written so far in a single sentence.

By naming something, I give it form and pull it from latent space

When I name a function, I help give it form. When I name a variable, I help give it form. When I name an architectural pattern — “this is a pub-sub system,” “this is a state machine” — I am reaching into the latent space of my experience and selecting a form by the act of naming it. The name is the handle. The latent space is the source. The form is what appears.

It is, at least to me, a useful description of what happens when a programmer creates. The latent space is real — it is the structured, high-dimensional encoding of everything you know and have experienced, most of which you could never articulate directly. Naming is the mechanism by which you reach into that space and collapse a cloud of possibilities into a specific form.

And this single formulation, By naming something, I give it form and pull it from latent space, allows me to approach my objective of passing the cognitive load of creation to AI.

I need to create the environment where the AI can name things from its own latent space and, by naming them, give them form. That environment is the subject of the next planned essay.

How to Implement Room Database CRUD in Android with RecyclerView (Step-by-Step Kotlin Guide)

In this blog, we will learn how to implement complete CRUD (Create, Read, Update, Delete) operations using Room Database in Android with Kotlin. This guide covers a practical implementation using RecyclerView to display data and perform real-time updates.

We will build a simple user management feature where users can add, view, update, and delete records. The project uses modern Android development practices including Coroutines, LiveData for observing database changes, and a clean adapter-based RecyclerView setup.

By the end of this tutorial, you will understand how to:
Insert data into Room Database
Observe and display data using LiveData
Update existing records dynamically
Delete items directly from RecyclerView
Structure your code for better scalability

class RoomDatabaseActivity : AppCompatActivity() {
    private lateinit var binding: ActivityRoomDatabaseBinding
    private lateinit var db: AppDatabase

    private lateinit var userAdapter: UserAdapter
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        enableEdgeToEdge()
        binding = DataBindingUtil.setContentView(this, R.layout.activity_room_database)
        ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets ->
            val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
            v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom)
            insets
        }
        initView()
    }

    private fun initView() {
        db = DatabaseBuilder.getInstance(this@RoomDatabaseActivity)

        userAdapter = UserAdapter(onDelete = { userData ->
            lifecycleScope.launch {
                db.userDao().deleteUser(userData)
            }
        }, onUpdate = { userData ->
            lifecycleScope.launch {
                db.userDao().updateUser(
                    userData.copy(name = userData.name + " Updated")
                )
            }
        })

        binding.rvUser.adapter = userAdapter
        binding.rvUser.layoutManager = LinearLayoutManager(this)

        binding.btnSubmit.setOnClickListener {
            if (binding.edtAge.text.toString().isNotEmpty() && binding.edtName.text.toString()
                    .isNotEmpty()
            ) {
                lifecycleScope.launch {

                    db.userDao().insertUser(
                        User(
                            name = binding.edtName.text.toString().trim(),
                            age = binding.edtAge.text.toString().toInt()
                        )
                    )
                }
            } else {
                Toast.makeText(this, "Enter Name & Age", Toast.LENGTH_SHORT).show()
            }
        }

        lifecycleScope.launch {
            db.userDao().getAllUsers().observe(this@RoomDatabaseActivity) { userList ->
                userAdapter.setData(userList)
            }
        }
    }
}

implement Room Database in Android with Kotlin, including Entity, DAO, CRUD operations, and a singleton database setup using best practices.

Database class

@Database(entities = [User::class], version = 1)
abstract class AppDatabase: RoomDatabase() {
    abstract fun userDao(): UserDao
}

User Table(Model)

@Entity(tableName = "user_table")
data class User(
    @PrimaryKey(autoGenerate = true)
    val id: Int = 0,
    val name: String,
    val age: Int
)

UserDao Class

@Dao
interface UserDao {
    // CREATE
    @Insert
    suspend fun insertUser(user: User)

    // READ
    @Query("SELECT * FROM user_table")
    fun getAllUsers(): LiveData<List<User>>

    // UPDATE
    @Update
    suspend fun updateUser(user: User)

    // DELETE
    @Delete
    suspend fun deleteUser(user: User)
}

Create Database Instance


object DatabaseBuilder {
    private var INSTANCE: AppDatabase? = null

    fun getInstance(context: Context): AppDatabase {
        return INSTANCE ?: synchronized(this) {
            val instance = Room.databaseBuilder(
                context.applicationContext,
                AppDatabase::class.java,
                "user_db"
            ).build()
            INSTANCE = instance
            instance
        }
    }
}

Adapter For Display Data

class UserAdapter(
    private val onDelete: (User) -> Unit,
    private val onUpdate: (User) -> Unit
) : RecyclerView.Adapter<UserAdapter.ViewHolder>() {
    private var list = ArrayList<User>()

    fun setData(data: List<User>) {
        list.clear()
        list.addAll(data)
        notifyDataSetChanged()
    }

    override fun onCreateViewHolder(
        parent: ViewGroup,
        viewType: Int
    ): ViewHolder {
        val binding =
            ItemUserDesignBinding.inflate(LayoutInflater.from(parent.context), parent, false)
        return ViewHolder(binding)
    }

    override fun onBindViewHolder(
        holder: ViewHolder,
        position: Int
    ) {
        val itemData = list[position]
        holder.setData(itemData, onDelete, onUpdate)

    }

    override fun getItemCount(): Int {
        return list.size
    }

    class ViewHolder(private val binding: ItemUserDesignBinding) :
        RecyclerView.ViewHolder(binding.root) {
        fun setData(itemData: User, onDelete: (User) -> Unit, onUpdate: (User) -> Unit) {
            binding.tvName.text = itemData.name
            binding.tvAge.text = itemData.age.toString()

            binding.btnDelete.setOnClickListener {
                onDelete(itemData)
            }

            binding.btnUpdate.setOnClickListener {
                onUpdate(itemData)
            }
        }
    }
}

This guide demonstrates how to implement Room Database in Android using Kotlin. It covers creating an Entity to define the table structure, a DAO for handling CRUD operations, and a Database class to manage data access.

A singleton pattern is used to ensure a single instance of the database throughout the app. LiveData is utilized to observe data changes and automatically update the UI, making the app more reactive and efficient.

Overall, this setup provides a simple and scalable approach to local data storage in Android applications.

Trying to solve a frustrating problem: why is debugging AI systems still so unclear?

I’ve been thinking about something that keeps coming up when working with AI systems. When a model gives a wrong or weird output, it’s surprisingly hard to figure out what actually went wrong. Most of the time we’re digging through logs
or guessing where things broke.
As part of the AWS AI Ideas hackathon, I started building a concept called AutopsyAI. The idea is to look at the full pipeline from input to output and try to explain where things might have failed, instead of just showing the final result. It’s still early and not a full product yet, more like an attempt to explore whether this problem is worth solving in a structured way.
Curious how others here deal with this. If you’ve worked with AI systems in production, how do you debug failures today? Does this feel like a real problem, or is it already solved better than I think?

Please do checkout my article and support it!
https://builder.aws.com/content/3AeXXMtLdDuPwRL4xcEjJEBoQkB/aideas-autopsyai-the-missing-debugger-for-ai-systems

Spider-Man fragman izle! Spider-Man Brand New Day fragman yayınlandı mı, nereden izlenir?

Sinema dünyasının en ikonik süper kahramanlarından biri olan Spider-Man, yeni filmi Spider-Man: Brand New Day ile yeniden gündemin merkezine yerleşti. Sony Pictures tarafından başlatılan kapsamlı tanıtım süreci, klasik fragman lansmanlarının ötesine geçerek küresel bir dijital etkinliğe dönüştü. Peki, Spider-Man Brand New Day fragman yayınlandı mı, nereden izlenir? Spider-Man fragman izle! Detaylar…

Same Framework, Different Engine: Porting AI Coding Workflows from Claude Code to Codex CLI

TL;DR

  • I built a sub-agent workflow framework for Claude Code that solved context exhaustion through specialized agents and structured workflows
  • For 8 months, Codex CLI had no sub-agents — the framework was Claude Code-only
  • Codex finally shipped sub-agent support — I expected days of migration, it took an afternoon
  • What surprised me most: if you design workflows around agent roles and context separation rather than tool-specific features, your investment survives platform shifts

The 8-Month Wait

Back in July 2025, I released the first version of this workflow as a Claude Code boilerplate. By October 2025, it had evolved into a full sub-agent framework — specialized agents for every phase of development, from requirements analysis through TDD implementation through quality gates. The idea was pretty simple: break complex coding tasks into specialized roles (requirement analyzer, technical designer, task executor, quality fixer…), give each agent a fresh context, and orchestrate them through structured handoffs. No single agent ever hits the context ceiling because no single agent tries to do everything.

The problem? Codex CLI had no sub-agent capability. Codex had been around since mid-2025, and I wanted the same workflow there too. So I kept trying to bridge the gap.

First, I built an MCP server in August 2025 that let any MCP-compatible tool — Codex, Cursor, whatever — define and spawn sub-agents through a standard protocol. It worked, but MCP added a layer of indirection that wasn’t there in Claude Code’s native sub-agents.

Then in December 2025, Codex shipped experimental Agent Skills support. I saw an opening and built sub-agents-skills — cross-LLM sub-agent orchestration packaged as Agent Skills, routing tasks to Codex, Claude Code, Cursor, or Gemini. Closer, but still not native sub-agents.

Through all of this, my main development stayed on Claude Code. The context separation and the small context windows of the time made it the clear choice for serious work. Codex filled a supporting role — I used it for skills refinement and as an objective reviewer on complex implementations, a fresh set of eyes from a different LLM.

I don’t use hooks extensively — I prefer keeping tasks small and baking quality gates into the completion criteria themselves. So what I was really waiting for was native sub-agent support in Codex, which would let the full orchestration workflow run without workarounds.

On March 16, 2026, Codex CLI shipped sub-agent support. During pre-release validation, I noticed something encouraging: Codex followed the workflow stopping points more strictly than expected. If the behavior stabilizes, it could be a viable primary development tool, not just a supporting one.

The port took almost no effort.

What “Near-Zero Migration” Actually Looks Like

When I say “the same framework,” I mean it. The core architecture didn’t change:

User Request
    ↓
requirement-analyzer → scale determination [STOP for confirmation]
    ↓
technical-designer → Design Doc
    ↓
document-reviewer [STOP for approval]
    ↓
work-planner → phased task breakdown [STOP]
    ↓
task-decomposer → atomic task files
    ↓
Per-task 4-step cycle:
  task-executor → escalation check → quality-fixer → git commit

22 sub-agents. 26 skills. The same stopping points, the same quality gates, the same TDD enforcement.

What changed was the container format, not the content:

Aspect Claude Code Codex CLI
Agent definitions Markdown with YAML frontmatter (agents/*.md) TOML files (.codex/agents/*.toml)
Skills location skills/ .agents/skills/
Tool declarations Explicit in frontmatter (tools: Read, Grep, Glob...) Not needed (inferred from sandbox mode)
Skill references Comma-separated names [[skills.config]] arrays
Config directory .claude/ .codex/

That’s it. The agent instructions — the actual substance of what each agent knows and does — are the same. The workflow logic is the same. The quality criteria are the same.

Why This Worked: Design Decisions That Paid Off

It worked for a surprisingly simple reason — three choices I made early on:

1. Natural Language as the Interface Layer

Every sub-agent’s behavior is defined in natural language instructions, not in platform-specific tool calls. The requirement-analyzer isn’t wired to Claude Code’s Agent tool or Codex’s spawn_agent — it follows a written protocol: “Extract task type, determine scale (1-2 files = Small, 3-5 = Medium, 6+ = Large), identify ADR necessity, output structured JSON.”

This means the instructions work on any LLM-powered agent system that can read text and follow procedures. In practice, that turned out to be enough. The framework is fundamentally a set of well-written job descriptions, not a set of API integrations.

2. Context Separation as Architecture

The core insight from the original article still applies: each agent runs in a fresh context without inheriting bias from previous steps. The document-reviewer doesn’t know what the technical-designer was “thinking” — it just reviews the output. The investigator explores without confirmation bias from whoever reported the bug.

This isn’t a Claude Code feature or a Codex feature. It’s an architectural pattern that happens to be implementable on both platforms once they support sub-agents.

3. Structured Handoffs Over Shared State

Agents communicate through artifacts (documents, JSON outputs, task files), not through shared memory or conversation threading. The technical-designer writes a Design Doc. The work-planner reads that Design Doc. Neither needs to know which platform spawned the other.

docs/
├── prd/          # PRD artifacts
├── adr/          # Architecture decision records
├── design/       # Design documents
├── plans/        # Work plans
│   └── tasks/    # Atomic task files (1 commit each)

This file-based protocol turned out to be surprisingly platform-agnostic.

The Framework in Action

codex-workflows ships as an npm package:

npx codex-workflows install

This drops the full agent and skill infrastructure into your project. From there, you invoke recipe skills that orchestrate the sub-agents:

Recipe What It Does
$recipe-implement Full lifecycle: requirements → design → implementation → quality
$recipe-design Requirements → design documents only
$recipe-build Execute pre-planned tasks autonomously
$recipe-diagnose Problem investigation → root cause → solutions
$recipe-front-build React/TypeScript implementation with frontend-specific agents
$recipe-fullstack-implement Cross-layer features with layer-aware task routing

Each recipe automatically loads the right foundational skills (coding standards, testing principles, documentation criteria) and spawns the right sequence of agents with the right stopping points.

Here’s what a real session looks like. I ran $recipe-implement Add a login screen with email/password and a simple auth API in Codex CLI against a fresh project with placeholder files:

1. Requirement analysis — the first mandatory stop:

• Spawned Plato [requirement-analyzer] (gpt-5.4-mini medium)

• Updated requirement analysis is now confirmed:
  - Scope: email/password login form, local mock auth abstraction,
    hardcoded success credentials [email protected] / password123,
    inline success message only
  - Route: fullstack
  - Scale: medium
  - ADR: not required

  Please confirm this analysis and answer these three questions:
  1. Should the auth API be a real HTTP endpoint, or is a local/mock
     API abstraction enough?
  2. What credentials should succeed initially?
  3. On successful login, should it only show success, navigate
     somewhere, or persist auth state too?

The workflow stops and waits. No implementation starts until I confirm scope.

2. Parallel design — backend and frontend at the same time:

• Spawned Volta [technical-designer] (gpt-5.4-mini medium)
  └ Create a backend Design Doc...

• Spawned Pasteur [technical-designer-frontend] (gpt-5.4-mini medium)
  └ Create a frontend Design Doc...

• Spawned Epicurus [document-reviewer] (gpt-5.4-mini medium)
  └ Review login-backend-design.md...

• Spawned Bohr [document-reviewer] (gpt-5.4-mini medium)
  └ Review login-frontend-design.md...

• Spawned Euclid [design-sync] (gpt-5.4-mini medium)
  └ Verify consistency between Design Docs...

Five agents in parallel: two designers, two reviewers, one cross-layer sync checker. Each running in its own fresh context.

3. Design gate — another mandatory stop:

• The design gate is now clean enough to stop for approval.

  - Backend design: approved
  - Frontend design: approved
  - Cross-layer sync: NO_CONFLICTS

  Aligned contract:
  - Success: { ok: true }
  - Failure: { ok: false, error }
  - Inline success copy is UI-owned, not backend-owned

  Please approve the design docs so I can move to
  acceptance-test generation and the work plan.

4. Autonomous execution after batch approval:

› batch approval

• Spawned Ohm [task-decomposer] (gpt-5.4-mini medium)

• Verification passed:
  - npm test
  - npm run build

After batch approval, the framework decomposed the work plan into tasks and executed them autonomously — no more stopping points until the quality gates pass.

The whole flow from $recipe-implement to green tests took one session. The same flow, the same stopping points, the same agent roles that I’ve been running on Claude Code for months.

Getting Started

The framework is open source:

If you’re already using the Claude Code version, the Codex version follows the same patterns. If you’re new to both, pick whichever CLI you’re already using — the workflow knowledge transfers either way.

npx codex-workflows install

The whole port changed config file formats and directory conventions. The agent instructions — the part that actually matters — didn’t need a single edit. That’s the thing I’d want to know if I were deciding whether to invest time in workflow design for AI coding tools.

If you’ve been running sub-agent workflows with either Claude Code or Codex CLI, I’d be curious how your setup compares. What worked? What broke?