Profile Builder Demo

Archived 2026-07-16: this tests the superseded Model/Point projection architecture. It is evidence for the current Spaceholder Inputs review, not an implementation or authoring contract.

This demo shows how a learner-scoped profile builder looks using the block function model syntax: inline model, spaceholder fill sites, bool points as GFM checkboxes, a gated summary block, and a triggered save action.

Authored source

---
title: Build Your Profile
scope: actor
model:
  id: profile
  full-name:
    type: text
    label: Full Name
    prompt: what is your full name?
  email:
    type: text
    label: Email
    prompt: what is your email address?
  interests:
    web-fundamentals:
      type: bool
      label: Web Fundamentals
    python:
      type: bool
      label: Python
    data-and-charts:
      type: bool
      label: Data & Charts
    interactive-authoring:
      type: bool
      label: Interactive Authoring
  goals:
    type: md
    label: Learning Goals
    prompt: what are your learning goals?
  profile-ready:
    type: bool
    value: full-name && goals
    label: Profile Ready
---

# Build Your Profile

```block
id: basic-info
role: learner
```

## Basic Info

**Name:** {full-name}

**Email:** {email}

---

```block
id: interests
role: learner
```

## Which topics are you most interested in?

{interests}

---

```block
id: goals
role: learner
```

## What are your goals?

{goals}

---

```block
id: summary
role: learner
when: profile-ready
```

## Summary

### {{full-name}}

**Email:** {{email}}

**Goals:**

{{goals}}

**Interests:**

- {{web-fundamentals}} Web Fundamentals
- {{python}} Python
- {{data-and-charts}} Data & Charts
- {{interactive-authoring}} Interactive Authoring

[Save Profile][save]

[save]: ./profile.actions.md#save "@action"

What this demonstrates

Inline model. The frontmatter declares every point the profile needs — text fields, booleans, a markdown block, and one computed readiness gate. No external model file needed for a self-contained source.

Fill vs render. The input blocks use {point} fill sites (read + write); the summary uses {{point}} render sites (read-only). The engine infers each block's signature from these — no in/out declarations.

Bool → GFM checkbox. The bool codec renders as - [x]/- [ ]. A fill site {web-fundamentals} is an interactive checkbox; a render site {{web-fundamentals}} is a static one. Same grammar, different direction.

Computed gating. profile-ready is a value: point — a pure expression over other points, never directly filled. The summary block's when: profile-ready keeps it hidden until the learner has entered a name and goals. No authored control flow; the block lights up as a function of state.

Triggered action. "Save Profile" is a reference link into a companion profile.actions.md. The manifest at the bottom is the import surface. The save action would author the desired saved state; reconciliation derives the mutation. In GitHub the link renders as a real link to the actions definition.

Jane's Input Source

The stored input is just an instance of the model — bare values keyed by point id. The model already declares each type, so nothing is restated: full-name is known to be text, goals to be md, the topics to be bool. providedBy sits on the source, not each value.

---
type: pathmx/inputs
model: ./profile-builder.source.md
scope: actor
subject: { id: jane }
providedBy: { actorType: user, id: jane, role: learner }
updatedAt: 2026-06-29T15:02:00-04:00
---
full-name: Jane Doe
email: [email protected]
web-fundamentals: true
python: false
data-and-charts: true
interactive-authoring: false
goals: |
  I want to build interactive data visualizations and get comfortable with
  web fundamentals so I can ship my own learning tools.

profile-ready is absent on purpose — it's a computed point (value: full-name && goals), recomputed at projection, never stored. To project Jane's profile, the player loads the model, overlays these values onto the matching points, recomputes profile-ready (now true), and the summary block's when: profile-ready gate opens.