jostlebot commited on
Commit
d0e10e8
Β·
0 Parent(s):

Initial hub

Browse files
Files changed (3) hide show
  1. README.md +16 -0
  2. app.py +74 -0
  3. 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