Skip to content

Commit

Permalink
feat(docs): added documentation website
Browse files Browse the repository at this point in the history
  • Loading branch information
CorentinTh committed Sep 2, 2024
1 parent b848f84 commit 178747e
Show file tree
Hide file tree
Showing 24 changed files with 1,478 additions and 9 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,5 @@ logs
!.env.example

.wrangler
coverage
coverage
cache
3 changes: 2 additions & 1 deletion packages/app-client/.env.example
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
VITE_BASE_API_URL=http://localhost:8787
VITE_BASE_API_URL=http://localhost:8787
VITE_FALLBACK_DOCUMENTATION_URL=http://localhost:3001
2 changes: 2 additions & 0 deletions packages/app-client/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,5 @@ gitignore
# System Files
.DS_Store
Thumbs.db

cache
3 changes: 2 additions & 1 deletion packages/app-client/public/robots.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
User-agent: *
Disallow: /
Allow: /$
Allow: /og-image.png
Allow: /og-image.png
Allow: /docs/
2 changes: 2 additions & 0 deletions packages/app-client/src/modules/config/config.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
export const config = {
baseApiUrl: import.meta.env.VITE_BASE_API_URL ?? window.location.origin,
isBundledWithDocumentation: import.meta.env.VITE_IS_BUNDLED_WITH_DOCUMENTATION === 'true',
fallbackDocumentationUrl: import.meta.env.VITE_FALLBACK_DOCUMENTATION_URL ?? 'https://enclosed.cc',
};
69 changes: 69 additions & 0 deletions packages/app-client/src/modules/docs/docs.models.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import { describe, expect, test } from 'vitest';
import { buildDocUrl, joinUrlParts } from './docs.models';

describe('docs models', () => {
describe('buildDocUrl', () => {
test('if the app is bundled with documentation, we use the same origin', () => {
expect(
buildDocUrl({
path: '/test',
isBundledWithDocumentation: true,
currentOrigin: 'http://localhost',
fallbackDocumentationUrl: 'https://enclosed.cc/',
}),
).to.eql('http://localhost/docs/test');
});

test('if the app is not bundled with documentation, we use the fallback URL', () => {
expect(
buildDocUrl({
path: '/test',
isBundledWithDocumentation: false,
currentOrigin: 'http://localhost',
fallbackDocumentationUrl: 'https://enclosed.cc/',
}),
).to.eql('https://enclosed.cc/test');

expect(
buildDocUrl({
path: '/test',
isBundledWithDocumentation: false,
currentOrigin: 'http://localhost',
fallbackDocumentationUrl: 'https://enclosed.cc/docs',
}),
).to.eql('https://enclosed.cc/docs/test');
});

test('with resilience to trailing slashes', () => {
expect(
buildDocUrl({
path: 'test',
isBundledWithDocumentation: false,
currentOrigin: 'http://localhost',
fallbackDocumentationUrl: 'https://enclosed.cc/',
}),
).to.eql('https://enclosed.cc/test');

expect(
buildDocUrl({
path: '/test',
isBundledWithDocumentation: false,
currentOrigin: 'http://localhost',
fallbackDocumentationUrl: 'https://enclosed.cc/',
}),
).to.eql('https://enclosed.cc/test');
});
});

describe('joinUrlParts', () => {
test('it merges url parts and trim slashes', () => {
expect(joinUrlParts('/part1/', '/part2/', 'part3', 'part4/')).to.eql('part1/part2/part3/part4');
expect(joinUrlParts('/part1/part2/', 'part3', 'part4/')).to.eql('part1/part2/part3/part4');
expect(joinUrlParts('')).to.eql('');
});

test('multiple slashes inside a part are preserved', () => {
expect(joinUrlParts('/part1//part2/', '/part3/')).to.eql('part1//part2/part3');
});
});
});
23 changes: 23 additions & 0 deletions packages/app-client/src/modules/docs/docs.models.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { config } from '../config/config';

export { buildDocUrl, joinUrlParts };

function joinUrlParts(...parts: string[]): string {
return parts.map(part => part.replace(/(^\/|\/$)/g, '')).join('/');
}

