Skip to content

Commit cac8caa

Browse files
committed
Added docs
1 parent 086c91b commit cac8caa

28 files changed

Lines changed: 1948 additions & 2 deletions

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ yarn-debug.log
77
yarn-error.log
88

99
dist
10+
dist/
1011

1112
packages/electron/out
1213
packages/backend/.starquery/

docs/.vitepress/.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
dist/
2+
cache/

docs/.vitepress/config.ts

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
import tailwindcss from '@tailwindcss/vite'
2+
import { defineConfig } from 'vitepress'
3+
4+
export default defineConfig({
5+
title: 'StarQuery',
6+
description: 'Tasteful data tools. Serious control.',
7+
cleanUrls: true,
8+
lastUpdated: true,
9+
vite: {
10+
plugins: [tailwindcss()],
11+
},
12+
head: [
13+
['link', { rel: 'icon', href: '/logo.svg' }],
14+
['meta', { name: 'theme-color', content: '#d63472' }],
15+
],
16+
themeConfig: {
17+
logo: '/logo.svg',
18+
siteTitle: 'StarQuery',
19+
nav: [
20+
{ text: 'Guide', link: '/guide/getting-started' },
21+
{ text: 'Deployment', link: '/deploy/docker' },
22+
{ text: 'Desktop', link: '/guide/electron' },
23+
{ text: 'Reference', link: '/reference/configuration' },
24+
],
25+
sidebar: {
26+
'/guide/': [
27+
{
28+
text: 'Guide',
29+
items: [
30+
{ text: 'Getting Started', link: '/guide/getting-started' },
31+
{ text: 'Runtime Modes', link: '/guide/runtime-modes' },
32+
{ text: 'Datasources', link: '/guide/datasources' },
33+
{ text: 'Electron Desktop', link: '/guide/electron' },
34+
{ text: 'Development', link: '/guide/development' },
35+
],
36+
},
37+
],
38+
'/deploy/': [
39+
{
40+
text: 'Deployment',
41+
items: [
42+
{ text: 'Docker', link: '/deploy/docker' },
43+
{ text: 'Hosted Configuration', link: '/deploy/hosted-configuration' },
44+
],
45+
},
46+
],
47+
'/reference/': [
48+
{
49+
text: 'Reference',
50+
items: [
51+
{ text: 'Configuration', link: '/reference/configuration' },
52+
{ text: 'Permissions', link: '/reference/permissions' },
53+
{ text: 'Exports', link: '/reference/exports' },
54+
],
55+
},
56+
],
57+
},
58+
search: {
59+
provider: 'local',
60+
},
61+
outline: {
62+
level: [2, 3],
63+
},
64+
footer: {
65+
message: 'Tasteful data tools. Serious control.',
66+
copyright: 'Copyright © StarQuery',
67+
},
68+
},
69+
})
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
<script setup lang="ts">
2+
import { computed, onMounted, ref } from 'vue'
3+
4+
type GithubRepository = {
5+
stargazers_count?: number
6+
}
7+
8+
const repoUrl = 'https://github.com/interaapps/starquery'
9+
const repoApiUrl = 'https://api.github.com/repos/interaapps/starquery'
10+
const starCount = ref<number | null>(null)
11+
12+
const label = computed(() => {
13+
if (typeof starCount.value !== 'number') {
14+
return 'Star on GitHub'
15+
}
16+
17+
return `Star on GitHub · ${new Intl.NumberFormat().format(starCount.value)}`
18+
})
19+
20+
onMounted(async () => {
21+
try {
22+
const response = await fetch(repoApiUrl, {
23+
headers: {
24+
Accept: 'application/vnd.github+json',
25+
},
26+
})
27+
28+
if (!response.ok) {
29+
return
30+
}
31+
32+
const repository = (await response.json()) as GithubRepository
33+
starCount.value =
34+
typeof repository.stargazers_count === 'number' ? repository.stargazers_count : null
35+
} catch {
36+
starCount.value = null
37+
}
38+
})
39+
</script>
40+
41+
<template>
42+
<a
43+
:href="repoUrl"
44+
class="hidden whitespace-nowrap rounded-full border border-[var(--vp-c-border)] bg-[var(--vp-c-bg)] px-4 py-[0.3rem] text-[0.92rem] font-semibold tracking-[-0.01em] text-[var(--vp-c-default-1)] no-underline transition-colors hover:border-primary-300 hover:bg-primary-50 hover:text-primary-700 dark:hover:border-primary-700 dark:hover:bg-primary-950/40 dark:hover:text-primary-200 md:inline-flex md:items-center md:justify-center"
45+
target="_blank"
46+
rel="noreferrer"
47+
>
48+
{{ label }}
49+
</a>
50+
</template>
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
<script setup lang="ts">
2+
import InstallNavButton from "./InstallNavButton.vue";
3+
</script>
4+
<template>
5+
<div class="flex flex-col items-center py-20 lg:py-30">
6+
<div class="flex flex-col gap-10 items-center relative z-10">
7+
<h1 class="text-primary-500 font-extrabold !text-5xl lg:!text-7xl text-center">
8+
Data management, <br> made tasteful.
9+
</h1>
10+
11+
<InstallNavButton large />
12+
</div>
13+
14+
<div class="relative w-full -mt-20 -mb-40">
15+
<div class="flex flex-col items-center select-none pointer-events-none">
16+
<div
17+
class="relative animate-[spin_60s_linear_infinite] select-none opacity-20 hidden dark:block w-full"
18+
>
19+
<img
20+
src="/logo-part-outline.svg"
21+
class="h-full w-full relative"
22+
style="animation: first-star 10s; transform: rotate(106deg)"
23+
/>
24+
<img
25+
src="/logo-part-outline.svg"
26+
class="h-full w-full absolute top-0"
27+
style="animation: second-star 10s"
28+
/>
29+
</div>
30+
<div
31+
class="relative animate-[spin_60s_linear_infinite] select-none opacity-20 block dark:hidden"
32+
>
33+
<img
34+
src="/logo-part-outline-dark.svg"
35+
class="h-full w-full relative"
36+
style="animation: first-star 10s; transform: rotate(106deg)"
37+
/>
38+
<img
39+
src="/logo-part-outline-dark.svg"
40+
class="h-full w-full absolute top-0"
41+
style="animation: second-star 10s"
42+
/>
43+
</div>
44+
</div>
45+
46+
<div class="absolute h-full w-full flex items-center justify-center top-0">
47+
<img class="w-full !max-w-100%" src="/screenshot.png" />
48+
</div>
49+
50+
51+
</div>
52+
</div>
53+
</template>
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
<template>
2+
<section class="mt-10 grid items-center gap-8 pt-2 md:grid-cols-[minmax(0,1fr)_minmax(0,1.15fr)]">
3+
<div>
4+
<div class="mb-4 text-[0.78rem] font-bold uppercase tracking-[0.16em] text-[var(--vp-c-default-2)]">
5+
Product Preview
6+
</div>
7+
<h2 class="mb-4 text-[clamp(1.9rem,3vw,3rem)] leading-[1.02] tracking-[-0.05em] text-[var(--vp-c-default-1)]">
8+
Built for real data work, without looking like a generic admin panel.
9+
</h2>
10+
<p class="m-0 text-[var(--vp-c-default-2)]">
11+
StarQuery combines dense operational workflows with a calmer interface language. The goal
12+
is not just capability, but capability that still feels considered.
13+
</p>
14+
15+
<div class="mt-5 grid gap-4">
16+
<div
17+
class="grid gap-1 rounded-[18px] border border-[var(--vp-c-border)] bg-[linear-gradient(180deg,var(--vp-c-bg),var(--vp-c-bg-soft))] px-4 py-4"
18+
>
19+
<strong class="text-[0.98rem] tracking-[-0.02em] text-[var(--vp-c-default-1)]">One consistent workspace</strong>
20+
<span class="text-[var(--vp-c-default-2)]">Queries, browsers, editors, exports and admin workflows follow the same design logic.</span>
21+
</div>
22+
<div
23+
class="grid gap-1 rounded-[18px] border border-[var(--vp-c-border)] bg-[linear-gradient(180deg,var(--vp-c-bg),var(--vp-c-bg-soft))] px-4 py-4"
24+
>
25+
<strong class="text-[0.98rem] tracking-[-0.02em] text-[var(--vp-c-default-1)]">Dense, but readable</strong>
26+
<span class="text-[var(--vp-c-default-2)]">Power features stay accessible without collapsing into noisy, cramped tooling.</span>
27+
</div>
28+
<div
29+
class="grid gap-1 rounded-[18px] border border-[var(--vp-c-border)] bg-[linear-gradient(180deg,var(--vp-c-bg),var(--vp-c-bg-soft))] px-4 py-4"
30+
>
31+
<strong class="text-[0.98rem] tracking-[-0.02em] text-[var(--vp-c-default-1)]">Use it solo or with a team</strong>
32+
<span class="text-[var(--vp-c-default-2)]">The same experience works for quick local sessions and for shared, browser-based deployments.</span>
33+
</div>
34+
</div>
35+
</div>
36+
37+
<div class="relative">
38+
<img
39+
class="block h-auto w-full drop-shadow-[0_30px_80px_rgba(17,24,39,0.14)]"
40+
src="/screenshot.png"
41+
alt="StarQuery screenshot"
42+
/>
43+
</div>
44+
</section>
45+
</template>
Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
<script setup lang="ts">
2+
import { computed, onMounted, ref } from 'vue'
3+
4+
type PlatformTarget = 'macOS' | 'Windows' | 'Linux'
5+
6+
type GithubReleaseAsset = {
7+
name: string
8+
browser_download_url: string
9+
}
10+
11+
type GithubLatestRelease = {
12+
html_url: string
13+
assets?: GithubReleaseAsset[]
14+
}
15+
16+
const latestReleaseUrl = 'https://github.com/interaapps/starquery/releases/latest'
17+
const githubLatestReleaseApi = 'https://api.github.com/repos/interaapps/starquery/releases/latest'
18+
const platform = ref<PlatformTarget | null>(null)
19+
const downloadUrl = ref(latestReleaseUrl)
20+
const isLoading = ref(false)
21+
22+
defineProps<{
23+
large?: boolean
24+
}>()
25+
26+
const label = computed(() => {
27+
if (!platform.value) {
28+
return 'Install'
29+
}
30+
31+
return `Install for ${platform.value}`
32+
})
33+
34+
function detectPlatform(): PlatformTarget | null {
35+
const value = `${navigator.platform} ${navigator.userAgent}`.toLowerCase()
36+
37+
if (value.includes('mac')) {
38+
return 'macOS'
39+
}
40+
41+
if (value.includes('win')) {
42+
return 'Windows'
43+
}
44+
45+
if (value.includes('linux')) {
46+
return 'Linux'
47+
}
48+
49+
return null
50+
}
51+
52+
function getAssetMatchers(target: PlatformTarget) {
53+
if (target === 'macOS') {
54+
return [
55+
(name: string) => name.endsWith('.zip') && (name.includes('darwin') || name.includes('mac')),
56+
(name: string) => name.endsWith('.zip'),
57+
]
58+
}
59+
60+
if (target === 'Windows') {
61+
return [
62+
(name: string) => name.endsWith('.exe'),
63+
(name: string) => name.endsWith('.msix'),
64+
(name: string) => name.endsWith('.nupkg'),
65+
]
66+
}
67+
68+
return [
69+
(name: string) => name.endsWith('.deb'),
70+
(name: string) => name.endsWith('.rpm'),
71+
(name: string) => name.endsWith('.appimage'),
72+
(name: string) => name.endsWith('.tar.gz'),
73+
]
74+
}
75+
76+
function findBestAssetUrl(target: PlatformTarget, assets: GithubReleaseAsset[]) {
77+
const normalizedAssets = assets.map((asset) => ({
78+
...asset,
79+
normalizedName: asset.name.toLowerCase(),
80+
}))
81+
82+
for (const matcher of getAssetMatchers(target)) {
83+
const match = normalizedAssets.find((asset) => matcher(asset.normalizedName))
84+
if (match) {
85+
return match.browser_download_url
86+
}
87+
}
88+
89+
return null
90+
}
91+
92+
async function loadLatestReleaseAsset(target: PlatformTarget) {
93+
isLoading.value = true
94+
95+
try {
96+
const response = await fetch(githubLatestReleaseApi, {
97+
headers: {
98+
Accept: 'application/vnd.github+json',
99+
},
100+
})
101+
102+
if (!response.ok) {
103+
return
104+
}
105+
106+
const release = (await response.json()) as GithubLatestRelease
107+
const assetUrl = findBestAssetUrl(target, release.assets ?? [])
108+
downloadUrl.value = assetUrl || release.html_url || latestReleaseUrl
109+
} catch {
110+
downloadUrl.value = latestReleaseUrl
111+
} finally {
112+
isLoading.value = false
113+
}
114+
}
115+
116+
onMounted(() => {
117+
const detectedPlatform = detectPlatform()
118+
platform.value = detectedPlatform
119+
120+
if (detectedPlatform) {
121+
void loadLatestReleaseAsset(detectedPlatform)
122+
}
123+
})
124+
</script>
125+
126+
<template>
127+
<a
128+
:href="downloadUrl"
129+
class="whitespace-nowrap rounded-full border border-transparent bg-primary-500 hover:bg-primary-600 hover:scale-110 active:scale-95 transition-all text-[0.92rem] font-bold tracking-[-0.01em] !text-white !no-underline md:inline-flex md:items-center md:justify-center"
130+
:class="large ? '!text-xl py-3 px-8' : 'py-[0.3rem] px-4'"
131+
target="_blank"
132+
rel="noreferrer"
133+
:aria-busy="isLoading ? 'true' : 'false'"
134+
>
135+
{{ label }}
136+
</a>
137+
</template>

0 commit comments

Comments
 (0)