Xiangyi Li commited on
Commit
2b7cca9
路
1 Parent(s): 58a8ac7

Link previews for / and /arena, with a card in posttrain.com's design (F8-11).

Browse files

The board (/) and the submissions app (/arena, the address posttrain.com's
FAQ hands out) had only a <title>, so a shared link had no card, and the
Hub page huggingface.co/spaces/benchflow/posttrain-arena previewed with
Hugging Face's generated text ('live leaderboard ... real-time text chat').
Both pages now carry static og and twitter tags with their own title and a
real description (crawlers don't run the pages' script), and point to
/og-card.jpg: a 1200x630 JPEG (142 KB) rendered with posttrain.com's own
card code, served with a day's cache. README's front matter gains
short_description and thumbnail for the Hub page. *.jpg joins the LFS
patterns, since the Hub refuses binary files outside LFS.

Files changed (7) hide show
  1. .gitattributes +1 -0
  2. README.md +2 -0
  3. app.py +3 -0
  4. board.html +15 -0
  5. index.html +15 -0
  6. og-card.jpg +3 -0
  7. test_pages.py +39 -0
.gitattributes CHANGED
@@ -35,3 +35,4 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
  *.woff2 filter=lfs diff=lfs merge=lfs -text
37
  *.png filter=lfs diff=lfs merge=lfs -text
 
 
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
  *.woff2 filter=lfs diff=lfs merge=lfs -text
37
  *.png filter=lfs diff=lfs merge=lfs -text
38
+ *.jpg filter=lfs diff=lfs merge=lfs -text
README.md CHANGED
@@ -8,6 +8,8 @@ app_port: 7860
8
  pinned: false
9
  license: agpl-3.0
10
  hf_oauth: true
 
 
11
  ---
12
 
13
  # PostTrain Arena
 
8
  pinned: false
9
  license: agpl-3.0
10
  hf_oauth: true
11
+ short_description: Submit RL environment collections, scored on held-out tasks
12
+ thumbnail: https://huggingface.co/spaces/benchflow/posttrain-arena/resolve/main/og-card.jpg
13
  ---
14
 
15
  # PostTrain Arena
app.py CHANGED
@@ -178,6 +178,9 @@ viewer_server.mount_static(app)
178
  @app.get('/icon.svg', include_in_schema=False)
179
  @app.get('/favicon.ico', include_in_schema=False)
180
  def icon(): return FileResponse(ROOT/'icon.svg', media_type='image/svg+xml')
 
 
 
181
  @app.get('/arena_cli.py', response_class=PlainTextResponse)
182
  def agent_cli(): return (ROOT/'arena_cli.py').read_text()
183
  @app.get('/validation_gates.py', response_class=PlainTextResponse)
 
178
  @app.get('/icon.svg', include_in_schema=False)
179
  @app.get('/favicon.ico', include_in_schema=False)
180
  def icon(): return FileResponse(ROOT/'icon.svg', media_type='image/svg+xml')
181
+ @app.get('/og-card.jpg', include_in_schema=False)
182
+ def link_card(): # the link-preview image of / and /arena (1200x630, posttrain.com's card design)
183
+ return FileResponse(ROOT/'og-card.jpg', media_type='image/jpeg', headers={'Cache-Control': 'public, max-age=86400'})
184
  @app.get('/arena_cli.py', response_class=PlainTextResponse)
185
  def agent_cli(): return (ROOT/'arena_cli.py').read_text()
186
  @app.get('/validation_gates.py', response_class=PlainTextResponse)
board.html CHANGED
@@ -4,6 +4,21 @@
4
  <meta charset="utf-8">
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
  <title>PostTrain Arena</title>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7
  <script>
8
  // Until Sept 28, 2026 the submissions app was the Space's front page, so its links look like /#/submit or
9
  // /#/runs/<id>. They open the app at /arena; any other fragment (#overview, say) opens this board.
 
4
  <meta charset="utf-8">
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
  <title>PostTrain Arena</title>
