Skip to content

Commit 1a7a04f

Browse files
Add inline submit form and org-wide repo sync
Homepage changes: - Add inline submit form below search: paste a GitHub URL, see a preview of where docs will live, one click to submit - Accepts full URLs or owner/repo shorthand - "No results" area now links to the submit form - Mobile-responsive layout for the submit row Sync workflow (sync-repos.yml): - Runs every 6 hours + manual trigger - Scans all org repos for arch-docs workflow - Auto-adds any missing repos to repos.yaml - Forks → Community category, org-native → Supermodel Open Source - Auto-detects description, language, pill from GitHub API - Commits and pushes to trigger homepage rebuild This ensures repos like volt that are set up internally but never added to repos.yaml will auto-appear on the homepage.
1 parent fa6acbf commit 1a7a04f

File tree

2 files changed

+244
-3
lines changed

2 files changed

+244
-3
lines changed

.github/workflows/sync-repos.yml

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
name: Sync Repos from Org
2+
3+
on:
4+
schedule:
5+
- cron: '0 */6 * * *' # Every 6 hours
6+
workflow_dispatch: # Manual trigger
7+
8+
concurrency:
9+
group: add-repo
10+
cancel-in-progress: false
11+
12+
jobs:
13+
sync:
14+
runs-on: ubuntu-latest
15+
permissions:
16+
contents: write
17+
env:
18+
GH_TOKEN: ${{ secrets.BOT_TOKEN }}
19+
steps:
20+
- uses: actions/checkout@v4
21+
22+
- name: Discover repos with arch-docs
23+
id: discover
24+
run: |
25+
ORG="supermodeltools"
26+
ADDED=0
27+
28+
# Get all repos in the org
29+
REPOS=$(gh api --paginate "orgs/$ORG/repos?per_page=100&type=all" --jq '.[].name')
30+
31+
for REPO_NAME in $REPOS; do
32+
# Skip if already in repos.yaml
33+
if grep -q "name: ${REPO_NAME}$" repos.yaml; then
34+
continue
35+
fi
36+
37+
# Skip the homepage repo itself
38+
if [ "$REPO_NAME" = "supermodeltools.github.io" ]; then
39+
continue
40+
fi
41+
42+
# Check if repo has arch-docs workflow
43+
if ! gh api "repos/$ORG/$REPO_NAME/contents/.github/workflows/arch-docs.yml" &>/dev/null; then
44+
continue
45+
fi
46+
47+
echo "Found unlisted repo with arch-docs: $REPO_NAME"
48+
49+
# Get repo metadata
50+
REPO_JSON=$(gh api "repos/$ORG/$REPO_NAME")
51+
DESCRIPTION=$(echo "$REPO_JSON" | jq -r '.description // "Architecture documentation"' | head -c 200)
52+
LANGUAGE=$(echo "$REPO_JSON" | jq -r '.language // "Unknown"')
53+
IS_FORK=$(echo "$REPO_JSON" | jq -r '.fork')
54+
PARENT=$(echo "$REPO_JSON" | jq -r '.parent.full_name // ""')
55+
56+
# Map language to pill
57+
case "$LANGUAGE" in
58+
JavaScript) PILL="JavaScript"; PILL_CLASS="pill-blue" ;;
59+
TypeScript) PILL="TypeScript"; PILL_CLASS="pill-blue" ;;
60+
Python) PILL="Python"; PILL_CLASS="pill-green" ;;
61+
Go) PILL="Go"; PILL_CLASS="pill-accent" ;;
62+
Rust) PILL="Rust"; PILL_CLASS="pill-accent" ;;
63+
Java) PILL="Java"; PILL_CLASS="pill-orange" ;;
64+
Kotlin) PILL="Kotlin"; PILL_CLASS="pill-orange" ;;
65+
Scala) PILL="Scala"; PILL_CLASS="pill-orange" ;;
66+
Ruby) PILL="Ruby"; PILL_CLASS="pill-orange" ;;
67+
C) PILL="C"; PILL_CLASS="pill-accent" ;;
68+
C++) PILL="C++"; PILL_CLASS="pill-accent" ;;
69+
C#) PILL="C#"; PILL_CLASS="pill-green" ;;
70+
Swift) PILL="Swift"; PILL_CLASS="pill-orange" ;;
71+
PHP) PILL="PHP"; PILL_CLASS="pill-blue" ;;
72+
Shell|Bash) PILL="DevOps"; PILL_CLASS="pill-green" ;;
73+
HCL) PILL="DevOps"; PILL_CLASS="pill-green" ;;
74+
*) PILL="$LANGUAGE"; PILL_CLASS="pill-blue" ;;
75+
esac
76+
77+
# Determine category: forks → Community (index 1), org-native → Supermodel Open Source (index 0)
78+
if [ "$IS_FORK" = "true" ] && [ -n "$PARENT" ]; then
79+
CATEGORY_INDEX=1
80+
export REPO_NAME PARENT DESCRIPTION PILL PILL_CLASS
81+
yq -i '.categories[1].repos += [{
82+
"name": strenv(REPO_NAME),
83+
"upstream": strenv(PARENT),
84+
"description": strenv(DESCRIPTION),
85+
"pill": strenv(PILL),
86+
"pill_class": strenv(PILL_CLASS)
87+
}]' repos.yaml
88+
else
89+
export REPO_NAME DESCRIPTION PILL PILL_CLASS
90+
yq -i '.categories[0].repos += [{
91+
"name": strenv(REPO_NAME),
92+
"description": strenv(DESCRIPTION),
93+
"pill": strenv(PILL),
94+
"pill_class": strenv(PILL_CLASS)
95+
}]' repos.yaml
96+
fi
97+
98+
ADDED=$((ADDED + 1))
99+
echo " Added $REPO_NAME (fork=$IS_FORK, lang=$LANGUAGE)"
100+
done
101+
102+
echo "added=$ADDED" >> "$GITHUB_OUTPUT"
103+
echo "Total repos added: $ADDED"
104+
105+
- name: Commit and push
106+
if: steps.discover.outputs.added != '0'
107+
run: |
108+
ADDED="${{ steps.discover.outputs.added }}"
109+
git config user.name "supermodel-bot"
110+
git config user.email "bot@supermodeltools.com"
111+
git add repos.yaml
112+
git commit -m "Sync $ADDED repo(s) discovered with arch-docs"
113+
114+
# Push with BOT_TOKEN to trigger build-index workflow
115+
git remote set-url origin "https://x-access-token:${GH_TOKEN}@github.com/${{ github.repository }}.git"
116+
git push origin main

