DEV Community

Cover image for I Was Tired of Writing the Same Logic Twice — So I Built .bridge
Cahyanudien Aziz Saputra
Cahyanudien Aziz Saputra

Posted on • Originally published at blog.cahyanudien.site

I Was Tired of Writing the Same Logic Twice — So I Built .bridge

If you've ever worked on a full-stack project with Laravel on the backend and TypeScript on the frontend, you know the pain.

You write a calculateTotal() function in PHP. Then you write it again in TypeScript. Then maybe a third time for a Node.js script. Same logic. Different syntax. Three places to maintain. Three places to introduce bugs.

I got tired of it. So I built something.


The Problem

Here's a real scenario. You have a pricing function in Laravel:

public function calculateTotal(float $price, float $tax): float
{
    $total = $price * (1 + $tax);
    return $total;
}
Enter fullscreen mode Exit fullscreen mode

Your frontend needs the same calculation client-side, so you write it in TypeScript:

export function calculateTotal(price: number, tax: number): number {
    let total = price * (1 + tax);
    return total;
}
Enter fullscreen mode Exit fullscreen mode

Now your product manager asks you to change the formula. You update the PHP. You forget to update the TypeScript. Three weeks later, a bug report comes in because the two implementations drifted apart.

This happens constantly in full-stack PHP/JS projects. And it's not a skill problem — it's a tooling problem.


The Idea: One Source of Truth

What if you could write the logic once, in a clean neutral syntax, and compile it to whatever target you need?

That's .bridge.

function calculateTotal(price: float, tax: float): float {
  let total = price * (1 + tax)
  return total
}
Enter fullscreen mode Exit fullscreen mode

Run one command:

bridge build
Enter fullscreen mode Exit fullscreen mode

And you get:

PHP (Laravel-ready)

<?php

namespace App\Bridge;

class Logic
{
    public function calculateTotal(float $price, float $tax): float
    {
        $total = $price * (1 + $tax);
        return $total;
    }
}
Enter fullscreen mode Exit fullscreen mode

TypeScript

export function calculateTotal(price: number, tax: number): number {
    let total = price * (1 + tax);
    return total;
}
Enter fullscreen mode Exit fullscreen mode

Node.js (ESM)

export function calculateTotal(price, tax) {
    let total = price * (1 + tax);
    return total;
}
Enter fullscreen mode Exit fullscreen mode

Same logic. Three targets. Zero drift.


How It Works

.bridge uses a TypeScript-like syntax that's intentionally minimal. The type system maps cleanly to each target:

.bridge PHP TypeScript
float float number
int int number
string string string
bool bool boolean

The compiler reads your .bridge files and generates idiomatic code for each target — not just a generic translation, but code that fits naturally into a Laravel class or a TypeScript module.


Getting Started in 60 Seconds

Install the CLI:

npm install -g @cas8398/bridge-cli
Enter fullscreen mode Exit fullscreen mode

Create a project:

bridge new my-app
cd my-app
Enter fullscreen mode Exit fullscreen mode

You get a minimal scaffold:

my-app/
├── bridge.config.json
└── src/
    └── logic.bridge
Enter fullscreen mode Exit fullscreen mode

Open src/logic.bridge, write your shared logic, then:

bridge build
Enter fullscreen mode Exit fullscreen mode

Your compiled files land in .bridge/php/, .bridge/ts/, and .bridge/node/ — ready to copy into your existing project or reference directly.


There's Also a Reverse Command

Already have PHP or TypeScript code you want to bring into .bridge? There's a command for that too:

bridge to-bridge .bridge/php/Logic.php
Enter fullscreen mode Exit fullscreen mode

It reverse-compiles back into .bridge syntax, which you can then edit and recompile to all targets. Useful for migrating existing logic incrementally.


VS Code Support

There's a VS Code extension with syntax highlighting and snippets for .bridge files:

👉 Bridge Language Support on the Marketplace

Type func + Tab to scaffold a function. Type let + Tab for a variable. Nothing fancy, but it makes the editing experience feel native.


What It's Not

I want to be honest about scope. .bridge is not a full programming language. It doesn't handle classes, conditionals, loops, or complex control flow yet. Right now it's focused on pure functions — stateless logic that takes inputs and returns outputs.

That's actually the sweet spot for shared business logic: validation rules, calculations, formatters, transformers. The stuff you really don't want living in two places.


Why I Built It as a CLI, Not a Library

I considered building this as a Babel plugin or a TypeScript transformer, but those tie you to a specific ecosystem. A standalone CLI means you can use it regardless of your build toolchain — whether you're on Vite, Laravel Mix, plain webpack, or no bundler at all. It sits outside your stack and just generates files.


Try It

It's early, rough in places, and very much a raw dev release — but the core idea works. If you've felt this pain on a PHP/JS full-stack project, I'd love to know if .bridge fits your workflow.


Built with TypeScript. MIT licensed. Feedback welcome via GitHub Issues.

Top comments (0)