init from demo
This commit is contained in:
commit
b94c19a64d
13 changed files with 4270 additions and 0 deletions
4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
.DS_Store
|
||||||
|
/dist/
|
||||||
|
node_modules/
|
||||||
|
yarn-error.log
|
59
README.md
Normal file
59
README.md
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
# Vrg Archive
|
||||||
|
|
||||||
|
This is an [Observable Framework](https://observablehq.com/framework/) app. To install the required dependencies, run:
|
||||||
|
|
||||||
|
```
|
||||||
|
npm install
|
||||||
|
```
|
||||||
|
|
||||||
|
Then, to start the local preview server, run:
|
||||||
|
|
||||||
|
```
|
||||||
|
npm run dev
|
||||||
|
```
|
||||||
|
|
||||||
|
Then visit <http://localhost:3000> to preview your app.
|
||||||
|
|
||||||
|
For more, see <https://observablehq.com/framework/getting-started>.
|
||||||
|
|
||||||
|
## Project structure
|
||||||
|
|
||||||
|
A typical Framework project looks like this:
|
||||||
|
|
||||||
|
```ini
|
||||||
|
.
|
||||||
|
├─ src
|
||||||
|
│ ├─ components
|
||||||
|
│ │ └─ timeline.js # an importable module
|
||||||
|
│ ├─ data
|
||||||
|
│ │ ├─ launches.csv.js # a data loader
|
||||||
|
│ │ └─ events.json # a static data file
|
||||||
|
│ ├─ example-dashboard.md # a page
|
||||||
|
│ ├─ example-report.md # another page
|
||||||
|
│ └─ index.md # the home page
|
||||||
|
├─ .gitignore
|
||||||
|
├─ observablehq.config.js # the app config file
|
||||||
|
├─ package.json
|
||||||
|
└─ README.md
|
||||||
|
```
|
||||||
|
|
||||||
|
**`src`** - This is the “source root” — where your source files live. Pages go here. Each page is a Markdown file. Observable Framework uses [file-based routing](https://observablehq.com/framework/project-structure#routing), which means that the name of the file controls where the page is served. You can create as many pages as you like. Use folders to organize your pages.
|
||||||
|
|
||||||
|
**`src/index.md`** - This is the home page for your app. You can have as many additional pages as you’d like, but you should always have a home page, too.
|
||||||
|
|
||||||
|
**`src/data`** - You can put [data loaders](https://observablehq.com/framework/data-loaders) or static data files anywhere in your source root, but we recommend putting them here.
|
||||||
|
|
||||||
|
**`src/components`** - You can put shared [JavaScript modules](https://observablehq.com/framework/imports) anywhere in your source root, but we recommend putting them here. This helps you pull code out of Markdown files and into JavaScript modules, making it easier to reuse code across pages, write tests and run linters, and even share code with vanilla web applications.
|
||||||
|
|
||||||
|
**`observablehq.config.js`** - This is the [app configuration](https://observablehq.com/framework/config) file, such as the pages and sections in the sidebar navigation, and the app’s title.
|
||||||
|
|
||||||
|
## Command reference
|
||||||
|
|
||||||
|
| Command | Description |
|
||||||
|
| ----------------- | -------------------------------------------------------- |
|
||||||
|
| `npm install` | Install or reinstall dependencies |
|
||||||
|
| `npm run dev` | Start local preview server |
|
||||||
|
| `npm run build` | Build your static site, generating `./dist` |
|
||||||
|
| `npm run deploy` | Deploy your app to Observable |
|
||||||
|
| `npm run clean` | Clear the local data loader cache |
|
||||||
|
| `npm run observable` | Run commands like `observable help` |
|
38
observablehq.config.js
Normal file
38
observablehq.config.js
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
// See https://observablehq.com/framework/config for documentation.
|
||||||
|
export default {
|
||||||
|
// The app’s title; used in the sidebar and webpage titles.
|
||||||
|
title: "Vrg Archive",
|
||||||
|
|
||||||
|
// The pages and sections in the sidebar. If you don’t specify this option,
|
||||||
|
// all pages will be listed in alphabetical order. Listing pages explicitly
|
||||||
|
// lets you organize them into sections and have unlisted pages.
|
||||||
|
// pages: [
|
||||||
|
// {
|
||||||
|
// name: "Examples",
|
||||||
|
// pages: [
|
||||||
|
// {name: "Dashboard", path: "/example-dashboard"},
|
||||||
|
// {name: "Report", path: "/example-report"}
|
||||||
|
// ]
|
||||||
|
// }
|
||||||
|
// ],
|
||||||
|
|
||||||
|
// Content to add to the head of the page, e.g. for a favicon:
|
||||||
|
head: '<link rel="icon" href="observable.png" type="image/png" sizes="32x32">',
|
||||||
|
|
||||||
|
// The path to the source root.
|
||||||
|
root: "src",
|
||||||
|
|
||||||
|
// Some additional configuration options and their defaults:
|
||||||
|
// theme: "default", // try "light", "dark", "slate", etc.
|
||||||
|
// header: "", // what to show in the header (HTML)
|
||||||
|
// footer: "Built with Observable.", // what to show in the footer (HTML)
|
||||||
|
// sidebar: true, // whether to show the sidebar
|
||||||
|
// toc: true, // whether to show the table of contents
|
||||||
|
// pager: true, // whether to show previous & next links in the footer
|
||||||
|
// output: "dist", // path to the output root for build
|
||||||
|
// search: true, // activate search
|
||||||
|
// linkify: true, // convert URLs in Markdown to links
|
||||||
|
// typographer: false, // smart quotes and other typographic improvements
|
||||||
|
// preserveExtension: false, // drop .html from URLs
|
||||||
|
// preserveIndex: false, // drop /index from URLs
|
||||||
|
};
|
3776
package-lock.json
generated
Normal file
3776
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load diff
22
package.json
Normal file
22
package.json
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
{
|
||||||
|
"type": "module",
|
||||||
|
"private": true,
|
||||||
|
"scripts": {
|
||||||
|
"clean": "rimraf src/.observablehq/cache",
|
||||||
|
"build": "observable build",
|
||||||
|
"dev": "observable preview",
|
||||||
|
"deploy": "observable deploy",
|
||||||
|
"observable": "observable"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@observablehq/framework": "^1.13.2",
|
||||||
|
"d3-dsv": "^3.0.1",
|
||||||
|
"d3-time-format": "^4.1.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"rimraf": "^5.0.5"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
}
|
||||||
|
}
|
1
src/.gitignore
vendored
Normal file
1
src/.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
/.observablehq/cache/
|
16
src/components/timeline.js
Normal file
16
src/components/timeline.js
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
import * as Plot from "npm:@observablehq/plot";
|
||||||
|
|
||||||
|
export function timeline(events, {width, height} = {}) {
|
||||||
|
return Plot.plot({
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
marginTop: 30,
|
||||||
|
x: {nice: true, label: null, tickFormat: ""},
|
||||||
|
y: {axis: null},
|
||||||
|
marks: [
|
||||||
|
Plot.ruleX(events, {x: "year", y: "y", markerEnd: "dot", strokeWidth: 2.5}),
|
||||||
|
Plot.ruleY([0]),
|
||||||
|
Plot.text(events, {x: "year", y: "y", text: "name", lineAnchor: "bottom", dy: -10, lineWidth: 10, fontSize: 12})
|
||||||
|
]
|
||||||
|
});
|
||||||
|
}
|
8
src/data/events.json
Normal file
8
src/data/events.json
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
[
|
||||||
|
{"name": "Sputnik 1", "year": 1957, "y": 10},
|
||||||
|
{"name": "Apollo 11", "year": 1969, "y": 20},
|
||||||
|
{"name": "Viking 1 and 2", "year": 1975, "y": 30},
|
||||||
|
{"name": "Space Shuttle Columbia", "year": 1981, "y": 40},
|
||||||
|
{"name": "Hubble Space Telescope", "year": 1990, "y": 50},
|
||||||
|
{"name": "ISS Construction", "year": 1998, "y": 60}
|
||||||
|
]
|
61
src/data/launches.csv.js
Normal file
61
src/data/launches.csv.js
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
import {csvFormat, tsvParse} from "d3-dsv";
|
||||||
|
import {utcParse} from "d3-time-format";
|
||||||
|
|
||||||
|
async function text(url) {
|
||||||
|
const response = await fetch(url);
|
||||||
|
if (!response.ok) throw new Error(`fetch failed: ${response.status}`);
|
||||||
|
return response.text();
|
||||||
|
}
|
||||||
|
|
||||||
|
// “Top” vehicles
|
||||||
|
const TOP_LAUNCH_VEHICLES = new Set([
|
||||||
|
"Falcon9",
|
||||||
|
"R-7",
|
||||||
|
"R-14",
|
||||||
|
"Thor",
|
||||||
|
"DF5",
|
||||||
|
"R-36",
|
||||||
|
"Proton",
|
||||||
|
"Titan",
|
||||||
|
"Zenit",
|
||||||
|
"Atlas"
|
||||||
|
]);
|
||||||
|
|
||||||
|
// “Top” launching states
|
||||||
|
const TOP_STATES_MAP = new Map([
|
||||||
|
["US", "United States"],
|
||||||
|
["SU", "Soviet Union"],
|
||||||
|
["RU", "Russia"],
|
||||||
|
["CN", "China"]
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Load and parse launch vehicles.
|
||||||
|
const launchVehicles = tsvParse(await text("https://planet4589.org/space/gcat/tsv/tables/lv.tsv"));
|
||||||
|
|
||||||
|
// Construct map to lookup vehicle family from name.
|
||||||
|
const launchVehicleFamilyMap = new Map(launchVehicles.map((d) => [d["#LV_Name"], d.LV_Family.trim()]));
|
||||||
|
|
||||||
|
// Reduce cardinality by mapping smaller states to “Other”.
|
||||||
|
function normalizeState(d) {
|
||||||
|
return TOP_STATES_MAP.get(d) ?? "Other";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reduce cardinality by mapping smaller launch families to “Other”.
|
||||||
|
function normalizeFamily(d) {
|
||||||
|
const family = launchVehicleFamilyMap.get(d);
|
||||||
|
return TOP_LAUNCH_VEHICLES.has(family) ? family : "Other";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse dates!
|
||||||
|
const parseDate = utcParse("%Y %b %_d");
|
||||||
|
|
||||||
|
// Load and parse launch-log and trim down to smaller size.
|
||||||
|
const launchHistory = tsvParse(await text("https://planet4589.org/space/gcat/tsv/derived/launchlog.tsv"), (d) => ({
|
||||||
|
date: parseDate(d.Launch_Date.slice(0, 11)),
|
||||||
|
state: normalizeState(d.LVState),
|
||||||
|
stateId: d.LVState,
|
||||||
|
family: normalizeFamily(d.LV_Type)
|
||||||
|
})).filter((d) => d.date != null);
|
||||||
|
|
||||||
|
// Write out csv formatted data.
|
||||||
|
process.stdout.write(csvFormat(launchHistory));
|
99
src/example-dashboard.md
Normal file
99
src/example-dashboard.md
Normal file
|
@ -0,0 +1,99 @@
|
||||||
|
---
|
||||||
|
theme: dashboard
|
||||||
|
title: Example dashboard
|
||||||
|
toc: false
|
||||||
|
---
|
||||||
|
|
||||||
|
# Rocket launches 🚀
|
||||||
|
|
||||||
|
<!-- Load and transform the data -->
|
||||||
|
|
||||||
|
```js
|
||||||
|
const launches = FileAttachment("data/launches.csv").csv({typed: true});
|
||||||
|
```
|
||||||
|
|
||||||
|
<!-- A shared color scale for consistency, sorted by the number of launches -->
|
||||||
|
|
||||||
|
```js
|
||||||
|
const color = Plot.scale({
|
||||||
|
color: {
|
||||||
|
type: "categorical",
|
||||||
|
domain: d3.groupSort(launches, (D) => -D.length, (d) => d.state).filter((d) => d !== "Other"),
|
||||||
|
unknown: "var(--theme-foreground-muted)"
|
||||||
|
}
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
<!-- Cards with big numbers -->
|
||||||
|
|
||||||
|
<div class="grid grid-cols-4">
|
||||||
|
<div class="card">
|
||||||
|
<h2>United States 🇺🇸</h2>
|
||||||
|
<span class="big">${launches.filter((d) => d.stateId === "US").length.toLocaleString("en-US")}</span>
|
||||||
|
</div>
|
||||||
|
<div class="card">
|
||||||
|
<h2>Russia 🇷🇺 <span class="muted">/ Soviet Union</span></h2>
|
||||||
|
<span class="big">${launches.filter((d) => d.stateId === "SU" || d.stateId === "RU").length.toLocaleString("en-US")}</span>
|
||||||
|
</div>
|
||||||
|
<div class="card">
|
||||||
|
<h2>China 🇨🇳</h2>
|
||||||
|
<span class="big">${launches.filter((d) => d.stateId === "CN").length.toLocaleString("en-US")}</span>
|
||||||
|
</div>
|
||||||
|
<div class="card">
|
||||||
|
<h2>Other</h2>
|
||||||
|
<span class="big">${launches.filter((d) => d.stateId !== "US" && d.stateId !== "SU" && d.stateId !== "RU" && d.stateId !== "CN").length.toLocaleString("en-US")}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Plot of launch history -->
|
||||||
|
|
||||||
|
```js
|
||||||
|
function launchTimeline(data, {width} = {}) {
|
||||||
|
return Plot.plot({
|
||||||
|
title: "Launches over the years",
|
||||||
|
width,
|
||||||
|
height: 300,
|
||||||
|
y: {grid: true, label: "Launches"},
|
||||||
|
color: {...color, legend: true},
|
||||||
|
marks: [
|
||||||
|
Plot.rectY(data, Plot.binX({y: "count"}, {x: "date", fill: "state", interval: "year", tip: true})),
|
||||||
|
Plot.ruleY([0])
|
||||||
|
]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
<div class="grid grid-cols-1">
|
||||||
|
<div class="card">
|
||||||
|
${resize((width) => launchTimeline(launches, {width}))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Plot of launch vehicles -->
|
||||||
|
|
||||||
|
```js
|
||||||
|
function vehicleChart(data, {width}) {
|
||||||
|
return Plot.plot({
|
||||||
|
title: "Popular launch vehicles",
|
||||||
|
width,
|
||||||
|
height: 300,
|
||||||
|
marginTop: 0,
|
||||||
|
marginLeft: 50,
|
||||||
|
x: {grid: true, label: "Launches"},
|
||||||
|
y: {label: null},
|
||||||
|
color: {...color, legend: true},
|
||||||
|
marks: [
|
||||||
|
Plot.rectX(data, Plot.groupY({x: "count"}, {y: "family", fill: "state", tip: true, sort: {y: "-x"}})),
|
||||||
|
Plot.ruleX([0])
|
||||||
|
]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
<div class="grid grid-cols-1">
|
||||||
|
<div class="card">
|
||||||
|
${resize((width) => vehicleChart(launches, {width}))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
Data: Jonathan C. McDowell, [General Catalog of Artificial Space Objects](https://planet4589.org/space/gcat)
|
75
src/example-report.md
Normal file
75
src/example-report.md
Normal file
|
@ -0,0 +1,75 @@
|
||||||
|
---
|
||||||
|
title: Example report
|
||||||
|
---
|
||||||
|
|
||||||
|
# A brief history of space exploration
|
||||||
|
|
||||||
|
This report is a brief overview of the history and current state of rocket launches and space exploration.
|
||||||
|
|
||||||
|
## Background
|
||||||
|
|
||||||
|
The history of rocket launches dates back to ancient China, where gunpowder-filled tubes were used as primitive forms of propulsion.
|
||||||
|
|
||||||
|
Fast-forward to the 20th century during the Cold War era, the United States and the Soviet Union embarked on a space race, a competition to innovate and explore beyond Earth.
|
||||||
|
|
||||||
|
This led to the launch of the first artificial satellite, Sputnik 1, and the crewed moon landing by Apollo 11. As technology advanced, rocket launches became synonymous with space exploration and satellite deployment.
|
||||||
|
|
||||||
|
## The Space Shuttle era
|
||||||
|
|
||||||
|
```js
|
||||||
|
import {timeline} from "./components/timeline.js";
|
||||||
|
```
|
||||||
|
|
||||||
|
```js
|
||||||
|
const events = FileAttachment("./data/events.json").json();
|
||||||
|
```
|
||||||
|
|
||||||
|
```js
|
||||||
|
timeline(events, {height: 300})
|
||||||
|
```
|
||||||
|
|
||||||
|
### Sputnik 1 (1957)
|
||||||
|
|
||||||
|
This was the first artificial satellite. Launched by the Soviet Union, it marked the beginning of the space age.
|
||||||
|
|
||||||
|
### Apollo 11 (1969)
|
||||||
|
|
||||||
|
The historic Apollo 11 mission, led by NASA, marked the first successful human landing on the Moon. Astronauts Neil Armstrong and Buzz Aldrin became the first humans to set foot on the lunar surface.
|
||||||
|
|
||||||
|
### Viking 1 and 2 (1975)
|
||||||
|
|
||||||
|
NASA’s Viking program successfully launched two spacecraft, Viking 1 and Viking 2, to Mars. These missions were the first to successfully land and operate on the Martian surface, conducting experiments to search for signs of life.
|
||||||
|
|
||||||
|
### Space Shuttle Columbia (1981)
|
||||||
|
|
||||||
|
The first orbital space shuttle mission, STS-1, launched the Space Shuttle Columbia on April 12, 1981. The shuttle program revolutionized space travel, providing a reusable spacecraft for a variety of missions.
|
||||||
|
|
||||||
|
### Hubble Space Telescope (1990)
|
||||||
|
|
||||||
|
The Hubble Space Telescope has provided unparalleled images and data, revolutionizing our understanding of the universe and contributing to countless astronomical discoveries.
|
||||||
|
|
||||||
|
### International Space Station (ISS) construction (1998—2011)
|
||||||
|
|
||||||
|
The ISS, a collaborative effort involving multiple space agencies, began construction with the launch of its first module, Zarya, in 1998. Over the following years, various modules were added, making the ISS a symbol of international cooperation in space exploration.
|
||||||
|
|
||||||
|
## Commercial spaceflight
|
||||||
|
|
||||||
|
After the Space Shuttle program, a new era emerged with a shift towards commercial spaceflight.
|
||||||
|
|
||||||
|
Private companies like Blue Origin, founded by Jeff Bezos in 2000, and SpaceX, founded by Elon Musk in 2002, entered the scene. These companies focused on developing reusable rocket technologies, significantly reducing launch costs.
|
||||||
|
|
||||||
|
SpaceX, in particular, achieved milestones like the first privately developed spacecraft to reach orbit (Dragon in 2010) and the first privately funded spacecraft to dock with the ISS (Dragon in 2012).
|
||||||
|
|
||||||
|
## Recent launch activity
|
||||||
|
|
||||||
|
The proliferation of commercial space companies has driven a surge in global launch activity within the last few years.
|
||||||
|
|
||||||
|
SpaceX’s Falcon 9 and Falcon Heavy, along with other vehicles from companies like Rocket Lab, have become workhorses for deploying satellites, conducting scientific missions, and ferrying crew to the ISS.
|
||||||
|
|
||||||
|
The advent of small satellite constellations, such as Starlink by SpaceX, has further fueled this increase in launches. The push for lunar exploration has added momentum to launch activities, with initiatives like NASA’s Artemis program and plans for crewed missions to the Moon and Mars.
|
||||||
|
|
||||||
|
## Looking forward
|
||||||
|
|
||||||
|
As technology continues to advance and global interest in space exploration grows, the future promises even more exciting developments in the realm of rocket launches and space travel.
|
||||||
|
|
||||||
|
Exploration will not only be limited to the Moon or Mars, but extend to other parts of our solar system such as Jupiter and Saturn’s moons, and beyond.
|
111
src/index.md
Normal file
111
src/index.md
Normal file
|
@ -0,0 +1,111 @@
|
||||||
|
---
|
||||||
|
toc: false
|
||||||
|
---
|
||||||
|
|
||||||
|
<div class="hero">
|
||||||
|
<h1>Vrg Archive</h1>
|
||||||
|
<h2>Welcome to your new app! Edit <code style="font-size: 90%;">src/index.md</code> to change this page.</h2>
|
||||||
|
<a href="https://observablehq.com/framework/getting-started">Get started<span style="display: inline-block; margin-left: 0.25rem;">↗︎</span></a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="grid grid-cols-2" style="grid-auto-rows: 504px;">
|
||||||
|
<div class="card">${
|
||||||
|
resize((width) => Plot.plot({
|
||||||
|
title: "Your awesomeness over time 🚀",
|
||||||
|
subtitle: "Up and to the right!",
|
||||||
|
width,
|
||||||
|
y: {grid: true, label: "Awesomeness"},
|
||||||
|
marks: [
|
||||||
|
Plot.ruleY([0]),
|
||||||
|
Plot.lineY(aapl, {x: "Date", y: "Close", tip: true})
|
||||||
|
]
|
||||||
|
}))
|
||||||
|
}</div>
|
||||||
|
<div class="card">${
|
||||||
|
resize((width) => Plot.plot({
|
||||||
|
title: "How big are penguins, anyway? 🐧",
|
||||||
|
width,
|
||||||
|
grid: true,
|
||||||
|
x: {label: "Body mass (g)"},
|
||||||
|
y: {label: "Flipper length (mm)"},
|
||||||
|
color: {legend: true},
|
||||||
|
marks: [
|
||||||
|
Plot.linearRegressionY(penguins, {x: "body_mass_g", y: "flipper_length_mm", stroke: "species"}),
|
||||||
|
Plot.dot(penguins, {x: "body_mass_g", y: "flipper_length_mm", stroke: "species", tip: true})
|
||||||
|
]
|
||||||
|
}))
|
||||||
|
}</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Next steps
|
||||||
|
|
||||||
|
Here are some ideas of things you could try…
|
||||||
|
|
||||||
|
<div class="grid grid-cols-4">
|
||||||
|
<div class="card">
|
||||||
|
Chart your own data using <a href="https://observablehq.com/framework/lib/plot"><code>Plot</code></a> and <a href="https://observablehq.com/framework/files"><code>FileAttachment</code></a>. Make it responsive using <a href="https://observablehq.com/framework/javascript#resize(render)"><code>resize</code></a>.
|
||||||
|
</div>
|
||||||
|
<div class="card">
|
||||||
|
Create a <a href="https://observablehq.com/framework/project-structure">new page</a> by adding a Markdown file (<code>whatever.md</code>) to the <code>src</code> folder.
|
||||||
|
</div>
|
||||||
|
<div class="card">
|
||||||
|
Add a drop-down menu using <a href="https://observablehq.com/framework/inputs/select"><code>Inputs.select</code></a> and use it to filter the data shown in a chart.
|
||||||
|
</div>
|
||||||
|
<div class="card">
|
||||||
|
Write a <a href="https://observablehq.com/framework/loaders">data loader</a> that queries a local database or API, generating a data snapshot on build.
|
||||||
|
</div>
|
||||||
|
<div class="card">
|
||||||
|
Import a <a href="https://observablehq.com/framework/imports">recommended library</a> from npm, such as <a href="https://observablehq.com/framework/lib/leaflet">Leaflet</a>, <a href="https://observablehq.com/framework/lib/dot">GraphViz</a>, <a href="https://observablehq.com/framework/lib/tex">TeX</a>, or <a href="https://observablehq.com/framework/lib/duckdb">DuckDB</a>.
|
||||||
|
</div>
|
||||||
|
<div class="card">
|
||||||
|
Ask for help, or share your work or ideas, on our <a href="https://github.com/observablehq/framework/discussions">GitHub discussions</a>.
|
||||||
|
</div>
|
||||||
|
<div class="card">
|
||||||
|
Visit <a href="https://github.com/observablehq/framework">Framework on GitHub</a> and give us a star. Or file an issue if you’ve found a bug!
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
|
||||||
|
.hero {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
font-family: var(--sans-serif);
|
||||||
|
margin: 4rem 0 8rem;
|
||||||
|
text-wrap: balance;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero h1 {
|
||||||
|
margin: 1rem 0;
|
||||||
|
padding: 1rem 0;
|
||||||
|
max-width: none;
|
||||||
|
font-size: 14vw;
|
||||||
|
font-weight: 900;
|
||||||
|
line-height: 1;
|
||||||
|
background: linear-gradient(30deg, var(--theme-foreground-focus), currentColor);
|
||||||
|
-webkit-background-clip: text;
|
||||||
|
-webkit-text-fill-color: transparent;
|
||||||
|
background-clip: text;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero h2 {
|
||||||
|
margin: 0;
|
||||||
|
max-width: 34em;
|
||||||
|
font-size: 20px;
|
||||||
|
font-style: initial;
|
||||||
|
font-weight: 500;
|
||||||
|
line-height: 1.5;
|
||||||
|
color: var(--theme-foreground-muted);
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 640px) {
|
||||||
|
.hero h1 {
|
||||||
|
font-size: 90px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
BIN
src/observable.png
Normal file
BIN
src/observable.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 394 B |
Loading…
Reference in a new issue