Skip to content

Commit b9a7ff3

Browse files
committed
Let Pseudo handle taking part and talk about the next forum
The join section is gone; 참여하기 in the nav, the Builder button and old #join links now open Pseudo, which explains the runner, first-contribution and Builder paths with their links. Pseudo greets with the next Data Forum while it is close and answers who is speaking, how to get there and how to sign up from data/events.json. The Iterglow public key now comes from the ITERGLOW_SDK_KEY secret at deploy time and only while an experiment is on; check_data.py rejects a key in the repo. check_data.py also warns when a Pseudo explanation points at a term the web book dropped or uses a spelling other than the glossary's.
1 parent e190261 commit b9a7ff3

9 files changed

Lines changed: 169 additions & 67 deletions

File tree

‎.github/workflows/deploy.yml‎

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,31 @@ jobs:
6161
mkdir _site
6262
cp -r index.html article.html game.html lab.html library.html 404.html .nojekyll robots.txt sitemap.xml assets data articles builders badges _site/
6363
64+
# The Iterglow public SDK key lives in the ITERGLOW_SDK_KEY secret, not in the repo. It is added to the
65+
# published experiments.json only while an experiment is switched on; with no key, experiments stay off.
66+
- name: Add the Iterglow key
67+
env:
68+
ITERGLOW_SDK_KEY: ${{ secrets.ITERGLOW_SDK_KEY }}
69+
run: |
70+
python3 - <<'PY'
71+
import json, os
72+
path = "_site/data/experiments.json"
73+
with open(path, encoding="utf-8") as f:
74+
cfg = json.load(f)
75+
key = os.environ.get("ITERGLOW_SDK_KEY", "").strip()
76+
if not cfg.get("enabled"):
77+
print("experiments off")
78+
elif key.startswith("pk_"):
79+
cfg["apiKey"] = key
80+
print("experiments on")
81+
else:
82+
cfg["enabled"] = False
83+
print("::warning::experiments.json is enabled but the ITERGLOW_SDK_KEY secret is missing; experiments stay off")
84+
with open(path, "w", encoding="utf-8") as f:
85+
json.dump(cfg, f, ensure_ascii=False, indent=2)
86+
f.write("\n")
87+
PY
88+
6489
# Browsers keep scripts and styles for up to ten minutes; a version on their URLs makes each deploy load
6590
# its own files instead of new HTML running last deploy's scripts.
6691
- name: Version script and style URLs

