IT-BOS commited on
Commit
bf4e44d
·
verified ·
1 Parent(s): 0dbd495

Upload 9 files

Browse files
Files changed (4) hide show
  1. README.md +4 -0
  2. app.py +56 -2
  3. modules.py +5 -3
  4. videos.py +75 -0
README.md CHANGED
@@ -16,3 +16,7 @@ To edit a module, change the matching entry in `MODULES` in `modules.py`. To cha
16
 
17
  To make the Space private, set Visibility to Private in the Space settings.
18
  Quizzes are matched to modules by position, so if you add a module, add a matching list in `quizzes.py`.
 
 
 
 
 
16
 
17
  To make the Space private, set Visibility to Private in the Space settings.
18
  Quizzes are matched to modules by position, so if you add a module, add a matching list in `quizzes.py`.
19
+
20
+ ## Videos
21
+
22
+ `videos.py` holds the official Anthropic videos embedded in each module (played in page through youtube-nocookie) and the Claude Academy links shown after the key takeaways. To add a video, take the 11 character id from the share link on the Anthropic YouTube channel or from a claude.com tutorial page and add an entry under the module index. Content is Anthropic's; the source link under each player credits the original page.
app.py CHANGED
@@ -20,6 +20,7 @@ from modules import MODULES, IT_HELP
20
  from quizzes import QUIZZES
21
  from teams import TEAMS, TEAMS_INTRO
22
  from figures import FIGURES, TEAM_FIGURE
 
23
 
24
  # Palette sampled from the BOS logo, teal as the single accent
25
  BLUE = "#15516B"
@@ -160,6 +161,31 @@ footer {{ display: none !important; }}
160
  .help p {{ margin: 0; max-width: none; font-size: 15px; }}
161
  .help p b {{ color: var(--blue); }}
162
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
163
  /* Quiz */
164
  .quiz {{ background: var(--paper) !important; border: 1px solid var(--rule) !important; border-radius: 16px !important; box-shadow: var(--shadow);
165
  padding: 30px 40px 28px !important; margin-top: 16px; gap: 4px !important; }}
@@ -331,7 +357,7 @@ def render_home(progress: dict) -> str:
331
  <div class="row"><span class="num">{'&#10003;' if is_done else i + 1}</span>{status}</div>
332
  <h4>{html.escape(m['title'])}</h4>
333
  <p>{html.escape(m['summary'])}</p>
334
- <div class="foot"><span>{MINUTES[i]} min read</span><b>{len(QUIZZES[i])} questions</b></div>
335
  </button>""")
336
  parts.append(f"""
337
  <button type="button" class="mcard ref" style="animation-delay:{N*40}ms" onclick="document.getElementById('rail-team').click()">
@@ -355,6 +381,8 @@ def render_module(idx: int, progress: dict) -> str:
355
  f'<h2>{html.escape(m["title"])}</h2>',
356
  f'<p class="summary">{html.escape(m["summary"])}</p>',
357
  ]
 
 
358
  for s in m["sections"]:
359
  parts.append(f'<h3>{html.escape(s["heading"])}</h3>')
360
  parts.append(s["body"])
@@ -362,17 +390,43 @@ def render_module(idx: int, progress: dict) -> str:
362
  if fig:
363
  parts.append(figure(*fig))
364
  parts.append('<div class="takeaways"><h3>Key takeaways</h3><ol>' + "".join(f"<li>{html.escape(t)}</li>" for t in m["takeaways"]) + "</ol></div>")
 
365
  parts.append(f'<div class="help"><p><b>Need help?</b> {html.escape(IT_HELP)}</p></div>')
366
  parts.append("</div>")
367
  return "\n".join(parts)
368
 
369
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
370
  def render_team_header() -> str:
371
  return (
372
  '<div class="card reader" style="padding-bottom:22px">'
373
  '<div class="meta"><span class="pill">Reference</span><span>Tools by team</span></div>'
374
  "<h2>Where Claude fits next to Zoho, Apollo, and Microsoft 365</h2>"
375
- f"{TEAMS_INTRO}{figure(*TEAM_FIGURE)}</div>"
376
  )
377
 
378
 
 
20
  from quizzes import QUIZZES
21
  from teams import TEAMS, TEAMS_INTRO
22
  from figures import FIGURES, TEAM_FIGURE
23
+ from videos import VIDEOS, LINKS, TEAM_LINKS
24
 
25
  # Palette sampled from the BOS logo, teal as the single accent
26
  BLUE = "#15516B"
 
