Skip to content

Commit

Permalink
feat: next.immich.app
Browse files Browse the repository at this point in the history
  • Loading branch information
jrasm91 committed Jan 21, 2025
1 parent d830164 commit 07e3387
Show file tree
Hide file tree
Showing 48 changed files with 3,116 additions and 23 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
app_name: ['my', 'buy', 'get']
app_name: ['my', 'buy', 'get', 'next']

steps:
- name: Checkout code
Expand Down Expand Up @@ -64,7 +64,7 @@ jobs:
fail-fast: false
max-parallel: 1
matrix:
app_name: ['my', 'buy', 'get']
app_name: ['my', 'buy', 'get', 'next']
env:
TF_VAR_app_name: ${{ matrix.app_name }}
TF_VAR_stage: ${{ github.event_name == 'pull_request' && format('pr-{0}', github.event.number) || '' }}
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/destroy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ jobs:
max-parallel: 1
matrix:
environment: ['dev', 'prod']
name: ['my', 'buy', 'get']
name: ['my', 'buy', 'get', 'next']
steps:
- name: Checkout code
uses: actions/checkout@v4
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
app_name: [my, buy, get]
app_name: [my, buy, get, next]

steps:
- name: Checkout code
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ node_modules
Thumbs.db

# Env
.env
.env.*
!.env.example
!.env.test
Expand Down
32 changes: 32 additions & 0 deletions apps/next.immich.app/routes/+layout.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<script lang="ts">
import { afterNavigate, beforeNavigate } from '$app/navigation';
import { page } from '$app/state';
import '$lib/app.css';
import { onMount, type Snippet } from 'svelte';
interface Props {
children?: Snippet;
}
let { children }: Props = $props();
let pathname = '';
onMount(() => {
pathname = page.url.pathname;
});
beforeNavigate(() => {
const newPathname = $state.snapshot(page.url.pathname);
pathname = newPathname;
});
afterNavigate(() => {
const newPathname = $state.snapshot(page.url.pathname);
if (pathname === newPathname) {
return;
}
window.scrollTo({ top: 0, behavior: 'auto' });
});
</script>

{@render children?.()}
1 change: 1 addition & 0 deletions apps/next.immich.app/routes/+layout.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const ssr = false;
62 changes: 62 additions & 0 deletions apps/next.immich.app/routes/+page.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
<script lang="ts">
import qrCode from '$lib/assets/img/app-qr-code-dark.svg';
import screenshot from '$lib/assets/img/screenshot-dark.webp';
import DocsHeader from '$lib/components/DocsHeader.svelte';
import PageContent from '$lib/components/PageContent.svelte';
import {
AppShell,
AppShellHeader,
appStoreBadge,
Button,
Heading,
HStack,
Icon,
Logo,
playStoreBadge,
Text,
VStack,
} from '@immich/ui';
import { mdiOpenInNew } from '@mdi/js';
</script>

<AppShell>
<AppShellHeader>
<DocsHeader />
</AppShellHeader>

<PageContent class="mx-auto max-w-screen-lg">
<VStack gap={8} class="p-8 text-center">
<Logo size="giant" variant="logo" class="border" />
<Heading size="title"
>Self-hosted <span class="text-primary">photo and<br /> video management</span> solution</Heading
>
<Text
>Easily back up, organize, and manage your photos on your own server. Immich helps you<br /> browse, search and organize
your photos and videos with ease, without sacrificing your privacy.</Text
>
<HStack>
<Button size="large" href="/download">Download</Button>
<Button size="large" href="https://demo.immich.app/" color="secondary">
<span>Open Demo</span>
<Icon icon={mdiOpenInNew} />
</Button>
</HStack>
<Button size="large" variant="ghost">Join our Discord</Button>

<img src={screenshot} alt="Immich application" />