‎CONTRIBUTING.md‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@ PR을 올리기 전에 `python3 scripts/check_data.py`를 실행해 주세요.
2121
| `data/growth.json` | 기수별 누적 러너 수. 프로젝트 시트를 xlsx로 내려받아 `python scripts/runners_from_sheet.py 파일.xlsx > data/growth.json`으로 만듭니다. 이름은 파일에 남지 않습니다. |
2222
| `data/events.json` | Data Forum 같은 행사를 추가할 때. 다가오는 행사에는 `tagline`, `time`, `venue`, `address`, `signupStart`·`signupEnd`(신청 기간), `capacity`(정원), `code`(추천 코드 안내), `timetable`, `poster`·`timetableImage`(`assets/img/`의 이미지)를 적을 수 있습니다. 신청 기간에 따라 첫 화면 띠와 카드의 문구가 ‘신청 예정 · 받는 중 · 마감’으로 바뀝니다. 행사 전에는 `date`·`time`으로 캘린더 추가 링크(Google, .ics)를, `address`(없으면 `venue`)로 네이버 지도·카카오맵 링크를 카드에 만듭니다. `time`은 `13:30–17:30`처럼 한국 시간으로 적습니다. 행사 다음 날부터 6주 동안은 큰 카드가 ‘지난 행사’로 남고, `participants`(참가 인원)와 `recap`(`{"label": "후기 보기", "url": "https://..."}`)을 넣으면 카드에 함께 보입니다. |
2323
| `data/topics.json` | 자료실의 주제와 자료를 고칠 때. 주제마다 `shelf`(`causal` 인과추론, `exp` 온라인 실험), `name`, `about`, 검색어 `keys`, 자료 `items`를 적습니다. 자료는 `kind`(`video`·`read`·`code`·`slides`·`case`), `repo`(`repos.json`의 레포), `title`, `url`이고, 영상에 딸린 노트북은 `notebook`, 발표 자료 PDF는 `slides`로 붙입니다. 연재 글은 `articles.json`에 `topics`(주제 id 목록)를 적으면 공개일부터 그 주제에 함께 나옵니다. |
24-
| `data/experiments.json` | 허브에서 Iterglow(가짜연구소 실험 플랫폼)로 A/B 테스트를 돌릴 때. 기본은 꺼져 있습니다(`"enabled": false`). 켜려면 Iterglow 프로젝트의 공개 SDK 키(`pk_…`)를 `apiKey`에, 관리자가 만든 sdk_v1 실험의 `experimentId`와 연결된 flag의 `flagKey`를 실험마다 적습니다. 서버 키나 계정 세션은 절대 넣지 않습니다. `goals`는 허브가 이미 보내는 이벤트 이름을 Iterglow 지표 이름에 잇습니다. 켜져 있는 동안 SDK가 방문자 브라우저에 익명 ID(`experibase_uid`)를 만들고, 그 ID와 페이지 경로, 기기 종류를 Iterglow로 보냅니다. 첫 실험은 `pseudo-greeting`(Pseudo가 먼저 인사하기)이고, 코드는 `assets/js/experiment.js`에 있습니다. |
25-
| `data/pseudo.json` | Pseudo가 용어를 설명할 때 쓰는 한두 문장 풀이. 키는 `glossary.json`의 용어 id(`term-…`)입니다. 풀이가 없는 용어는 원어와 웹북 장만 알려 줍니다. 해요체로, 예시를 하나 넣어 짧게 씁니다. |
24+
| `data/experiments.json` | 허브에서 Iterglow(가짜연구소 실험 플랫폼)로 A/B 테스트를 돌릴 때. 기본은 꺼져 있습니다(`"enabled": false`). 켜려면 관리자가 만든 sdk_v1 실험의 `experimentId`와 연결된 flag의 `flagKey`를 실험마다 적고 `enabled`를 `true`로 바꿉니다. 공개 SDK 키(`pk_…`)는 저장소에 적지 않고(`apiKey`는 비워 둡니다) 저장소 Actions secret `ITERGLOW_SDK_KEY`에 둡니다. 배포가 실험이 켜져 있을 때만 그 키를 게시본에 넣고, secret이 없으면 실험은 꺼진 채로 배포됩니다. 공개 키는 실험이 켜지면 방문자 브라우저로 전달되는 값이라 관리 권한은 없지만, 서버 키나 계정 세션은 어디에도 넣지 않습니다. `goals`는 허브가 이미 보내는 이벤트 이름을 Iterglow 지표 이름에 잇습니다. 켜져 있는 동안 SDK가 방문자 브라우저에 익명 ID(`experibase_uid`)를 만들고, 그 ID와 페이지 경로, 기기 종류를 Iterglow로 보냅니다. 첫 실험은 `pseudo-greeting`(Pseudo가 먼저 인사하기)이고, 코드는 `assets/js/experiment.js`에 있습니다. |
25+
| `data/pseudo.json` | Pseudo가 용어를 설명할 때 쓰는 한두 문장 풀이. 키는 `glossary.json`의 용어 id(`term-…`)입니다. 풀이가 없는 용어는 원어와 웹북 장만 알려 줍니다. 해요체로, 예시를 하나 넣어 짧게 씁니다. 다른 용어를 쓸 때는 용어집의 번역어 그대로 씁니다(예: 처치군이 아니라 실험군). 배포 때마다 웹북 용어집을 새로 읽고, 웹북에서 사라진 용어나 다른 표기를 쓴 풀이는 `check_data.py`가 경고로 알려 줍니다. |
2626
| `assets/js/helper.js` | Pseudo(자료실 마스코트)의 답과 추천 질문, 마스코트가 먼저 거는 말(`LINES`: 페이지마다 첫 인사와 특정 섹션·스크롤 위치에서 한 번씩, 방문당 한 번, 닫으면 그 방문 동안 조용히)을 고칠 때. Pseudo는 `topics.json`의 이름·`keys`와 `glossary.json`의 용어로 답을 찾으므로, 잘 못 찾는 질문이 있으면 먼저 해당 주제의 `keys`를 늘려 보세요. 질문 내용은 `helper_ask` 이벤트(앞 100자)로만 남고 저장하지 않습니다. |
2727
| `data/glossary.json` | 직접 고치지 않습니다. 배포할 때 `scripts/build_glossary.py`가 웹북 용어집 페이지를 읽어 새로 만듭니다. 용어를 고치려면 Causal-Inference-with-Python의 `TRANSLATION_GUIDE.md` 용어표를 고치세요. 웹북이 다시 배포된 다음 허브 배포 때 반영됩니다. |
2828
| `data/repos.json` | 레포를 추가하거나 설명·단계·트랙·상태를 바꿀 때 |

