nsarrazin HF staff commited on
Commit
5d07536
β€’
1 Parent(s): abe7804

Added ChatUI branding & put theming behind an env variable (#298)

Browse files

* Moved all huggingchat branding behind an env variable

* Refactored branding to use multiple env variables

* pr review

* prettier

* move the ethics modal behind the flag PUBLIC_APP_DISCLAIMER

* inline chat ui logo so it would take the color

* flex-none

.env CHANGED
@@ -68,3 +68,16 @@ PUBLIC_ANNOUNCEMENT_BANNERS=`[
68
  PARQUET_EXPORT_DATASET=
69
  PARQUET_EXPORT_HF_TOKEN=
70
  PARQUET_EXPORT_SECRET=
 
 
 
 
 
 
 
 
 
 
 
 
 
68
  PARQUET_EXPORT_DATASET=
69
  PARQUET_EXPORT_HF_TOKEN=
70
  PARQUET_EXPORT_SECRET=
71
+
72
+
73
+ PUBLIC_APP_NAME=ChatUI # name used as title throughout the app
74
+ PUBLIC_APP_ASSETS=chatui # used to find logos & favicons in static/$PUBLIC_APP_ASSETS
75
+ PUBLIC_APP_COLOR=blue # can be any of tailwind colors: https://tailwindcss.com/docs/customizing-colors#default-color-palette
76
+ PUBLIC_APP_DATA_SHARING=#set to 1 to enable options & text regarding data sharing
77
+ PUBLIC_APP_DISCLAIMER=#set to 1 to show a disclaimer on login page
78
+
79
+ # PUBLIC_APP_NAME=HuggingChat
80
+ # PUBLIC_APP_ASSETS=huggingchat
81
+ # PUBLIC_APP_COLOR=yellow
82
+ # PUBLIC_APP_DATA_SHARING=1
83
+ # PUBLIC_APP_DISCLAIMER=1
src/app.html CHANGED
@@ -2,29 +2,7 @@
2
  <html lang="en" class="h-full">
3
  <head>
4
  <meta charset="utf-8" />
5
- <link rel="icon" href="%sveltekit.assets%/favicon.svg" type="image/svg+xml" />
6
- <link rel="icon" href="%sveltekit.assets%/favicon.png" type="image/png" />
7
- <!-- Icon Support for iOS Bookmark Home Screen -->
8
- <link
9
- rel="apple-touch-icon"
10
- href="%sveltekit.assets%/touch-icon-ipad-retina.png"
11
- sizes="167x167"
12
- type="image/png"
13
- />
14
- <link
15
- rel="apple-touch-icon"
16
- href="%sveltekit.assets%/touch-icon-ipad.png"
17
- sizes="152x152"
18
- type="image/png"
19
- />
20
- <link
21
- rel="apple-touch-icon"
22
- href="%sveltekit.assets%/touch-icon-iphone-retina.png"
23
- sizes="180x180"
24
- type="image/png"
25
- />
26
  <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no" />
27
- <title>HuggingChat</title>
28
  <script>
29
  if (
30
  localStorage.theme === "dark" ||
2
  <html lang="en" class="h-full">
3
  <head>
4
  <meta charset="utf-8" />
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5
  <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no" />
 
6
  <script>
7
  if (
8
  localStorage.theme === "dark" ||
src/hooks.server.ts CHANGED
@@ -4,6 +4,7 @@ import {
4
  PUBLIC_GOOGLE_ANALYTICS_ID,
5
  PUBLIC_DEPRECATED_GOOGLE_ANALYTICS_ID,
6
  PUBLIC_ORIGIN,
 
7
  } from "$env/static/public";
8
  import { collections } from "$lib/server/database";
9
  import { base } from "$app/paths";
@@ -67,9 +68,14 @@ export const handle: Handle = async ({ event, resolve }) => {
67
  return errorResponse(401, ERROR_MESSAGES.authOnly);
68
  }
69
 
70
- // if login is not required and the call is not from /settings, we check if the user has accepted the ethics modal first.
 
71
  // If login is required, `ethicsModalAcceptedAt` is already true at this point, so do not pass this condition. This saves a DB call.
72
- if (!requiresUser && !event.url.pathname.startsWith(`${base}/settings`)) {
 
 
 
 
73
  const hasAcceptedEthicsModal = await collections.settings.countDocuments({
74
  sessionId: event.locals.sessionId,
75
  ethicsModalAcceptedAt: { $exists: true },
4
  PUBLIC_GOOGLE_ANALYTICS_ID,
5
  PUBLIC_DEPRECATED_GOOGLE_ANALYTICS_ID,
6
  PUBLIC_ORIGIN,
7
+ PUBLIC_APP_DISCLAIMER,
8
  } from "$env/static/public";
9
  import { collections } from "$lib/server/database";
10
  import { base } from "$app/paths";
68
  return errorResponse(401, ERROR_MESSAGES.authOnly);
69
  }
70
 
71
+ // if login is not required and the call is not from /settings and we display the ethics modal with PUBLIC_APP_DISCLAIMER
72
+ // we check if the user has accepted the ethics modal first.
73
  // If login is required, `ethicsModalAcceptedAt` is already true at this point, so do not pass this condition. This saves a DB call.
74
+ if (
75
+ !requiresUser &&
76
+ !event.url.pathname.startsWith(`${base}/settings`) &&
77
+ !!PUBLIC_APP_DISCLAIMER
78
+ ) {
79
  const hasAcceptedEthicsModal = await collections.settings.countDocuments({
80
  sessionId: event.locals.sessionId,
81
  ethicsModalAcceptedAt: { $exists: true },
src/lib/components/AnnouncementBanner.svelte CHANGED
@@ -5,7 +5,7 @@
5
 
6
  <div class="flex items-center rounded-xl bg-gray-100 p-1 text-sm dark:bg-gray-800 {classNames}">
7
  <span
8
- class="mr-2 inline-flex items-center rounded-lg bg-gradient-to-br from-yellow-300 px-2 py-1 text-xxs font-medium uppercase leading-3 text-yellow-700 dark:from-[#373010] dark:text-yellow-400"
9
  >New</span
10
  >
11
  {title}
5
 
6
  <div class="flex items-center rounded-xl bg-gray-100 p-1 text-sm dark:bg-gray-800 {classNames}">
7
  <span
8
+ class="mr-2 inline-flex items-center rounded-lg bg-gradient-to-br from-primary-300 px-2 py-1 text-xxs font-medium uppercase leading-3 text-primary-700 dark:from-primary-900 dark:text-primary-400"
9
  >New</span
10
  >
11
  {title}
src/lib/components/LoginModal.svelte CHANGED
@@ -2,12 +2,11 @@
2
  import { browser } from "$app/environment";
3
  import { base } from "$app/paths";
4
  import { page } from "$app/stores";
5
- import { PUBLIC_VERSION } from "$env/static/public";
6
- import Logo from "$lib/components/icons/Logo.svelte";
7
  import LogoHuggingFaceBorderless from "$lib/components/icons/LogoHuggingFaceBorderless.svelte";
8
  import Modal from "$lib/components/Modal.svelte";
9
  import type { LayoutData } from "../../routes/$types";
10
-
11
  export let settings: LayoutData["settings"];
12
 
13
  const isIframe = browser && window.self !== window.parent;
@@ -15,10 +14,11 @@
15
 
16
  <Modal>
17
  <div
18
- class="flex w-full flex-col items-center gap-6 bg-gradient-to-t from-yellow-500/40 via-yellow-500/10 to-yellow-500/0 px-4 pb-10 pt-9 text-center"
19
  >
20
  <h2 class="flex items-center text-2xl font-semibold text-gray-800">
21
- <Logo classNames="text-3xl mr-1.5" />HuggingChat
 
22
  <div
23
  class="ml-3 flex h-6 items-center rounded-lg border border-gray-100 bg-gray-50 px-2 text-base text-gray-400"
24
  >
@@ -32,20 +32,27 @@
32
  AI is an area of active research with known problems such as biased generation and
33
  misinformation. Do not use this application for high-stakes decisions or advice.
34
  </p>
35
- <p class="px-2 text-sm text-gray-500">
36
- Your conversations will be shared with model authors unless you disable it from your settings.
37
- </p>
 
 
 
38
  <form
39
  action="{base}/{$page.data.requiresLogin ? 'login' : 'settings'}"
40
  target={isIframe ? "_blank" : ""}
41
  method="POST"
 
42
  >
43
  {#if $page.data.requiresLogin}
44
  <button
45
  type="submit"
46
- class="mt-2 flex items-center whitespace-nowrap rounded-full bg-black px-5 py-2 text-lg font-semibold text-gray-100 transition-colors hover:bg-yellow-500"
47
  >
48
- Sign in with <LogoHuggingFaceBorderless classNames="text-xl mr-1 ml-1.5" /> Hugging Face
 
 
 
49
  </button>
50
  <p class="mt-2 px-2 text-sm text-gray-500">to start chatting right away</p>
51
  {:else}
@@ -55,7 +62,7 @@
55
  {/each}
56
  <button
57
  type="submit"
58
- class="mt-2 rounded-full bg-black px-5 py-2 text-lg font-semibold text-gray-100 transition-colors hover:bg-yellow-500"
59
  >
60
  Start chatting
61
  </button>
2
  import { browser } from "$app/environment";
3
  import { base } from "$app/paths";
4
  import { page } from "$app/stores";
5
+ import { PUBLIC_APP_DATA_SHARING, PUBLIC_APP_NAME, PUBLIC_VERSION } from "$env/static/public";
 
6
  import LogoHuggingFaceBorderless from "$lib/components/icons/LogoHuggingFaceBorderless.svelte";
7
  import Modal from "$lib/components/Modal.svelte";
8
  import type { LayoutData } from "../../routes/$types";
9
+ import Logo from "./icons/Logo.svelte";
10
  export let settings: LayoutData["settings"];
11
 
12
  const isIframe = browser && window.self !== window.parent;
14
 
15
  <Modal>
16
  <div
17
+ class="flex w-full flex-col items-center gap-6 bg-gradient-to-t from-primary-500/40 via-primary-500/10 to-primary-500/0 px-4 pb-10 pt-9 text-center "
18
  >
19
  <h2 class="flex items-center text-2xl font-semibold text-gray-800">
20
+ <Logo classNames="mr-1" />
21
+ {PUBLIC_APP_NAME}
22
  <div
23
  class="ml-3 flex h-6 items-center rounded-lg border border-gray-100 bg-gray-50 px-2 text-base text-gray-400"
24
  >
32
  AI is an area of active research with known problems such as biased generation and
33
  misinformation. Do not use this application for high-stakes decisions or advice.
34
  </p>
35
+ {#if PUBLIC_APP_DATA_SHARING}
36
+ <p class="px-2 text-sm text-gray-500">
37
+ Your conversations will be shared with model authors unless you disable it from your
38
+ settings.
39
+ </p>
40
+ {/if}
41
  <form
42
  action="{base}/{$page.data.requiresLogin ? 'login' : 'settings'}"
43
  target={isIframe ? "_blank" : ""}
44
  method="POST"
45
+ class="flex w-full flex-col items-center gap-2"
46
  >
47
  {#if $page.data.requiresLogin}
48
  <button
49
  type="submit"
50
+ class="mt-2 flex items-center whitespace-nowrap rounded-full bg-black px-5 py-2 text-lg font-semibold text-gray-100 transition-colors hover:bg-primary-500"
51
  >
52
+ Sign in
53
+ {#if PUBLIC_APP_NAME === "HuggingChat"}
54
+ with <LogoHuggingFaceBorderless classNames="text-xl mr-1 ml-1.5" /> Hugging Face
55
+ {/if}
56
  </button>
57
  <p class="mt-2 px-2 text-sm text-gray-500">to start chatting right away</p>
58
  {:else}
62
  {/each}
63
  <button
64
  type="submit"
65
+ class="mt-2 rounded-full bg-black px-5 py-2 text-lg font-semibold text-gray-100 transition-colors hover:bg-primary-500"
66
  >
67
  Start chatting
68
  </button>
src/lib/components/ModelsModal.svelte CHANGED
@@ -41,7 +41,7 @@
41
  {#each models as model}
42
  <div
43
  class="rounded-xl border border-gray-100 {model.id === selectedModelId
44
- ? 'bg-gradient-to-r from-yellow-200/40 via-yellow-500/10'
45
  : ''}"
46
  >
47
  <label class="group flex cursor-pointer p-3" on:change aria-label={model.displayName}>
@@ -62,7 +62,7 @@
62
  </span>
63
  <CarbonCheckmark
64
  class="-mr-1 -mt-1 ml-auto shrink-0 text-xl {model.id === selectedModelId
65
- ? 'text-yellow-400'
66
  : 'text-transparent group-hover:text-gray-200'}"
67
  />
68
  </label>
41
  {#each models as model}
42
  <div
43
  class="rounded-xl border border-gray-100 {model.id === selectedModelId
44
+ ? 'bg-gradient-to-r from-primary-200/40 via-primary-500/10'
45
  : ''}"
46
  >
47
  <label class="group flex cursor-pointer p-3" on:change aria-label={model.displayName}>
62
  </span>
63
  <CarbonCheckmark
64
  class="-mr-1 -mt-1 ml-auto shrink-0 text-xl {model.id === selectedModelId
65
+ ? 'text-primary-400'
66
  : 'text-transparent group-hover:text-gray-200'}"
67
  />
68
  </label>
src/lib/components/NavMenu.svelte CHANGED
@@ -4,7 +4,7 @@
4
 
5
  import Logo from "$lib/components/icons/Logo.svelte";
6
  import { switchTheme } from "$lib/switchTheme";
7
- import { PUBLIC_ORIGIN } from "$env/static/public";
8
  import NavConversationItem from "./NavConversationItem.svelte";
9
  import type { LayoutData } from "../../routes/$types";
10
 
@@ -23,8 +23,8 @@
23
 
24
  <div class="sticky top-0 flex flex-none items-center justify-between px-3 py-3.5 max-sm:pt-0">
25
  <a class="flex items-center rounded-xl text-lg font-semibold" href="{PUBLIC_ORIGIN}{base}/">
26
- <Logo classNames="mr-1 text-3xl" />
27
- HuggingChat
28
  </a>
29
  <a
30
  href={`${base}/`}
@@ -75,18 +75,20 @@
75
  >
76
  Settings
77
  </button>
78
- <a
79
- href="https://huggingface.co/spaces/huggingchat/chat-ui/discussions"
80
- target="_blank"
81
- rel="noreferrer"
82
- class="flex h-9 flex-none items-center gap-1.5 rounded-lg pl-3 pr-2 text-gray-500 hover:bg-gray-100 dark:text-gray-400 dark:hover:bg-gray-700"
83
- >
84
- Feedback
85
- </a>
86
- <a
87
- href="{base}/privacy"
88
- class="flex h-9 flex-none items-center gap-1.5 rounded-lg pl-3 pr-2 text-gray-500 hover:bg-gray-100 dark:text-gray-400 dark:hover:bg-gray-700"
89
- >
90
- About & Privacy
91
- </a>
 
 
92
  </div>
4
 
5
  import Logo from "$lib/components/icons/Logo.svelte";
6
  import { switchTheme } from "$lib/switchTheme";
7
+ import { PUBLIC_APP_NAME, PUBLIC_ORIGIN } from "$env/static/public";
8
  import NavConversationItem from "./NavConversationItem.svelte";
9
  import type { LayoutData } from "../../routes/$types";
10
 
23
 
24
  <div class="sticky top-0 flex flex-none items-center justify-between px-3 py-3.5 max-sm:pt-0">
25
  <a class="flex items-center rounded-xl text-lg font-semibold" href="{PUBLIC_ORIGIN}{base}/">
26
+ <Logo classNames="mr-1" />
27
+ {PUBLIC_APP_NAME}
28
  </a>
29
  <a
30
  href={`${base}/`}
75
  >
76
  Settings
77
  </button>
78
+ {#if PUBLIC_APP_NAME === "HuggingChat"}
79
+ <a
80
+ href="https://huggingface.co/spaces/huggingchat/chat-ui/discussions"
81
+ target="_blank"
82
+ rel="noreferrer"
83
+ class="flex h-9 flex-none items-center gap-1.5 rounded-lg pl-3 pr-2 text-gray-500 hover:bg-gray-100 dark:text-gray-400 dark:hover:bg-gray-700"
84
+ >
85
+ Feedback
86
+ </a>
87
+ <a
88
+ href="{base}/privacy"
89
+ class="flex h-9 flex-none items-center gap-1.5 rounded-lg pl-3 pr-2 text-gray-500 hover:bg-gray-100 dark:text-gray-400 dark:hover:bg-gray-700"
90
+ >
91
+ About & Privacy
92
+ </a>
93
+ {/if}
94
  </div>
src/lib/components/SettingsModal.svelte CHANGED
@@ -7,6 +7,7 @@
7
  import type { Settings } from "$lib/types/Settings";
8
  import { enhance } from "$app/forms";
9
  import { base } from "$app/paths";
 
10
 
11
  export let settings: Pick<Settings, "shareConversationsWithModelAuthors">;
12
 
@@ -32,32 +33,35 @@
32
  method="post"
33
  action="{base}/settings"
34
  >
35
- <label class="flex cursor-pointer select-none items-center gap-2 text-gray-500">
36
- {#each Object.entries(settings).filter(([k]) => k !== "shareConversationsWithModelAuthors") as [key, val]}
37
- <input type="hidden" name={key} value={val} />
38
- {/each}
39
- <Switch
40
- name="shareConversationsWithModelAuthors"
41
- bind:checked={shareConversationsWithModelAuthors}
42
- />
43
- Share conversations with model authors
44
- </label>
 
45
 
46
- <p class="text-gray-800">
47
- Sharing your data will help improve the training data and make open models better over time.
48
- </p>
49
- <p class="text-gray-800">
50
- You can change this setting at any time, it applies to all your conversations.
51
- </p>
52
- <p class="text-gray-800">
53
- Read more about this model's authors,
54
- <a
55
- href="https://open-assistant.io/"
56
- target="_blank"
57
- rel="noreferrer"
58
- class="underline decoration-gray-300 hover:decoration-gray-700">Open Assistant</a
59
- >.
60
- </p>
 
 
61
  <form
62
  method="post"
63
  action="{base}/conversations?/delete"
7
  import type { Settings } from "$lib/types/Settings";
8
  import { enhance } from "$app/forms";
9
  import { base } from "$app/paths";
10
+ import { PUBLIC_APP_DATA_SHARING } from "$env/static/public";
11
 
12
  export let settings: Pick<Settings, "shareConversationsWithModelAuthors">;
13
 
33
  method="post"
34
  action="{base}/settings"
35
  >
36
+ {#if PUBLIC_APP_DATA_SHARING}
37
+ <label class="flex cursor-pointer select-none items-center gap-2 text-gray-500">
38
+ {#each Object.entries(settings).filter(([k]) => k !== "shareConversationsWithModelAuthors") as [key, val]}
39
+ <input type="hidden" name={key} value={val} />
40
+ {/each}
41
+ <Switch
42
+ name="shareConversationsWithModelAuthors"
43
+ bind:checked={shareConversationsWithModelAuthors}
44
+ />
45
+ Share conversations with model authors
46
+ </label>
47
 
48
+ <p class="text-gray-800">
49
+ Sharing your data will help improve the training data and make open models better over
50
+ time.
51
+ </p>
52
+ <p class="text-gray-800">
53
+ You can change this setting at any time, it applies to all your conversations.
54
+ </p>
55
+ <p class="text-gray-800">
56
+ Read more about this model's authors,
57
+ <a
58
+ href="https://open-assistant.io/"
59
+ target="_blank"
60
+ rel="noreferrer"
61
+ class="underline decoration-gray-300 hover:decoration-gray-700">Open Assistant</a
62
+ >.
63
+ </p>
64
+ {/if}
65
  <form
66
  method="post"
67
  action="{base}/conversations?/delete"
src/lib/components/chat/ChatIntroduction.svelte CHANGED
@@ -1,5 +1,5 @@
1
  <script lang="ts">
2
- import { PUBLIC_VERSION } from "$env/static/public";
3
  import { PUBLIC_ANNOUNCEMENT_BANNERS } from "$env/static/public";
4
  import Logo from "$lib/components/icons/Logo.svelte";
5
  import { createEventDispatcher } from "svelte";
@@ -31,8 +31,8 @@
31
  <div class="lg:col-span-1">
32
  <div>
33
  <div class="mb-3 flex items-center text-2xl font-semibold">
34
- <Logo classNames="mr-1 text-yellow-400 text-4xl flex-none" />
35
- HuggingChat
36
  <div
37
  class="ml-3 flex h-6 items-center rounded-lg border border-gray-100 bg-gray-50 px-2 text-base text-gray-400 dark:border-gray-700/60 dark:bg-gray-800"
38
  >
1
  <script lang="ts">
2
+ import { PUBLIC_APP_NAME, PUBLIC_VERSION } from "$env/static/public";
3
  import { PUBLIC_ANNOUNCEMENT_BANNERS } from "$env/static/public";
4
  import Logo from "$lib/components/icons/Logo.svelte";
5
  import { createEventDispatcher } from "svelte";
31
  <div class="lg:col-span-1">
32
  <div>
33
  <div class="mb-3 flex items-center text-2xl font-semibold">
34
+ <Logo classNames="mr-1 flex-none" />
35
+ {PUBLIC_APP_NAME}
36
  <div
37
  class="ml-3 flex h-6 items-center rounded-lg border border-gray-100 bg-gray-50 px-2 text-base text-gray-400 dark:border-gray-700/60 dark:bg-gray-800"
38
  >
src/lib/components/chat/ChatWindow.svelte CHANGED
@@ -137,7 +137,7 @@
137
  type="button"
138
  on:click={() => dispatch("share")}
139
  >
140
- <CarbonExport class="text-[.6rem] sm:mr-1.5 sm:text-yellow-500" />
141
  <div class="max-sm:hidden">Share this conversation</div>
142
  </button>
143
  {/if}
137
  type="button"
138
  on:click={() => dispatch("share")}
139
  >
140
+ <CarbonExport class="text-[.6rem] sm:mr-1.5 sm:text-primary-500" />
141
  <div class="max-sm:hidden">Share this conversation</div>
142
  </button>
143
  {/if}
src/lib/components/icons/Logo.svelte CHANGED
@@ -1,25 +1,28 @@
1
  <script lang="ts">
 
 
 
 
2
  export let classNames = "";
3
  </script>
4
 
5
- <svg
6
- width="1em"
7
- height="1em"
8
- class={classNames}
9
- viewBox="0 0 13 12"
10
- fill="none"
11
- xmlns="http://www.w3.org/2000/svg"
12
- >
13
- <path
14
- fill="#FFD21E"
15
- d="M1.76 5.63a3.7 3.7 0 0 1 3.7-3.7h1.7a3.43 3.43 0 0 1 0 6.87H3.07L2.01 9.83a.14.14 0 0 1-.25-.1v-4.1Z"
16
- />
17
- <path
18
- fill="#32343D"
19
- d="M7.37 4.8c.13.05.19.33.33.25a.54.54 0 0 0 .22-.73.54.54 0 0 0-.73-.22.54.54 0 0 0-.22.73c.06.13.27-.08.4-.03ZM4.83 4.8c-.14.05-.2.33-.33.25a.54.54 0 0 1-.23-.73A.54.54 0 0 1 5 4.1c.26.14.36.47.22.73-.06.13-.27-.08-.4-.03ZM6.12 7.4c1.06 0 1.4-.96 1.4-1.44 0-.49-.62.26-1.4.26-.77 0-1.4-.75-1.4-.26 0 .48.34 1.43 1.4 1.43Z"
20
- />
21
- <path
22
- fill="#FF323D"
23
- d="M6.97 7.12c-.2.16-.49.27-.85.27-.34 0-.6-.1-.81-.24a.94.94 0 0 1 .57-.49c.04-.01.09.06.13.14.05.07.1.15.14.15.05 0 .1-.08.14-.15.05-.08.1-.15.14-.13a.93.93 0 0 1 .54.45Z"
24
  />
25
- </svg>
1
  <script lang="ts">
2
+ import { page } from "$app/stores";
3
+ import { PUBLIC_APP_ASSETS, PUBLIC_APP_NAME, PUBLIC_ORIGIN } from "$env/static/public";
4
+ import { base } from "$app/paths";
5
+
6
  export let classNames = "";
7
  </script>
8
 
9
+ {#if PUBLIC_APP_ASSETS === "chatui"}
10
+ <svg
11
+ height="30"
12
+ width="30"
13
+ viewBox="0 0 30 30"
14
+ xmlns="http://www.w3.org/2000/svg"
15
+ class={classNames}
16
+ >
17
+ <path
18
+ d="M4.06151 14.1464C4.06151 11.8818 4.9611 9.71004 6.56237 8.10877C8.16364 6.5075 10.3354 5.60791 12.6 5.60791H16.5231C18.6254 5.60791 20.6416 6.44307 22.1282 7.92965C23.6148 9.41624 24.45 11.4325 24.45 13.5348C24.45 15.6372 23.6148 17.6534 22.1282 19.14C20.6416 20.6266 18.6254 21.4618 16.5231 21.4618H7.08459L4.63844 23.8387C4.59547 23.8942 4.53557 23.9343 4.4678 23.9527C4.40004 23.9712 4.32811 23.9671 4.2629 23.941C4.1977 23.9149 4.14276 23.8683 4.10643 23.8082C4.07009 23.7481 4.05432 23.6778 4.06151 23.6079V14.1464Z"
19
+ class="fill-primary-500"
20
+ />
21
+ </svg>
22
+ {:else}
23
+ <object
24
+ class={classNames}
25
+ data="{PUBLIC_ORIGIN || $page.url.origin}{base}/{PUBLIC_APP_ASSETS}/favicon.svg"
26
+ title="{PUBLIC_APP_NAME} logo"
 
27
  />
28
+ {/if}
src/routes/+layout.svelte CHANGED
@@ -4,7 +4,7 @@
4
  import { page } from "$app/stores";
5
  import "../styles/main.css";
6
  import { base } from "$app/paths";
7
- import { PUBLIC_ORIGIN } from "$env/static/public";
8
 
9
  import { shareConversation } from "$lib/shareConversation";
10
  import { UrlDependency } from "$lib/types/UrlDependency";
@@ -15,6 +15,7 @@
15
  import Toast from "$lib/components/Toast.svelte";
16
  import SettingsModal from "$lib/components/SettingsModal.svelte";
17
  import LoginModal from "$lib/components/LoginModal.svelte";
 
18
 
19
  export let data;
20
 
@@ -94,18 +95,54 @@
94
 
95
  const requiresLogin =
96
  !$page.error &&
97
- (data.requiresLogin ? !data.user : !data.settings.ethicsModalAcceptedAt) &&
98
- !$page.route.id?.startsWith("/r/");
 
 
99
  </script>
100
 
101
  <svelte:head>
 
102
  <meta name="description" content="The first open source alternative to ChatGPT. πŸ’ͺ" />
103
  <meta name="twitter:card" content="summary_large_image" />
104
  <meta name="twitter:site" content="@huggingface" />
105
- <meta property="og:title" content="HuggingChat" />
106
  <meta property="og:type" content="website" />
107
  <meta property="og:url" content="{PUBLIC_ORIGIN || $page.url.origin}{base}" />
108
- <meta property="og:image" content="{PUBLIC_ORIGIN || $page.url.origin}{base}/thumbnail.png" />
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
109
  </svelte:head>
110
 
111
  <div
4
  import { page } from "$app/stores";
5
  import "../styles/main.css";
6
  import { base } from "$app/paths";
7
+ import { PUBLIC_ORIGIN, PUBLIC_APP_DISCLAIMER } from "$env/static/public";
8
 
9
  import { shareConversation } from "$lib/shareConversation";
10
  import { UrlDependency } from "$lib/types/UrlDependency";
15
  import Toast from "$lib/components/Toast.svelte";
16
  import SettingsModal from "$lib/components/SettingsModal.svelte";
17
  import LoginModal from "$lib/components/LoginModal.svelte";
18
+ import { PUBLIC_APP_ASSETS, PUBLIC_APP_NAME } from "$env/static/public";
19
 
20
  export let data;
21
 
95
 
96
  const requiresLogin =
97
  !$page.error &&
98
+ !$page.route.id?.startsWith("/r/") &&
99
+ (data.requiresLogin
100
+ ? !data.user
101
+ : !data.settings.ethicsModalAcceptedAt && !!PUBLIC_APP_DISCLAIMER);
102
  </script>
103
 
104
  <svelte:head>
105
+ <title>{PUBLIC_APP_NAME}</title>
106
  <meta name="description" content="The first open source alternative to ChatGPT. πŸ’ͺ" />
107
  <meta name="twitter:card" content="summary_large_image" />
108
  <meta name="twitter:site" content="@huggingface" />
109
+ <meta property="og:title" content={PUBLIC_APP_NAME} />
110
  <meta property="og:type" content="website" />
111
  <meta property="og:url" content="{PUBLIC_ORIGIN || $page.url.origin}{base}" />
112
+ <meta
113
+ property="og:image"
114
+ content="{PUBLIC_ORIGIN || $page.url.origin}{base}/{PUBLIC_APP_ASSETS}/thumbnail.png"
115
+ />
116
+ <link
117
+ rel="icon"
118
+ href="{PUBLIC_ORIGIN || $page.url.origin}{base}/{PUBLIC_APP_ASSETS}/favicon.svg"
119
+ type="image/svg+xml"
120
+ />
121
+ <link
122
+ rel="icon"
123
+ href="{PUBLIC_ORIGIN || $page.url.origin}{base}/{PUBLIC_APP_ASSETS}/favicon.png"
124
+ type="image/png"
125
+ />
126
+ <!-- Icon Support for iOS Bookmark Home Screen -->
127
+ <link
128
+ rel="apple-touch-icon"
129
+ href="{PUBLIC_ORIGIN || $page.url.origin}{base}/{PUBLIC_APP_ASSETS}/touch-icon-ipad-retina.png"
130
+ sizes="167x167"
131
+ type="image/png"
132
+ />
133
+ <link
134
+ rel="apple-touch-icon"
135
+ href="{PUBLIC_ORIGIN || $page.url.origin}{base}/{PUBLIC_APP_ASSETS}/touch-icon-ipad.png"
136
+ sizes="152x152"
137
+ type="image/png"
138
+ />
139
+ <link
140
+ rel="apple-touch-icon"
141
+ href="{PUBLIC_ORIGIN ||
142
+ $page.url.origin}{base}/{PUBLIC_APP_ASSETS}/touch-icon-iphone-retina.png"
143
+ sizes="180x180"
144
+ type="image/png"
145
+ />
146
  </svelte:head>
147
 
148
  <div
src/routes/r/[id]/+page.svelte CHANGED
@@ -2,6 +2,7 @@
2
  import { goto } from "$app/navigation";
3
  import { base } from "$app/paths";
4
  import { page } from "$app/stores";
 
5
  import ChatWindow from "$lib/components/chat/ChatWindow.svelte";
6
  import { ERROR_MESSAGES, error } from "$lib/stores/errors";
7
  import { pendingMessage } from "$lib/stores/pendingMessage";
@@ -80,5 +81,7 @@
80
  currentModel={findCurrentModel(data.models, data.model)}
81
  settings={data.settings}
82
  loginRequired={!$page.error &&
83
- (data.requiresLogin ? !data.user : !data.settings.ethicsModalAcceptedAt)}
 
 
84
  />
2
  import { goto } from "$app/navigation";
3
  import { base } from "$app/paths";
4
  import { page } from "$app/stores";
5
+ import { PUBLIC_APP_DISCLAIMER } from "$env/static/public";
6
  import ChatWindow from "$lib/components/chat/ChatWindow.svelte";
7
  import { ERROR_MESSAGES, error } from "$lib/stores/errors";
8
  import { pendingMessage } from "$lib/stores/pendingMessage";
81
  currentModel={findCurrentModel(data.models, data.model)}
82
  settings={data.settings}
83
  loginRequired={!$page.error &&
84
+ (data.requiresLogin
85
+ ? !data.user
86
+ : !data.settings.ethicsModalAcceptedAt && !!PUBLIC_APP_DISCLAIMER)}
87
  />
static/chatui/favicon.png ADDED
static/chatui/favicon.svg ADDED
static/chatui/touch-icon-ipad-retina.png ADDED
static/chatui/touch-icon-ipad.png ADDED
static/chatui/touch-icon-iphone-retina.png ADDED
static/{favicon.png β†’ huggingchat/favicon.png} RENAMED
File without changes
static/{favicon.svg β†’ huggingchat/favicon.svg} RENAMED
File without changes
static/{thumbnail.png β†’ huggingchat/thumbnail.png} RENAMED
File without changes
static/{touch-icon-ipad-retina.png β†’ huggingchat/touch-icon-ipad-retina.png} RENAMED
File without changes
static/{touch-icon-ipad.png β†’ huggingchat/touch-icon-ipad.png} RENAMED
File without changes
static/{touch-icon-iphone-retina.png β†’ huggingchat/touch-icon-iphone-retina.png} RENAMED
File without changes
svelte.config.js CHANGED
@@ -1,12 +1,11 @@
1
  import adapter from "@sveltejs/adapter-node";
2
  import { vitePreprocess } from "@sveltejs/kit/vite";
3
  import dotenv from "dotenv";
4
- import pkg from "./package.json" assert { type: "json" };
5
 
6
  dotenv.config({ path: "./.env.local" });
7
  dotenv.config({ path: "./.env" });
8
 
9
- process.env.PUBLIC_VERSION = pkg.version.replace(/\.0\b/g, "");
10
 
11
  /** @type {import('@sveltejs/kit').Config} */
12
  const config = {
1
  import adapter from "@sveltejs/adapter-node";
2
  import { vitePreprocess } from "@sveltejs/kit/vite";
3
  import dotenv from "dotenv";
 
4
 
5
  dotenv.config({ path: "./.env.local" });
6
  dotenv.config({ path: "./.env" });
7
 
8
+ process.env.PUBLIC_VERSION = process.env.npm_package_version;
9
 
10
  /** @type {import('@sveltejs/kit').Config} */
11
  const config = {
tailwind.config.cjs CHANGED
@@ -1,4 +1,8 @@
1
  const defaultTheme = require("tailwindcss/defaultTheme");
 
 
 
 
2
 
3
  /** @type {import('tailwindcss').Config} */
4
  export default {
@@ -6,6 +10,9 @@ export default {
6
  content: ["./src/**/*.{html,js,svelte,ts}"],
7
  theme: {
8
  extend: {
 
 
 
9
  // fontFamily: {
10
  // sans: ['"Inter"', ...defaultTheme.fontFamily.sans]
11
  // },
1
  const defaultTheme = require("tailwindcss/defaultTheme");
2
+ const colors = require("tailwindcss/colors");
3
+
4
+ import dotenv from "dotenv";
5
+ dotenv.config({ path: "./.env" });
6
 
7
  /** @type {import('tailwindcss').Config} */
8
  export default {
10
  content: ["./src/**/*.{html,js,svelte,ts}"],
11
  theme: {
12
  extend: {
13
+ colors: {
14
+ primary: colors[process.env.PUBLIC_APP_COLOR],
15
+ },
16
  // fontFamily: {
17
  // sans: ['"Inter"', ...defaultTheme.fontFamily.sans]
18
  // },