function buildDocUrl({
path,
currentOrigin = window.location.origin,
isBundledWithDocumentation = config.isBundledWithDocumentation,
fallbackDocumentationUrl = config.fallbackDocumentationUrl,
}: {
path: string;
currentOrigin?: string;
isBundledWithDocumentation?: boolean;
fallbackDocumentationUrl?: string;
}): string {
const origin = isBundledWithDocumentation ? joinUrlParts(currentOrigin, 'docs') : fallbackDocumentationUrl;

return joinUrlParts(origin, path);
}
38 changes: 33 additions & 5 deletions packages/app-client/src/modules/ui/layouts/app.layout.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { A, useNavigate } from '@solidjs/router';
import type { Component, ParentComponent } from 'solid-js';
import { DropdownMenu } from '@kobalte/core/dropdown-menu';
import { DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from '../components/dropdown-menu';
import { DropdownMenuContent, DropdownMenuItem, DropdownMenuSeparator, DropdownMenuTrigger } from '../components/dropdown-menu';
import { Button } from '@/modules/ui/components/button';
import { useThemeStore } from '@/modules/theme/theme.store';
import { useNoteContext } from '@/modules/notes/notes.context';
import { buildDocUrl } from '@/modules/docs/docs.models';

export const Navbar: Component = () => {
const themeStore = useThemeStore();
Expand Down Expand Up @@ -43,21 +44,48 @@ export const Navbar: Component = () => {
<DropdownMenuTrigger as={Button} class="text-lg px-0 size-9" variant="ghost" aria-label="Change theme">
<div classList={{ 'i-tabler-moon': themeStore.getColorMode() === 'dark', 'i-tabler-sun': themeStore.getColorMode() === 'light' }}></div>
</DropdownMenuTrigger>
<DropdownMenuContent>
<DropdownMenuItem onClick={() => themeStore.setColorMode({ mode: 'light' })} class="flex items-center gap-2">
<DropdownMenuContent class="w-42">
<DropdownMenuItem onClick={() => themeStore.setColorMode({ mode: 'light' })} class="flex items-center gap-2 cursor-pointer">
<div class="i-tabler-sun text-lg"></div>
Light mode
</DropdownMenuItem>
<DropdownMenuItem onClick={() => themeStore.setColorMode({ mode: 'dark' })} class="flex items-center gap-2">
<DropdownMenuItem onClick={() => themeStore.setColorMode({ mode: 'dark' })} class="flex items-center gap-2 cursor-pointer">
<div class="i-tabler-moon text-lg"></div>
Dark mode
</DropdownMenuItem>
<DropdownMenuItem onClick={() => themeStore.setColorMode({ mode: 'system' })} class="flex items-center gap-2">
<DropdownMenuItem onClick={() => themeStore.setColorMode({ mode: 'system' })} class="flex items-center gap-2 cursor-pointer">
<div class="i-tabler-device-laptop text-lg"></div>
System
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>

<DropdownMenu>
<DropdownMenuTrigger as={Button} class="text-lg px-0 size-9" variant="ghost" aria-label="Change theme">
<div class="i-tabler-dots-vertical"></div>
</DropdownMenuTrigger>

<DropdownMenuContent class="w-46">
<DropdownMenuItem as="a" class="flex items-center gap-2 cursor-pointer" target="_blank" href={buildDocUrl({ path: '/' })}>
<div class="i-tabler-file-text text-lg"></div>
Documentation
</DropdownMenuItem>

<DropdownMenuItem as="a" class="flex items-center gap-2 cursor-pointer" target="_blank" href={buildDocUrl({ path: '/cli' })}>
<div class="i-tabler-terminal text-lg"></div>
Enclosed CLI
</DropdownMenuItem>

<DropdownMenuSeparator />

<DropdownMenuItem as="a" class="flex items-center gap-2 cursor-pointer" target="_blank" href="https://buymeacoffee.com/cthmsst" rel="noopener noreferrer">
<div class="i-tabler-pig-money text-lg"></div>
Support Enclosed
</DropdownMenuItem>

</DropdownMenuContent>

</DropdownMenu>
</div>
</div>
</div>
Expand Down
5 changes: 4 additions & 1 deletion packages/deploy-cloudflare/build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,18 @@

# Build the app server and client
pnpm --filter @enclosed/app-server build:cloudflare
pnpm --filter @enclosed/app-client build
VITE_IS_BUNDLED_WITH_DOCUMENTATION=true pnpm --filter @enclosed/app-client build
DOCS_BASE_PATH=/docs/ pnpm --filter @enclosed/docs build

# Reset the dist folder
rm -rf dist
mkdir dist
mkdir dist/docs

# Copy the app server and client to the dist folder
cp -r ../app-server/dist-cloudflare/* dist/
cp -r ../app-client/dist/* dist/
cp -r ../docs/dist/* dist/docs/

# Copy routes.json to the dist folder
cp _routes.json dist/
125 changes: 125 additions & 0 deletions packages/docs/.vitepress/config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
import { defineConfig } from 'vitepress';

const basePath = process.env.DOCS_BASE_PATH; // undefined for root /

const createAbsoluteUrl = (path: string) => 'https://enclosed.cc/' + path.replace(/(^\/$)/g, '');

// https://vitepress.dev/reference/site-config
export default defineConfig({
title: 'Enclosed',
description: 'Send private and secure notes',
base: basePath,
lang: 'en-US',
lastUpdated: true,
srcDir: './src',
outDir: './dist',

markdown: {
theme: {
dark: 'github-dark',
light: 'github-light',
},
},

head: [
['link', { rel: 'icon', href: '/favicon.ico' }],
['meta', { name: 'author', content: 'Corentin Thomasset' }],
['meta', { name: 'keywords', content: 'Enclosed, notes, secure, private, encrypted, self-hosted' }],

['meta', {name: 'og:title', content: 'Enclosed documentation'}],
['meta', {name: 'og:description', content: 'Send private and secure notes'}],
['meta', {name: 'og:image', content: createAbsoluteUrl('og-image.png')}],
['meta', {name: 'og:url', content: 'https://enclosed.cc'}],
['meta', {name: 'og:type', content: 'website'}],
['meta', {name: 'og:site_name', content: 'Enclosed'}],
['meta', {name: 'og:locale', content: 'en_US'}],

['meta', {name: 'twitter:card', content: 'summary'}],
['meta', {name: 'twitter:site', content: '@cthmsst'}],
['meta', {name: 'twitter:creator', content: '@cthmsst'}],
['meta', {name: 'twitter:title', content: 'Enclosed documentation'}],
['meta', {name: 'twitter:description', content: 'Send private and secure notes'}],
['meta', {name: 'twitter:image', content: createAbsoluteUrl('og-image.png')}],
],

themeConfig: {

logo: {
light: '/logo-light.svg',
dark: '/logo-dark.svg',
alt: 'Logo',
},

siteTitle: 'Enclosed - DOCS',

// https://vitepress.dev/reference/default-theme-config
nav: [
{ text: 'Enclosed App', link: 'https://enclosed.cc' },
],

sidebar: [
{
text: 'Enclosed',
items: [
{ text: 'Introduction', link: '/' },
{ text: 'How it works?', link: '/how-it-works' },
],
},
{
text: 'Self hosting',
items: [
{ text: 'Using Docker', link: '/self-hosting/docker' },
{ text: 'Using Docker Compose', link: '/self-hosting/docker-compose' },
{ text: 'Configuration', link: '/self-hosting/configuration' },
],
},
{
text: 'Integrations',
items: [
{ text: 'CLI', link: '/integrations/cli' },
{ text: 'NPM package', link: '/integrations/npm-package' },
]
},
],


footer: {
copyright: 'Copyright © 2024-present Corentin Thomasset',
},

editLink: {
pattern: 'https://github.com/CorentinTh/enclosed/edit/main/packages/docs/src/:path',
text: 'Edit this page on GitHub',
},

socialLinks: [
{ icon: 'github', link: 'https://github.com/CorentinTh/enclosed', ariaLabel: 'GitHub' },
{ icon: 'twitter', link: 'https://twitter.com/cthmsst', ariaLabel: 'Twitter' },
],

search: {
provider: 'local',

options: {
detailedView: true,

miniSearch: {
/**
* @type {Pick<import('minisearch').Options, 'extractField' | 'tokenize' | 'processTerm'>}
*/
options: {
},
/**
* @type {import('minisearch').SearchOptions}
*/
searchOptions: {
fuzzy: 0.3,
prefix: true,
boost: { title: 4, text: 2, titles: 1 },
},
},
},
},
},
});

