Use Phast app for product names and preserve phast wordplay
This commit is contained in:
1 parent
1f15789abd
commit
64d2374f60
7 files changed
+51
-28
No files matched your search
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
## Scope
|
## Scope
|
||||||
|
|
||||||
Build and maintain Phast as a deliberately small Python + Prefab + MCP application platform.
|
Build and maintain Phast app as a deliberately small Python + Prefab + MCP application platform.
|
||||||
|
|
||||||
## Product model
|
## Product model
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
# phast
|
# Phast app
|
||||||
|
|
||||||
Canonical source of truth for Phast.
|
Canonical source of truth for Phast app.
|
||||||
|
|
||||||
> **Connect your tools once. Bring your tool belt anywhere.**
|
> **Connect your tools once. Bring your tool belt anywhere.**
|
||||||
|
|
||||||
Phast gives a person one portable MCP plus a programmable Prefab home. Connect `my.phast.app/mcp` to an agent to create and manage Phasts. A created Phast has two matching surfaces:
|
Phast app gives a person one portable MCP plus a programmable Prefab home. Connect `my.phast.app/mcp` to an agent to create and manage Phast apps. A created Phast app has two matching surfaces:
|
||||||
|
|
||||||
- `user.phast.app` — human / Prefab home
|
- `user.phast.app` — human / Prefab home
|
||||||
- `user.phast.app/mcp` — the user's portable MCP tool belt
|
- `user.phast.app/mcp` — the user's portable MCP tool belt
|
||||||
@@ -29,10 +29,33 @@ Connect once to `my.phast.app/mcp` → create/manage `user.phast.app` → search
|
|||||||
|
|
||||||
## Boundaries
|
## Boundaries
|
||||||
|
|
||||||
- **Phast composes.** It owns the portable MCP/tool belt and Prefab composition.
|
- **Phast app composes.** It owns the portable MCP/tool belt and Prefab composition.
|
||||||
- **Oracle discovers.** Provider/MCP/OAuth discovery comes from the capability graph, not a hard-coded Phast directory.
|
- **Oracle discovers.** Provider/MCP/OAuth discovery comes from the capability graph, not a hard-coded Phast app directory.
|
||||||
- **Persimmons holds secrets.** Phast stores connection/authority references, not secret values.
|
- **Persimmons holds secrets.** Phast app stores connection/authority references, not secret values.
|
||||||
- **Factory builds/operates.** Provisioning uses bounded deterministic infrastructure routes.
|
- **Factory builds/operates.** Provisioning uses bounded deterministic infrastructure routes.
|
||||||
- **Clients are replaceable.** ChatGPT, Claude, Codex, or another MCP client should be able to use the same Phast without recollecting the user's tools.
|
- **Clients are replaceable.** ChatGPT, Claude, Codex, or another MCP client should be able to use the same Phast app without recollecting the user's tools.
|
||||||
|
|
||||||
V0 is intentionally not arbitrary app generation. Prove the portable-tool-belt + editable-home loop first.
|
V0 is intentionally not arbitrary app generation. Prove the portable-tool-belt + editable-home loop first.
|
||||||
|
|
||||||
|
## Naming and copy
|
||||||
|
|
||||||
|
Use **Phast app** when naming the product or one of its instances; use
|
||||||
|
**Phast apps** for the plural. Write “your Phast app,” “create a Phast app,”
|
||||||
|
and “My Phast app” for the management connector. Existing all-caps display
|
||||||
|
styles may use “PHAST APP.” Apply this to page titles, metadata, navigation,
|
||||||
|
buttons, examples, generated homes, MCP display text, and documentation.
|
||||||
|
|
||||||
|
Keep deliberate substitutions for “fast”: “make something phast,”
|
||||||
|
“built phast,” and “make MCP apps phast.” Do not rename literal domains,
|
||||||
|
URLs, `phast.json`, environment variables, CSS classes, tool names, or
|
||||||
|
schema keys/values as part of a copy edit. Preserve user-chosen app names.
|
||||||
|
|
||||||
|
The public copy lives in `index.html` (phast.app), `my/index.html`
|
||||||
|
(my.phast.app), and `server.py` (generated personal homes and MCP display
|
||||||
|
text). `phast.json` supplies the management display name. Review these
|
||||||
|
surfaces together when changing product naming.
|
||||||
|
|
||||||
|
Chair review: the standalone “PHAST.” wordmark and the “My Phast” connector
|
||||||
|
label could be separate brand treatments. This change proposes “PHAST APP.”
|
||||||
|
and “My Phast app” consistently; the chair should confirm those treatments.
|
||||||
|
The phrase “your Phast” names an app instance, so it becomes “your Phast app.”
|
||||||
+1
-1
@@ -1 +1 @@
|
|||||||
"""Phast application runtime."""
|
"""Phast app runtime."""
|
||||||
+5
-5
@@ -4,8 +4,8 @@
|
|||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta name="viewport" content="width=device-width,initial-scale=1">
|
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||||||
<meta name="theme-color" content="#050505">
|
<meta name="theme-color" content="#050505">
|
||||||
<meta name="description" content="Phast — make MCP apps phast.">
|
<meta name="description" content="Phast app — make MCP apps phast.">
|
||||||
<title>phast</title>
|
<title>Phast app</title>
|
||||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||||
<link href="https://fonts.googleapis.com/css2?family=Bangers&family=DM+Mono:wght@400;500&family=Inter:wght@500;700;900&display=swap" rel="stylesheet">
|
<link href="https://fonts.googleapis.com/css2?family=Bangers&family=DM+Mono:wght@400;500&family=Inter:wght@500;700;900&display=swap" rel="stylesheet">
|
||||||
@@ -26,14 +26,14 @@
|
|||||||
<h1><span class="make-line">MAKE SOMETHING</span><span class="phast-line">PHAST</span></h1>
|
<h1><span class="make-line">MAKE SOMETHING</span><span class="phast-line">PHAST</span></h1>
|
||||||
<div class="sequence">
|
<div class="sequence">
|
||||||
<div class="step"><b>01 CONNECT</b><span>add my.phast.app/mcp</span></div>
|
<div class="step"><b>01 CONNECT</b><span>add my.phast.app/mcp</span></div>
|
||||||
<div class="step"><b>02 MAKE</b><span>create your Phast</span></div>
|
<div class="step"><b>02 MAKE</b><span>create your Phast app</span></div>
|
||||||
<div class="step"><b>03 TUNE</b><span>tools + prefab widgets</span></div>
|
<div class="step"><b>03 TUNE</b><span>tools + prefab widgets</span></div>
|
||||||
<div class="step"><b>04 RUN</b><span>use it from any agent</span></div>
|
<div class="step"><b>04 RUN</b><span>use it from any agent</span></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="copy">
|
<div class="copy">
|
||||||
<p><strong>Connect your tools once.</strong><br>Bring your tool belt anywhere. ChatGPT, Claude, Codex — same Phast, same tools, same home.</p>
|
<p><strong>Connect your tools once.</strong><br>Bring your tool belt anywhere. ChatGPT, Claude, Codex — same Phast app, same tools, same home.</p>
|
||||||
<a class="cta" href="https://my.phast.app"><span>BUILD YOUR PHAST</span><span>→</span></a>
|
<a class="cta" href="https://my.phast.app"><span>BUILD YOUR PHAST APP</span><span>→</span></a>
|
||||||
<p class="meta" style="margin-top:14px;color:#666">one connector // many personal MCPs</p>
|
<p class="meta" style="margin-top:14px;color:#666">one connector // many personal MCPs</p>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|||||||
+5
-5
@@ -20,17 +20,17 @@
|
|||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<main class="page">
|
<main class="page">
|
||||||
<header class="top"><a class="brand" href="https://phast.app">PHAST.</a><span class="topnote">MY PHAST // CONTROL MCP</span></header>
|
<header class="top"><a class="brand" href="https://phast.app">PHAST APP.</a><span class="topnote">MY PHAST APP // CONTROL MCP</span></header>
|
||||||
<section class="hero">
|
<section class="hero">
|
||||||
<div><p class="kicker">START HERE // ONE CONNECTION</p><h1>YOUR MCP.<span>BUILT PHAST.</span></h1></div>
|
<div><p class="kicker">START HERE // ONE CONNECTION</p><h1>YOUR MCP.<span>BUILT PHAST.</span></h1></div>
|
||||||
<div class="intro"><p>Add <strong>My Phast</strong> to your agent once. Then create personal MCPs, add tools, stream Prefab, and keep what works.</p><button class="connector" id="copy"><span>COPY YOUR PHAST APP MCP</span><span>↗</span></button><div class="endpoint">https://my.phast.app/mcp</div></div>
|
<div class="intro"><p>Add <strong>My Phast app</strong> to your agent once. Then create personal MCPs, add tools, stream Prefab, and keep what works.</p><button class="connector" id="copy"><span>COPY YOUR PHAST APP MCP</span><span>↗</span></button><div class="endpoint">https://my.phast.app/mcp</div></div>
|
||||||
</section>
|
</section>
|
||||||
<section class="lane">
|
<section class="lane">
|
||||||
<div class="lanehead"><h2>ZERO → PERSONAL MCP</h2><span class="mono">CHAT IS THE SETUP UI</span></div>
|
<div class="lanehead"><h2>ZERO → PERSONAL MCP</h2><span class="mono">CHAT IS THE SETUP UI</span></div>
|
||||||
<div class="steps">
|
<div class="steps">
|
||||||
<article class="step" data-n="1"><span class="label">01 // CONNECT</span><h3>ADD MY PHAST</h3><p>Connect the management MCP in ChatGPT, Claude, Codex, or another MCP client. Authenticate once with Teahub.</p><div class="cmd"><b>MCP</b> my.phast.app/mcp</div></article>
|
<article class="step" data-n="1"><span class="label">01 // CONNECT</span><h3>ADD MY PHAST APP</h3><p>Connect the management MCP in ChatGPT, Claude, Codex, or another MCP client. Authenticate once with Teahub.</p><div class="cmd"><b>MCP</b> my.phast.app/mcp</div></article>
|
||||||
<article class="step" data-n="2"><span class="label">02 // CREATE</span><h3>TELL YOUR AGENT</h3><p>No project wizard. Name it in chat. Wildcard DNS, TLS, home, and MCP are already waiting.</p><div class="cmd"><b>YOU</b> create me a phast called sunday</div></article>
|
<article class="step" data-n="2"><span class="label">02 // CREATE</span><h3>TELL YOUR AGENT</h3><p>No project wizard. Name it in chat. Wildcard DNS, TLS, home, and MCP are already waiting.</p><div class="cmd"><b>YOU</b> create me a Phast app called sunday</div></article>
|
||||||
<article class="step" data-n="3"><span class="label">03 // TUNE</span><h3>BUILD THE BELT</h3><p>Add providers, tools, and Prefab widgets. Your agent and your web home edit the same Phast.</p><div class="cmd"><b>YOU</b> add github + a PR widget</div></article>
|
<article class="step" data-n="3"><span class="label">03 // TUNE</span><h3>BUILD THE BELT</h3><p>Add providers, tools, and Prefab widgets. Your agent and your web home edit the same Phast app.</p><div class="cmd"><b>YOU</b> add github + a PR widget</div></article>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
<section class="what">
|
<section class="what">
|
||||||
|
|||||||
+1
-1
@@ -2,7 +2,7 @@
|
|||||||
"schema_version": 1,
|
"schema_version": 1,
|
||||||
"kind": "phast",
|
"kind": "phast",
|
||||||
"slug": "my",
|
"slug": "my",
|
||||||
"name": "My Phast",
|
"name": "My Phast app",
|
||||||
"host": "my.phast.app",
|
"host": "my.phast.app",
|
||||||
"surfaces": {"human": "/", "mcp": "/mcp"},
|
"surfaces": {"human": "/", "mcp": "/mcp"},
|
||||||
"tools": {
|
"tools": {
|
||||||
|
|||||||
@@ -95,7 +95,7 @@ def path(value: str) -> Path:
|
|||||||
def read(value: str) -> dict[str, Any]:
|
def read(value: str) -> dict[str, Any]:
|
||||||
p = path(value)
|
p = path(value)
|
||||||
if not p.exists():
|
if not p.exists():
|
||||||
raise KeyError("unknown Phast")
|
raise KeyError("unknown Phast app")
|
||||||
return json.loads(p.read_text())
|
return json.loads(p.read_text())
|
||||||
|
|
||||||
|
|
||||||
@@ -120,7 +120,7 @@ def write(value: str, data: dict[str, Any]) -> dict[str, Any]:
|
|||||||
def mine(value: str) -> dict[str, Any]:
|
def mine(value: str) -> dict[str, Any]:
|
||||||
data = read(value)
|
data = read(value)
|
||||||
if data.get("owner") != actor():
|
if data.get("owner") != actor():
|
||||||
raise PermissionError("not your Phast")
|
raise PermissionError("not your Phast app")
|
||||||
return data
|
return data
|
||||||
|
|
||||||
|
|
||||||
@@ -180,14 +180,14 @@ def human(data: dict[str, Any]) -> str:
|
|||||||
'<!doctype html><meta name="viewport" content="width=device-width">'
|
'<!doctype html><meta name="viewport" content="width=device-width">'
|
||||||
+ "<title>"
|
+ "<title>"
|
||||||
+ data["name"]
|
+ data["name"]
|
||||||
+ " - phast</title>"
|
+ " - Phast app</title>"
|
||||||
+ "<style>body{margin:0;background:#f5f3ee;color:#121211;font:14px system-ui}"
|
+ "<style>body{margin:0;background:#f5f3ee;color:#121211;font:14px system-ui}"
|
||||||
+ "main{max-width:1000px;margin:auto;padding:32px}header{display:flex;justify-content:space-between}"
|
+ "main{max-width:1000px;margin:auto;padding:32px}header{display:flex;justify-content:space-between}"
|
||||||
+ "b{font-size:28px}em{color:#ff4d00}h1{font-size:72px;letter-spacing:-5px;margin:80px 0 40px}"
|
+ "b{font-size:28px}em{color:#ff4d00}h1{font-size:72px;letter-spacing:-5px;margin:80px 0 40px}"
|
||||||
+ "section{display:grid;grid-template-columns:repeat(3,1fr);gap:14px}"
|
+ "section{display:grid;grid-template-columns:repeat(3,1fr);gap:14px}"
|
||||||
+ "article{border:1px solid #d5d1c8;padding:18px;min-height:150px}p{color:#77746c}"
|
+ "article{border:1px solid #d5d1c8;padding:18px;min-height:150px}p{color:#77746c}"
|
||||||
+ "@media(max-width:700px){section{grid-template-columns:1fr}}</style>"
|
+ "@media(max-width:700px){section{grid-template-columns:1fr}}</style>"
|
||||||
+ "<main><header><b>phast<em>.</em></b><code>"
|
+ "<main><header><b>Phast app<em>.</em></b><code>"
|
||||||
+ data["host"]
|
+ data["host"]
|
||||||
+ "/mcp</code></header><h1>"
|
+ "/mcp</code></header><h1>"
|
||||||
+ data["name"]
|
+ data["name"]
|
||||||
@@ -198,9 +198,9 @@ def human(data: dict[str, Any]) -> str:
|
|||||||
|
|
||||||
|
|
||||||
m = FastMCP(
|
m = FastMCP(
|
||||||
"My Phast",
|
"My Phast app",
|
||||||
version="0.2.0",
|
version="0.2.0",
|
||||||
instructions="Create and manage portable Phast MCP tool belts and Prefab homes.",
|
instructions="Create and manage portable Phast app MCP tool belts and Prefab homes.",
|
||||||
auth=auth("https://my.phast.app"),
|
auth=auth("https://my.phast.app"),
|
||||||
mask_error_details=True,
|
mask_error_details=True,
|
||||||
)
|
)
|
||||||
@@ -317,7 +317,7 @@ def inst(value: str):
|
|||||||
personal = FastMCP(
|
personal = FastMCP(
|
||||||
data["name"],
|
data["name"],
|
||||||
version="0.2.0",
|
version="0.2.0",
|
||||||
instructions="Portable personal Phast MCP.",
|
instructions="Portable personal Phast app MCP.",
|
||||||
auth=auth("https://my.phast.app", "https://" + data["host"]),
|
auth=auth("https://my.phast.app", "https://" + data["host"]),
|
||||||
mask_error_details=True,
|
mask_error_details=True,
|
||||||
)
|
)
|
||||||
@@ -385,7 +385,7 @@ class Router:
|
|||||||
try:
|
try:
|
||||||
data = read(value)
|
data = read(value)
|
||||||
except Exception:
|
except Exception:
|
||||||
await JSONResponse({"error": "unknown Phast"}, status_code=404)(scope, receive, send)
|
await JSONResponse({"error": "unknown Phast app"}, status_code=404)(scope, receive, send)
|
||||||
return
|
return
|
||||||
|
|
||||||
if request_path == "/" and method in {"GET", "HEAD"}:
|
if request_path == "/" and method in {"GET", "HEAD"}:
|
||||||
|
|||||||
Reference in new issue
Block a user