generate-index.go

Lines changed: 128 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -347,6 +347,62 @@ a:focus-visible { outline: 2px solid var(--accent-light); outline-offset: 2px; b
347347
font-size: 15px;
348348
display: none;
349349
}
350+
.no-results a { cursor: pointer; }
351+
.submit-box {
352+
max-width: 480px;
353+
margin: 16px auto 0;
354+
}
355+
.submit-label {
356+
font-size: 13px;
357+
color: var(--text-muted);
358+
margin-bottom: 6px;
359+
}
360+
.submit-row {
361+
display: flex;
362+
gap: 8px;
363+
}
364+
.submit-input {
365+
flex: 1;
366+
padding: 10px 14px;
367+
background: var(--bg-card);
368+
border: 1px solid var(--border);
369+
border-radius: var(--radius);
370+
color: var(--text);
371+
font-size: 14px;
372+
font-family: var(--mono);
373+
outline: none;
374+
transition: border-color 0.2s;
375+
}
376+
.submit-input:focus { border-color: var(--accent); }
377+
.submit-input::placeholder { color: var(--text-muted); font-family: var(--font); }
378+
.submit-btn {
379+
padding: 10px 20px;
380+
background: var(--accent);
381+
color: #fff;
382+
border: none;
383+
border-radius: var(--radius);
384+
font-size: 14px;
385+
font-weight: 600;
386+
font-family: inherit;
387+
cursor: pointer;
388+
white-space: nowrap;
389+
transition: background 0.2s;
390+
opacity: 0.4;
391+
pointer-events: none;
392+
}
393+
.submit-btn.active {
394+
opacity: 1;
395+
pointer-events: auto;
396+
}
397+
.submit-btn.active:hover { background: var(--accent-light); }
398+
.submit-preview {
399+
margin-top: 8px;
400+
font-size: 13px;
401+
color: var(--green);
402+
font-family: var(--mono);
403+
display: none;
404+
}
405+
.submit-preview.visible { display: block; }
350406
@media (max-width: 768px) {
351407
.container { padding: 0 16px; }
352408
.hero { padding: 40px 0 32px; }
@@ -357,6 +413,9 @@ a:focus-visible { outline: 2px solid var(--accent-light); outline-offset: 2px; b
357413
.card { padding: 18px; }
358414
.section-title { font-size: 18px; }
359415
.site-footer { margin-top: 40px; padding: 24px 0; }
416+
.submit-row { flex-direction: column; }
417+
.submit-btn { width: 100%; }
418+
.site-nav { gap: 10px; flex-wrap: wrap; justify-content: flex-end; }
360419
}
361420
</style>
362421
</head>
@@ -399,9 +458,20 @@ a:focus-visible { outline: 2px solid var(--accent-light); outline-offset: 2px; b
399458
<svg class="search-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="11" cy="11" r="8"/><path d="m21 21-4.3-4.3"/></svg>
400459
<input type="text" class="search-input" id="search" placeholder="Search repositories..." autocomplete="off">
401460
</div>
461+
<div class="submit-box">
462+
<div class="submit-label">Don't see your repo? Paste a URL to generate arch docs:</div>
463+
<div class="submit-row">
464+
<input type="text" class="submit-input" id="submit-url" placeholder="https://github.com/owner/repo" autocomplete="off" spellcheck="false">
465+
<button class="submit-btn" id="submit-btn" type="button">Request</button>
466+
</div>
467+
<div class="submit-preview" id="submit-preview"></div>
468+
</div>
402469
</div>
403470
404-
<div id="no-results" class="no-results">No repositories match your search.</div>
471+
<div id="no-results" class="no-results">
472+
No repositories match your search.
473+
<br><a id="no-results-request">Request docs for this repo &rarr;</a>
474+
</div>
405475
406476
{{range .Categories}}
407477
<div class="section" data-section="{{.Slug}}">
@@ -434,12 +504,19 @@ a:focus-visible { outline: 2px solid var(--accent-light); outline-offset: 2px; b
434504
435505
<script>
436506
(function() {
437-
var input = document.getElementById('search');
507+
var searchInput = document.getElementById('search');
438508
var cards = document.querySelectorAll('.card');
439509
var sections = document.querySelectorAll('.section');
440510
var noResults = document.getElementById('no-results');
511+
var submitInput = document.getElementById('submit-url');
512+
var submitBtn = document.getElementById('submit-btn');
513+
var submitPreview = document.getElementById('submit-preview');
514+
var noResultsRequest = document.getElementById('no-results-request');
515+
516+
var issueBase = 'https://github.com/supermodeltools/supermodeltools.github.io/issues/new?template=request-repo.yml';
441517
442-
input.addEventListener('input', function() {
518+
// --- Search ---
519+
searchInput.addEventListener('input', function() {
443520
var q = this.value.toLowerCase().trim();
444521
var anyVisible = false;
445522
@@ -458,6 +535,54 @@ a:focus-visible { outline: 2px solid var(--accent-light); outline-offset: 2px; b
458535
459536
noResults.style.display = anyVisible ? 'none' : 'block';
460537
});
538+
539+
// --- Submit form ---
540+
function parseRepo(val) {
541+
val = val.trim().replace(/\/+$/, '').replace(/\.git$/, '');
542+
var m = val.match(/github\.com\/([a-zA-Z0-9._-]+\/[a-zA-Z0-9._-]+)/);
543+
if (m) return m[1];
544+
m = val.match(/^([a-zA-Z0-9._-]+\/[a-zA-Z0-9._-]+)$/);
545+
if (m) return m[1];
546+
return null;
547+
}
548+
549+
submitInput.addEventListener('input', function() {
550+
var parsed = parseRepo(this.value);
551+
if (parsed) {
552+
var name = parsed.split('/')[1];
553+
submitPreview.textContent = '\u2192 Docs will be at repos.supermodeltools.com/' + name + '/';
554+
submitPreview.classList.add('visible');
555+
submitBtn.classList.add('active');
556+
} else {
557+
submitPreview.classList.remove('visible');
558+
submitBtn.classList.remove('active');
559+
}
560+
});
561+
562+
function submitRequest() {
563+
var parsed = parseRepo(submitInput.value);
564+
if (!parsed) return;
565+
var repoUrl = 'https://github.com/' + parsed;
566+
var name = parsed.split('/')[1];
567+
var url = issueBase
568+
+ '&repo_url=' + encodeURIComponent(repoUrl)
569+
+ '&title=' + encodeURIComponent('[Repo Request] ' + name);
570+
window.open(url, '_blank');
571+
}
572+
573+
submitBtn.addEventListener('click', submitRequest);
574+
submitInput.addEventListener('keydown', function(e) {
575+
if (e.key === 'Enter') submitRequest();
576+
});
577+
578+
// "No results" request link: pre-fill with search query as a guess
579+
noResultsRequest.addEventListener('click', function() {
580+
var q = searchInput.value.trim();
581+
submitInput.value = q;
582+
submitInput.dispatchEvent(new Event('input'));
583+
submitInput.focus();
584+
window.scrollTo({ top: 0, behavior: 'smooth' });
585+
});
461586
})();
462587
</script>
463588
</body>

0 commit comments

Comments
 (0)