Skip to content

Commit ab29052

Browse files
authored
Merge pull request #1 from opensource-observer/carl/oso-1926-create-a-standalone-ddp-public-repo-and-ensure-it-works
initial commit
2 parents 7ff96e1 + a4ceece commit ab29052

74 files changed

Lines changed: 18678 additions & 0 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.env.example

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# OSO API Key
2+
# Get your API key from https://www.oso.xyz/start
3+
OSO_API_KEY=your_api_key_here

.gitignore

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# Local cache
2+
__marimo__
3+
4+
# Python
5+
.venv/
6+
__pycache__/
7+
*.py[cod]
8+
9+
# Environment variables
10+
.env
11+
.env.local
12+
13+
# Next.js
14+
app/.next/
15+
app/out/
16+
app/node_modules/
17+
18+
# OS
19+
.DS_Store
20+
21+
# Claude Code local settings
22+
.claude/

README.md

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
# Developer Data Portal
2+
3+
A data portal that serves Marimo notebooks through a Next.js interface. Built on [OSO](https://www.oso.xyz).
4+
5+
## Quickstart
6+
7+
```bash
8+
# 1. Get an OSO API key at https://www.oso.xyz/start
9+
cp .env.example .env
10+
# Add your key: OSO_API_KEY=your_key_here
11+
12+
# 2. Install dependencies
13+
uv sync
14+
cd app && pnpm install && cd ..
15+
16+
# 3. Start
17+
cd app && pnpm dev:all
18+
```
19+
20+
Open http://localhost:3000.
21+
22+
## Prerequisites
23+
24+
- OSO API key ([get one here](https://www.oso.xyz/start))
25+
- [uv](https://docs.astral.sh/uv/) — Python package manager
26+
- Node.js 20+ and [pnpm](https://pnpm.io/)
27+
28+
## Structure
29+
30+
```
31+
ddp/
32+
├── notebooks/ # Marimo notebooks (.py)
33+
│ ├── home.py
34+
│ ├── quick-start.py
35+
│ ├── publications.py
36+
│ ├── agent-guide.py
37+
│ ├── data/
38+
│ │ ├── sources/ # Open Dev Data, GitHub Archive, OSS Directory
39+
│ │ ├── models/ # Ecosystems, Repositories, Developers, Commits, Events, Timeseries Metrics
40+
│ │ └── metric-definitions/ # Activity, Alignment, Lifecycle, Retention
41+
│ └── insights/ # 2025 Developer Trends, Lifecycle, Speedrun Ethereum, DeFi Journeys, Retention
42+
├── app/ # Next.js app (UI shell)
43+
│ ├── app/ # Pages (App Router)
44+
│ └── components/ # Sidebar, MarimoIframe
45+
├── serve_notebooks.py # Marimo ASGI server (port 8000)
46+
└── pyproject.toml
47+
```
48+
49+
## How it works
50+
51+
- **Marimo server** (`localhost:8000`) — runs notebook kernels via `serve_notebooks.py`
52+
- **Next.js app** (`localhost:3000`) — navigation shell that embeds notebooks in iframes
53+
54+
Each page in the Next.js app is a thin wrapper around a `MarimoIframe` component:
55+
56+
```tsx
57+
<MarimoIframe notebookName="notebooks/insights/developer-lifecycle" />
58+
```
59+
60+
## Adding a notebook
61+
62+
1. Create `notebooks/<category>/<name>.py` using the standard template below
63+
2. Add a page at `app/app/<category>/<name>/page.tsx`
64+
3. Add a nav entry to `app/components/Sidebar.tsx`
65+
66+
### Notebook template
67+
68+
```python
69+
import marimo
70+
71+
__generated_with = "unknown"
72+
app = marimo.App(width="full")
73+
74+
@app.cell(hide_code=True)
75+
def setup_pyoso():
76+
# This code sets up pyoso to be used as a database provider for this notebook
77+
# This code is autogenerated. Modification could lead to unexpected results :)
78+
import pyoso
79+
import marimo as mo
80+
pyoso_db_conn = pyoso.Client().dbapi_connection()
81+
return mo, pyoso_db_conn
82+
83+
# Add cells here
84+
85+
if __name__ == "__main__":
86+
app.run()
87+
```
88+
89+
For detailed notebook conventions, see [`notebooks/claude.md`](notebooks/claude.md).
90+
91+
## Running servers separately
92+
93+
```bash
94+
# Terminal 1 — Marimo
95+
uv run python serve_notebooks.py
96+
97+
# Terminal 2 — Next.js
98+
cd app && pnpm dev
99+
```
100+
101+
Notebooks are served at `http://localhost:8000/notebooks/<name>` — Marimo must be running for iframes to render.
102+
103+
## Configuration
104+
105+
| Variable | Description |
106+
|----------|-------------|
107+
| `OSO_API_KEY` | Required. OSO data warehouse access key. |
108+
109+
The Marimo port defaults to `8000`. To change it, update `serve_notebooks.py` and the `marimoPort` prop on `MarimoIframe` in any relevant pages.

app/app/agent-guide/page.tsx

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import MarimoIframe from '@/components/MarimoIframe';
2+
3+
export default function AgentGuide() {
4+
return (
5+
<div className="h-full w-full">
6+
<MarimoIframe notebookName="notebooks/agent-guide" />
7+
</div>
8+
);
9+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import MarimoIframe from '@/components/MarimoIframe';
2+
3+
export default function Activity() {
4+
return (
5+
<div className="h-full w-full">
6+
<MarimoIframe notebookName="notebooks/data/metric-definitions/activity" />
7+
</div>
8+
);
9+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import MarimoIframe from '@/components/MarimoIframe';
2+
3+
export default function Alignment() {
4+
return (
5+
<div className="h-full w-full">
6+
<MarimoIframe notebookName="notebooks/data/metric-definitions/alignment" />
7+
</div>
8+
);
9+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import MarimoIframe from '@/components/MarimoIframe';
2+
3+
export default function Lifecycle() {
4+
return (
5+
<div className="h-full w-full">
6+
<MarimoIframe notebookName="notebooks/data/metric-definitions/lifecycle" />
7+
</div>
8+
);
9+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import MarimoIframe from '@/components/MarimoIframe';
2+
3+
export default function Retention() {
4+
return (
5+
<div className="h-full w-full">
6+
<MarimoIframe notebookName="notebooks/data/metric-definitions/retention" />
7+
</div>
8+
);
9+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import MarimoIframe from '@/components/MarimoIframe';
2+
3+
export default function Commits() {
4+
return (
5+
<div className="h-full w-full">
6+
<MarimoIframe notebookName="notebooks/data/models/commits" />
7+
</div>
8+
);
9+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import MarimoIframe from '@/components/MarimoIframe';
2+
3+
export default function Developers() {
4+
return (
5+
<div className="h-full w-full">
6+
<MarimoIframe notebookName="notebooks/data/models/developers" />
7+
</div>
8+
);
9+
}

0 commit comments

Comments
 (0)