Skip to main content
ephaptic logo

ephaptic


GitHub License GitHub Actions Workflow Status GitHub Actions Workflow Status GitHub Actions Workflow Status PyPI - Version NPM - Version

What is ephaptic?


ephaptic (adj.)
electrical conduction of a nerve impulse across an ephapse without the mediation of a neurotransmitter.

Nah, just kidding. It's an RPC framework.

ephaptic — Call your backend straight from your frontend. No JSON. Low latency. Invisible middleware.

Getting Started

  • Ephaptic is designed to be invisible. Write a function on the server, call it on the client. No extra boilerplate.

  • Plus, it's horizontally scalable with Redis (optional), and features extremely low latency thanks to msgpack.

  • Oh, and the client can also listen to events broadcasted by the server. No, like literally. You just need to add an eventListener. Did I mention? Events can be sent to specific targets, specific users - not just anyone online.

  • Saved the best for last: it's type-safe. Don't believe me? Try it out for yourself. Simply type hint return values and parameters on the backend, and watch those very Python types transform into interfaces and types on the TypeScript frontend. Plus, you can use Pydantic - which means, for those of you who are FastAPI users, this is going to be great.

What are you waiting for? Let's go.

To see why you might want to use Ephaptic instead of traditional REST, see the article on it.
Python
$ pip install ephaptic
from fastapi import FastAPI # or `from quart import Quart`
from ephaptic import Ephaptic

app = FastAPI() # or `app = Quart(__name__)`

ephaptic = Ephaptic.from_app(app) # Finds which framework you're using, and creates an ephaptic server.

You can also specify a custom path:

ephaptic = Ephaptic.from_app(app, path="/websocket")

And you can even use Redis for horizontal scaling!

ephaptic = Ephaptic.from_app(app, redis_url="redis://my-redis-container:6379/0")

Now, how do you expose your function to the frontend?

@ephaptic.expose
async def add(num1: int, num2: int) -> int:
    return num1 + num2
If you're trying to expose functions statelessly, e.g. in a different file, feel free to instead import and use the expose function from the library instead of the instance. Please note that if you do this, you must define all exposed functions before creating the ephaptic instance - easily done by simply placing your import line above the ephaptic constructor. The same thing can be done with the global identity_loader decorator.

Yep, it's really that simple.

But what if your code throws an error? No sweat — it surfaces on the frontend as a typed error you can catch. Raise a ServiceError for structured, typed errors (carrying a code, message, and data), or let ephaptic turn unexpected exceptions into a safe, generic error (details stay on the server unless you opt into debug mode). See the error handling docs.

And, want to say something to the frontend?

class Notification(BaseModel):
    message: str
    priority: Literal["high", "low", "default"]

await ephaptic.to(user1, user2).emit(Notification(message="Hello, world!", priority="high"))

To create a schema of your RPC endpoints (pass --watch to auto-regenerate on file changes):

$ ephaptic generate src.app:ephaptic -o schema.json

Or output TypeScript directly, skipping the JSON layer:

$ ephaptic generate src.app:ephaptic -o ephaptic.d.ts

Pydantic is entirely supported. It's validated for arguments, it's auto-serialized when you return a pydantic model, and your models receive type definitions in the schema.

To receive authentication objects and handle them:

from ephaptic import identity_loader

@identity_loader
async def load_identity(auth): # You can use synchronous functions here too.
    jwt = auth.get("token")
    if not jwt: return None # unauthorized
    ... # app logic to retrieve user ID
    return user_id

From here, you can use ephaptic.active_user() within any exposed function, and it will give you the current active user ID / whatever else your identity loading function returns. (This is also how ephaptic.to works.)

JavaScript/TypeScript — Browser (Svelte, React, Angular, Vite, etc.)

To use with a framework / Vite:

$ npm install @ephaptic/client

Then:

import { connect } from "@ephaptic/client";

const client = connect(); // Defaults to `/_ephaptic`.

Or, you can use it with a custom URL:

const client = connect({ url: '/ws' });
const client = connect({ url: 'wss://my-backend.deployment/ephaptic' });

You can even send auth objects to the server for identity loading.

const client = connect({ url: '...', auth: { token: window.localStorage.getItem('jwtToken') } })

And you can load types, too (pass --watch to auto-reload on changes):

$ ephaptic generate ./schema.json -o schema.d.ts
import { connect } from "@ephaptic/client";
import { type EphapticService } from './schema';

const client = connect(...) as EphapticService;

Or, to use in your browser:

<script type="module">
import { connect } from 'https://cdn.jsdelivr.net/npm/@ephaptic/client@latest/+esm';

const client = connect(...);
</script>

See more in the docs.

Conformance

Ephaptic's wire protocol is specified in specs/SERVER.md and specs/CLIENT.md. Each package ships a CONFORMANCE.md recording exactly which requirements it satisfies, which it does not, and why.

License

MIT


© ephaptic 2025 · I read this and now I don't know if Ephaptic is worth it anymore. Who cares.

Release files for ephaptic 0.5.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for ephaptic 0.5.0
File Size Uploaded
ephaptic-0.5.0.tar.gz 35.6 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for ephaptic 0.5.0
File Interpreter ABI Platform
ephaptic-0.5.0-py3-none-any.whl Python 3 none any Details

Total release size: 73.6 kB

Release files / ephaptic-0.5.0.tar.gz

Download URL ephaptic-0.5.0.tar.gz
Size 35.6 kB
Tags Source
SHA-256 checksum
How to use checksums
2bebbee83991777a7976617c78b3c67942129e835af5d06164589d17d62b1e3c
BLAKE2b-256 checksum
How to use checksums
cf58ec115942d48255bc31dd92f96d362527d29c4b8c52cbdc79cdd652729e15
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.6

Release files / ephaptic-0.5.0-py3-none-any.whl

Download URL ephaptic-0.5.0-py3-none-any.whl
Size 38.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
d6542d6c0ed06866112db01f02e761660d48e2379b6d5778496f6d3c6131c681
BLAKE2b-256 checksum
How to use checksums
bbc4cd377b128c945d663d87872b51f06acc2d7ca0d310fb4edab4f7cc349c67
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.6

Release history Release notifications | RSS feed

This release

0.5.0 This release

2 release files

0.4.6

2 release files

0.4.5

2 release files

0.4.4

2 release files

0.4.3

2 release files

0.4.1

2 release files

0.4.0

2 release files

0.3.6

2 release files

0.3.5

2 release files

0.3.4

2 release files

0.3.3

2 release files

0.3.2

2 release files

0.3.1

2 release files

0.3.0

2 release files

0.2.8

2 release files

0.2.7

2 release files

0.2.6

2 release files

0.2.5

2 release files

0.2.4

2 release files

0.2.3

2 release files

0.2.2

2 release files

0.2.1

2 release files

0.2.0

2 release files

0.1.3

2 release files

0.1.2

2 release files

0.1.1

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page