<hr class="border-t w-full max-w-screen-sm m-8" />
<Heading size="title">Download mobile app</Heading>
<Text>Download Immich app and start backing up your photos and videos securely to your own server</Text>
<HStack gap={0}>
<Button href="" variant="ghost" class="p-0">
<img src={playStoreBadge} alt="Playstore Badge" class="h-24" />
</Button>
<Button href="" variant="ghost" class="p-0">
<img src={appStoreBadge} alt="Playstore Badge" class="h-24 p-4" />
</Button>
</HStack>
<img src={qrCode} alt="QRCode" class="h-36" />
</VStack>
</PageContent>
</AppShell>
18 changes: 18 additions & 0 deletions apps/next.immich.app/routes/about/+page.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<script lang="ts">
import DocsHeader from '$lib/components/DocsHeader.svelte';
import PageContent from '$lib/components/PageContent.svelte';
import { AppShell, AppShellHeader, Heading, Stack, Text } from '@immich/ui';
</script>

<AppShell>
<AppShellHeader>
<DocsHeader />
</AppShellHeader>

<PageContent class="mx-auto w-full max-w-screen-lg">
<Stack>
<Heading size="title">About</Heading>
<Text>Meet the team</Text>
</Stack>
</PageContent>
</AppShell>
12 changes: 12 additions & 0 deletions apps/next.immich.app/routes/api/+layout.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { goto } from '$app/navigation';
import { loadOpenApi } from '$lib/services/open-api.svelte';
import type { LayoutLoad } from './$types';

export const load = (async ({ fetch }) => {
try {
await loadOpenApi(fetch);
} catch (error) {
console.log('Failed to load open-api specification', error);
await goto('/');
}
}) satisfies LayoutLoad;
112 changes: 112 additions & 0 deletions apps/next.immich.app/routes/api/+page.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
<script lang="ts">
import DocsHeader from '$lib/components/DocsHeader.svelte';
import PageContent from '$lib/components/PageContent.svelte';
import {
Alert,
AppShell,
AppShellHeader,
AppShellSidebar,
Card,
CardBody,
CardHeader,
Code,
Heading,
Link,
NavbarGroup,
NavbarItem,
Text,
} from '@immich/ui';
import { mdiCodeJson, mdiHomeOutline, mdiLightbulbOnOutline, mdiPencilRuler } from '@mdi/js';
</script>

<AppShell>
<AppShellHeader>
<DocsHeader />
</AppShellHeader>

<AppShellSidebar class="min-w-[300px]">
<div class="mt-4 mr-0 md:mr-4">
<NavbarGroup title="API Documentation" />
<NavbarItem title="Overview" href="/api" icon={mdiHomeOutline} />
<NavbarItem title="Endpoints" href="/api/endpoints" icon={mdiCodeJson} />
<NavbarItem title="Models" href="/api/models" icon={mdiPencilRuler} />
</div>
</AppShellSidebar>

<PageContent>
<Heading size="large">Welcome</Heading>
<Text>This is documentation for the API that powers <Link href="https://immich.app">Immich</Link></Text>

<section class="mt-4">
<Heading size="small">Authentication</Heading>
<Text>Users or applications can authenticate with the Immich Api using one of the values listed below.</Text>

<Card class="mt-2">
<CardHeader class="py-1 bg-subtle">
<div class="grid grid-cols-3">
<div class="font-bold">Value</div>
<div class="font-bold">Type</div>
<div class="font-bold">Description</div>
</div>
</CardHeader>
<CardBody>
<div class="grid grid-cols-3 gap-y-1">
<div><Code>x-api-key</Code></div>
<div>Header</div>
<div>Api key value sent as a http header</div>

<div><Code>x-immich-user-token</Code></div>
<div>Header</div>
<div>Session token sent as a http header</div>

<div><Code>x-immich-session-token</Code></div>
<div>Header</div>
<div>Session token sent as a http header</div>

<div><Code>apiKey</Code></div>
<div>Query Param</div>
<div>Api key value sent as a query parameter</div>