161
  .help p {{ margin: 0; max-width: none; font-size: 15px; }}
162
  .help p b {{ color: var(--blue); }}
163
 
164
+ /* Watch panel */
165
+ .watch {{ margin: 0 0 36px; padding: 22px 24px 20px; background: linear-gradient(180deg, #F7FBFB, var(--wash)); border: 1px solid var(--rule); border-radius: 14px; max-width: 760px; }}
166
+ .watch .wh {{ display: flex; align-items: baseline; justify-content: space-between; gap: 12px; margin-bottom: 12px; }}
167
+ .watch .wh h3 {{ margin: 0 !important; font-size: 17px !important; color: var(--teal-deep) !important; }}
168
+ .watch .wh span {{ font-size: 13px; color: var(--muted); }}
169
+ .watch .frame {{ position: relative; width: 100%; padding-top: 56.25%; border-radius: 12px; overflow: hidden; background: #0E3A4D; box-shadow: 0 10px 28px -14px rgba(14,58,77,.45); }}
170
+ .watch .frame iframe {{ position: absolute; inset: 0; width: 100%; height: 100%; border: 0; }}
171
+ .watch .wt {{ margin: 14px 0 4px; font-size: 16px; font-weight: 700; color: var(--blue); }}
172
+ .watch .wb {{ margin: 0; font-size: 14.5px; line-height: 1.55; color: var(--ink); max-width: none; }}
173
+ .watch .ws {{ margin: 8px 0 0; font-size: 12.5px; color: var(--muted); max-width: none; }}
174
+ .watch .ws a {{ color: var(--teal-deep); text-decoration: none; font-weight: 700; }}
175
+ .watch + .watch {{ margin-top: -18px; }}
176
+
177
+ /* Further learning cards */
178
+ .more {{ margin-top: 26px; max-width: 760px; }}
179
+ .more h3 {{ font-size: 17px !important; color: var(--blue) !important; margin: 0 0 12px !important; }}
180
+ .more .lgrid {{ display: grid; grid-template-columns: repeat(2, 1fr); gap: 12px; }}
181
+ .more a.lcard {{ display: block; padding: 16px 18px; border: 1px solid var(--rule); border-radius: 12px; background: var(--paper); text-decoration: none; color: var(--ink);
182
+ transition: border-color .15s ease, transform .15s ease, box-shadow .15s ease; }}
183
+ .more a.lcard:hover {{ border-color: #BFE3DF; transform: translateY(-2px); box-shadow: var(--shadow); }}
184
+ .more a.lcard .lt {{ font-size: 15px; font-weight: 700; color: var(--blue); margin: 0 0 3px; max-width: none; }}
185
+ .more a.lcard .lm {{ font-size: 12.5px; color: var(--teal-deep); font-weight: 700; margin: 0 0 8px; max-width: none; }}
186
+ .more a.lcard .lb {{ font-size: 14px; line-height: 1.5; color: var(--muted); margin: 0; max-width: none; }}
187
+ @media (max-width: 720px) {{ .more .lgrid {{ grid-template-columns: 1fr; }} }}
188
+
189
  /* Quiz */
190
  .quiz {{ background: var(--paper) !important; border: 1px solid var(--rule) !important; border-radius: 16px !important; box-shadow: var(--shadow);
191
  padding: 30px 40px 28px !important; margin-top: 16px; gap: 4px !important; }}
 
357
  <div class="row"><span class="num">{'&#10003;' if is_done else i + 1}</span>{status}</div>
358
  <h4>{html.escape(m['title'])}</h4>
359
  <p>{html.escape(m['summary'])}</p>
360
+ <div class="foot"><span>{MINUTES[i]} min read{(' + ' + str(sum(v['minutes'] for v in VIDEOS.get(i, []))) + ' min video') if VIDEOS.get(i) else ''}</span><b>{len(QUIZZES[i])} questions</b></div>
361
  </button>""")
362
  parts.append(f"""
363
  <button type="button" class="mcard ref" style="animation-delay:{N*40}ms" onclick="document.getElementById('rail-team').click()">
 
381
  f'<h2>{html.escape(m["title"])}</h2>',
382
  f'<p class="summary">{html.escape(m["summary"])}</p>',
383
  ]
384
+ for v in VIDEOS.get(idx, []):
385
+ parts.append(watch_panel(v))
386
  for s in m["sections"]:
387
  parts.append(f'<h3>{html.escape(s["heading"])}</h3>')
388
  parts.append(s["body"])
 
390
  if fig:
391
  parts.append(figure(*fig))
392
  parts.append('<div class="takeaways"><h3>Key takeaways</h3><ol>' + "".join(f"<li>{html.escape(t)}</li>" for t in m["takeaways"]) + "</ol></div>")
393
+ parts.append(link_cards(LINKS.get(idx, [])))
394
  parts.append(f'<div class="help"><p><b>Need help?</b> {html.escape(IT_HELP)}</p></div>')
395
  parts.append("</div>")
396
  return "\n".join(parts)
397
 
398
 
399
+ def watch_panel(v: dict) -> str:
400
+ src = f"https://www.youtube-nocookie.com/embed/{v['id']}?rel=0&modestbranding=1"
401
+ return (
402
+ '<div class="watch">'
403
+ f'<div class="wh"><h3>Watch</h3><span>Anthropic, {v["minutes"]} min</span></div>'
404
+ f'<div class="frame"><iframe src="{src}" title="{html.escape(v["title"])}" loading="lazy" '
405
+ 'allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" '
406
+ 'referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe></div>'
407
+ f'<p class="wt">{html.escape(v["title"])}</p><p class="wb">{html.escape(v["blurb"])}</p>'
408
+ f'<p class="ws">Published by Anthropic. <a href="{v["source"]}" target="_blank" rel="noopener">Open the original tutorial page</a></p>'
409
+ "</div>"
410
+ )
411
+
412
+
413
+ def link_cards(links: list, heading: str = "Go further with Anthropic's free courses") -> str:
414
+ if not links:
415
+ return ""
416
+ cards = "".join(
417
+ f'<a class="lcard" href="{l["url"]}" target="_blank" rel="noopener"><p class="lt">{html.escape(l["title"])}</p>'
418
+ f'<p class="lm">{html.escape(l["meta"])}</p><p class="lb">{html.escape(l["blurb"])}</p></a>'
419
+ for l in links
420
+ )
421
+ return f'<div class="more"><h3>{html.escape(heading)}</h3><div class="lgrid">{cards}</div></div>'
422
+
423
+
424
  def render_team_header() -> str:
425
  return (
426
  '<div class="card reader" style="padding-bottom:22px">'
427
  '<div class="meta"><span class="pill">Reference</span><span>Tools by team</span></div>'
428
  "<h2>Where Claude fits next to Zoho, Apollo, and Microsoft 365</h2>"
429
+ f"{TEAMS_INTRO}{figure(*TEAM_FIGURE)}{link_cards(TEAM_LINKS, 'Role based tutorials from Anthropic')}</div>"
430
  )
431
 
432
 
modules.py CHANGED
@@ -29,11 +29,13 @@ MODULES = [
29
  {
30
  "heading": "Why this training exists",
31
  "body": """
32
- <p>BOS Staffing, Security, Medical, have adopted Claude Enterprise as the company
 
33
  standard AI tool. Everyone now has access to the same assistant, working from the
34
  same rules, under a company agreement that governs how our data is handled.</p>
35
- <p> This training is meant to get every BOS employee to a shared baseline: what
36
- these tools actually do, how to get useful work
 
37
  out of them, and where the hard lines are on client and company data.</p>
38
  <p><b>How to use this platform.</b> The six modules build on each other. Start at
39
  the top and read in order. Module 1 and 2 give you the mental model. Modules 3 and
 
29
  {
30
  "heading": "Why this training exists",
31
  "body": """
32
+ <p>BOS Security, including BOS Staffing, BOS Medical Staffing, and the VirtuGuard
33
+ remote video monitoring division, has adopted Claude Enterprise as the company
34
  standard AI tool. Everyone now has access to the same assistant, working from the
35
  same rules, under a company agreement that governs how our data is handled.</p>
36
+ <p>That is a real change from a year ago, when people were experimenting with
37
+ whatever free tool they found online. This training is meant to get every BOS
38
+ employee to a shared baseline: what these tools actually do, how to get useful work
39
  out of them, and where the hard lines are on client and company data.</p>
40
  <p><b>How to use this platform.</b> The six modules build on each other. Start at
41
  the top and read in order. Module 1 and 2 give you the mental model. Modules 3 and
videos.py ADDED
@@ -0,0 +1,75 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Official Anthropic videos and further reading, keyed by module index (0 based).
3
+
4
+ Video IDs below were taken from the embed markup on claude.com tutorial pages
5
+ (claude.com/resources/tutorials/<slug>), which host the videos on YouTube.
6
+ To add one: open the tutorial page or the Anthropic YouTube channel
7
+ (youtube.com/@anthropic-ai), copy the 11 character id from the share link,
8
+ and add an entry. Videos play inside the BOS page via youtube-nocookie.
9
+ """
10
+
11
+ VIDEOS = {
12
+ 0: [
13
+ {
14
+ "id": "j1Vk6Y-23CY",
15
+ "title": "What happens when you talk to AI?",
16
+ "minutes": 5,
17
+ "blurb": "Anthropic's plain language walkthrough of what is going on when the model appears to be thinking. Good first watch before the reading below.",
18
+ "source": "https://claude.com/resources/tutorials/what-happens-when-you-talk-to-ai",
19
+ }
20
+ ],
21
+ 1: [
22
+ {
23
+ "id": "005JLRt3gXI",
24
+ "title": "Why do AI models hallucinate?",
25
+ "minutes": 5,
26
+ "blurb": "What researchers mean by hallucination, why it happens, and how to spot it in your own conversations.",
27
+ "source": "https://claude.com/resources/tutorials/why-do-ai-models-hallucinate",
28
+ }
29
+ ],
30
+ 3: [
31
+ {
32
+ "id": "GJ5jTgcbRHA",
33
+ "title": "Intro to Projects",
34
+ "minutes": 7,
35
+ "blurb": "How Projects hold standing instructions and reference files so every chat starts with the right context. Watch this before asking BOS IT about a shared project.",
36
+ "source": "https://claude.com/resources/tutorials/intro-to-projects",
37
+ }
38
+ ],
39
+ 4: [
40
+ {
41
+ "id": "cIMlBw2nqfA",
42
+ "title": "Can you trust what AI tells you?",
43
+ "minutes": 5,
44
+ "blurb": "Trust as a dial rather than a switch, the two ways answers go wrong, and how to set your own level of scrutiny. Pairs with the accuracy rules in this module.",
45
+ "source": "https://claude.com/resources/tutorials/can-you-trust-what-ai-tells-you",
46
+ }
47
+ ],
48
+ }
49
+
50
+ # Further reading from Anthropic's free Academy. These open in a new tab.
51
+ LINKS = {
52
+ 1: [
53
+ {"title": "AI Capabilities and Limitations", "meta": "Claude Academy course, 3.5 hr", "url": "https://academy.claude.com/courses/ai-capabilities-and-limitations",
54
+ "blurb": "A fuller mental model of prediction, knowledge, working memory, and context limits."},
55
+ ],
56
+ 2: [
57
+ {"title": "Claude 101", "meta": "Claude Academy course, 2.5 hr, completion badge", "url": "https://academy.claude.com/courses/claude-101",
58
+ "blurb": "Anthropic's own onboarding course: first conversation, prompting, Projects, Artifacts, Skills, and connected tools."},
59
+ {"title": "Getting started with Claude.ai", "meta": "Tutorial, 5 min", "url": "https://academy.claude.com/tutorials/getting-started-with-claude-ai",
60
+ "blurb": "Prompting, document uploads, search, and customization options in one short pass."},
61
+ ],
62
+ 5: [
63
+ {"title": "AI Fluency: Framework and Foundations", "meta": "Claude Academy course, 4 hr", "url": "https://academy.claude.com/courses/ai-fluency-framework-foundations",
64
+ "blurb": "The 4D framework: Delegation, Description, Discernment, and Diligence. The optional stretch goal for anyone who wants to go further."},
65
+ {"title": "The 4 Ds of AI Fluency, behavioral indicators", "meta": "Tutorial, 5 min read", "url": "https://claude.com/resources/tutorials/the-4-ds-of-ai-fluency-behavioral-indicators",
66
+ "blurb": "A quick reference of what fluent use looks like day to day."},
67
+ ],
68
+ }
69
+
70
+ TEAM_LINKS = [
71
+ {"title": "Claude Academy tutorials", "meta": "Filter by Sales, HR, Marketing, or Professional", "url": "https://claude.com/resources/tutorials",
72
+ "blurb": "Role based walkthroughs from Anthropic, including Cowork for sales account research and marketing ops."},
73
+ {"title": "Claude Enterprise Administrator Guide", "meta": "Tutorial, 20 min", "url": "https://academy.claude.com/tutorials/claude-enterprise-administrator-guide",
74
+ "blurb": "For BOS IT. Identity, governance, and enablement for the company workspace."},
75
+ ]