Skip to content

Commit ca01da7

Browse files
authored
Improve feature list UI, update readme (growthbook#244)
* Improve display of non-boolean features in feature list * Update readme screenshot and text * Improve override rule column * Add in-app help for GrowthBook Cloud * Switch to new env-scoped API keys for GrowthBook SDK
1 parent c758961 commit ca01da7

File tree

8 files changed

+78
-17
lines changed

8 files changed

+78
-17
lines changed

README.md

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
<p align="center"><a href="https://www.growthbook.io"><img src="https://www.growthbook.io/logos/[email protected]" width="400px" alt="GrowthBook - The Open Source A/B Testing Platform" /></a></p>
2-
<p align="center"><b>The Open Source A/B Testing and Feature Flagging Platform</b></p>
1+
<p align="center"><a href="https://www.growthbook.io"><img src="https://www.growthbook.io/logos/[email protected]" width="400px" alt="GrowthBook - Open Source Feature Flagging and A/B Testing" /></a></p>
2+
<p align="center"><b>Open Source Feature Flagging and A/B Testing</b></p>
33
<p align="center">
44
<a href="https://github.com/growthbook/growthbook/actions/workflows/ci.yml"><img src="https://img.shields.io/github/workflow/status/growthbook/growthbook/CI" alt="Build Status" height="22"/></a>
55
<a href="https://github.com/growthbook/growthbook/blob/main/LICENSE"><img src="https://img.shields.io/github/license/growthbook/growthbook" alt="MIT License" height="22"/></a>
@@ -17,27 +17,25 @@ docker-compose up -d
1717

1818
Then visit http://localhost:3000
1919

20-
[![GrowthBook Screenshot](/growthbook-screenshot.png)](https://www.growthbook.io)
20+
[![GrowthBook Screenshot](/features-screenshot.png)](https://www.growthbook.io)
2121

2222
## Our Philosophy
2323

24-
The top 1% of companies spend thousands of hours building their own A/B testing and feature flagging platforms in-house.
24+
The top 1% of companies spend thousands of hours building their own feature flagging and A/B testing platforms in-house.
2525
The other 99% are left paying for expensive 3rd party SaaS tools or hacking together unmaintained open source libraries.
2626

27-
GrowthBook gives you the flexibility and power of a fully-featured in-house platform without needing to build it yourself.
27+
We want to give all companies the flexibility and power of a fully-featured in-house platform without needing to build it themselves.
2828

2929
## Major Features
3030

31-
- ❄️ Pull data from Snowflake, Redshift, BigQuery, Mixpanel, Google Analytics, [and more](https://docs.growthbook.io/app/datasources)
32-
- 🆎 Bayesian statistics engine with support for binomial, count, duration, and revenue metrics
33-
- ⬇️ Drill down into A/B test results by browser, country, or any other attribute
34-
- 🪐 Export results as a Jupyter Notebook!
31+
- 🏁 Feature flags with advanced targeting, gradual rollouts, and experiments
3532
- 💻 SDKs for [React](https://docs.growthbook.io/lib/react), [Javascript](https://docs.growthbook.io/lib/js), [PHP](https://docs.growthbook.io/lib/php), [Ruby](https://docs.growthbook.io/lib/ruby), [Python](https://docs.growthbook.io/lib/python), [Go](https://docs.growthbook.io/lib/go), and [Kotlin (Android)](https://docs.growthbook.io/lib/kotlin) with more coming soon
36-
- 🏁 Feature flags with targeting, gradual rollouts, and experiments
37-
- 👁️ [Visual Editor](https://docs.growthbook.io/app/visual) for non-technical users to create experiments _(beta)_
38-
- 📝 Document experiments with screenshots and GitHub Flavored Markdown
39-
- 🔔 Automated email alerts when tests become significant
40-
- 💡 Lightweight idea board and objective prioritization framework
33+
- 🆎 Powerful A/B test analysis with support for binomial, count, duration, and revenue metrics
34+
- ❄️ Use your existing data stack - BigQuery, Mixpanel, Redshift, Google Analytics, [and more](https://docs.growthbook.io/app/datasources)
35+
- ⬇️ Drill down into A/B test results by browser, country, or any other custom attribute
36+
- 🪐 Export reports as a Jupyter Notebook!
37+
- 📝 Document everything with screenshots and GitHub Flavored Markdown throughout
38+
- 🔔 Automated email alerts when A/B tests become significant
4139

4240
## Try GrowthBook
4341

features-screenshot.png

89.5 KB
Loading
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import { useFeature } from "@growthbook/growthbook-react";
2+
import { useEffect } from "react";
3+
import useUser from "../../hooks/useUser";
4+
import { isCloud } from "../../services/env";
5+
6+
export default function InAppHelp() {
7+
const config = useFeature("papercups-config").value;
8+
const { name, email, userId } = useUser();
9+
useEffect(() => {
10+
if (!isCloud() || !config) return;
11+
if (window["Papercups"]) return;
12+
window["Papercups"] = {
13+
config: {
14+
...config,
15+
customer: {
16+
name,
17+
email,
18+
external_id: userId,
19+
},
20+
},
21+
};
22+
const s = document.createElement("script");
23+
s.async = true;
24+
s.src = config.baseUrl + "/widget.js";
25+
document.head.appendChild(s);
26+
}, [config]);
27+
28+
return null;
29+
}

packages/front-end/components/Features/FeatureList.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ export default function FeatureList({ features }: Props) {
3232
<ValueDisplay
3333
value={feature.defaultValue}
3434
type={feature.valueType}
35+
full={false}
3536
/>
3637
</div>
3738
</div>

packages/front-end/components/Features/ValueDisplay.tsx

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,11 @@ import stringify from "json-stringify-pretty-compact";
66
export default function ValueDisplay({
77
value,
88
type,
9+
full = true,
910
}: {
1011
value: string;
1112
type: FeatureValueType;
13+
full?: boolean;
1214
}) {
1315
const formatted = useMemo(() => {
1416
if (type === "boolean") return value;
@@ -39,6 +41,22 @@ export default function ValueDisplay({
3941
);
4042
}
4143

44+
if (!full) {
45+
return (
46+
<div
47+
style={{
48+
textOverflow: "ellipsis",
49+
overflow: "hidden",
50+
maxWidth: "180px",
51+
whiteSpace: "nowrap",
52+
}}
53+
className="text-muted"
54+
>
55+
{formatted}
56+
</div>
57+
);
58+
}
59+
4260
return (
4361
<div style={{ maxHeight: 150, overflowY: "auto" }}>
4462
<Code

packages/front-end/components/ProtectedPage.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import { OrganizationSettings } from "back-end/types/organization";
1313
import { useGrowthBook } from "@growthbook/growthbook-react";
1414
import { useRouter } from "next/router";
1515
import { isCloud } from "../services/env";
16+
import InAppHelp from "./Auth/InAppHelp";
1617

1718
type User = { id: string; email: string; name: string };
1819

@@ -212,6 +213,7 @@ const ProtectedPage: React.FC<{
212213

213214
return (
214215
<UserContext.Provider value={userContextValue} key={orgId}>
216+
<InAppHelp />
215217
{orgId ? (
216218
<WatchProvider>{children}</WatchProvider>
217219
) : (

packages/front-end/pages/_app.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,8 @@ function App({
5656
}, [ready]);
5757

5858
useEffect(() => {
59-
// Load feature definitions JSON (from API, database, etc.)
60-
fetch("https://cdn.growthbook.io/api/features/key_486336ff87c125f4")
59+
// Load feature definitions JSON from GrowthBook API
60+
fetch("https://cdn.growthbook.io/api/features/key_prod_cb40dfcb0eb98e44")
6161
.then((res) => res.json())
6262
.then((json) => {
6363
growthbook.setFeatures(json.features);

packages/front-end/pages/features/index.tsx

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,9 @@ export default function FeaturesPage() {
155155
</thead>
156156
<tbody>
157157
{sorted.map((feature) => {
158+
const firstRule = feature.rules?.[0];
159+
const totalRules = feature.rules?.length || 0;
160+
158161
return (
159162
<tr key={feature.id}>
160163
<td>
@@ -180,9 +183,19 @@ export default function FeaturesPage() {
180183
<ValueDisplay
181184
value={feature.defaultValue}
182185
type={feature.valueType}
186+
full={false}
183187
/>
184188
</td>
185-
<td>{feature.rules?.length > 0 ? "yes" : "no"}</td>
189+
<td>
190+
{firstRule && (
191+
<span className="text-dark">{firstRule.type}</span>
192+
)}
193+
{totalRules > 1 && (
194+
<small className="text-muted ml-1">
195+
+{totalRules - 1} more
196+
</small>
197+
)}
198+
</td>
186199
<td title={datetime(feature.dateUpdated)}>
187200
{ago(feature.dateUpdated)}
188201
</td>

0 commit comments

Comments
 (0)