Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
68407179f0 | ||
|
|
652146ad96 | ||
|
|
dafe769cda | ||
|
|
ad9b10ba94 |
No files matched your search
@@ -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)}
|
||||
|
||||
@@ -12,7 +12,7 @@ import type { CraftAppSlug } from "./crafting-apps";
|
||||
//
|
||||
// Release tags are `v<version>` and live at github.com/storytold/<slug>.
|
||||
|
||||
export const CRAFTING_APPS_LATEST_VERSION = "0.2.0";
|
||||
export const CRAFTING_APPS_LATEST_VERSION = "0.2.1";
|
||||
|
||||
export type CraftDesktopPlatform = "macOS" | "Windows" | "Linux";
|
||||
|
||||
@@ -43,6 +43,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[];
|
||||
};
|
||||
|
||||
@@ -171,15 +173,35 @@ export function craftRelease(
|
||||
return { version, assets };
|
||||
}
|
||||
|
||||
// Windows on ARM builds, which only some apps' releases include so far.
|
||||
const WITH_WINDOWS_ARM64: readonly CraftReleaseAsset[] = [
|
||||
...CRAFT_RELEASE_ASSETS,
|
||||
{
|
||||
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",
|
||||
},
|
||||
];
|
||||
|
||||
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,
|
||||
photocraft: craftRelease("0.3.0", WITH_WINDOWS_ARM64),
|
||||
vectorcraft: craftRelease("0.4.0", WITH_WINDOWS_ARM64),
|
||||
filmcraft: LATEST,
|
||||
lightcraft: LATEST,
|
||||
printcraft: LATEST,
|
||||
effectcraft: LATEST,
|
||||
// 0.2.1 shipped before the PrintCraft → PdfCraft rename.
|
||||
pdfcraft: { ...LATEST, fileSlug: "printcraft" },
|
||||
effectcraft: craftRelease("0.4.0", WITH_WINDOWS_ARM64),
|
||||
designcraft: LATEST,
|
||||
};
|
||||
@@ -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}` };
|
||||
});
|
||||
|
||||