Mobile "Publish to web" + anonymous demo publish (AI welcome, no auth)
Turns a no-login demo card into a real, scannable web profile with an optional
AI welcome — completing the owner side of the welcome feature without auth.
Backend:
- POST /v1/demo/publish (public, rate-limited 10/h/IP): creates a fresh
password-less owner (so the profile shows the right name + fits the free-tier
1-card limit), builds a card (contact title + profile links), optionally
generates an AI welcome, and publishes. Returns { handle, profileUrl }.
- demo_service + handlers/demo; 2 tests (publish→public profile w/ welcome,
name required). Gate green (120 tests). Verified live: publish → Astro renders
the welcome hero + image (from MinIO) + We-Met form, 18KB page.
Mobile:
- publish.tsx: enter an optional AI welcome scene + message, Publish → shows the
live cardclaws URL (Open/Done) and points the card's QR at it.
- demo.tsx: "Publish to web · AI welcome" button (saves, then opens publish).
- api.publishToWeb; LocalCard.publishedUrl.
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
63fdc4913b
commit
fd7a55e809
@@ -331,6 +331,50 @@ async fn we_met_capture_and_owner_list() {
|
||||
assert_eq!(s, StatusCode::BAD_REQUEST);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn demo_publish_creates_scannable_profile_with_welcome() {
|
||||
let app = require_app!();
|
||||
let (status, body) = app
|
||||
.request(
|
||||
"POST",
|
||||
"/v1/demo/publish",
|
||||
None,
|
||||
Some(json!({
|
||||
"name": "Omar Sobh",
|
||||
"title": "Founder",
|
||||
"links": [{ "label": "Site", "url": "https://cardclaws.com" }],
|
||||
"welcomePrompt": "a calm forest at dawn",
|
||||
"welcomeMessage": "Great to meet you"
|
||||
})),
|
||||
)
|
||||
.await;
|
||||
assert_eq!(status, StatusCode::OK, "publish failed: {body}");
|
||||
let handle = body["handle"].as_str().unwrap();
|
||||
assert!(body["profileUrl"].as_str().unwrap().ends_with(handle));
|
||||
|
||||
// The published card resolves publicly with the owner name + welcome.
|
||||
let (status, profile) = app
|
||||
.request("GET", &format!("/v1/cards/handle/{handle}"), None, None)
|
||||
.await;
|
||||
assert_eq!(status, StatusCode::OK);
|
||||
assert_eq!(profile["ownerDisplayName"], "Omar Sobh");
|
||||
assert_eq!(profile["welcome"]["message"], "Great to meet you");
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn demo_publish_requires_a_name() {
|
||||
let app = require_app!();
|
||||
let (status, _) = app
|
||||
.request(
|
||||
"POST",
|
||||
"/v1/demo/publish",
|
||||
None,
|
||||
Some(json!({ "name": " " })),
|
||||
)
|
||||
.await;
|
||||
assert_eq!(status, StatusCode::BAD_REQUEST);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn connections_list_is_owner_only() {
|
||||
let app = require_app!();
|
||||
|
||||
Reference in New Issue
Block a user