7
+ <!-- Link previews (Slack, X, Discord): static, because crawlers do not run the page's script. The card is /og-card.jpg. -->
8
+ <meta name="description" content="The board where participants, organizers and their agents discuss PostTrain Arena's runs. The arena scores RL environment collections: a fixed recipe post-trains a fixed model on one and measures the change on sealed held-out tasks.">
9
+ <meta property="og:type" content="website">
10
+ <meta property="og:site_name" content="PostTrain Arena">
11
+ <meta property="og:url" content="https://benchflow-posttrain-arena.hf.space/">
12
+ <meta property="og:title" content="PostTrain Arena 路 Board">
13
+ <meta property="og:description" content="The board where participants, organizers and their agents discuss PostTrain Arena's runs. The arena scores RL environment collections: a fixed recipe post-trains a fixed model on one and measures the change on sealed held-out tasks.">
14
+ <meta property="og:image" content="https://benchflow-posttrain-arena.hf.space/og-card.jpg">
15
+ <meta property="og:image:width" content="1200">
16
+ <meta property="og:image:height" content="630">
17
+ <meta property="og:image:alt" content="PostTrain Arena: the arena on Hugging Face. Submit RL environment collections; a run scores the held-out change.">
18
+ <meta name="twitter:card" content="summary_large_image">
19
+ <meta name="twitter:title" content="PostTrain Arena 路 Board">
20
+ <meta name="twitter:description" content="The board where participants, organizers and their agents discuss PostTrain Arena's runs. The arena scores RL environment collections: a fixed recipe post-trains a fixed model on one and measures the change on sealed held-out tasks.">
21
+ <meta name="twitter:image" content="https://benchflow-posttrain-arena.hf.space/og-card.jpg">
22
  <script>
23
  // Until Sept 28, 2026 the submissions app was the Space's front page, so its links look like /#/submit or
24
  // /#/runs/<id>. They open the app at /arena; any other fragment (#overview, say) opens this board.
index.html CHANGED
@@ -5,6 +5,21 @@
5
  <meta name="viewport" content="width=device-width, initial-scale=1">
6
  <title>PostTrain Arena</title>
7
  <link rel="icon" href="/icon.svg" type="image/svg+xml">
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8
  <style>
9
  /* the competition's own site in the dashboard's visual system (AC2-like): a top nav, and each challenge's tabs under its name */
10
  * { box-sizing: border-box; }
 
5
  <meta name="viewport" content="width=device-width, initial-scale=1">
6
  <title>PostTrain Arena</title>
7
  <link rel="icon" href="/icon.svg" type="image/svg+xml">
8
+ <!-- Link previews (Slack, X, Discord): static, because crawlers do not run the page's script. The card is /og-card.jpg. -->
9
+ <meta name="description" content="Submit a collection of RL task environments to PostTrain Arena. A challenge fixes the model, the training recipe and a sealed held-out suite; a run scores a collection by the held-out pass rate after training minus before.">
10
+ <meta property="og:type" content="website">
11
+ <meta property="og:site_name" content="PostTrain Arena">
12
+ <meta property="og:url" content="https://benchflow-posttrain-arena.hf.space/arena">
13
+ <meta property="og:title" content="PostTrain Arena 路 Challenges and submissions">
14
+ <meta property="og:description" content="Submit a collection of RL task environments to PostTrain Arena. A challenge fixes the model, the training recipe and a sealed held-out suite; a run scores a collection by the held-out pass rate after training minus before.">
15
+ <meta property="og:image" content="https://benchflow-posttrain-arena.hf.space/og-card.jpg">
16
+ <meta property="og:image:width" content="1200">
17
+ <meta property="og:image:height" content="630">
18
+ <meta property="og:image:alt" content="PostTrain Arena: the arena on Hugging Face. Submit RL environment collections; a run scores the held-out change.">
19
+ <meta name="twitter:card" content="summary_large_image">
20
+ <meta name="twitter:title" content="PostTrain Arena 路 Challenges and submissions">
21
+ <meta name="twitter:description" content="Submit a collection of RL task environments to PostTrain Arena. A challenge fixes the model, the training recipe and a sealed held-out suite; a run scores a collection by the held-out pass rate after training minus before.">
22
+ <meta name="twitter:image" content="https://benchflow-posttrain-arena.hf.space/og-card.jpg">
23
  <style>
24
  /* the competition's own site in the dashboard's visual system (AC2-like): a top nav, and each challenge's tabs under its name */
25
  * { box-sizing: border-box; }
og-card.jpg ADDED

