Skip to main content

faceplant

Build a faceplant platform service in ~30 lines. Identity, the 30-second broker heartbeat, dashboards, the runtime plugin host, the daily garbage collector, and MCP tool serving are all under the hood — you write domain code.

pip install faceplant

Quickstart — a whole service

from faceplant import Service, Table, Column

svc = Service(
    "billing",
    description="Track usage bills.",
    icon="receipt",
    category="tools",
)

@svc.get("/data")
async def bills(user):                       # user.email, user.slug, user.dir
    rows = load_bills(user.dir)              # per-user private storage, created for you
    return Table(
        title="Bills",
        columns=[Column(key="month", header="Month"),
                 Column(key="amount", header="Amount")],
        rows=rows,
    )

@svc.responder("billing.total")              # a broker API other services can call
async def total(data):
    return {"total": sum_bills()}

app = svc.app                                # uvicorn src.main:app

That's the entire service. Service(...) already gave you:

  • a gateway card heartbeated every 30s (stop the pod → the card disappears);
  • /health, /manifest, /_plugins and CORS;
  • identity: user is injected from the platform JWT (401 when absent), with user.dir for per-user storage and user.tags / user.services;
  • the runtime plugin host: other services can extend this one with signed wheels, with zero code here (svc.registry if you want to add hook points);
  • the daily GC that reclaims a user's data ~10 days after they're gone.

More surfaces (each one decorator)

@svc.consumer("CHAT", filter_keys=["chat.>"])   # subscribe to broker events
async def on_chat(data): ...

@svc.mcp_tool()                                  # a tool for coding agents  (pip install faceplant[mcp])
async def get_bill(month: str) -> str: ...

svc.announce_wheel(target="faceplant-users",     # ship an extension wheel AT another service
                   wheel="plugin", entrypoint="billing_gate.plugin:register")

@svc.manifest                                    # compute the dashboard per request
def dash(user): return Stack(children=[...])

Escape hatches, always available: svc.app is a real FastAPI app (add WebSockets, SSE, middleware); svc.broker.request(key, data) / .publish(...); await svc.provision(fn) for blocking work off the DNS-critical event loop; @svc.background for startup loops; @svc.on_purge / @svc.gc_verdict to customize GC.

Testing is safe by default

Service only starts its heartbeat when a broker is actually configured (BROKER_URL set). A bare pytest or with TestClient(app) runs offline — no accidental registration against a live gateway. To test online behavior, use the in-process stub:

from fastapi.testclient import TestClient
from faceplant.testing import StubBroker, dev_jwt

def test_bills():
    with TestClient(svc.app) as client:                    # offline: no heartbeat
        r = client.get("/data", headers={"authorization": f"Bearer {dev_jwt('a@b.co')}"})
        assert r.status_code == 200

async def test_registration():
    stub = StubBroker(); stub.install(svc)
    await stub.beat(svc)
    assert "billing.total" in stub.responders

Deployment is boilerplate-free too

Your repo needs no Dockerfile and no k8s/values-prod.yaml — the SDK generates them. A deployable service is just src/main.py, pyproject.toml, and a ~10-line deploy workflow that calls the SDK's reusable one:

jobs:
  deploy:
    uses: faceplant-ai/faceplant-sdk/.github/workflows/deploy-service.yml@v1
    with: { service: billing, kind: stateless }
    secrets: inherit

Or generate the files to check in: faceplant init --name billing. See docs/deployment.md.

Docs

One page per concept in docs/: identity, widgets, plugin-host, providers, consumers & responders, mcp, gc, escape hatches, testing, and migrating from the template.

License

MIT.

Metadata

Release files for faceplant 0.9.6

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

Source distribution (sdist)

Source distribution for faceplant 0.9.6
File Size Uploaded
faceplant-0.9.6.tar.gz 201.7 kB Details

Built distribution (wheel)

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

Total release size: 287.6 kB

Release files / faceplant-0.9.6.tar.gz

Download URL faceplant-0.9.6.tar.gz
Size 201.7 kB
Tags Source
SHA-256 checksum
How to use checksums
138a774c0701cd41cc026021af339ff179b355c70aa3aff9737c8695f88ef305
BLAKE2b-256 checksum
How to use checksums
8bbb44933641d57c80f0efaffc70671a897eefa2a5d7ee73d6e2141c59f9d284
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.12.3

Release files / faceplant-0.9.6-py3-none-any.whl

Download URL faceplant-0.9.6-py3-none-any.whl
Size 86.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
7d8cd1b424a3788a91c3f46a45039ac9dc9dd2e73075f0bf6a64cee6af99b98f
BLAKE2b-256 checksum
How to use checksums
9385db9efb12a49e76369977ef03d2715702910cf59f8a2f51a103b8b9b87f8d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.12.3

Release history Release notifications | RSS feed

0.9.7

2 release files

This release

0.9.6 This release

2 release files

0.9.5

2 release files

0.9.4

2 release files

0.9.3

2 release files

0.9.2

2 release files

0.9.1

2 release files

0.9.0

2 release files

0.8.1

2 release files

0.8.0

2 release files

0.7.7

2 release files

0.7.6

2 release files

0.7.5

2 release files

0.7.4

2 release files

0.7.3

2 release files

0.7.2

2 release files

0.7.1

2 release files

0.7.0

2 release files

0.6.0

2 release files

0.5.0

2 release files

0.4.0

2 release files

0.3.0

2 release files

0.2.0

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