DSL - one language for everything

May 2025. Prisma on backend, separate types on frontend. Two sources of truth - desync.

Idea: one DSL that works everywhere.

What it looks like

// On backend
const users = await DSL.user.findMany({ where: { role: 'admin' } })

// On frontend - same syntax
const users = await DSL.user.findMany({ where: { role: 'admin' } })

One API. Backend goes to database directly. Frontend - via HTTP, but syntax is identical.

How to add a new table

Before: create Prisma model, write migration, make API endpoints, describe types for frontend, connect everything.

Now:

const Project = defineModel('Project', {
  fields: {
    name: { type: 'string' },
    status: { type: 'enum', values: ['active', 'archived'] }
  }
})

Generator creates:

  • Prisma schema
  • Migration
  • CRUD endpoints
  • TypeScript types
  • DSL methods for frontend

Immediately available: DSL.project.findMany(), DSL.project.create(), on both backend and frontend.

Why TypeScript

AI generates TypeScript better than Prisma schema. Familiar syntax, autocomplete works, errors caught immediately.

Asked AI to create a model - got working DSL. Ran generator - table in database, API ready, frontend can use it.

Single source of truth

Model described once. Everything else - derived.

Changed field type in DSL - Prisma updates, types update, frontend gets new structure. No desync between layers.

Downside

Another layer of abstraction. Prisma updated - update the generator.

But for development speed - worth it. New entity from idea to working CRUD - 5 minutes.

← Back to blog