Skip to content

Commit 08862ab

Browse files
authored
docs: add getting started overview
1 parent 94f0f64 commit 08862ab

49 files changed

Lines changed: 1784 additions & 474 deletions

Some content is hidden

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

.github/workflows/docs.yml

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,15 +34,12 @@ jobs:
3434
cache: pnpm
3535
cache-dependency-path: docs/pnpm-lock.yaml
3636

37-
- name: Install dependencies
38-
run: pnpm --dir docs install --frozen-lockfile
39-
4037
- name: Build docs
4138
env:
4239
VITEPRESS_SITE_URL: ${{ vars.VITEPRESS_SITE_URL }}
4340
VITEPRESS_BASE: ${{ vars.VITEPRESS_BASE }}
4441
VITEPRESS_GTAG_ID: ${{ vars.VITEPRESS_GTAG_ID }}
45-
run: pnpm --dir docs run build
42+
run: make docs-build
4643

4744
- name: Configure Pages
4845
if: github.event_name == 'push' && github.ref == 'refs/heads/main' && vars.SKIP_DOCS_DEPLOY != 'true'

Makefile

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ LDFLAGS := -X $(MODULE)/internal/buildinfo.Version=$(VERSION) \
1212
-X $(MODULE)/internal/buildinfo.Commit=$(COMMIT) \
1313
-X $(MODULE)/internal/buildinfo.Date=$(DATE)
1414

15-
.PHONY: all build build-go test test-fast test-race test-docker-entrypoint lint fmt check verify-fast verify-race clean run ui-install ui-build ui-dev
15+
.PHONY: all build build-go docs-build test test-fast test-race test-docker-entrypoint lint fmt check verify-fast verify-race clean run ui-install ui-build ui-dev
1616

1717
all: build
1818

@@ -22,6 +22,10 @@ ui-install:
2222
ui-build: ui-install
2323
cd ui && pnpm run build
2424

25+
docs-build:
26+
cd docs && pnpm install --frozen-lockfile
27+
cd docs && pnpm run build
28+
2529
build: ui-build build-go
2630

2731
build-go:

README.md

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,35 @@
1-
![SynapS3 dashboard](docs/assets/readme-dashboard.png)
2-
31
# SynapS3
42

