Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ba3b299715 | ||
|
|
17373314ae | ||
|
|
931a8b925c | ||
|
|
0e1991de6d | ||
|
|
d950e57352 | ||
|
|
652146ad96 | ||
|
|
dafe769cda | ||
|
|
ad9b10ba94 | ||
|
|
3880127f68 |
No files matched your search
@@ -34,7 +34,6 @@ artcraft-services/
|
||||
├── frontend/
|
||||
│ ├── apps/artcraft-webapp/ # Browser application at app.getartcraft.com
|
||||
│ ├── apps/artcraft-website-next/ # Current public website at getartcraft.com (Next.js)
|
||||
│ ├── apps/artcraft-website/ # Legacy product website (Vite)
|
||||
│ ├── apps/artcraft-desktop-website/ # Static landing page at desktop.getartcraft.com (Vite)
|
||||
│ └── libs/ # Shared React components and TypeScript libraries
|
||||
└── Cargo.toml # Rust workspace
|
||||
@@ -42,9 +41,9 @@ artcraft-services/
|
||||
|
||||
## Updating Desktop Download Links
|
||||
|
||||
Desktop release links are configured independently in **three places**. When
|
||||
Desktop release links are configured independently in **two places**. When
|
||||
updating the advertised ArtCraft release, update both `WINDOWS_VERSION` and
|
||||
`MAC_VERSION` in all three unless the request explicitly targets one platform or
|
||||
`MAC_VERSION` in both unless the request explicitly targets one platform or
|
||||
app:
|
||||
|
||||
1. **Current public website (Next.js):**
|
||||
@@ -52,11 +51,7 @@ app:
|
||||
This controls the installer links and visible version at
|
||||
`https://getartcraft.com/download`. Add the release to `DOWNLOAD_HISTORY`
|
||||
(newest first), then update both version selectors.
|
||||
2. **Legacy website (Vite):**
|
||||
[frontend/apps/artcraft-website/src/config/github_download_links.ts](frontend/apps/artcraft-website/src/config/github_download_links.ts).
|
||||
Add the release to `DOWNLOAD_HISTORY` and update both version selectors.
|
||||
Updating only this file does **not** update the current public website.
|
||||
3. **Browser webapp:**
|
||||
2. **Browser webapp:**
|
||||
[frontend/apps/artcraft-webapp/src/config/github_download_links.ts](frontend/apps/artcraft-webapp/src/config/github_download_links.ts).
|
||||
Update both version constants; these links are used by the welcome and
|
||||
checkout-success pages at `app.getartcraft.com`.
|
||||
@@ -65,7 +60,7 @@ Keep previous releases for rollback. The Next.js download page reads its visible
|
||||
version from `DOWNLOAD_VERSIONS`, which uses the same selectors as the URLs; do
|
||||
not hardcode a separate version in the page component.
|
||||
|
||||
Check that all three configs produce the requested release tag and installer
|
||||
Check that both configs produce the requested release tag and installer
|
||||
filenames for Windows (`ArtCraft_<version>_x64-setup.exe`) and macOS
|
||||
(`ArtCraft_<version>_universal.dmg`). Run `npm run typecheck` from
|
||||
`frontend/apps/artcraft-website-next` after changing its config. Repository edits
|
||||
|
||||
@@ -104,7 +104,7 @@ and signals for state, Three.js for 3D scenes, and shared UI and generation tool
|
||||
| Path | Purpose |
|
||||
|----------------------------------|-----------------------------------------------|
|
||||
| `frontend/apps/artcraft-webapp` | Browser application at `app.getartcraft.com` |
|
||||
| `frontend/apps/artcraft-website` | Product website at `getartcraft.com` |
|
||||
| `frontend/apps/artcraft-website-next` | Product website at `getartcraft.com` (Next.js) |
|
||||
| `frontend/libs/api` | HTTP clients, API host selection, and models |
|
||||
| `frontend/libs/omni-gen` | Shared generation logic |
|
||||
| `frontend/libs/components` | Reusable UI, editors, and generation controls |
|
||||
@@ -190,14 +190,11 @@ The browser app runs at `http://localhost:4201`. `VITE_USE_LOCAL_API=true` selec
|
||||
the hosted API. API host selection lives in
|
||||
[`StorytellerApiHostStore`](./frontend/libs/api/src/lib/config/StorytellerApiHostStore.ts).
|
||||
|
||||
From `frontend`, build the web app or run the product website with:
|
||||
From `frontend`, build the web app with `npx nx build artcraft-webapp`. The
|
||||
product website is a standalone Next.js app (not part of the Nx workspace); run it
|
||||
from the repository root with `./script/website/unix_frontend_website_dev.sh`.
|
||||
|
||||
```bash
|
||||
npx nx build artcraft-webapp
|
||||
npx nx dev artcraft-website
|
||||
```
|
||||
|
||||
The website runs at `http://localhost:4200`. Repository-root launchers are in
|
||||
The website runs at `http://localhost:3000`. Repository-root launchers are in
|
||||
[`script/website`](./script/website). For desktop development, use the
|
||||
[ArtCraft desktop repository](https://github.com/storytold/artcraft).
|
||||
|
||||
|
||||
@@ -255,7 +255,6 @@ From the services repository:
|
||||
SQLX_OFFLINE=true cargo test --offline -p storyteller-web --bin storyteller-web login_challenges
|
||||
cd frontend
|
||||
npm exec vitest -- run --config apps/artcraft-webapp/vite.config.ts src/pages/login/desktop-login.spec.tsx src/pages/login/login-bridge-continuation.spec.tsx
|
||||
npm exec vitest -- run --config apps/artcraft-website/vite.config.ts src/pages/login/desktop-login.spec.tsx
|
||||
```
|
||||
|
||||
`SQLX_OFFLINE` controls compile-time query metadata only. These tests still execute
|
||||
|
||||
@@ -35,6 +35,6 @@ VITE_USE_LOCAL_API=true npx nx dev artcraft-webapp
|
||||
The web app runs at `http://localhost:4201`, using the local backend. To develop
|
||||
against the hosted API, omit `VITE_USE_LOCAL_API=true`.
|
||||
|
||||
For the product website, run `npx nx dev artcraft-website` from `frontend`; it uses
|
||||
`http://localhost:4200`. Repository-root launchers live under [`script/website`](../script/website).
|
||||
For the product website, run `./script/website/unix_frontend_website_dev.sh` from the
|
||||
repository root; it is a standalone Next.js app on `http://localhost:3000`. Repository-root launchers live under [`script/website`](../script/website).
|
||||
See the [frontend README](../frontend/README.md) for builds and troubleshooting.
|
||||
@@ -1,10 +1,11 @@
|
||||
use std::str::FromStr;
|
||||
use std::time::Duration;
|
||||
|
||||
use log::info;
|
||||
|
||||
use errors::AnyhowResult;
|
||||
use shared_env_var_config::mysql::env_get_mysql_connection_string_or_default;
|
||||
use sqlx::mysql::MySqlPoolOptions;
|
||||
use sqlx::mysql::{MySqlConnectOptions, MySqlPoolOptions};
|
||||
use sqlx::MySqlPool;
|
||||
|
||||
pub async fn connect_to_database() -> AnyhowResult<MySqlPool> {
|
||||
@@ -20,20 +21,37 @@ pub async fn connect_to_database() -> AnyhowResult<MySqlPool> {
|
||||
// shorter timeout sheds load and surfaces the problem instead of hiding it behind long waits.
|
||||
let acquire_timeout_seconds = easyenv::get_env_num::<u64>("MYSQL_ACQUIRE_TIMEOUT_SECONDS", 10)?;
|
||||
|
||||
// NB: Every cached prepared statement stays open on the server until its connection evicts it
|
||||
// or closes, and the server caps the total across ALL clients (`max_prepared_stmt_count`,
|
||||
// 16382 on the managed DB). sqlx's default of 100 per connection let `replicas *
|
||||
// MYSQL_MAX_CONNECTIONS * 100` blow past that cap, failing new prepares with MySQL error 1461.
|
||||
// Keep `replicas * MYSQL_MAX_CONNECTIONS * MYSQL_STATEMENT_CACHE_CAPACITY` well under it.
|
||||
let statement_cache_capacity = easyenv::get_env_num::<usize>("MYSQL_STATEMENT_CACHE_CAPACITY", 25)?;
|
||||
|
||||
// NB: Recycling connections releases any server-side statements orphaned by cancelled queries
|
||||
// (eg. a client disconnect between prepare and close). sqlx's default lifetime is 30 minutes.
|
||||
let max_lifetime_seconds = easyenv::get_env_num::<u64>("MYSQL_MAX_LIFETIME_SECONDS", 600)?;
|
||||
|
||||
// NB: Log the settings before building/connecting so a connect failure has context. We do NOT
|
||||
// log the connection string (it contains credentials).
|
||||
info!(
|
||||
"Building MySQL pool: max_connections={}, min_connections={}, acquire_timeout_seconds={}",
|
||||
"Building MySQL pool: max_connections={}, min_connections={}, acquire_timeout_seconds={}, \
|
||||
statement_cache_capacity={}, max_lifetime_seconds={}",
|
||||
max_connections, min_connections, acquire_timeout_seconds,
|
||||
statement_cache_capacity, max_lifetime_seconds,
|
||||
);
|
||||
|
||||
let connect_options = MySqlConnectOptions::from_str(&db_connection_string)?
|
||||
.statement_cache_capacity(statement_cache_capacity);
|
||||
|
||||
let pool_options = MySqlPoolOptions::new()
|
||||
.max_connections(max_connections)
|
||||
.min_connections(min_connections)
|
||||
.acquire_timeout(Duration::from_secs(acquire_timeout_seconds));
|
||||
.acquire_timeout(Duration::from_secs(acquire_timeout_seconds))
|
||||
.max_lifetime(Some(Duration::from_secs(max_lifetime_seconds)));
|
||||
|
||||
let pool = pool_options
|
||||
.connect(&db_connection_string)
|
||||
.connect_with(connect_options)
|
||||
.await?;
|
||||
|
||||
Ok(pool)
|
||||
|
||||
@@ -31,7 +31,7 @@ From the **repository root**, the launcher scripts (these preflight your
|
||||
environment, install dependencies, and free the dev port first):
|
||||
|
||||
```bash
|
||||
./script/website/unix_frontend_website_dev.sh # artcraft-website (marketing site), port 4200
|
||||
./script/website/unix_frontend_website_dev.sh # artcraft-website-next (marketing site), port 3000
|
||||
./script/website/unix_frontend_webapp_dev.sh # artcraft-webapp (user dashboard), port 4201
|
||||
```
|
||||
|
||||
@@ -46,14 +46,12 @@ by its full or relative path:
|
||||
Or directly from this directory:
|
||||
|
||||
```bash
|
||||
nx dev artcraft-website
|
||||
npx nx dev @frontend/artcraft-webapp
|
||||
```
|
||||
|
||||
## Building
|
||||
|
||||
```bash
|
||||
npx nx build artcraft-website
|
||||
npx nx build artcraft-webapp
|
||||
```
|
||||
|
||||
|
||||
@@ -4,8 +4,6 @@ import react from '@vitejs/plugin-react';
|
||||
import wasm from 'vite-plugin-wasm';
|
||||
import topLevelAwait from 'vite-plugin-top-level-await';
|
||||
import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin';
|
||||
import { execSync } from 'child_process';
|
||||
import path from 'path';
|
||||
|
||||
// Dev-only CDN proxy. Media assets (splats, GLBs, images) are fetched with
|
||||
// fetch(), but the CDNs only send CORS headers for the production origin —
|
||||
@@ -71,21 +69,6 @@ function cdnProxyPlugin() {
|
||||
};
|
||||
}
|
||||
|
||||
// Custom plugin to generate news.json on dev server start
|
||||
function generateNewsPlugin() {
|
||||
return {
|
||||
name: 'generate-news',
|
||||
buildStart() {
|
||||
try {
|
||||
const scriptPath = path.resolve(__dirname, '../../scripts/generate-news-json.mjs');
|
||||
execSync(`node "${scriptPath}"`, { stdio: 'inherit' });
|
||||
} catch (e) {
|
||||
console.warn('Failed to generate news.json:', e);
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export default defineConfig(() => ({
|
||||
root: __dirname,
|
||||
cacheDir: '../../node_modules/.vite/apps/artcraft-webapp',
|
||||
@@ -110,7 +93,7 @@ export default defineConfig(() => ({
|
||||
port: 4301,
|
||||
host: 'localhost',
|
||||
},
|
||||
plugins: [cdnProxyPlugin(), generateNewsPlugin(), nxViteTsPaths(), react(), wasm(), topLevelAwait()],
|
||||
plugins: [cdnProxyPlugin(), nxViteTsPaths(), react(), wasm(), topLevelAwait()],
|
||||
// Uncomment this if you are using workers.
|
||||
// worker: {
|
||||
// plugins: [ nxViteTsPaths() ],
|
||||
|
||||
@@ -32,6 +32,18 @@ const nextConfig: NextConfig = {
|
||||
destination: "/apps/vectorcraft",
|
||||
permanent: true,
|
||||
},
|
||||
// PrintCraft was renamed PdfCraft. Old page links and share images
|
||||
// (cached by social sites) follow it.
|
||||
{
|
||||
source: "/apps/printcraft",
|
||||
destination: "/apps/pdfcraft",
|
||||
permanent: true,
|
||||
},
|
||||
{
|
||||
source: "/images/apps/printcraft/:file",
|
||||
destination: "/images/apps/pdfcraft/:file",
|
||||
permanent: true,
|
||||
},
|
||||
// Legacy share-link form (`/media?media=<token>`) from the Vite site;
|
||||
// the canonical route is /media/<token>. Mirrored in netlify.toml so
|
||||
// the edge answers it before the Next runtime.
|
||||
|
||||
|
After Width: | Height: | Size: 86 KiB |
|
After Width: | Height: | Size: 100 KiB |
|
After Width: | Height: | Size: 75 KiB |
|
After Width: | Height: | Size: 75 KiB |
|
After Width: | Height: | Size: 123 KiB |
|
Before Width: | Height: | Size: 86 KiB |
|
Before Width: | Height: | Size: 100 KiB |
|
Before Width: | Height: | Size: 75 KiB |
|
Before Width: | Height: | Size: 75 KiB |
|
Before Width: | Height: | Size: 123 KiB |
|
Before Width: | Height: | Size: 42 KiB After Width: | Height: | Size: 49 KiB |
|
Before Width: | Height: | Size: 71 KiB After Width: | Height: | Size: 77 KiB |
|
Before Width: | Height: | Size: 99 KiB After Width: | Height: | Size: 102 KiB |
|
After Width: | Height: | Size: 78 KiB |
|
Before Width: | Height: | Size: 86 KiB After Width: | Height: | Size: 92 KiB |
|
Before Width: | Height: | Size: 74 KiB After Width: | Height: | Size: 78 KiB |
@@ -321,14 +321,14 @@ html[data-ruler="on"]::-webkit-scrollbar {
|
||||
.app-vectorcraft { --app: #e8573f; --app-ink: #b83a24; }
|
||||
.app-filmcraft { --app: #8b5cf6; --app-ink: #6a3fd6; }
|
||||
.app-lightcraft { --app: #f2a516; --app-ink: #8a5800; }
|
||||
.app-printcraft { --app: #12a58a; --app-ink: #0a7563; }
|
||||
.app-pdfcraft { --app: #12a58a; --app-ink: #0a7563; }
|
||||
.app-effectcraft { --app: #e0368f; --app-ink: #b0206c; }
|
||||
.app-designcraft { --app: #7bb51c; --app-ink: #457008; }
|
||||
:root[data-theme="dark"] .app-photocraft { --app-ink: #7fb0ff; }
|
||||
:root[data-theme="dark"] .app-vectorcraft { --app-ink: #ff8a70; }
|
||||
:root[data-theme="dark"] .app-filmcraft { --app-ink: #b69cff; }
|
||||
:root[data-theme="dark"] .app-lightcraft { --app-ink: #ffc14d; }
|
||||
:root[data-theme="dark"] .app-printcraft { --app-ink: #3fd6b8; }
|
||||
:root[data-theme="dark"] .app-pdfcraft { --app-ink: #3fd6b8; }
|
||||
:root[data-theme="dark"] .app-effectcraft { --app-ink: #ff7ab8; }
|
||||
:root[data-theme="dark"] .app-designcraft { --app-ink: #a6e04a; }
|
||||
@media (prefers-color-scheme: dark) {
|
||||
@@ -336,7 +336,7 @@ html[data-ruler="on"]::-webkit-scrollbar {
|
||||
:root:not([data-theme="light"]) .app-vectorcraft { --app-ink: #ff8a70; }
|
||||
:root:not([data-theme="light"]) .app-filmcraft { --app-ink: #b69cff; }
|
||||
:root:not([data-theme="light"]) .app-lightcraft { --app-ink: #ffc14d; }
|
||||
:root:not([data-theme="light"]) .app-printcraft { --app-ink: #3fd6b8; }
|
||||
:root:not([data-theme="light"]) .app-pdfcraft { --app-ink: #3fd6b8; }
|
||||
:root:not([data-theme="light"]) .app-effectcraft { --app-ink: #ff7ab8; }
|
||||
:root:not([data-theme="light"]) .app-designcraft { --app-ink: #a6e04a; }
|
||||
}
|
||||
|
||||
@@ -32,11 +32,12 @@ import { ColorAccent } from "./app-wordmark";
|
||||
const CELL_HEADING_CLASSES =
|
||||
"mt-4 font-display text-3xl font-medium leading-[1.05] tracking-[-0.03em] text-ink-strong sm:text-4xl";
|
||||
|
||||
// The hero carries shot 01. Window captures lead with a full-width shot,
|
||||
// then pair; portrait pages (layout spreads) sit four across.
|
||||
// The hero carries shot 01. Window captures pair up, and an odd one out
|
||||
// leads at full width; portrait pages (layout spreads) sit four across.
|
||||
export function AppGallery({ app, index }: { app: CraftApp; index: string }) {
|
||||
const [, ...shots] = app.shots;
|
||||
const portrait = shots.every((shot) => shot.portrait);
|
||||
const leadFullWidth = !portrait && shots.length % 2 === 1;
|
||||
return (
|
||||
<SectionShell id="gallery">
|
||||
<SectionEyebrow
|
||||
@@ -55,7 +56,7 @@ export function AppGallery({ app, index }: { app: CraftApp; index: string }) {
|
||||
<figure
|
||||
key={shot.file}
|
||||
data-reveal
|
||||
className={twMerge("bg-bg", !portrait && i === 0 && "md:col-span-2")}
|
||||
className={twMerge("bg-bg", leadFullWidth && i === 0 && "md:col-span-2")}
|
||||
>
|
||||
<a
|
||||
href={craftShotSourceUrl(app, shot)}
|
||||
|
||||
@@ -3,17 +3,14 @@ import type { CraftAppSlug } from "./crafting-apps";
|
||||
// GitHub releases for the Crafting Apps, which drive every download button on
|
||||
// the /apps pages.
|
||||
//
|
||||
// To bump every app: change CRAFTING_APPS_LATEST_VERSION.
|
||||
// To pin one app to another version: give it its own release in
|
||||
// CRAFT_APP_RELEASES, e.g. `craftRelease("0.1.1")`.
|
||||
// To bump an app: change its version in CRAFT_APP_RELEASES (each app has its
|
||||
// own, e.g. `craftRelease("0.4.0")`).
|
||||
// To hide an app's downloads (Discord waitlist instead): set it to null.
|
||||
// If a release renames, adds or drops files, edit CRAFT_RELEASE_ASSETS, or
|
||||
// pass a custom list as craftRelease's second argument for a single app.
|
||||
//
|
||||
// Release tags are `v<version>` and live at github.com/storytold/<slug>.
|
||||
|
||||
export const CRAFTING_APPS_LATEST_VERSION = "0.2.0";
|
||||
|
||||
export type CraftDesktopPlatform = "macOS" | "Windows" | "Linux";
|
||||
|
||||
/** Order of the per-platform download buttons. */
|
||||
@@ -22,7 +19,7 @@ export const CRAFT_DESKTOP_PLATFORMS: CraftDesktopPlatform[] = ["macOS", "Window
|
||||
export type CraftReleaseAsset = {
|
||||
/** Asset filename; `{slug}` and `{version}` are filled in per app. */
|
||||
file: string;
|
||||
/** Group in the full file list. "Other" holds the CLI, web build and checksums. */
|
||||
/** Group in the full file list. "Other" holds the FreeBSD build, web build and checksums. */
|
||||
group: CraftDesktopPlatform | "Other";
|
||||
/** Short name, e.g. "Installer (x64)". */
|
||||
label: string;
|
||||
@@ -43,6 +40,8 @@ export type CraftRelease = {
|
||||
version: string;
|
||||
/** Git tag. Defaults to `v<version>`. */
|
||||
tag?: string;
|
||||
/** Fills `{slug}` in filenames. Defaults to the app's slug; a release from before a rename keeps the old one. */
|
||||
fileSlug?: string;
|
||||
assets: readonly CraftReleaseAsset[];
|
||||
};
|
||||
|
||||
@@ -92,6 +91,20 @@ export const CRAFT_RELEASE_ASSETS: readonly CraftReleaseAsset[] = [
|
||||
description: "Unzip and run on 32-bit Windows.",
|
||||
arch: "x86",
|
||||
},
|
||||
{
|
||||
file: "{slug}-{version}-windows-arm64.msi",
|
||||
group: "Windows",
|
||||
label: "Installer (ARM64)",
|
||||
description: "Windows 11 on ARM laptops.",
|
||||
arch: "aarch64",
|
||||
},
|
||||
{
|
||||
file: "{slug}-{version}-windows-arm64-portable.zip",
|
||||
group: "Windows",
|
||||
label: "Portable (ARM64)",
|
||||
description: "Unzip and run on Windows on ARM.",
|
||||
arch: "aarch64",
|
||||
},
|
||||
{
|
||||
file: "{slug}-{version}-linux-x86_64.AppImage",
|
||||
group: "Linux",
|
||||
@@ -100,6 +113,13 @@ export const CRAFT_RELEASE_ASSETS: readonly CraftReleaseAsset[] = [
|
||||
arch: "x86_64",
|
||||
recommended: true,
|
||||
},
|
||||
{
|
||||
file: "{slug}-{version}-linux-x86_64.flatpak",
|
||||
group: "Linux",
|
||||
label: "Flatpak (x86_64)",
|
||||
description: "Sandboxed. Install with flatpak install --user.",
|
||||
arch: "x86_64",
|
||||
},
|
||||
{
|
||||
file: "{slug}-{version}-linux-x86_64.deb",
|
||||
group: "Linux",
|
||||
@@ -129,6 +149,13 @@ export const CRAFT_RELEASE_ASSETS: readonly CraftReleaseAsset[] = [
|
||||
arch: "aarch64",
|
||||
recommended: true,
|
||||
},
|
||||
{
|
||||
file: "{slug}-{version}-linux-aarch64.flatpak",
|
||||
group: "Linux",
|
||||
label: "Flatpak (ARM64)",
|
||||
description: "Sandboxed, on 64-bit ARM.",
|
||||
arch: "aarch64",
|
||||
},
|
||||
{
|
||||
file: "{slug}-{version}-linux-aarch64.deb",
|
||||
group: "Linux",
|
||||
@@ -150,6 +177,12 @@ export const CRAFT_RELEASE_ASSETS: readonly CraftReleaseAsset[] = [
|
||||
description: "Plain binaries for 64-bit ARM.",
|
||||
arch: "aarch64",
|
||||
},
|
||||
{
|
||||
file: "{slug}-{version}-freebsd-x86_64.tar.gz",
|
||||
group: "Other",
|
||||
label: "FreeBSD (x86_64)",
|
||||
description: "Plain binaries for FreeBSD 14.",
|
||||
},
|
||||
{
|
||||
file: "{slug}-web-{version}.zip",
|
||||
group: "Other",
|
||||
@@ -171,15 +204,13 @@ export function craftRelease(
|
||||
return { version, assets };
|
||||
}
|
||||
|
||||
const LATEST = craftRelease(CRAFTING_APPS_LATEST_VERSION);
|
||||
|
||||
// Every app must be listed, so a new slug fails the type check until it is.
|
||||
export const CRAFT_APP_RELEASES: Record<CraftAppSlug, CraftRelease | null> = {
|
||||
photocraft: LATEST,
|
||||
vectorcraft: LATEST,
|
||||
filmcraft: LATEST,
|
||||
lightcraft: LATEST,
|
||||
printcraft: LATEST,
|
||||
effectcraft: LATEST,
|
||||
designcraft: LATEST,
|
||||
photocraft: craftRelease("0.5.0"),
|
||||
vectorcraft: craftRelease("0.6.0"),
|
||||
filmcraft: craftRelease("0.4.0"),
|
||||
lightcraft: craftRelease("0.4.0"),
|
||||
pdfcraft: craftRelease("0.4.0"),
|
||||
effectcraft: craftRelease("0.6.0"),
|
||||
designcraft: craftRelease("0.4.0"),
|
||||
};
|
||||
@@ -25,7 +25,7 @@ export type CraftAppSlug =
|
||||
| "vectorcraft"
|
||||
| "filmcraft"
|
||||
| "lightcraft"
|
||||
| "printcraft"
|
||||
| "pdfcraft"
|
||||
| "effectcraft"
|
||||
| "designcraft";
|
||||
|
||||
@@ -177,25 +177,31 @@ export const CRAFTING_APPS: CraftApp[] = [
|
||||
file: "hero.webp",
|
||||
source: "shot-1-neon.png",
|
||||
caption: "Neon Drive — made in VectorCraft",
|
||||
alt: "VectorCraft editing a synthwave poster titled Neon Drive with an outer glow in the Appearance panel",
|
||||
alt: "VectorCraft editing the Neon Drive poster, with the title's live outer glow settings in the Appearance panel and its character settings in the Properties panel",
|
||||
},
|
||||
{
|
||||
file: "ribbons.webp",
|
||||
source: "shot-2-ribbons.png",
|
||||
caption: "Live blends between editable spines",
|
||||
alt: "VectorCraft showing live blends: 70 smooth-color steps between two ribbon paths",
|
||||
caption: "Live blends and layers",
|
||||
alt: "VectorCraft showing three live blend ribbons clipped to the artboard, one selected with its key paths, and the Layers panel listing the clip group and blends",
|
||||
},
|
||||
{
|
||||
file: "bezier.webp",
|
||||
source: "shot-4-bezier.png",
|
||||
caption: "Pen and direct selection",
|
||||
alt: "VectorCraft direct-selecting the anchor points and bezier handles of a crescent moon, with the contextual task bar below it",
|
||||
},
|
||||
{
|
||||
file: "perspective.webp",
|
||||
source: "shot-5-perspective.png",
|
||||
caption: "Perspective grid, still editable",
|
||||
alt: "VectorCraft with two lit building facades drawn on the left and right planes of a two-point perspective grid at sunset",
|
||||
},
|
||||
{
|
||||
file: "sheet.webp",
|
||||
source: "shot-3-sheet.png",
|
||||
caption: "Booleans, mesh, repeat and envelope",
|
||||
alt: "VectorCraft feature sheet with exact booleans, a gradient mesh, a live radial repeat and an envelope distort",
|
||||
},
|
||||
{
|
||||
file: "bezier.webp",
|
||||
source: "shot-4-bezier.png",
|
||||
caption: "Direct selection on bezier anchors",
|
||||
alt: "VectorCraft direct-selecting the anchors and handles of a crescent moon path",
|
||||
alt: "VectorCraft in its light theme with four artboards: shape booleans, a gradient mesh, a live radial repeat and an envelope distort",
|
||||
},
|
||||
],
|
||||
},
|
||||
@@ -328,8 +334,8 @@ export const CRAFTING_APPS: CraftApp[] = [
|
||||
],
|
||||
},
|
||||
{
|
||||
slug: "printcraft",
|
||||
prefix: "Print",
|
||||
slug: "pdfcraft",
|
||||
prefix: "Pdf",
|
||||
category: "PDF workbench",
|
||||
status: "Early alpha",
|
||||
headline: ["The ", "open-source", " PDF workbench."],
|
||||
@@ -367,27 +373,27 @@ export const CRAFTING_APPS: CraftApp[] = [
|
||||
shots: [
|
||||
{
|
||||
file: "hero.webp",
|
||||
source: "printcraft-viewer.png",
|
||||
source: "pdfcraft-viewer.png",
|
||||
caption: "Viewer with threaded comments",
|
||||
alt: "PrintCraft showing a showcase PDF cover with the tools sidebar and threaded comments",
|
||||
alt: "PdfCraft showing a showcase PDF cover with the All tools panel and threaded comments",
|
||||
},
|
||||
{
|
||||
file: "organize.webp",
|
||||
source: "printcraft-organize.png",
|
||||
source: "pdfcraft-organize.png",
|
||||
caption: "Organize pages like cards",
|
||||
alt: "PrintCraft page organizer with three pages selected for rotate, delete and extract",
|
||||
alt: "PdfCraft page organizer with three pages selected and the page tools in the toolbar above",
|
||||
},
|
||||
{
|
||||
file: "palette.webp",
|
||||
source: "printcraft-palette.png",
|
||||
source: "pdfcraft-palette.png",
|
||||
caption: "A command palette for every tool",
|
||||
alt: "PrintCraft command palette filtering page tools by the word page",
|
||||
alt: "PdfCraft command palette searching for page and listing the page tools",
|
||||
},
|
||||
{
|
||||
file: "twoup.webp",
|
||||
source: "printcraft-twoup.png",
|
||||
source: "pdfcraft-twoup.png",
|
||||
caption: "Two-up Read mode, dark theme",
|
||||
alt: "PrintCraft two-up Read mode in the dark theme showing typeset specimen pages",
|
||||
alt: "PdfCraft two-up Read mode in the dark theme showing typeset specimen pages",
|
||||
},
|
||||
],
|
||||
},
|
||||
@@ -649,7 +655,7 @@ export function craftReleaseDownloads(
|
||||
const base = `${craftAppRepo(app)}/releases/download/${craftReleaseTag(release)}`;
|
||||
return release.assets.map(({ file, ...asset }) => {
|
||||
const fileName = file
|
||||
.replaceAll("{slug}", app.slug)
|
||||
.replaceAll("{slug}", release.fileSlug ?? app.slug)
|
||||
.replaceAll("{version}", release.version);
|
||||
return { ...asset, fileName, href: `${base}/${fileName}` };
|
||||
});
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
# Google OAuth Configuration
|
||||
# Get the Client ID from the Google Cloud Console:
|
||||
# https://console.cloud.google.com/apis/credentials
|
||||
VITE_GOOGLE_CLIENT_ID=YOUR_CLIENT_ID.apps.googleusercontent.com
|
||||
@@ -1,143 +0,0 @@
|
||||
# Website → Webapp Migration
|
||||
|
||||
The marketing site (`artcraft-website`) is being split apart from the app
|
||||
(`artcraft-webapp`). Anything that isn't pure marketing content belongs in
|
||||
the webapp at `app.getartcraft.com`.
|
||||
|
||||
The migration is **gated by a single boolean** so it can be reverted while
|
||||
we soak the new redirect behavior in production. When we're confident the
|
||||
webapp is handling everything cleanly, do the **cleanup pass** below to
|
||||
permanently delete everything that's only kept around for the rollback path.
|
||||
|
||||
---
|
||||
|
||||
## The switch
|
||||
|
||||
`src/config/links.ts`:
|
||||
|
||||
```ts
|
||||
export const USE_WEBAPP_FOR_APP_FEATURES = true;
|
||||
```
|
||||
|
||||
- `true` (default): legacy paths redirect to the webapp; navbar shows
|
||||
"Launch App"; in-page links go cross-origin to `app.getartcraft.com`.
|
||||
- `false`: everything runs locally on the marketing site (the original
|
||||
pre-split behavior).
|
||||
|
||||
In dev, `WEBAPP_URL` auto-switches to `http://localhost:4201/` so cross-app
|
||||
links work against the local webapp Vite server.
|
||||
|
||||
---
|
||||
|
||||
## What's behind the flag
|
||||
|
||||
### Pages that exist locally only as a fallback
|
||||
|
||||
When `USE_WEBAPP_FOR_APP_FEATURES = true`, these routes mount
|
||||
`<WebappRedirect to="…" />` instead of the page component. The page files
|
||||
are kept on disk so we can roll back by flipping the flag.
|
||||
|
||||
- `src/pages/login/`
|
||||
- `src/pages/signup/`
|
||||
- `src/pages/forgot-password/`
|
||||
- `src/pages/create-image/`
|
||||
- `src/pages/create-video/`
|
||||
- `src/pages/create-vfx/` (the `/background-change` route)
|
||||
- `src/pages/library/`
|
||||
- `src/pages/referrals/`
|
||||
- `src/pages/welcome/`
|
||||
- `src/pages/onboarding/`
|
||||
- `src/pages/checkout/` (success + cancel)
|
||||
|
||||
### Components only used by the above
|
||||
|
||||
- `src/components/auth/` (SignupForm, GoogleLoginButton)
|
||||
- `src/components/credits-modal.tsx`
|
||||
- `src/components/generation-gallery/`
|
||||
- `src/components/lightbox/lightbox.tsx` (the modal `Lightbox`; the
|
||||
`LightboxDetails` + `shared.ts` files in the same folder are still used
|
||||
by the public `/media` page and must be kept)
|
||||
- `src/components/navbar/task-queue.tsx`
|
||||
- `src/components/prompt-box/`
|
||||
- `src/components/settings-modal/`
|
||||
|
||||
### Lib files only used by the above
|
||||
|
||||
- `src/lib/cost-estimate-api.ts`
|
||||
- `src/lib/enter-to-generate-store.ts`
|
||||
- `src/lib/omni-gen-hooks.ts`
|
||||
- `src/lib/prompts-cache.ts`
|
||||
- `src/lib/recreate.ts`
|
||||
|
||||
### Files with conditional flag branches (need cleanup, not deletion)
|
||||
|
||||
- `src/app/app.tsx` — drop the `appOrWebapp()` helper, drop the local route
|
||||
imports, leave only the `<WebappRedirect />` routes
|
||||
- `src/components/navbar/navbar.tsx` — drop the `!USE_WEBAPP_FOR_APP_FEATURES`
|
||||
branches (Login + Sign up buttons in desktop and mobile); keep only Launch
|
||||
App for logged-in users and the Pricing + Launch App combo for logged-out
|
||||
users
|
||||
- `src/components/footer/footer.tsx` — drop the conditional Image/Video
|
||||
links in the Pages column
|
||||
- `src/components/download-modal.tsx` — drop the inline `SignupForm` flow
|
||||
and the `view`/`navigate` state; keep only the webapp `/signup` and
|
||||
`/login` link buttons
|
||||
- `src/pages/landing3/landing3.tsx` — `appLink("/create-image")` /
|
||||
`appLink("/create-video")` can become bare `webappUrl("…")` calls (or
|
||||
inline `${WEBAPP_URL}create-image`)
|
||||
- `src/pages/media/media.tsx` — drop the local
|
||||
`applyRecreateFromMediaToken` branch and the `useNavigate` import; keep
|
||||
only the `window.location.href = …` webapp redirect
|
||||
- `src/pages/pricing/pricing.tsx` — the "Buy Credits" section + `CreditsModal`
|
||||
is currently shown unconditionally; once `credits-modal.tsx` is deleted,
|
||||
remove the section, the `creditsModalOpen` state, the `isLoggedIn` state,
|
||||
and the session-check `useEffect`
|
||||
|
||||
### The flag itself
|
||||
|
||||
`src/config/links.ts` — drop `USE_WEBAPP_FOR_APP_FEATURES`, drop the
|
||||
`appLink()` helper (use `webappUrl()` directly everywhere). Keep
|
||||
`WEBAPP_URL`, `webappUrl()`, `SOCIAL_LINKS`, `SUPPORT_EMAIL`, and the dev
|
||||
override.
|
||||
|
||||
---
|
||||
|
||||
## Cleanup pass — what to do when we're ready to commit to the webapp split
|
||||
|
||||
1. **Confirm the flag has been `true` in production for long enough** that
|
||||
we're sure no real users hit the local routes.
|
||||
2. **Delete** every directory and file listed under "Pages that exist
|
||||
locally only as a fallback", "Components only used by the above", and
|
||||
"Lib files only used by the above".
|
||||
3. **Strip the flag branches** from each file under "Files with conditional
|
||||
flag branches".
|
||||
4. **Remove `USE_WEBAPP_FOR_APP_FEATURES`** and `appLink()` from
|
||||
`src/config/links.ts`.
|
||||
5. **Run** `npx tsc -p tsconfig.app.json --noEmit` from
|
||||
`frontend/apps/artcraft-website` and fix any references the cleanup
|
||||
exposed. (Pre-existing errors in `download-button.tsx` `LINUX` and
|
||||
`pricing-table.tsx` `maybeReferralUsername` are unrelated and can be
|
||||
ignored.)
|
||||
6. **Verify** in dev with `nx serve @frontend/artcraft-website` that every
|
||||
navbar/footer/landing/media flow still works and that legacy URLs still
|
||||
redirect to the webapp via `WebappRedirect`.
|
||||
|
||||
---
|
||||
|
||||
## What stays on the marketing site no matter what
|
||||
|
||||
These are pure marketing content and are **not** behind the flag:
|
||||
|
||||
- `/` → `landing3`
|
||||
- `/landing3`
|
||||
- `/seedance-2` → `landing-sd2`
|
||||
- `/download`
|
||||
- `/media`, `/media/:id` (public viewer; the lightbox's "Recreate" button
|
||||
does cross-origin to the webapp, but the viewer itself stays here)
|
||||
- `/press-kit`
|
||||
- `/tutorials`, `/tutorials/:slug`
|
||||
- `/faq`, `/faq/:slug`
|
||||
- `/news`, `/news/:slug`
|
||||
- `/support`
|
||||
- `/pricing` — Stripe checkout flow stays here (PricingTable → Stripe →
|
||||
`/checkout/success` → WebappRedirect → webapp)
|
||||
@@ -1,157 +0,0 @@
|
||||
/background-change /index.html 200
|
||||
/background-change/ /index.html 200
|
||||
/background-change/* /index.html 200
|
||||
|
||||
/checkout_cancel /index.html 200
|
||||
/checkout_cancel/ /index.html 200
|
||||
/checkout_cancel/* /index.html 200
|
||||
|
||||
/onboarding /index.html 200
|
||||
/onboarding/ /index.html 200
|
||||
/onboarding/* /index.html 200
|
||||
|
||||
/portal_closed /index.html 200
|
||||
/portal_closed/ /index.html 200
|
||||
/portal_closed/* /index.html 200
|
||||
|
||||
/checkout_success /index.html 200
|
||||
/checkout_success/ /index.html 200
|
||||
/checkout_success/* /index.html 200
|
||||
|
||||
/checkout* /index.html 200
|
||||
/checkout/* /index.html 200
|
||||
|
||||
/create-image /index.html 200
|
||||
/create-image/ /index.html 200
|
||||
/create-image/* /index.html 200
|
||||
|
||||
/create-video /index.html 200
|
||||
/create-video/ /index.html 200
|
||||
/create-video/* /index.html 200
|
||||
|
||||
/support /index.html 200
|
||||
/support/ /index.html 200
|
||||
/support/* /index.html 200
|
||||
|
||||
/library /index.html 200
|
||||
/library/ /index.html 200
|
||||
/library/* /index.html 200
|
||||
|
||||
/download /index.html 200
|
||||
/download/ /index.html 200
|
||||
|
||||
/tutorials /index.html 200
|
||||
/tutorials/ /index.html 200
|
||||
|
||||
/login /index.html 200
|
||||
/login/ /index.html 200
|
||||
/login/* /index.html 200
|
||||
|
||||
/media /index.html 200
|
||||
/media/ /index.html 200
|
||||
/media/* /index.html 200
|
||||
|
||||
# Prerendered: serve the per-route index.html so social crawlers get the
|
||||
# correct OG/title tags (see scripts/prerender-meta.mjs). The SPA still boots
|
||||
# from this file and React Router takes over for users.
|
||||
/pricing /pricing/index.html 200
|
||||
/pricing/ /pricing/index.html 200
|
||||
/pricing/* /index.html 200
|
||||
|
||||
/beta /beta/index.html 200
|
||||
/beta/ /beta/index.html 200
|
||||
/beta/* /index.html 200
|
||||
|
||||
/faq /index.html 200
|
||||
/faq/ /index.html 200
|
||||
/faq/* /index.html 200
|
||||
|
||||
/news /index.html 200
|
||||
/news/ /index.html 200
|
||||
/news/* /index.html 200
|
||||
|
||||
/press-kit /index.html 200
|
||||
/press-kit/ /index.html 200
|
||||
/press-kit/* /index.html 200
|
||||
|
||||
/referrals /index.html 200
|
||||
/referrals/ /index.html 200
|
||||
/referrals/* /index.html 200
|
||||
|
||||
# Redirects for growth measurement
|
||||
/reddit /?utm_source=reddit 301
|
||||
|
||||
/news.json /index.html 200
|
||||
|
||||
/signup /index.html 200
|
||||
/signup/ /index.html 200
|
||||
/signup/* /index.html 200
|
||||
|
||||
/forgot-password /index.html 200
|
||||
/forgot-password/ /index.html 200
|
||||
/forgot-password/* /index.html 200
|
||||
|
||||
/welcome /index.html 200
|
||||
/welcome/ /index.html 200
|
||||
/welcome/* /index.html 200
|
||||
|
||||
/password-reset /index.html 200
|
||||
/password-reset/ /index.html 200
|
||||
/password-reset/* /index.html 200
|
||||
|
||||
# Prerendered: exact paths serve their per-route index.html (correct OG tags
|
||||
# for social crawlers); deep sub-paths fall back to the SPA shell. See
|
||||
# scripts/prerender-meta.mjs. NOTE: these exact-match serving rules MUST come
|
||||
# before the /seedance2* alias below, otherwise that wildcard would 301
|
||||
# /seedance2-5 away to /seedance-2 (first match wins in _redirects).
|
||||
/seedance2-5 /seedance2-5/index.html 200
|
||||
/seedance2-5/ /seedance2-5/index.html 200
|
||||
/seedance2-5/* /index.html 200
|
||||
|
||||
/seedance-2 /seedance-2/index.html 200
|
||||
/seedance-2/ /seedance-2/index.html 200
|
||||
/seedance-2/* /index.html 200
|
||||
|
||||
/minimax-h3 /minimax-h3/index.html 200
|
||||
/minimax-h3/ /minimax-h3/index.html 200
|
||||
/minimax-h3/* /index.html 200
|
||||
|
||||
/creators/jboogxcreative /creators/jboogxcreative/index.html 200
|
||||
/creators/jboogxcreative/ /creators/jboogxcreative/index.html 200
|
||||
/creators/* /index.html 200
|
||||
|
||||
# Similar URLs — creator spotlight aliases
|
||||
/jboogx /creators/jboogxcreative 301
|
||||
/jboogx/ /creators/jboogxcreative 301
|
||||
/jboogxcreative /creators/jboogxcreative 301
|
||||
/jboogxcreative/ /creators/jboogxcreative 301
|
||||
|
||||
# Similar URLs: MiniMax H3 aliases
|
||||
/minimax /minimax-h3 301
|
||||
/minimax/ /minimax-h3 301
|
||||
/minimaxh3 /minimax-h3 301
|
||||
/minimaxh3* /minimax-h3 301
|
||||
/minimax-h-3 /minimax-h3 301
|
||||
/minimax-h-3* /minimax-h3 301
|
||||
/hailuo /minimax-h3 301
|
||||
/hailuo/ /minimax-h3 301
|
||||
|
||||
# Google ads breakage
|
||||
/seedance-2{ignore} /seedance-2 301
|
||||
/seedance-2{ignore}* /seedance-2 301
|
||||
/seedance-2%7Bignore%7D /seedance-2 301
|
||||
/seedance-2%7Bignore%7D* /seedance-2 301
|
||||
|
||||
# Similar URLs — Seedance 2.5 aliases (kept above the broad /seedance2* rule)
|
||||
/seedance-2-5 /seedance2-5 301
|
||||
/seedance-2-5* /seedance2-5 301
|
||||
/seedance-2.5 /seedance2-5 301
|
||||
/seedance-2.5* /seedance2-5 301
|
||||
/seedance25 /seedance2-5 301
|
||||
/seedance25* /seedance2-5 301
|
||||
|
||||
# Similar URLs — Seedance 2.0 aliases
|
||||
/seedance2 /seedance-2 301
|
||||
/seedance2* /seedance-2 301
|
||||
/seedance-2.0 /seedance-2 301
|
||||
/seedance-2.0* /seedance-2 301
|
||||
@@ -1,52 +0,0 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<!-- Google tag (gtag.js) -->
|
||||
<script>
|
||||
window.dataLayer = window.dataLayer || [];
|
||||
function gtag() {
|
||||
dataLayer.push(arguments);
|
||||
}
|
||||
if (window.location.pathname === "/login/desktop") {
|
||||
const policy = document.createElement("meta");
|
||||
policy.name = "referrer";
|
||||
policy.content = "no-referrer";
|
||||
document.head.appendChild(policy);
|
||||
} else {
|
||||
const analytics = document.createElement("script");
|
||||
analytics.async = true;
|
||||
analytics.src = "https://www.googletagmanager.com/gtag/js?id=G-VKW89949V0";
|
||||
document.head.appendChild(analytics);
|
||||
gtag("js", new Date());
|
||||
gtag("config", "G-VKW89949V0");
|
||||
}
|
||||
</script>
|
||||
|
||||
<meta charset="utf-8" />
|
||||
<title>ArtCraft. AI Video and Images. Fast and Open Desktop App.</title>
|
||||
<meta
|
||||
name="description"
|
||||
content="ArtCraft is an Open Desktop app for generating AI Video and Images. You own ArtCraft!"
|
||||
/>
|
||||
<meta
|
||||
name="keywords"
|
||||
content="ArtCraft, AI, AI Video, AI Images, Open Source"
|
||||
/>
|
||||
|
||||
<base href="/" />
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<link rel="icon" type="image/x-icon" href="/favicon.ico" />
|
||||
<link rel="stylesheet" href="/src/styles.css" />
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
||||
<link
|
||||
href="https://fonts.googleapis.com/css2?family=Bricolage+Grotesque:opsz,wght@12..96,200..800&family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&family=Outfit:wght@100..900&family=Source+Sans+3:ital,wght@0,200..900;1,200..900&family=Instrument+Serif:ital@0;1&family=Geist+Mono:wght@300..800&display=swap"
|
||||
rel="stylesheet"
|
||||
/>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
<script type="module" src="/src/main.tsx"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,29 +0,0 @@
|
||||
# Netlify settings used to discover this file:
|
||||
# Base directory: frontend
|
||||
# Package directory: apps/artcraft-website (relative to the base directory)
|
||||
# Manage the build command and publish directory here; leave those UI fields empty.
|
||||
# Paths below are relative to the frontend workspace.
|
||||
|
||||
[build]
|
||||
command = "bash ./apps/artcraft-website/script/netlify_build.sh"
|
||||
publish = "apps/artcraft-website/dist/"
|
||||
|
||||
[[headers]]
|
||||
for = "/build/*"
|
||||
|
||||
[headers.values]
|
||||
"Cache-Control" = "public, max-age=31560000, immutable"
|
||||
|
||||
# [[redirects]]
|
||||
# from = "/ingest/static/*"
|
||||
# to = "https://us-assets.i.posthog.com/static/:splat"
|
||||
# host = "us-assets.i.posthog.com"
|
||||
# status = 200
|
||||
# force = true
|
||||
#
|
||||
# [[redirects]]
|
||||
# from = "/ingest/*"
|
||||
# to = "https://us.i.posthog.com/:splat"
|
||||
# host = "us.i.posthog.com"
|
||||
# status = 200
|
||||
# force = true
|
||||
@@ -1,8 +0,0 @@
|
||||
{
|
||||
"name": "@frontend/artcraft-website",
|
||||
"version": "0.0.1",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"react-masonry-css": "^1.0.16"
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
const { join } = require('path');
|
||||
|
||||
// Note: If you use library-specific PostCSS/Tailwind configuration then you should remove the `postcssConfig` build
|
||||
// option from your application's configuration (i.e. project.json).
|
||||
//
|
||||
// See: https://nx.dev/guides/using-tailwind-css-in-react#step-4:-applying-configuration-to-libraries
|
||||
|
||||
module.exports = {
|
||||
plugins: {
|
||||
tailwindcss: {
|
||||
config: join(__dirname, 'tailwind.config.js'),
|
||||
},
|
||||
autoprefixer: {},
|
||||
},
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg id="Layer_2" data-name="Layer 2" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 116.34 97.5">
|
||||
<defs>
|
||||
<style>
|
||||
.cls-1 {
|
||||
fill: #4e7bfb;
|
||||
}
|
||||
</style>
|
||||
</defs>
|
||||
<g id="Layer_1-2" data-name="Layer 1">
|
||||
<path class="cls-1" d="M104.28,49.49L81.55,0h-31.23l-3.17,4.76L14.75,53.63,0,75.85l21.55,21.55,63.79-36.94,16.99,37.04,14.01-21.74-12.06-26.27ZM32.89,65.66l32.42-48.87,10.91,23.77-43.32,25.09Z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 483 B |
|
Before Width: | Height: | Size: 38 KiB |
|
Before Width: | Height: | Size: 662 KiB |
|
Before Width: | Height: | Size: 45 KiB |
|
Before Width: | Height: | Size: 199 KiB |
|
Before Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 463 KiB |
|
Before Width: | Height: | Size: 181 KiB |
|
Before Width: | Height: | Size: 8.8 KiB |
|
Before Width: | Height: | Size: 6.2 KiB |
|
Before Width: | Height: | Size: 1.8 MiB |
|
Before Width: | Height: | Size: 19 MiB |
|
Before Width: | Height: | Size: 1.2 MiB |
|
Before Width: | Height: | Size: 20 MiB |
|
Before Width: | Height: | Size: 1.2 MiB |
|
Before Width: | Height: | Size: 22 MiB |
|
Before Width: | Height: | Size: 73 KiB |
|
Before Width: | Height: | Size: 2.0 MiB |
|
Before Width: | Height: | Size: 2.3 MiB |
|
Before Width: | Height: | Size: 1.4 MiB |
|
Before Width: | Height: | Size: 16 MiB |
|
Before Width: | Height: | Size: 1.2 MiB |
|
Before Width: | Height: | Size: 1.8 MiB |
|
Before Width: | Height: | Size: 22 MiB |
|
Before Width: | Height: | Size: 2.2 MiB |
|
Before Width: | Height: | Size: 29 KiB |
|
Before Width: | Height: | Size: 374 KiB |
|
Before Width: | Height: | Size: 216 KiB |
|
Before Width: | Height: | Size: 167 KiB |
|
Before Width: | Height: | Size: 199 KiB |
|
Before Width: | Height: | Size: 182 KiB |
|
Before Width: | Height: | Size: 132 KiB |
|
Before Width: | Height: | Size: 157 KiB |
|
Before Width: | Height: | Size: 4.2 MiB |
|
Before Width: | Height: | Size: 7.4 MiB |
|
Before Width: | Height: | Size: 24 KiB |
|
Before Width: | Height: | Size: 48 KiB |
|
Before Width: | Height: | Size: 25 KiB |
@@ -1 +0,0 @@
|
||||
<svg fill="currentColor" fill-rule="evenodd" height="1em" style="flex:none;line-height:1" viewBox="0 0 24 24" width="1em" xmlns="http://www.w3.org/2000/svg"><title>Qwen</title><path d="M12.604 1.34c.393.69.784 1.382 1.174 2.075a.18.18 0 00.157.091h5.552c.174 0 .322.11.446.327l1.454 2.57c.19.337.24.478.024.837-.26.43-.513.864-.76 1.3l-.367.658c-.106.196-.223.28-.04.512l2.652 4.637c.172.301.111.494-.043.77-.437.785-.882 1.564-1.335 2.34-.159.272-.352.375-.68.37-.777-.016-1.552-.01-2.327.016a.099.099 0 00-.081.05 575.097 575.097 0 01-2.705 4.74c-.169.293-.38.363-.725.364-.997.003-2.002.004-3.017.002a.537.537 0 01-.465-.271l-1.335-2.323a.09.09 0 00-.083-.049H4.982c-.285.03-.553-.001-.805-.092l-1.603-2.77a.543.543 0 01-.002-.54l1.207-2.12a.198.198 0 000-.197 550.951 550.951 0 01-1.875-3.272l-.79-1.395c-.16-.31-.173-.496.095-.965.465-.813.927-1.625 1.387-2.436.132-.234.304-.334.584-.335a338.3 338.3 0 012.589-.001.124.124 0 00.107-.063l2.806-4.895a.488.488 0 01.422-.246c.524-.001 1.053 0 1.583-.006L11.704 1c.341-.003.724.032.9.34zm-3.432.403a.06.06 0 00-.052.03L6.254 6.788a.157.157 0 01-.135.078H3.253c-.056 0-.07.025-.041.074l5.81 10.156c.025.042.013.062-.034.063l-2.795.015a.218.218 0 00-.2.116l-1.32 2.31c-.044.078-.021.118.068.118l5.716.008c.046 0 .08.02.104.061l1.403 2.454c.046.081.092.082.139 0l5.006-8.76.783-1.382a.055.055 0 01.096 0l1.424 2.53a.122.122 0 00.107.062l2.763-.02a.04.04 0 00.035-.02.041.041 0 000-.04l-2.9-5.086a.108.108 0 010-.113l.293-.507 1.12-1.977c.024-.041.012-.062-.035-.062H9.2c-.059 0-.073-.026-.043-.077l1.434-2.505a.107.107 0 000-.114L9.225 1.774a.06.06 0 00-.053-.031zm6.29 8.02c.046 0 .058.02.034.06l-.832 1.465-2.613 4.585a.056.056 0 01-.05.029.058.058 0 01-.05-.029L8.498 9.841c-.02-.034-.01-.052.028-.054l.216-.012 6.722-.012z"></path></svg>
|
||||
|
Before Width: | Height: | Size: 1.7 KiB |
@@ -1,6 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg id="Layer_2" data-name="Layer 2" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72.22 65.68">
|
||||
<g id="Layer_1-2" data-name="Layer 1">
|
||||
<path d="M69.38,45.46c-3.18-6.24-6.58-12.49-9.86-18.53-3.31-6.08-6.72-12.37-9.91-18.63l-.05-.09C46.44,3.07,41.24,0,35.66,0s-10.34,3-13.13,8.23L.97,48.96l-.03.07c-1.51,3.8-1.2,8.03.82,11.31,1.9,3.08,5.01,4.96,8.76,5.28.38.03.75.05,1.1.05,2.94,0,4.98-1.12,7.33-2.41,7.13-3.91,19.45-11.21,27.61-16.04,2.6-1.54,4.95-2.93,6.31-3.73l10.71,20.43c.2.39.54.7.95.86.46.19.98.2,1.43,0,1.39-.66,3.05-2.47,3.07-2.49,5.22-5.9,3.03-11.55.34-16.83ZM34.53,14.8c.31-.46.77-.99,1.32-.99.58,0,1.29.57,1.85,1.49,1.57,2.56,2.99,5.44,4.35,8.22,1.34,2.73,2.72,5.55,4.29,8.15l.02.05-29.6,16.99L34.53,14.8Z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 781 B |
@@ -1 +0,0 @@
|
||||
<svg fill="currentColor" fill-rule="evenodd" height="1em" style="flex:none;line-height:1" viewBox="0 0 24 24" width="1em" xmlns="http://www.w3.org/2000/svg"><title>Flux</title><path d="M0 20.683L12.01 2.5 24 20.683h-2.233L12.009 5.878 3.471 18.806h12.122l1.239 1.877H0z"></path><path d="M8.069 16.724l2.073-3.115 2.074 3.115H8.069zM18.24 20.683l-5.668-8.707h2.177l5.686 8.707h-2.196zM19.74 11.676l2.13-3.19 2.13 3.19h-4.26z"></path></svg>
|
||||
|
Before Width: | Height: | Size: 438 B |
@@ -1 +0,0 @@
|
||||
<svg fill="currentColor" fill-rule="evenodd" height="1em" style="flex:none;line-height:1" viewBox="0 0 24 24" width="1em" xmlns="http://www.w3.org/2000/svg"><title>ByteDance</title><path d="M14.944 18.587l-1.704-.445V10.01l1.824-.462c1-.254 1.84-.461 1.88-.453.032 0 .056 2.235.056 4.972v4.973l-.176-.008c-.104 0-.952-.207-1.88-.446z"></path><path d="M7 16.542c0-2.736.024-4.98.064-4.98.032-.008.872.2 1.88.454l1.816.461-.016 4.05-.024 4.049-1.632.422c-.896.23-1.736.445-1.856.469L7 21.523v-4.98z"></path><path d="M19.24 12.477c0-9.03.008-9.515.144-9.475.072.024.784.207 1.576.406.792.207 1.576.405 1.744.445l.296.08-.016 8.56-.024 8.568-1.624.414c-.888.23-1.728.437-1.856.47l-.24.055v-9.523z"></path><path d="M1 12.509c0-4.678.024-8.505.064-8.505.032 0 .872.207 1.872.454l1.824.461v7.582c0 4.16-.016 7.574-.032 7.574-.024 0-.872.215-1.88.47L1 21.013v-8.505z"></path></svg>
|
||||
|
Before Width: | Height: | Size: 873 B |
@@ -1 +0,0 @@
|
||||
<svg fill="currentColor" fill-rule="evenodd" height="1em" style="flex:none;line-height:1" viewBox="0 0 24 24" width="1em" xmlns="http://www.w3.org/2000/svg"><title>Fal</title><path clip-rule="evenodd" d="M15.477 0c.415 0 .749.338.788.752a7.775 7.775 0 006.985 6.984c.413.04.752.373.752.788v6.952c0 .415-.338.748-.752.788a7.775 7.775 0 00-6.985 6.984c-.04.414-.373.752-.788.752H8.525c-.416 0-.749-.338-.789-.752a7.775 7.775 0 00-6.984-6.984c-.414-.04-.752-.373-.752-.788V8.524c0-.415.338-.748.752-.788A7.775 7.775 0 007.736.752C7.776.338 8.11 0 8.526 0h6.95zM4.819 11.98a7.226 7.226 0 007.223 7.23 7.226 7.226 0 007.223-7.23c0-3.994-3.234-7.23-7.223-7.23a7.227 7.227 0 00-7.223 7.23z"></path></svg>
|
||||
|
Before Width: | Height: | Size: 697 B |
@@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640"><!--!Font Awesome Free 7.0.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.--><path d="M64 144C64 117.5 85.5 96 112 96L208 96C234.5 96 256 117.5 256 144L256 160L384 160L384 144C384 117.5 405.5 96 432 96L528 96C554.5 96 576 117.5 576 144L576 240C576 266.5 554.5 288 528 288L432 288C405.5 288 384 266.5 384 240L384 224L256 224L256 240C256 247.3 254.3 254.3 251.4 260.5L320 352L400 352C426.5 352 448 373.5 448 400L448 496C448 522.5 426.5 544 400 544L304 544C277.5 544 256 522.5 256 496L256 400C256 392.7 257.7 385.7 260.6 379.5L192 288L112 288C85.5 288 64 266.5 64 240L64 144z"/></svg>
|
||||
|
Before Width: | Height: | Size: 717 B |
@@ -1 +0,0 @@
|
||||
<svg fill="currentColor" fill-rule="evenodd" height="1em" style="flex:none;line-height:1" viewBox="0 0 24 24" width="1em" xmlns="http://www.w3.org/2000/svg"><title>Gemini</title><path d="M20.616 10.835a14.147 14.147 0 01-4.45-3.001 14.111 14.111 0 01-3.678-6.452.503.503 0 00-.975 0 14.134 14.134 0 01-3.679 6.452 14.155 14.155 0 01-4.45 3.001c-.65.28-1.318.505-2.002.678a.502.502 0 000 .975c.684.172 1.35.397 2.002.677a14.147 14.147 0 014.45 3.001 14.112 14.112 0 013.679 6.453.502.502 0 00.975 0c.172-.685.397-1.351.677-2.003a14.145 14.145 0 013.001-4.45 14.113 14.113 0 016.453-3.678.503.503 0 000-.975 13.245 13.245 0 01-2.003-.678z"></path></svg>
|
||||
|
Before Width: | Height: | Size: 651 B |
@@ -1 +0,0 @@
|
||||
<svg fill="currentColor" fill-rule="evenodd" height="1em" style="flex:none;line-height:1" viewBox="0 0 24 24" width="1em" xmlns="http://www.w3.org/2000/svg"><title>Grok</title><path d="M9.27 15.29l7.978-5.897c.391-.29.95-.177 1.137.272.98 2.369.542 5.215-1.41 7.169-1.951 1.954-4.667 2.382-7.149 1.406l-2.711 1.257c3.889 2.661 8.611 2.003 11.562-.953 2.341-2.344 3.066-5.539 2.388-8.42l.006.007c-.983-4.232.242-5.924 2.75-9.383.06-.082.12-.164.179-.248l-3.301 3.305v-.01L9.267 15.292M7.623 16.723c-2.792-2.67-2.31-6.801.071-9.184 1.761-1.763 4.647-2.483 7.166-1.425l2.705-1.25a7.808 7.808 0 00-1.829-1A8.975 8.975 0 005.984 5.83c-2.533 2.536-3.33 6.436-1.962 9.764 1.022 2.487-.653 4.246-2.34 6.022-.599.63-1.199 1.259-1.682 1.925l7.62-6.815"></path></svg>
|
||||
|
Before Width: | Height: | Size: 756 B |
@@ -1,4 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 12 12">
|
||||
<path d="M.03,2.19c.14.03.29.07.43.09,1.26.16,1.76-1.08,2.78-1.5,1.26-.52,2.77-.09,2.67,1.5s-1.89,2.3-2.88,3.2c-.38.34-.74.91-.36,1.4.5.64,1.25.06,1.65-.36,1.18-1.22,2.38-3.76,4.38-3.57,1.47.14,2.2,1.65,2.32,2.97h.96l.03.03v1.36h-.99c-.09,1.37-.54,3.03-1.78,3.79-.9.55-2.02.51-2.73-.31-.78-.89-.43-1.96.16-2.84.71-1.06,1.85-1.83,3.12-2.04.04-.61-.34-1.2-.94-1.35-1.15-.3-2.03.74-2.65,1.54-.79,1-1.87,2.88-3.33,2.8-1.19-.07-1.99-1.08-1.93-2.24.05-1.04,1.04-1.89,1.83-2.46.52-.38,1.71-1.05,1.81-1.72.06-.41-.18-.75-.61-.65-.59.13-1.03.85-1.49,1.22-.69.56-1.57.85-2.43.48v-1.3ZM9.73,7.28c-.28.07-.56.16-.81.3-.58.31-1.35,1.09-1.45,1.77-.08.58.45.87.95.62.87-.43,1.26-1.79,1.31-2.69Z"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 824 B |
@@ -1 +0,0 @@
|
||||
<svg fill="currentColor" fill-rule="evenodd" height="1em" style="flex:none;line-height:1" viewBox="0 0 24 24" width="1em" xmlns="http://www.w3.org/2000/svg"><title>Kling</title><path clip-rule="evenodd" d="M5.493 21.234c-1.112-1.451-1.109-4.263-.081-7.459l-4.557-2.63a1.683 1.683 0 01-.85-1.304 1.505 1.505 0 01.08-.622 13.18 13.18 0 011.037-2.255c3.476-6.02 10.916-8.23 16.619-4.938.46.266.82.67 1.081 1.184.785 1.545.685 4.096-.234 6.954l4.557 2.631c.339.196.596.492.736.832a1.53 1.53 0 01.034 1.093 13.146 13.146 0 01-1.037 2.255c-3.476 6.02-10.916 8.23-16.619 4.938a2.6 2.6 0 01-.766-.68zm11.096-6.615c-2.073 3.591-5.808 5.316-8.343 3.852-1.267-.731-1.994-2.122-2.145-3.778-.095-1.035.036-2.173.4-3.32.217-.684.517-1.37.902-2.039l.008-.014c2.073-3.59 5.808-5.315 8.343-3.852.633.366 1.13.895 1.49 1.54.986 1.772.922 4.415-.285 6.914-.111.23-.232.457-.362.683l-.008.014z"></path></svg>
|
||||
|
Before Width: | Height: | Size: 888 B |
@@ -1,14 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 12 12">
|
||||
<defs>
|
||||
<style>
|
||||
.cls-1 {
|
||||
fill: #010101;
|
||||
}
|
||||
</style>
|
||||
</defs>
|
||||
<path d="M9.26.37c.36.29.62.65.72,1.11.01.14.01.27.01.41t0,.06c0,.51-.07.99-.22,1.47t-.02.06c-.24.83-.68,1.56-1.25,2.21-.02.02-.04.05-.06.07-.21.23-.42.43-.66.63-.02.02-.04.03-.06.05-.87.72-1.93,1.12-3.04,1.29-.03,0-.06.01-.09.02-.63.1-1.3.08-1.85-.27-.11-.08-.21-.18-.31-.28-.02-.02-.03-.03-.05-.05-.32-.34-.43-.82-.43-1.27.02-.45.27-.87.59-1.17.36-.31.81-.47,1.29-.48.62-.01,1.16-.23,1.64-.62.02-.02.04-.03.07-.05.39-.33.67-.89.73-1.39,0-.11.02-.22.02-.33.03-.51.2-.93.57-1.29.07-.06.15-.12.23-.18.02-.01.03-.02.05-.04.63-.43,1.49-.36,2.09.06Z"/>
|
||||
<path d="M8.61,6.51c.06,0,.1.02.14.06t.04.05s.03.04.04.06c.01.02.03.04.04.06.01.02.03.04.04.06.4.57.68,1.19.88,1.85t.02.05c.22.71.32,1.62-.02,2.29-.24.47-.63.72-1.11.91-.48.14-1.02.06-1.46-.17-.47-.28-.74-.67-.89-1.19-.03-.12-.04-.25-.04-.37-.02-.65-.25-1.22-.71-1.68-.06-.05-.12-.11-.19-.16-.03-.03-.05-.05-.08-.08.13-.04.25-.08.38-.12.99-.29,2.17-.79,2.86-1.61l.04-.03Z"/>
|
||||
<path class="cls-1" d="M4.96.4c.34.27.63.67.69,1.1.02.29.02.58-.08.85t-.03.08c-.16.44-.5.77-.92.97-.29.13-.53.17-.85.18-.68.04-1.21.26-1.72.69-.02.02-.05.04-.07.06,0-.36,0-.71,0-1.07,0-.17,0-.33,0-.5,0-.16,0-.32,0-.48,0-.06,0-.12,0-.18,0-.63.12-1.11.56-1.58.67-.65,1.69-.66,2.43-.13Z"/>
|
||||
<path d="M1.98,7.67s.07.05.1.07c.02.01.04.03.06.04.04.03.09.07.13.1.41.3.88.5,1.39.51.58.01,1.1.17,1.52.59.35.4.5.86.47,1.39-.05.49-.31.89-.67,1.21-.46.35-1.01.43-1.57.36-.47-.1-.88-.4-1.15-.79-.07-.12-.13-.23-.18-.36,0-.02-.02-.05-.03-.07-.1-.31-.09-.61-.09-.93,0-.06,0-.12,0-.18,0-.16,0-.32,0-.48,0-.16,0-.33,0-.49,0-.32,0-.64,0-.96Z"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.7 KiB |
@@ -1 +0,0 @@
|
||||
<svg fill="currentColor" fill-rule="evenodd" height="1em" style="flex:none;line-height:1" viewBox="0 0 24 24" width="1em" xmlns="http://www.w3.org/2000/svg"><title>Midjourney</title><path d="M22.369 17.676c-1.387 1.259-3.17 2.378-5.332 3.417.044.03.086.057.13.083l.018.01.019.012c.216.123.42.184.641.184.222 0 .426-.061.642-.184l.018-.011.019-.011c.14-.084.266-.178.492-.366l.178-.148c.279-.232.426-.342.625-.456.304-.174.612-.266.949-.266.337 0 .645.092.949.266l.023.014c.188.109.334.219.602.442l.178.148c.221.184.346.278.483.36l.028.017.018.01c.21.12.407.181.62.185h.022a.31.31 0 110 .618c-.337 0-.645-.092-.95-.266a3.137 3.137 0 01-.09-.054l-.022-.014-.022-.013-.02-.014a5.356 5.356 0 01-.49-.377l-.159-.132a3.836 3.836 0 00-.483-.36l-.027-.017-.019-.01a1.256 1.256 0 00-.641-.185c-.222 0-.426.061-.641.184l-.02.011-.018.011c-.14.084-.266.178-.492.366l-.158.132a5.125 5.125 0 01-.51.39l-.022.014-.022.014-.09.054a1.868 1.868 0 01-.95.266c-.337 0-.644-.092-.949-.266a3.137 3.137 0 01-.09-.054l-.022-.014-.022-.013-.026-.017a4.881 4.881 0 01-.425-.325.308.308 0 01-.12-.1l-.098-.081a3.836 3.836 0 00-.483-.36l-.027-.017-.019-.01a1.256 1.256 0 00-.641-.185c-.222 0-.426.061-.642.184l-.018.011-.019.011c-.14.084-.266.178-.492.366l-.158.132a5.125 5.125 0 01-.51.39l-.023.014-.022.014-.09.054A1.868 1.868 0 0112 22c-.337 0-.645-.092-.949-.266a3.137 3.137 0 01-.09-.054l-.022-.014-.022-.013-.021-.014a5.356 5.356 0 01-.49-.377l-.158-.132a3.836 3.836 0 00-.483-.36l-.028-.017-.018-.01a1.256 1.256 0 00-.642-.185c-.221 0-.425.061-.641.184l-.019.011-.018.011c-.141.084-.266.178-.492.366l-.158.132a5.125 5.125 0 01-.511.39l-.022.014-.022.014-.09.054a1.868 1.868 0 01-.986.264c-.746-.09-1.319-.38-1.89-.866l-.035-.03c-.047-.041-.118-.106-.192-.174l-.196-.181-.107-.1-.011-.01a1.531 1.531 0 00-.336-.253.313.313 0 00-.095-.03h-.005c-.119.022-.238.059-.361.11a.308.308 0 01-.077.061l-.008.005a.309.309 0 01-.126.034 5.66 5.66 0 00-.774.518l-.416.324-.055.043a6.542 6.542 0 01-.324.236c-.305.207-.552.315-.8.315a.31.31 0 01-.01-.618h.01c.09 0 .235-.062.438-.198l.04-.027c.077-.054.163-.117.27-.199l.385-.301.06-.047c.268-.206.506-.373.73-.505l-.633-1.21a.309.309 0 01.254-.451l20.287-1.305a.309.309 0 01.228.537zm-1.118.14L2.369 19.03l.423.809c.128-.045.256-.078.388-.1a.31.31 0 01.052-.005c.132 0 .26.032.386.093.153.073.294.179.483.35l.016.015.092.086.144.134.097.089c.065.06.125.114.16.144.485.418.948.658 1.554.736h.011a1.25 1.25 0 00.6-.172l.021-.011.019-.011.018-.011c.141-.084.266-.178.492-.366l.178-.148c.279-.232.426-.342.625-.456.305-.174.612-.266.95-.266.336 0 .644.092.948.266l.023.014c.188.109.335.219.603.442l.177.148c.222.184.346.278.484.36l.027.017.019.01c.215.124.42.185.641.185.222 0 .426-.061.641-.184l.019-.011.018-.011c.141-.084.267-.178.493-.366l.177-.148c.28-.232.427-.342.626-.456.304-.174.612-.266.949-.266.337 0 .644.092.949.266l.025.015c.187.109.334.22.603.443 1.867-.878 3.448-1.811 4.73-2.832l.02-.016zM3.653 2.026C6.073 3.06 8.69 4.941 10.8 7.258c2.46 2.7 4.109 5.828 4.637 9.149a.31.31 0 01-.421.335c-2.348-.945-4.54-1.258-6.59-1.02-1.739.2-3.337.792-4.816 1.703-.294.182-.62-.182-.405-.454 1.856-2.355 2.581-4.99 2.343-7.794-.195-2.292-1.031-4.61-2.284-6.709a.31.31 0 01.388-.442zM10.04 4.45c1.778.543 3.892 2.102 5.782 4.243 1.984 2.248 3.552 4.934 4.347 7.582a.31.31 0 01-.401.38l-.022-.01-.386-.154a10.594 10.594 0 00-.291-.112l-.016-.006c-.68-.247-1.199-.291-1.944-.101a.31.31 0 01-.375-.218C15.378 11.123 13.073 7.276 9.775 5c-.291-.201-.072-.653.266-.55zM4.273 2.996l.008.015c1.028 1.94 1.708 4.031 1.885 6.113.213 2.513-.31 4.906-1.673 7.092l-.02.031.003-.001c1.198-.581 2.47-.969 3.825-1.132l.055-.006c1.981-.23 4.083.029 6.309.837l.066.025-.007-.039c-.593-2.95-2.108-5.737-4.31-8.179l-.07-.078c-1.785-1.96-3.944-3.6-6.014-4.65l-.057-.028zm7.92 3.238l.048.048c2.237 2.295 3.885 5.431 4.974 9.191l.038.132.022-.004c.71-.133 1.284-.063 1.963.18l.027.01.066.024.046.018-.025-.073c-.811-2.307-2.208-4.62-3.936-6.594l-.058-.065c-1.02-1.155-2.103-2.132-3.15-2.856l-.015-.011z"></path></svg>
|
||||
|
Before Width: | Height: | Size: 3.9 KiB |
@@ -1 +0,0 @@
|
||||
<svg fill="currentColor" fill-rule="evenodd" height="1em" style="flex:none;line-height:1" viewBox="0 0 24 24" width="1em" xmlns="http://www.w3.org/2000/svg"><title>Minimax</title><path d="M16.278 2c1.156 0 2.093.927 2.093 2.07v12.501a.74.74 0 00.744.709.74.74 0 00.743-.709V9.099a2.06 2.06 0 012.071-2.049A2.06 2.06 0 0124 9.1v6.561a.649.649 0 01-.652.645.649.649 0 01-.653-.645V9.1a.762.762 0 00-.766-.758.762.762 0 00-.766.758v7.472a2.037 2.037 0 01-2.048 2.026 2.037 2.037 0 01-2.048-2.026v-12.5a.785.785 0 00-.788-.753.785.785 0 00-.789.752l-.001 15.904A2.037 2.037 0 0113.441 22a2.037 2.037 0 01-2.048-2.026V18.04c0-.356.292-.645.652-.645.36 0 .652.289.652.645v1.934c0 .263.142.506.372.638.23.131.514.131.744 0a.734.734 0 00.372-.638V4.07c0-1.143.937-2.07 2.093-2.07zm-5.674 0c1.156 0 2.093.927 2.093 2.07v11.523a.648.648 0 01-.652.645.648.648 0 01-.652-.645V4.07a.785.785 0 00-.789-.78.785.785 0 00-.789.78v14.013a2.06 2.06 0 01-2.07 2.048 2.06 2.06 0 01-2.071-2.048V9.1a.762.762 0 00-.766-.758.762.762 0 00-.766.758v3.8a2.06 2.06 0 01-2.071 2.049A2.06 2.06 0 010 12.9v-1.378c0-.357.292-.646.652-.646.36 0 .653.29.653.646V12.9c0 .418.343.757.766.757s.766-.339.766-.757V9.099a2.06 2.06 0 012.07-2.048 2.06 2.06 0 012.071 2.048v8.984c0 .419.343.758.767.758.423 0 .766-.339.766-.758V4.07c0-1.143.937-2.07 2.093-2.07z"></path></svg>
|
||||
|
Before Width: | Height: | Size: 1.3 KiB |
@@ -1 +0,0 @@
|
||||
<svg fill="currentColor" fill-rule="evenodd" height="1em" style="flex:none;line-height:1" viewBox="0 0 24 24" width="1em" xmlns="http://www.w3.org/2000/svg"><title>OpenAI</title><path d="M21.55 10.004a5.416 5.416 0 00-.478-4.501c-1.217-2.09-3.662-3.166-6.05-2.66A5.59 5.59 0 0010.831 1C8.39.995 6.224 2.546 5.473 4.838A5.553 5.553 0 001.76 7.496a5.487 5.487 0 00.691 6.5 5.416 5.416 0 00.477 4.502c1.217 2.09 3.662 3.165 6.05 2.66A5.586 5.586 0 0013.168 23c2.443.006 4.61-1.546 5.361-3.84a5.553 5.553 0 003.715-2.66 5.488 5.488 0 00-.693-6.497v.001zm-8.381 11.558a4.199 4.199 0 01-2.675-.954c.034-.018.093-.05.132-.074l4.44-2.53a.71.71 0 00.364-.623v-6.176l1.877 1.069c.02.01.033.029.036.05v5.115c-.003 2.274-1.87 4.118-4.174 4.123zM4.192 17.78a4.059 4.059 0 01-.498-2.763c.032.02.09.055.131.078l4.44 2.53c.225.13.504.13.73 0l5.42-3.088v2.138a.068.068 0 01-.027.057L9.9 19.288c-1.999 1.136-4.552.46-5.707-1.51h-.001zM3.023 8.216A4.15 4.15 0 015.198 6.41l-.002.151v5.06a.711.711 0 00.364.624l5.42 3.087-1.876 1.07a.067.067 0 01-.063.005l-4.489-2.559c-1.995-1.14-2.679-3.658-1.53-5.63h.001zm15.417 3.54l-5.42-3.088L14.896 7.6a.067.067 0 01.063-.006l4.489 2.557c1.998 1.14 2.683 3.662 1.529 5.633a4.163 4.163 0 01-2.174 1.807V12.38a.71.71 0 00-.363-.623zm1.867-2.773a6.04 6.04 0 00-.132-.078l-4.44-2.53a.731.731 0 00-.729 0l-5.42 3.088V7.325a.068.068 0 01.027-.057L14.1 4.713c2-1.137 4.555-.46 5.707 1.513.487.833.664 1.809.499 2.757h.001zm-11.741 3.81l-1.877-1.068a.065.065 0 01-.036-.051V6.559c.001-2.277 1.873-4.122 4.181-4.12.976 0 1.92.338 2.671.954-.034.018-.092.05-.131.073l-4.44 2.53a.71.71 0 00-.365.623l-.003 6.173v.002zm1.02-2.168L12 9.25l2.414 1.375v2.75L12 14.75l-2.415-1.375v-2.75z"></path></svg>
|
||||
|
Before Width: | Height: | Size: 1.7 KiB |
@@ -1,11 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 12 12">
|
||||
<defs>
|
||||
<style>
|
||||
.cls-1 {
|
||||
fill-rule: evenodd;
|
||||
}
|
||||
</style>
|
||||
</defs>
|
||||
<path class="cls-1" d="M8.6,2.63c.89,0,1.75.35,2.39.99.63.63.99,1.49,1,2.38,0,.66-.2,1.3-.56,1.84-.36.55-.87.98-1.47,1.24-.6.26-1.27.34-1.91.24-.65-.11-1.25-.4-1.73-.84-.59-.5-1.19-.98-1.79-1.47l.86-.69c.84.67,1.57,1.27,1.85,1.5.39.29.87.45,1.37.45,1.23,0,2.32-1.02,2.3-2.28,0-.42-.13-.84-.35-1.19s-.54-.65-.92-.84c-.38-.19-.8-.27-1.22-.23-.42.04-.82.19-1.17.44-1.82,1.51-3.71,2.97-5.56,4.44-.75.53-1.64,0-1.64-.87C.01,6.58.01,5.42.02,4.26c0-.88.89-1.41,1.65-.88l2.03,1.64-.84.68-1.75-1.38c0,1.12,0,2.24,0,3.36,1.75-1.36,3.49-2.74,5.2-4.15.62-.57,1.44-.89,2.29-.89h0Z"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 807 B |
@@ -1 +0,0 @@
|
||||
<svg fill="currentColor" fill-rule="evenodd" height="1em" style="flex:none;line-height:1" viewBox="0 0 24 24" width="1em" xmlns="http://www.w3.org/2000/svg"><title>Recraft</title><path d="M19.667 8.275c0-4.57-4.15-8.275-9.27-8.275-1.774 0-3.213 3.705-3.213 8.275 0 1.143.09 2.233.253 3.224H4.29L1 23h9.4v-6.447c5.117 0 9.266-3.707 9.266-8.275l.001-.002zm-9.27-6.76c.93 0 1.682 3.028 1.682 6.76 0 3.733-.752 6.76-1.681 6.76-.93 0-1.681-3.027-1.681-6.76 0-3.732.752-6.76 1.68-6.76z"></path><path d="M19.848 16.552h-9.44L14.028 23h9.438l-3.618-6.448z"></path></svg>
|
||||
|
Before Width: | Height: | Size: 562 B |
@@ -1 +0,0 @@
|
||||
<svg fill="currentColor" fill-rule="evenodd" height="1em" style="flex:none;line-height:1" viewBox="0 0 24 24" width="1em" xmlns="http://www.w3.org/2000/svg"><title>Replicate</title><path d="M22 10.552v2.26h-7.932V22H11.54V10.552H22zM22 2v2.264H4.528V22H2V2h20zm0 4.276V8.54H9.296V22H6.768V6.276H22z"></path></svg>
|
||||
|
Before Width: | Height: | Size: 313 B |
@@ -1 +0,0 @@
|
||||
<svg fill="currentColor" fill-rule="evenodd" height="1em" style="flex:none;line-height:1" viewBox="0 0 24 24" width="1em" xmlns="http://www.w3.org/2000/svg"><title>Suno</title><path d="M16.5 0C20.642 0 24 5.373 24 12h-9c0 6.627-3.358 12-7.5 12C3.358 24 0 18.627 0 12h9c0-6.627 3.358-12 7.5-12z"></path></svg>
|
||||
|
Before Width: | Height: | Size: 308 B |
@@ -1 +0,0 @@
|
||||
<svg fill="currentColor" fill-rule="evenodd" height="1em" style="flex:none;line-height:1" viewBox="0 0 24 24" width="1em" xmlns="http://www.w3.org/2000/svg"><title>Hunyuan</title><path d="M12 0c6.627 0 12 5.373 12 12s-5.373 12-12 12S0 18.627 0 12 5.373 0 12 0zm1.652 1.123l-.01-.001c.533.097 1.023.233 1.41.404 6.084 2.683 7.396 9.214 1.601 14.338a3.781 3.781 0 01-5.337-.328 3.654 3.654 0 01-.884-3.044c-1.934.6-3.295 2.305-3.524 4.45-.204 1.912.324 4.044 2.056 5.634l.245.067C10.1 22.876 11.036 23 12 23c6.075 0 11-4.925 11-11 0-5.513-4.056-10.08-9.348-10.877zM2.748 6.21c-.178.269-.348.536-.51.803l-.235.394.078-.167A10.957 10.957 0 001 12c0 4.919 3.228 9.083 7.682 10.49l.214.065C3.523 18.528 2.84 14.149 6.47 8.68A2.234 2.234 0 102.748 6.21zm10.157-5.172c4.408 1.33 3.61 5.41 2.447 6.924-.86 1.117-2.922 1.46-3.708 2.238-.666.657-1.077 1.462-1.212 2.291A5.303 5.303 0 0112 12.258a5.672 5.672 0 001.404-11.169 10.51 10.51 0 00-.5-.052z"></path></svg>
|
||||
|
Before Width: | Height: | Size: 954 B |
@@ -1,7 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 12 12">
|
||||
<path d="M7.51,3.04q.14,0,.27,0c.1,0,.2,0,.3,0,.1,0,.21,0,.31,0,.1,0,.21,0,.31,0,.26,0,.51,0,.77,0,.29.67.58,1.34.87,2.01.15.34.29.67.44,1.01.15.35.3.7.45,1.05.06.14.12.27.18.41.08.19.17.38.25.57q.04.09.08.17c.11.25.17.42.27.69h-2.36c-.45-1.18-.89-2.37-1.3-3.56-.31.75-.58,1.51-.85,2.27-.04.13-.09.25-.13.38-.11.3-.22.61-.32.92h-2.26c.29-.76.59-1.51.91-2.26.04-.1.09-.2.13-.31.09-.21.18-.43.27-.64.12-.27.23-.55.35-.82.11-.26.22-.53.34-.79.04-.1.08-.2.13-.3q.06-.14.12-.27c.03-.08.07-.16.1-.24.07-.15.12-.28.12-.28,0,0,.14,0,.26,0Z"/>
|
||||
<path d="M1.65,2.96h3.82v1.65h-1.74v4.43H1.65V2.96Z"/>
|
||||
<path d="M0,2.96h1.3v1.74H0v-1.74Z"/>
|
||||
<path d="M8.25,6.78h.17c.23.72.46,1.43.7,2.17h-1.56c.21-.73.45-1.45.7-2.17Z"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 854 B |
@@ -1 +0,0 @@
|
||||
<svg fill="currentColor" fill-rule="evenodd" height="1em" style="flex:none;line-height:1" viewBox="0 0 24 24" width="1em" xmlns="http://www.w3.org/2000/svg"><title>Vidu</title><path d="M20.607 2.247c-2.917-.966-5.426 1.084-6.011 2.96 0 0-2.105 6.76-3.002 9.58-.428 1.346-1.489 3.548-3.487 3.548-1.627 0-2.463-1.527-2.816-2.437L2.865 9.431c-.281-.681.013-2.04 1.14-2.447 1.204-.432 1.978.575 2.178 1.11l3.022 7.74c.72-.928 1.178-2.438 1.476-3.507l-1.984-5.21C7.756 4.686 5.267 3.58 2.962 4.43 1.095 5.118-.702 7.474.275 10.435l2.504 6.44c.38.976 1.881 4.163 5.275 4.163 4.073 0 5.601-3.473 6.449-6.218.424-1.373 2.749-8.797 2.749-8.797.338-1.109 1.71-1.428 2.568-1.148.605.196 1.698 1.031 1.345 2.325-.066.236-1.92 6.209-2.604 8.026-.357.948-1.262 3.006-3.324 2.72-.628 1.39-1.15 2.199-1.94 2.925 2.572 1.218 6.32-.009 7.898-4.776.586-1.773 2.644-8.166 2.644-8.166.598-1.963-.469-4.768-3.232-5.682z"></path></svg>
|
||||
|
Before Width: | Height: | Size: 912 B |
@@ -1,6 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg id="Layer_2" data-name="Layer 2" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 249.21 224.64">
|
||||
<g id="Layer_1-2" data-name="Layer 1">
|
||||
<path d="M6.64.07c2.98-.4,5.65.92,7.26,3.41l66.32,109.22c4.55,5.38,10.84,10.03,18,11.02,8.98,1.24,17.64-3.5,25.87-6.45,38.94-13.94,78-27.61,117.04-41.24,6.08-.57,9.93,4.49,7.2,10.08l-76.03,135.25c-2.61,3.2-7.54,4.48-11.03,1.92-3.25-2.39-7.45-7.65-10.43-10.68-9.93-10.07-19.84-20.11-29.75-30.2-11.48-11.69-20.14-24.31-39.09-20.64-14.85,2.87-21.88,16.72-32.48,25.55-3.85,3.21-9.25,3.5-12.46-.75-1.69-2.24-2.1-6.25-2.7-9.05C22.12,121.2,12.09,64.37,0,8.01-.16,4.05,2.67.61,6.64.07Z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 680 B |
|
Before Width: | Height: | Size: 27 KiB |
|
Before Width: | Height: | Size: 29 KiB |