npm package: @openfluke/portal
Description: Paragon Orchestrated Runtime for Isomorphic Technologies Across Layers — isomorphic Go/WASM loader for browser, Bun, and Node.
Latest version: 0.3.0

# @openfluke/portal

Paragon Orchestrated Runtime for Isomorphic Technologies Across Layers

`@openfluke/portal` is an isomorphic loader for Go-compiled WebAssembly (Paragon). It works seamlessly in Bun/Node.js backends and browser frontends (Vite/React/Ionic), exposing the same API across layers. Portal bundles `wasm_exec.js` (from the Go runtime) and your compiled `paragon.wasm`, so you can import `{ initPortal }` and immediately construct neural networks in either environment.

## Installation

```bash
# Add to your project
bun add @openfluke/portal
# or
npm install @openfluke/portal
```

## Usage

### Backend (Bun / Node.js)

Create a quick test script `index.ts`:

```ts
import { initPortal } from "@openfluke/portal";

const main = async () => {
  console.log("⚙️  initPortal()…");
  const portal = await initPortal();

  const configs = [
    {
      name: "Alpha",
      layers: [{ Width: 1, Height: 1 }, { Width: 2, Height: 1 }, { Width: 3, Height: 1 }],
      activations: ["linear", "relu", "softmax"],
    },
    {
      name: "Beta",
      layers: [{ Width: 1, Height: 1 }, { Width: 4, Height: 1 }, { Width: 3, Height: 1 }],
      activations: ["linear", "tanh", "softmax"],
    },
    {
      name: "Gamma",
      layers: [{ Width: 1, Height: 1 }, { Width: 3, Height: 1 }, { Width: 3, Height: 1 }],
      activations: ["linear", "sigmoid", "softmax"],
    },
  ];

  for (const cfg of configs) {
    const nn = portal.NewNetworkFloat32(
      JSON.stringify(cfg.layers),
      JSON.stringify(cfg.activations),
      JSON.stringify([true, true, true])
    );
    nn.PerturbWeights(JSON.stringify([0.1, Date.now() % 1000]));
    const input = JSON.stringify([[[Math.random()]]]);
    nn.Forward(input);
    console.log(cfg.name, "→", nn.ExtractOutput());
  }
};

main();
```

Run it:

```bash
bun run index.ts
```

### Frontend (React / Vite / Ionic)

Use the same API inside a React component. Example: run 3 networks with pulses of random data:

```tsx
import React, { useEffect, useState } from "react";
import { initPortal } from "@openfluke/portal";

export default function PortalDemo() {
  const [portal, setPortal] = useState<any>(null);
  const [output, setOutput] = useState<string>("Loading…");

  useEffect(() => {
    (async () => {
      const api = await initPortal();
      setPortal(api);

      const nn = api.NewNetworkFloat32(
        JSON.stringify([{ Width: 1, Height: 1 }, { Width: 2, Height: 1 }, { Width: 3, Height: 1 }]),
        JSON.stringify(["linear", "relu", "softmax"]),
        JSON.stringify([true, true, true])
      );

      nn.PerturbWeights(JSON.stringify([0.1, Date.now() % 1000]));
      nn.Forward(JSON.stringify([[[Math.random()]]]));
      setOutput(nn.ExtractOutput());
    })();
  }, []);

  return (
    <div>
      <h1>Portal Demo</h1>
      <pre>{output}</pre>
    </div>
  );
}
```

When you run `bun dev` with Vite/Ionic, the WASM is auto-loaded from the package’s `dist` folder. No manual `<script>` tags required.

## Development (Local Linking)

If you are developing Portal itself:

```bash
bun i
bun run clean && bun run build
bun link
```

Then in another project:

```bash
bun add @openfluke/portal@link:portal
```


- [Example Frontend Implementation](https://github.com/openfluke/icfront)
- [Example Backend Implementation](https://github.com/openfluke/icback)



# If running in frontend change vite.config.ts

```
/// <reference types="vitest" />

import legacy from '@vitejs/plugin-legacy'
import react from '@vitejs/plugin-react'
import { defineConfig } from 'vite'

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [
    react(),
    legacy()
  ],
  optimizeDeps: {
    exclude: ['@openfluke/portal'] // Prevents pre-bundling; allows relative asset imports (?raw/?url) and import.meta.url to resolve to actual dist/ files
  },
  assetsInclude: ['**/*.wasm'], // Treats .wasm as static assets (emits correctly in builds)
  test: {
    globals: true,
    environment: 'jsdom',
    setupFiles: './src/setupTests.ts',
  }
})
```


## License

Apache-2.0 © 2025 OpenFluke