<div><Code>sessionKey</Code></div>
<div>Query Param</div>
<div>Session token sent as a query parameter</div>

<div><Code>key</Code></div>
<div>Query Param</div>
<div>Shared link key sent as a query parameter</div>
</div>
</CardBody>
</Card>

<Alert color="success" title="Tip" icon={mdiLightbulbOnOutline}>
<Text
>User-scoped api keys can be created in <Link href="https://my.immich.app/user-settings?isOpen=api-keys"
>user settings</Link
>
</Text>
</Alert>
</section>

<section class="mt-4">
<Heading size="small">Open API</Heading>
<Text
>Immich uses the <Code>nest-swagger</Code> library to automatically generate a Open API compatible JSON document.
This document is used to generate this documentation, as well as the <Code>@immich/sdk</Code> TypeScript client sdk</Text
>
</section>

<section class="mt-4">
<Heading size="small">SDK</Heading>
<Text
>For more information about the <Code>@immich/sdk</Code> package, see the <Link
href="https://www.npmjs.com/package/@immich/sdk">project on npm</Link
></Text
>
</section>

<section class="mt-4">
<Heading size="small">SDK</Heading>
<Text>Immich</Text>
</section>
</PageContent>
</AppShell>
45 changes: 45 additions & 0 deletions apps/next.immich.app/routes/api/endpoints/+layout.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<script lang="ts">
import DocsHeader from '$lib/components/DocsHeader.svelte';
import PageContent from '$lib/components/PageContent.svelte';
import { getOpenApi } from '$lib/services/open-api.svelte';
import { getIcon } from '$lib/utils/icons';
import { AppShell, AppShellHeader, AppShellSidebar, Button, Icon, NavbarGroup, NavbarItem } from '@immich/ui';
import { mdiArrowLeft } from '@mdi/js';
import type { Snippet } from 'svelte';
type Props = {
children?: Snippet;
};
const { children }: Props = $props();
const { tags } = getOpenApi();
</script>

<AppShell>
<AppShellHeader>
<DocsHeader />
</AppShellHeader>

<AppShellSidebar class="min-w-[300px]">
<Button
variant="ghost"
color="secondary"
href="/api"
shape="rectangle"
class="flex justify-start py-4"
size="small"
>
<Icon icon={mdiArrowLeft} />
Back
</Button>
<NavbarGroup title="Endpoints" />
{#each tags as tag}
<NavbarItem title={tag.name} href={tag.href} icon={getIcon(tag.name)} variant="compact" />
{/each}
</AppShellSidebar>

<PageContent>
{@render children?.()}
</PageContent>
</AppShell>
33 changes: 33 additions & 0 deletions apps/next.immich.app/routes/api/endpoints/+page.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<script lang="ts">
import { getOpenApi, getTagEndpointHref } from '$lib/services/open-api.svelte';
import { getIcon } from '$lib/utils/icons';
import { Card, CardBody, CardHeader, CardTitle, Heading, Icon, Link, Stack } from '@immich/ui';
const { tags } = getOpenApi();
</script>

<Stack gap={8}>
<Heading size="large">API Endpoints</Heading>

<div class="grid grid-cols-1 lg:grid-cols-3 gap-2">
{#each tags as tag}
<Card color="secondary">
<CardHeader>
<CardTitle class="flex gap-2 items-center">
<Icon icon={getIcon(tag.name)} />
<Link href={tag.href}>{tag.name}</Link>
</CardTitle>
</CardHeader>
<CardBody>
<Stack gap={1}>
{#each tag.endpoints as endpoint}
<Link href={getTagEndpointHref(tag, endpoint)} class="no-underline hover:underline"
>{endpoint.method} {endpoint.route}</Link
>
{/each}
</Stack>
</CardBody>
</Card>
{/each}
</div>
</Stack>
Loading

0 comments on commit 07e3387

Please sign in to comment.