53
[![CI](https://github.com/strahe/SynapS3/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/strahe/SynapS3/actions/workflows/ci.yml)
64
[![Package](https://img.shields.io/badge/package-GHCR-blue?logo=github)](https://github.com/strahe/SynapS3/pkgs/container/synaps3)
75
[![Go Report](https://goreportcard.com/badge/github.com/strahe/synaps3)](https://goreportcard.com/report/github.com/strahe/synaps3)
86
[![Go Version](https://img.shields.io/github/go-mod/go-version/strahe/SynapS3?filename=go.mod)](go.mod)
97

10-
SynapS3 is an open-source, self-hosted S3-compatible gateway for storing objects on Filecoin.
8+
SynapS3 is an open-source, self-hosted S3-compatible gateway for Filecoin storage.
119

1210
## Documentation
1311

14-
- [Documentation](https://synaps3.strahe.com/)
12+
- [Documentation](https://synaps3.strahe.com/en/)
1513
- [中文文档](https://synaps3.strahe.com/zh/)
1614

1715
## Highlights
1816

19-
- S3-compatible bucket and object APIs.
20-
- Filecoin-backed object storage through storage providers.
21-
- Open-source, self-hosted deployment with Docker or source builds.
22-
- Admin-authenticated dashboard for buckets, objects, wallet, tasks, topology, settings, and health.
23-
- Multipart uploads for large objects.
24-
- Wallet funding, USDFC deposit, and background task controls.
25-
- Coming soon: automatic replica repair when storage providers become unavailable.
17+
- S3-compatible bucket, object, versioning, and multipart APIs.
18+
- Cache-first reads and writes, with Filecoin upload handled in the background.
19+
- Admin dashboard for objects, wallet, tasks, topology, settings, and health.
20+
- Docker Compose or source build for single-node deployments.
21+
22+
Coming soon: replica repair for provider outages.
23+
24+
## Dashboard
25+
26+
![SynapS3 dashboard](docs/assets/readme-dashboard.png)
27+
28+
## Architecture
29+
30+
![SynapS3 architecture](docs/public/architecture-overview.svg)
31+
32+
Writes commit to local cache and metadata before returning success. Reads use local cache first, then committed Filecoin copies when available.
2633

2734
## Core S3 Compatibility
2835

@@ -39,7 +46,7 @@ SynapS3 is an open-source, self-hosted S3-compatible gateway for storing objects
3946
| Object | `HeadObject` || Reads object metadata |
4047
| Object | `DeleteObject` || Creates a delete marker, or deletes a specific `versionId` |
4148
| Object | `DeleteObjects` || Creates delete markers, or deletes specific `versionId` entries |
42-
| Object | `CopyObject` || Source object must be readable from cache or committed provider storage |
49+
| Object | `CopyObject` || Source object must be readable from cache or committed Filecoin storage |
4350
| Object | `ListObjects` || Marker pagination |
4451
| Object | `ListObjectsV2` || Continuation-token pagination |
4552
| Object | `ListObjectVersions` || Lists object versions and delete markers |

docs/.vitepress/config.ts

Lines changed: 54 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,14 +49,14 @@ gtag('config', ${encodedGtagId});`,
4949
}
5050

5151
const enNav: DefaultTheme.NavItem[] = [
52-
{ text: 'Get Started', link: '/en/getting-started/quick-start' },
52+
{ text: 'Get Started', link: '/en/getting-started/overview' },
5353
{ text: 'Deploy', link: '/en/getting-started/docker' },
5454
{ text: 'Operate', link: '/en/operations/production-checklist' },
5555
{ text: 'Reference', link: '/en/reference/s3-compatibility' },
5656
]
5757

5858
const zhNav: DefaultTheme.NavItem[] = [
59-
{ text: '入门', link: '/zh/getting-started/quick-start' },
59+
{ text: '入门', link: '/zh/getting-started/overview' },
6060
{ text: '部署', link: '/zh/getting-started/docker' },
6161
{ text: '运维', link: '/zh/operations/production-checklist' },
6262
{ text: '参考', link: '/zh/reference/s3-compatibility' },
@@ -66,7 +66,7 @@ const enSidebar: DefaultTheme.Sidebar = [
6666
{
6767
text: 'Getting Started',
6868
items: [
69-
{ text: 'Overview', link: '/en/' },
69+
{ text: 'Overview', link: '/en/getting-started/overview' },
7070
{ text: 'Quick Start', link: '/en/getting-started/quick-start' },
7171
{ text: 'S3 Clients', link: '/en/getting-started/s3-clients' },
7272
],
@@ -112,7 +112,7 @@ const zhSidebar: DefaultTheme.Sidebar = [
112112
{
113113
text: '入门',
114114
items: [
115-
{ text: '概览', link: '/zh/' },
115+
{ text: '概览', link: '/zh/getting-started/overview' },
116116
{ text: '快速开始', link: '/zh/getting-started/quick-start' },
117117
{ text: 'S3 客户端', link: '/zh/getting-started/s3-clients' },
118118
],
@@ -154,6 +154,53 @@ const zhSidebar: DefaultTheme.Sidebar = [
154154
},
155155
]
156156

157+
type MarkdownFenceRenderer = (
158+
tokens: Array<{ content: string; info: string; map: [number, number] | null }>,
159+
idx: number,
160+
options: unknown,
161+
env: { path?: string; relativePath?: string } | undefined,
162+
self: { renderToken: MarkdownFenceRenderer },
163+
) => string
164+
165+
type MarkdownItLike = {
166+
renderer: {
167+
rules: {
168+
fence?: MarkdownFenceRenderer
169+
}
170+
}
171+
}
172+
173+
function stableHash(value: string) {
174+
let hash = 0
175+
176+
for (let index = 0; index < value.length; index += 1) {
177+
hash = Math.imul(31, hash) + value.charCodeAt(index)
178+
}
179+
180+
return (hash >>> 0).toString(36)
181+
}
182+
183+
function configureMermaidMarkdown(md: MarkdownItLike) {
184+
const defaultFence = md.renderer.rules.fence
185+
186+
md.renderer.rules.fence = (tokens, idx, options, env, self) => {
187+
const token = tokens[idx]
188+
const language = token.info.trim().split(/\s+/, 1)[0]
189+
190+
if (language !== 'mermaid' && language !== 'mmd') {
191+
return defaultFence
192+
? defaultFence(tokens, idx, options, env, self)
193+
: self.renderToken(tokens, idx, options, env, self)
194+
}
195+
196+
const source = `${env?.path || env?.relativePath || 'page'}:${idx}:${token.map?.join('-') || ''}`
197+
const id = `mermaid-${stableHash(source)}`
198+
const code = encodeURIComponent(token.content)
199+
200+
return `<ClientOnly><MermaidBlock id="${id}" code="${code}" /></ClientOnly>`
201+
}
202+
}
203+
157204
export default defineConfig({
158205
title: 'SynapS3',
159206
titleTemplate: ':title | SynapS3',
@@ -166,6 +213,9 @@ export default defineConfig({
166213
hostname: siteBaseUrl,
167214
},
168215
head,
216+
markdown: {
217+
config: configureMermaidMarkdown,
218+
},
169219
transformPageData(pageData) {
170220
if (pageData.relativePath !== 'index.md') {
171221
return
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
<template>
2+
<div class="mermaid-block">
3+
<div v-if="error" class="mermaid-block__error">
4+
<p>{{ error }}</p>
5+
<pre>{{ decodedCode }}</pre>
6+
</div>
7+
<div v-else ref="container" class="mermaid-block__svg" />
8+
</div>
9+
</template>
10+
11+
<script setup lang="ts">
12+
import { computed, nextTick, onBeforeUnmount, onMounted, ref, watch } from 'vue'
13+
import { useData } from 'vitepress'
14+
15+
const props = defineProps<{
16+
id: string
17+
code: string
18+
}>()
19+
20+
const { isDark } = useData()
21+
const container = ref<HTMLElement | null>(null)
22+
const error = ref('')
23+
const decodedCode = computed(() => decodeURIComponent(props.code))
24+
let renderVersion = 0
25+
26+
async function renderDiagram() {
27+
if (!container.value) {
28+
return
29+
}
30+
31+
const currentVersion = ++renderVersion
32+
error.value = ''
33+
34+
try {
35+
const mermaid = (await import('mermaid')).default
36+
37+
mermaid.initialize({
38+
securityLevel: 'strict',
39+
startOnLoad: false,
40+
theme: isDark.value ? 'dark' : 'default',
41+
})
42+
43+
const { svg } = await mermaid.render(`${props.id}-${currentVersion}`, decodedCode.value)
44+
45+
if (currentVersion === renderVersion && container.value) {
46+
container.value.innerHTML = svg
47+
}
48+
} catch (renderError) {
49+
if (currentVersion !== renderVersion || !container.value) {
50+
return
51+
}
52+
53+
container.value.innerHTML = ''
54+
error.value = renderError instanceof Error ? renderError.message : String(renderError)
55+
}
56+
}
57+
58+
onMounted(() => {
59+
void renderDiagram()
60+
})
61+
62+
onBeforeUnmount(() => {
63+
renderVersion += 1
64+
65+
if (container.value) {
66+
container.value.innerHTML = ''
67+
}
68+
})
69+
70+
watch(
71+
() => [props.code, isDark.value],
72+
() => {
73+
void nextTick(renderDiagram)
74+
},
75+
)
76+
</script>

docs/.vitepress/theme/index.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
import DefaultTheme from 'vitepress/theme'
2+
import MermaidBlock from './MermaidBlock.vue'
23
import './styles.css'
34

45
export default {
56
extends: DefaultTheme,
7+
enhanceApp({ app }) {
8+
app.component('MermaidBlock', MermaidBlock)
9+
},
610
}

docs/.vitepress/theme/styles.css

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,3 +37,60 @@
3737
.dark .VPHomeHero .image-src {
3838
box-shadow: 0 16px 48px rgb(0 0 0 / 36%);
3939
}
40+
41+
.architecture-overview {
42+
display: block;
43+
width: 100%;
44+
height: auto;
45+
border: 1px solid var(--vp-c-divider);
46+
border-radius: 8px;
47+
}
48+
49+
.architecture-overview--dark {
50+
display: none;
51+
}
52+
53+
.dark .architecture-overview--light {
54+
display: none;
55+
}
56+
57+
.dark .architecture-overview--dark {
58+
display: block;
59+
}
60+
61+
.mermaid-block {
62+
margin: 24px 0;
63+
overflow-x: auto;
64+
border: 1px solid var(--vp-c-divider);
65+
border-radius: 8px;
66+
background: var(--vp-c-bg-soft);
67+
}
68+
69+
.mermaid-block__svg {
70+
min-width: min-content;
71+
padding: 20px;
72+
}
73+
74+
.mermaid-block__svg svg {
75+
display: block;
76+
max-width: 100%;
77+
height: auto;
78+
margin: 0 auto;
79+
}
80+
81+
.mermaid-block__error {
82+
padding: 16px;
83+
color: var(--vp-c-danger-1);
84+
}
85+
86+
.mermaid-block__error p {
87+
margin: 0 0 12px;
88+
font-weight: 600;
89+
}
90+
91+
.mermaid-block__error pre {
92+
margin: 0;
93+
overflow-x: auto;
94+
color: var(--vp-c-text-1);
95+
white-space: pre;
96+
}

0 commit comments

Comments
 (0)