19 changes: 19 additions & 0 deletions packages/docs/.vitepress/theme/custom.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
:root {
--vp-c-brand-1: #000000;
--vp-c-brand-2: #000000;
}

.dark {
--vp-c-brand-1: #ffffff;
--vp-c-brand-2: #ffffff;

--vp-c-text-1: rgba(255, 255, 245, 0.92);
--vp-c-text-2: rgba(235, 235, 245, 0.6);
--vp-c-text-3: rgba(235, 235, 245, 0.38);
}


.VPSocialLink span{
height: 18px !important;
width: 18px !important;
}
4 changes: 4 additions & 0 deletions packages/docs/.vitepress/theme/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import DefaultTheme from 'vitepress/theme'
import './custom.css'

export default DefaultTheme
23 changes: 23 additions & 0 deletions packages/docs/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"name": "@enclosed/docs",
"version": "0.0.0",
"type": "module",
"packageManager": "pnpm@9.9.0",
"description": "Documentation website for Enclosed.",
"author": "Corentin Thomasset <corentinth@proton.me> (https://corentin.tech)",
"license": "Apache-2.0",
"repository": {
"type": "git",
"url": "https://github.com/CorentinTh/enclosed"
},
"main": "index.js",
"scripts": {
"dev": "vitepress dev --port 3001",
"build": "vitepress build",
"preview": "vitepress preview"
},
"keywords": [],
"devDependencies": {
"vitepress": "^1.3.4"
}
}
Loading

0 comments on commit 178747e

Please sign in to comment.