Skip to content

Commit 26f086c

Browse files
committed
Solid re-design of home / about / profile / press pages
1 parent 2576bb3 commit 26f086c

37 files changed

Lines changed: 4449 additions & 1110 deletions

android/app/build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ android {
1111
applicationId "com.compassconnections.app"
1212
minSdkVersion rootProject.ext.minSdkVersion
1313
targetSdkVersion rootProject.ext.targetSdkVersion
14-
versionCode 134
14+
versionCode 135
1515
versionName "1.32.0"
1616
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
1717
aaptOptions {

backend/api/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@compass/api",
3-
"version": "1.51.0",
3+
"version": "1.52.0",
44
"private": true,
55
"description": "Backend API endpoints",
66
"main": "src/serve.ts",

common/messages/de.json

Lines changed: 187 additions & 1 deletion
Large diffs are not rendered by default.

common/messages/fr.json

Lines changed: 187 additions & 1 deletion
Large diffs are not rendered by default.

common/src/constants.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,26 @@ export const formLink = 'https://forms.gle/tKnXUMAbEreMK6FC6'
2121
export const ANDROID_APP_URL =
2222
'https://play.google.com/store/apps/details?id=com.compassconnections.app'
2323

24+
/**
25+
* What Compass has cost and what it has been given, in USD, since launch.
26+
*
27+
* Lives here rather than in either page because the home strip and the about page both state it, and two
28+
* copies of a number that is the whole point of the transparency argument would be the one place it must
29+
* not drift. The authoritative breakdown is `web/public/md/financials.md` and the spreadsheet it links;
30+
* update all of them together.
31+
*
32+
* Not queried live: unlike the member count there is no endpoint behind it, and inventing one to avoid a
33+
* constant would put a bookkeeping figure on a page-load path.
34+
*/
35+
export const FINANCIALS = {
36+
spent: 457,
37+
donated: 145,
38+
/** Covered out of pocket by the founder — kept derived so it can never disagree with the two above. */
39+
get deficit() {
40+
return this.spent - this.donated
41+
},
42+
}
43+
2444
export const IS_MAINTENANCE = false // set to true to enable the maintenance mode banner
2545

2646
export const MIN_BIO_LENGTH = 250

docs/marketing-copy.md

Lines changed: 527 additions & 0 deletions
Large diffs are not rendered by default.

tests/e2e/utils/seed-showcase.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ const DEFAULT_AVATAR = '/images/default-avatar.png'
5858
* Missing portraits are not fatal: the profile still seeds, it just wears the default avatar.
5959
*
6060
* `pinned_url` and `photo_urls` are disjoint: the pinned photo must NOT also appear in `photo_urls`.
61-
* `ProfileCarousel` renders `buildArray(pinned_url, photo_urls)` without deduping, so a shared entry
61+
* `ProfileGallery` renders `buildArray(pinned_url, photo_urls)` without deduping, so a shared entry
6262
* shows up twice. (The photo editor wraps the same call in `uniq`, which masks it while editing.)
6363
*/
6464
function resolvePhotos(profile: ShowcaseProfile) {

tests/e2e/web/pages/profilePage.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,8 +88,10 @@ export class ProfilePage {
8888
this.ethnicityAboutSection = page.getByTestId('profile-content')
8989
this.dietAboutSection = page.getByTestId('profile-content')
9090
this.languagesAboutSection = page.getByTestId('profile-content')
91-
this.seekingAboutSection = page.getByTestId('profile-content')
92-
this.relationshipStatusAboutSection = page.getByTestId('profile-content')
91+
// Connection goals moved out of the Details rail into the hero callout: they decide whether the
92+
// rest of the profile is relevant at all, so they sit above the fold.
93+
this.seekingAboutSection = page.getByTestId('profile-connection-goals')
94+
this.relationshipStatusAboutSection = page.getByTestId('profile-connection-goals')
9395
this.educationAboutSection = page.getByTestId('profile-content')
9496
this.occupationAboutSection = page.getByTestId('profile-content')
9597
this.workAreaAboutSection = page.getByTestId('profile-content')

web/components/about/platform-stats.tsx

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -136,9 +136,14 @@ export function StatBand() {
136136
return () => observer.disconnect()
137137
}, [armed, node, run])
138138

139-
const showCountries = !!data && data.countryCount > 1
139+
// Countries used to be the second stat here and is now gone. Fifty-five countries across ~700 members is
140+
// *dispersion*, not reach — it is the figure that quietly says "nobody near you" while presenting itself
141+
// as an achievement, and it was the second thing on the page. Messages sits beside conversations instead
142+
// and answers the question a visitor is actually asking of a small platform: does anyone reply. The full
143+
// country breakdown still lives on /stats, where someone came to read numbers.
140144
const showConversations = !!data && data.conversations > 0
141-
const lastDelay = STAGGER_MS * ((showCountries ? 1 : 0) + (showConversations ? 1 : 0))
145+
const showMessages = !!data && data.messages > 0
146+
const lastDelay = STAGGER_MS * ((showConversations ? 1 : 0) + (showMessages ? 1 : 0))
142147

143148
useEffect(() => {
144149
if (!run) return
@@ -163,18 +168,18 @@ export function StatBand() {
163168
delay={0}
164169
run={run}
165170
/>
166-
{showCountries && (
171+
{showConversations && (
167172
<CountingStat
168-
target={data.countryCount}
169-
label={t('about.stat.countries', 'Countries')}
173+
target={data.conversations}
174+
label={t('about.stat.conversations', 'Conversations')}
170175
delay={next()}
171176
run={run}
172177
/>
173178
)}
174-
{showConversations && (
179+
{showMessages && (
175180
<CountingStat
176-
target={data.conversations}
177-
label={t('about.stat.conversations', 'Conversations')}
181+
target={data.messages}
182+
label={t('about.stat.messages', 'Messages')}
178183
delay={next()}
179184
run={run}
180185
/>
@@ -198,6 +203,13 @@ export function StatBand() {
198203
</span>
199204
}
200205
/>
206+
{/* One line, and only one. An earlier draft added a sentence here about how thinly the membership is
207+
spread; it was cut because this is the page's second element and the reader has not yet been given
208+
a single reason to want in — self-criticism before value is just discouragement. The same point is
209+
made properly on the home page, attached to something to do about it. */}
210+
<p className="w-full text-sm text-ink-500">
211+
{t('about.stat.caption', 'Read live from the database, not from a press kit.')}
212+
</p>
201213
</div>
202214
)
203215
}

web/components/answers/answer-compatibility-question-button.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,10 @@ export function AnswerCompatibilityQuestionButton(props: {
5353
) : (
5454
<button
5555
onClick={() => setOpen(true)}
56-
className="bg-ink-100 dark:bg-ink-300 text-ink-1000 hover:bg-ink-200 hover:dark:bg-ink-400 w-28 rounded-full px-2 py-0.5 text-xs transition-colors"
56+
// Matches the outlined importance/compatibility pills it sits beside in a prompt. It was the
57+
// only solid one of the three, which read as the loudest thing in a block it is not about.
58+
className="font-dm-sans border-canvas-300 text-ink-600 hover:border-primary-400 hover:bg-primary-50 h-fit whitespace-nowrap rounded-full border px-2.5 py-1 uppercase transition-colors"
59+
style={{fontSize: '10px', letterSpacing: '0.12em'}}
5760
>
5861
{t('answers.answer.answer_yourself', 'Answer yourself')}
5962
</button>

0 commit comments

Comments
 (0)