+
{thumb ? (
-

+

setLoaded(true)}
+ className={loaded ? "is-loaded" : undefined}
+ />
) : (
{project.title.slice(0, 1)}
@@ -32,9 +45,7 @@ export function ProjectCard({ project, index = 0 }: { project: Project; index?:
{year && {year}}
{project.title}
- {project.shortDescription && (
-
{project.shortDescription}
- )}
+ {project.shortDescription &&
{project.shortDescription}
}
diff --git a/client/src/lib/api.ts b/client/src/lib/api.ts
index ad2b1bd..8252bb4 100644
--- a/client/src/lib/api.ts
+++ b/client/src/lib/api.ts
@@ -316,3 +316,12 @@ export function thumbOf(p: Project): string {
""
);
}
+
+/** Prefer media alt text; fall back to project title for a11y. */
+export function thumbAltOf(p: Project): string {
+ const fromThumb = p.thumbnail?.alt?.trim();
+ if (fromThumb) return fromThumb;
+ const fromMedia = p.media?.find((m) => m.type === "image")?.alt?.trim();
+ if (fromMedia) return fromMedia;
+ return p.title || "";
+}
diff --git a/client/src/pages/AboutPage.scss b/client/src/pages/AboutPage.scss
index c9997d5..9749dd1 100644
--- a/client/src/pages/AboutPage.scss
+++ b/client/src/pages/AboutPage.scss
@@ -21,10 +21,17 @@
&__lead {
font-size: 1.15rem;
color: var(--text-muted);
- margin: 0 0 2.5rem;
+ margin: 0 0 1.5rem;
max-width: 36rem;
}
+ &__cta {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 0.75rem;
+ margin: 0 0 2.5rem;
+ }
+
&__grid {
display: grid;
gap: 2rem;
diff --git a/client/src/pages/AboutPage.tsx b/client/src/pages/AboutPage.tsx
index 0c06e74..ec3817a 100644
--- a/client/src/pages/AboutPage.tsx
+++ b/client/src/pages/AboutPage.tsx
@@ -13,6 +13,8 @@ export function AboutPage() {
api.site().then(setSite).catch(() => {});
}, []);
+ const contactEmail = site?.social?.email || "jmartin@jmartgraphix.com";
+
return (
About
@@ -21,6 +23,17 @@ export function AboutPage() {
{site?.about ||
"Creative professional specializing in 3D art, technical design, animation, and visual media."}
+
Disciplines
@@ -36,6 +49,9 @@ export function AboutPage() {
- {categories.map((c) => (
-
- {c.name}
- {typeof c.projectCount === "number" && (
-
{c.projectCount}
- )}
-
- ))}
- {views.map((v) => (
+ {liveCategories.map((c) => {
+ const countLabel =
+ typeof c.projectCount === "number"
+ ? `${c.projectCount} project${c.projectCount === 1 ? "" : "s"}`
+ : undefined;
+ return (
+
+ {c.name}
+ {typeof c.projectCount === "number" && (
+
{c.projectCount}
+ )}
+
+ );
+ })}
+ {liveViews.map((v) => (
+
404
+
Page not found
+
+ That URL doesn’t match anything on this site. It may have been moved or never existed.
+
+
+
+ Home
+
+
+ Portfolio
+
+
+ About
+
+
+
+ );
+}
diff --git a/client/src/pages/PortfolioPage.tsx b/client/src/pages/PortfolioPage.tsx
index 1362205..57d59c5 100644
--- a/client/src/pages/PortfolioPage.tsx
+++ b/client/src/pages/PortfolioPage.tsx
@@ -131,11 +131,14 @@ export function PortfolioPage() {
disabled={isViewMode}
>
- {categories.map((c) => (
-
- ))}
+ {categories
+ .filter((c) => typeof c.projectCount !== "number" || c.projectCount > 0)
+ .map((c) => (
+
+ ))}