Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion DESIGN.md
Original file line number Diff line number Diff line change
Expand Up @@ -287,7 +287,7 @@ A 14px circle (16px on the landing page) centered on a 2px vertical line. The se
Centered in the feed: a mono `fatal: …` line in Muted Ink, then one or two plain sentences (15px, max 24rem) with a single Commit Blue link when there is somewhere to go.

### Onboarding
A standalone page (no app shell) after a new account's first sign-in, drawn as a short history on the rail: one row per step with a mono prompt (`$ whoami`, `$ export LANE=teal`, `$ who --should-i-follow`, `$ man devnull`) and a hollow `$ git log` row at the end. Done steps are filled nodes on a solid lane segment with a one-line summary, the current step's node pops in (`node-in`) above a dashed Rail Gray tail and expands into a 1.5rem heading, a muted sentence, its content, and a primary action with a ghost Back; later steps are hollow Rail Gray nodes. The whole rail takes the lane being picked, live. Steps reuse the settings profile list, the color preview and swatches, the suggested-developer rows, and the shortcut sheet. "Skip setup" with an `esc` cap sits top right; Esc skips from any step unless a dialog is open; focus moves to each step's heading.
A standalone page (no app shell) after a new account's first sign-in, drawn as a short history on the rail: one row per step with a mono prompt (`$ whoami`, `$ export LANE=teal`, `$ who --should-i-follow`, `$ man devnull`) and a hollow `$ git log` row at the end. Done steps are filled nodes on a solid lane segment with a one-line summary, the current step's node pops in (`node-in`) above a dashed Rail Gray tail and expands into a 1.5rem heading, a muted sentence, its content, and a primary action with a ghost Back; later steps are hollow Rail Gray nodes. The whole rail takes the lane being picked, live. Steps reuse the settings profile list, the color preview and swatches, the suggested-developer rows, and the shortcut sheet. Above the suggestions, the follow step shows what the GitHub import brought over in one hairline panel under a mono `imported from github.com/{handle}` line: a big mono count each for following and followers that ticks up from zero while the faces behind it pop in with `node-in`, each pulsing in its own lane, then the GitHub accounts still to join, with an invite. A spinner line stands in while the import runs, and the panel is left out when GitHub brought nothing. "Skip setup" with an `esc` cap sits top right; Esc skips from any step unless a dialog is open; focus moves to each step's heading.

### Operations Console
Operations opens in place but is a separate app: no log nav, aside or composer (only the docked remotes follow), just the wordmark with a bordered mono `ops` chip. From lg a 240px Feed White sidebar groups the pages under mono labels (`monitor`: Overview, Health, Events; `product`: Forecasts, Growth, Activity, and Traffic with a Fathom token; `control`: Features; `elsewhere`: Moderation), with the active page on the Blue Wash like the side nav, and ends with the theme switch and a "Back to /dev/null" row with the admin's avatar and handle. Below lg the same pages, then Moderation, scroll sideways under the sticky header, with the current one scrolled into view, and the admin's avatar on the right of the header leads back to /dev/null. The header names the page and says in one line what it answers; on the right a mono live toggle (a pulsing Success dot and `15s`, or a Rail Gray dot and `paused`) and the refresh icon. Pages that move by the day (Forecasts, Growth) read `on demand` instead and only refresh from the icon.
Expand Down
2 changes: 1 addition & 1 deletion KNOWLEDGE_BASE.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ Livestream history: the team agreed on GitHub-only sign-in and importing profile

### First-time setup

The first GitHub sign-in opens a short onboarding flow: review your mirrored profile (after editing it on GitHub, **Sync from GitHub** pulls the changes in without leaving setup), choose a color, follow suggested developers, and learn about the composer, keyboard shortcuts, and terminal commits. Skip setup at any step or finish it to continue to the app. Completed or skipped setup does not appear again. New users also start with Tom as a mutual follow; Tom is the platform's fictional welcome bot. Tag @tom in a public commit to ask about the platform or find posts on a topic.
The first GitHub sign-in opens a short onboarding flow: review your mirrored profile (after editing it on GitHub, **Sync from GitHub** pulls the changes in without leaving setup), choose a color, see who came over from your GitHub network and follow suggested developers, and learn about the composer, keyboard shortcuts, and terminal commits. Skip setup at any step or finish it to continue to the app. The follow step shows what the one-time GitHub import brought over: the people you follow on GitHub who are already on /dev/null, whom you now follow, and your GitHub followers who are here, who now follow you. Completed or skipped setup does not appear again. New users also start with Tom as a mutual follow; Tom is the platform's fictional welcome bot. Tag @tom in a public commit to ask about the platform or find posts on a topic.

Sources: [onboarding page](resources/js/pages/onboarding/show.tsx), [sign-in tests](tests/Feature/Controllers/SessionControllerTest.php).

Expand Down
30 changes: 30 additions & 0 deletions app/Http/Controllers/OnboardingController.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
use App\Models\User;
use App\Queries\SuggestedUsersQuery;
use Illuminate\Container\Attributes\CurrentUser;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Http\RedirectResponse;
use Illuminate\Support\Collection;
use Inertia\Inertia;
Expand All @@ -22,6 +23,7 @@ public function show(ShowOnboardingRequest $request, #[CurrentUser] User $user,
'preferredLane' => $user->preferredLane(),
'automaticLane' => $user->automaticLane(),
'suggestions' => fn (): Collection => $suggested->get($user, limit: 5),
'githubImport' => fn (): ?array => $this->githubImport($request, $user),
'commitScriptUrl' => route('cli-script.show'),
]);
}
Expand All @@ -35,4 +37,32 @@ public function update(#[CurrentUser] User $user, UpdateUserOnboardedAt $action)

return redirect()->intended(route('log.show', $user->log, absolute: false));
}

/**
* What the GitHub import brought over: null until the job has run. The follows it made share its timestamp, give
* or take the time the job took. Tom's friendship is made at sign-up too, right before, so bots are left out.
*
* @return array{following: Collection<int, User>, followingCount: int, followers: Collection<int, User>, followersCount: int, pendingCount: int}|null
*/
private function githubImport(ShowOnboardingRequest $request, User $user): ?array
{
$importedAt = $user->github_follows_imported_at;

if ($importedAt === null) {
return null;
}

$imported = fn (BelongsToMany $follows): BelongsToMany => $follows
->wherePivotBetween('created_at', [$importedAt->copy()->subSeconds(10), $importedAt])
->whereNotIn('users.github_id', User::BOT_GITHUB_IDS);

return [
'following' => $imported($user->following())->oldest('users.id')->limit(5)->get(),
'followingCount' => $imported($user->following())->count(),
'followers' => $imported($user->followers())->oldest('users.id')->limit(5)->get(),
'followersCount' => $imported($user->followers())->count(),
// SKETCH: pending follows aren't stored yet (see the pending_follows table of feat/unclaimed-profiles).
'pendingCount' => app()->isLocal() ? $request->integer('pending') : 0,
];
}
}
1 change: 1 addition & 0 deletions database/factories/UserFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ public function definition(): array
'lane_color' => null,
'pinned_commit_id' => null,
'onboarded_at' => now(),
'github_follows_imported_at' => null,
'commit_rules_accepted_at' => now(),
'remember_token' => Str::random(10),
];
Expand Down
Loading
Loading