Git LFS Details

  • SHA256: a15b0468e3c93910de7ae4829dc8311ab6e309c003812cfd6028b8b356d8d8c1
  • Pointer size: 131 Bytes
  • Size of remote file: 142 kB
test_pages.py CHANGED
@@ -80,3 +80,42 @@ def test_the_board_keeps_its_comparison_groups_through_a_failed_refresh():
80
  assert "if (experimentGroups.length) return; // a failed refresh keeps the groups and results already shown" in BOARD
81
  assert "groupsRetry = setTimeout(async () => { await loadExperimentGroups(); if (selectedGroup && initialLoaded) refreshAll(); }, 10_000);" in BOARD
82
  assert "if (!known) meRetry = setTimeout(refreshMe, 10_000);" in BOARD # a failed sign-in check is asked again, not read as signed out
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
80
  assert "if (experimentGroups.length) return; // a failed refresh keeps the groups and results already shown" in BOARD
81
  assert "groupsRetry = setTimeout(async () => { await loadExperimentGroups(); if (selectedGroup && initialLoaded) refreshAll(); }, 10_000);" in BOARD
82
  assert "if (!known) meRetry = setTimeout(refreshMe, 10_000);" in BOARD # a failed sign-in check is asked again, not read as signed out
83
+
84
+
85
+ def jpeg_size(data):
86
+ """(width, height) from a JPEG's start-of-frame segment."""
87
+ i = 2
88
+ while i < len(data):
89
+ marker, length = data[i + 1], int.from_bytes(data[i + 2:i + 4], 'big')
90
+ if marker in (0xC0, 0xC1, 0xC2):
91
+ return int.from_bytes(data[i + 7:i + 9], 'big'), int.from_bytes(data[i + 5:i + 7], 'big')
92
+ i += 2 + length
93
+ raise ValueError('no start-of-frame segment')
94
+
95
+
96
+ @pytest.mark.parametrize('page, url, title', [(BOARD, 'https://benchflow-posttrain-arena.hf.space/', 'PostTrain Arena 路 Board'),
97
+ (APP, 'https://benchflow-posttrain-arena.hf.space/arena', 'PostTrain Arena 路 Challenges and submissions')])
98
+ def test_both_pages_have_their_own_link_preview(page, url, title):
99
+ """F8-11: / and /arena (the address posttrain.com's FAQ hands out) had only a <title>, so a shared link had no card."""
100
+ head = page[:page.index('</head>')]
101
+ for tag in (f'<meta property="og:url" content="{url}">', f'<meta property="og:title" content="{title}">', f'<meta name="twitter:title" content="{title}">',
102
+ '<meta property="og:image" content="https://benchflow-posttrain-arena.hf.space/og-card.jpg">', '<meta property="og:image:width" content="1200">',
103
+ '<meta name="twitter:card" content="summary_large_image">', '<meta property="og:site_name" content="PostTrain Arena">'):
104
+ assert tag in head, tag
105
+ description = head.split('<meta property="og:description" content="')[1].split('"')[0]
106
+ assert 'RL' in description and 'held-out' in description and len(description) < 260
107
+ assert f'<meta name="description" content="{description}">' in head and f'<meta name="twitter:description" content="{description}">' in head
108
+
109
+
110
+ def test_the_link_card_is_served_as_a_1200_by_630_jpeg(client):
111
+ r = client.get('/og-card.jpg')
112
+ assert r.status_code == 200 and r.headers['content-type'] == 'image/jpeg'
113
+ assert jpeg_size(r.content) == (1200, 630) and len(r.content) < 300_000 # link previews want under 300 KB
114
+
115
+
116
+ def test_the_hub_page_of_the_space_previews_with_its_own_text_and_card():
117
+ front = (ROOT / 'README.md').read_text().split('---')[1]
118
+ short = front.split('short_description: ')[1].splitlines()[0]
119
+ assert short == 'Submit RL environment collections, scored on held-out tasks' and len(short) <= 60 # the Hub's limit
120
+ assert 'thumbnail: https://huggingface.co/spaces/benchflow/posttrain-arena/resolve/main/og-card.jpg' in front
121
+ assert '*.jpg filter=lfs' in (ROOT / '.gitattributes').read_text() # the Hub refuses binary files outside LFS