Spaces:
Sleeping
Sleeping
Commit Β·
d0e10e8
0
Parent(s):
Initial hub
Browse files- README.md +16 -0
- app.py +74 -0
- requirements.txt +1 -0
README.md
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
title: Practice Fields Hub
|
| 3 |
+
emoji: π±
|
| 4 |
+
colorFrom: green
|
| 5 |
+
colorTo: blue
|
| 6 |
+
sdk: streamlit
|
| 7 |
+
sdk_version: 1.32.0
|
| 8 |
+
app_file: app.py
|
| 9 |
+
pinned: false
|
| 10 |
+
license: mit
|
| 11 |
+
short_description: "Curated therapeutic practice spaces"
|
| 12 |
+
---
|
| 13 |
+
|
| 14 |
+
# Practice Fields Hub
|
| 15 |
+
|
| 16 |
+
A clinician-curated portal linking to therapeutic practice spaces.
|
app.py
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Practice Fields Hub β Curated Therapeutic Practice Spaces"""
|
| 2 |
+
|
| 3 |
+
import streamlit as st
|
| 4 |
+
|
| 5 |
+
st.set_page_config(page_title="Practice Fields", page_icon="π±", layout="wide")
|
| 6 |
+
|
| 7 |
+
st.markdown("""
|
| 8 |
+
<style>
|
| 9 |
+
.stApp { background: linear-gradient(135deg, #f0f7ff 0%, #f5fff5 50%, #fffef5 100%); }
|
| 10 |
+
.hub-header { text-align: center; padding: 2rem 0; }
|
| 11 |
+
.hub-header h1 { color: #4a5a5a; font-size: 2.5rem; margin-bottom: 0.5rem; }
|
| 12 |
+
.hub-tagline { color: #6a7a7a; font-size: 1.1rem; font-style: italic; }
|
| 13 |
+
.clinician-badge { background: linear-gradient(135deg, #e8f4f8 0%, #e0f0e8 100%); border-radius: 12px; padding: 0.75rem 1.5rem; text-align: center; margin: 1rem auto; max-width: 500px; border: 1px solid rgba(180, 210, 200, 0.4); }
|
| 14 |
+
.field-card { background: linear-gradient(135deg, rgba(255,255,255,0.9) 0%, rgba(248,252,255,0.9) 100%); border-radius: 16px; padding: 1.5rem; margin: 0.75rem 0; border: 1px solid rgba(180, 210, 200, 0.4); transition: all 0.2s ease; text-decoration: none; display: block; color: inherit; }
|
| 15 |
+
.field-card:hover { transform: translateY(-2px); box-shadow: 0 4px 12px rgba(100, 140, 130, 0.15); border-color: rgba(140, 180, 170, 0.6); }
|
| 16 |
+
.field-icon { font-size: 2rem; margin-bottom: 0.5rem; }
|
| 17 |
+
.field-title { color: #3a5a5a; font-size: 1.2rem; font-weight: 600; margin-bottom: 0.5rem; }
|
| 18 |
+
.field-desc { color: #5a7070; font-size: 0.95rem; line-height: 1.4; }
|
| 19 |
+
.section-header { color: #5a6a6a; font-size: 1rem; text-transform: uppercase; letter-spacing: 0.1em; margin: 2rem 0 1rem 0; padding-bottom: 0.5rem; border-bottom: 1px solid rgba(180, 200, 190, 0.3); }
|
| 20 |
+
.footer-text { text-align: center; color: #7a8a8a; font-size: 0.85rem; padding: 2rem 0 1rem 0; border-top: 1px solid rgba(180, 200, 190, 0.2); margin-top: 2rem; }
|
| 21 |
+
.stTextInput input, .stTextArea textarea { background-color: white !important; border: 1px solid #d4e4d4 !important; border-radius: 8px !important; }
|
| 22 |
+
.stButton > button { background: linear-gradient(135deg, #d4e8d4 0%, #c4dcc4 100%); border: 1px solid #98b898; border-radius: 8px; color: #3a5a3a; }
|
| 23 |
+
</style>
|
| 24 |
+
""", unsafe_allow_html=True)
|
| 25 |
+
|
| 26 |
+
if "clinician_name" not in st.session_state:
|
| 27 |
+
st.session_state.clinician_name = ""
|
| 28 |
+
if "clinician_orientation" not in st.session_state:
|
| 29 |
+
st.session_state.clinician_orientation = ""
|
| 30 |
+
if "onboarded" not in st.session_state:
|
| 31 |
+
st.session_state.onboarded = False
|
| 32 |
+
|
| 33 |
+
SPACES = [
|
| 34 |
+
{"icon": "π", "title": "ShadowBox Library", "desc": "A resonant library for hard thoughts. Psychoeducation without synthetic intimacy.", "url": "https://huggingface.co/spaces/jostlebot/shadowbox.library"},
|
| 35 |
+
{"icon": "π", "title": "Tend & Send", "desc": "Craft messages with care. Practice tending to yourself before sending.", "url": "https://huggingface.co/spaces/jostlebot/TendSend.PrototypeBot"},
|
| 36 |
+
{"icon": "π€", "title": "Build a Bot", "desc": "AI literacy β understand how LLMs work, spot synthetic intimacy.", "url": "https://huggingface.co/spaces/jostlebot/BuildABot.2"},
|
| 37 |
+
{"icon": "π©Ί", "title": "Diagnosis Explorer", "desc": "Understand diagnostic categories with nuance.", "url": "https://huggingface.co/spaces/jostlebot/DiagnosisExplorer"},
|
| 38 |
+
{"icon": "πͺ", "title": "GSPT", "desc": "Generating Safer Passages of Text. Warm, boundaried reflections.", "url": "https://huggingface.co/spaces/jostlebot/GSPT"},
|
| 39 |
+
{"icon": "π", "title": "Learn NVC", "desc": "Practice Nonviolent Communication. Transform judgments into needs.", "url": "https://huggingface.co/spaces/jostlebot/LearnNVC"},
|
| 40 |
+
{"icon": "π¬", "title": "Practice Difficult Conversations", "desc": "Rehearse hard conversations before having them for real.", "url": "https://huggingface.co/spaces/jostlebot/PracticeDifficultConversations"},
|
| 41 |
+
]
|
| 42 |
+
|
| 43 |
+
if not st.session_state.onboarded:
|
| 44 |
+
st.markdown('<div class="hub-header"><h1>π± Practice Fields</h1><p class="hub-tagline">A curated collection of therapeutic practice spaces</p></div>', unsafe_allow_html=True)
|
| 45 |
+
st.markdown("### Welcome, Clinician")
|
| 46 |
+
st.markdown("Enter your information to personalize this hub for your clients.")
|
| 47 |
+
with st.form("onboarding"):
|
| 48 |
+
name = st.text_input("Your Name & Credentials", placeholder="e.g., Dr. Sarah Chen, LMHC")
|
| 49 |
+
orientation = st.text_area("Clinical Orientation (brief)", placeholder="e.g., Attachment-focused, DBT-informed, IFS...", height=80)
|
| 50 |
+
if st.form_submit_button("Enter Practice Fields", use_container_width=True):
|
| 51 |
+
if name:
|
| 52 |
+
st.session_state.clinician_name = name
|
| 53 |
+
st.session_state.clinician_orientation = orientation
|
| 54 |
+
st.session_state.onboarded = True
|
| 55 |
+
st.rerun()
|
| 56 |
+
else:
|
| 57 |
+
st.error("Please enter your name.")
|
| 58 |
+
else:
|
| 59 |
+
st.markdown('<div class="hub-header"><h1>π± Practice Fields</h1><p class="hub-tagline">Structured practice for relational growth</p></div>', unsafe_allow_html=True)
|
| 60 |
+
st.markdown(f'<div class="clinician-badge"><strong>{st.session_state.clinician_name}</strong><br><span style="color:#6a7a7a;font-size:0.9rem;">{st.session_state.clinician_orientation or "Clinical Practice"}</span></div>', unsafe_allow_html=True)
|
| 61 |
+
|
| 62 |
+
c1, c2, c3 = st.columns([1,1,1])
|
| 63 |
+
with c2:
|
| 64 |
+
if st.button("Change Clinician Info", use_container_width=True):
|
| 65 |
+
st.session_state.onboarded = False
|
| 66 |
+
st.rerun()
|
| 67 |
+
|
| 68 |
+
st.markdown('<p class="section-header">Practice Spaces</p>', unsafe_allow_html=True)
|
| 69 |
+
col1, col2 = st.columns(2)
|
| 70 |
+
for i, s in enumerate(SPACES):
|
| 71 |
+
with col1 if i % 2 == 0 else col2:
|
| 72 |
+
st.markdown(f'<a href="{s["url"]}" target="_blank" class="field-card"><div class="field-icon">{s["icon"]}</div><div class="field-title">{s["title"]}</div><div class="field-desc">{s["desc"]}</div></a>', unsafe_allow_html=True)
|
| 73 |
+
|
| 74 |
+
st.markdown('<div class="footer-text">Not therapy. Practice spaces to complement work with your therapist.<br><strong>988</strong> Β· <strong>741741</strong> Β· <strong>911</strong></div>', unsafe_allow_html=True)
|
requirements.txt
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
streamlit>=1.32.0
|