‎assets/css/hub.css‎

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -584,7 +584,6 @@ body::before { content: ""; position: fixed; inset: 0 0 auto; height: env(safe-a
584584
.btn.ghost { background: transparent; color: var(--ink); border: 1.5px solid var(--rule); }
585585
.btn.ghost:hover { border-color: var(--ink); }
586586
button.btn { font: inherit; font-weight: 600; font-size: 15px; cursor: pointer; }
587-
.join-foot { margin-top: 18px; color: var(--muted); }
588587

589588
/* Footer */
590589
.site-footer { border-top: 1px solid var(--rule); background: var(--surface); padding-block: 28px calc(28px + env(safe-area-inset-bottom, 0px)); font-size: 14px; color: var(--muted); }
@@ -1730,7 +1729,6 @@ a.ac-title:hover { text-decoration: underline; }
17301729
.loop { grid-template-columns: repeat(2, minmax(0, 1fr)); }
17311730
.loop > li:nth-child(2) > a::after { display: none; }
17321731
}
1733-
#join .steps li::before { display: none; }
17341732

17351733
/* ==========================================================================
17361734
The page is a line: the nav is six stations, each section a stop on it,
@@ -1740,7 +1738,7 @@ a.ac-title:hover { text-decoration: underline; }
17401738
#contrib, .s-ml { --sec: var(--l-ml); }
17411739
#events, .s-exp { --sec: var(--l-exp); }
17421740
#posts, .s-behavior { --sec: var(--l-behavior); }
1743-
#join, .s-research { --sec: var(--l-research); }
1741+
.s-research { --sec: var(--l-research); }
17441742

17451743
/* nav: a rail under the six labels, a stop under each, filled up to where the reader is */
17461744
.site-nav { position: relative; gap: 22px; padding: 0 6px; overflow: visible; }
@@ -1770,7 +1768,7 @@ a.ac-title:hover { text-decoration: underline; }
17701768

17711769
/* section heads: the station for that section, then the name */
17721770
.section-head h2 { display: flex; align-items: center; gap: 14px; font-size: clamp(28px, 3.4vw, 40px); letter-spacing: -.035em; }
1773-
#curriculum .section-head h2::before, #contrib .section-head h2::before, #events .section-head h2::before, #posts .section-head h2::before, #join .section-head h2::before {
1771+
#curriculum .section-head h2::before, #contrib .section-head h2::before, #events .section-head h2::before, #posts .section-head h2::before {
17741772
content: ""; width: 18px; height: 18px; flex-shrink: 0; border-radius: 50%; background: var(--surface); border: 5px solid var(--sec); box-sizing: border-box; }
17751773
.section-head > p { max-width: 40em; }
17761774

0 commit comments

Comments
 (0)