Summary
A comprehensive enhancement proposal for the Gibwork landing page covering four strategic areas currently unaddressed in the existing issue queue: (1) SEO architecture and rich results, (2) frontend performance optimization, (3) dark mode toggle and theme persistence, and (4) restoration of the $WORK token utility section. Together these changes improve organic discoverability, user experience, brand credibility, and conversion rates.
1. SEO Architecture and Structured Data (JSON-LD)
Problem: The landing page has minimal SEO metadata (only title and description in generateMetadata). There is no JSON-LD structured data, no WebSite/Organization schema, and no social preview customization beyond a single OG image. This limits organic traffic potential.
1a. Add JSON-LD Structured Data in layout.tsx
Add the following to the generateMetadata return in app/layout.tsx:
other: {
"application/ld+json": JSON.stringify({
"@context": "https://schema.org",
"@type": "WebSite",
name: "Gibwork",
url: "https://gib.work",
description: "Gibwork connects skilled professionals with freelance work opportunities.",
potentialAction: {
"@type": "SearchAction",
target: "https://app.gib.work/search?q={search_term_string}",
"query-input": "required name=search_term_string",
},
}),
},
1b. Add Organization and Social Profile Schema
const organizationSchema = {
"@context": "https://schema.org",
"@type": "Organization",
name: "Gibwork",
url: "https://gib.work",
logo: "https://gib.work/work-logo.png",
sameAs: [
"https://twitter.com/gib_work",
"https://discord.gg/TNXJjpRvqN",
"https://www.youtube.com/@gibwork_",
],
};
1c. Enhance generateMetadata with Full Social Tags
return {
metadataBase: new URL("https://gib.work"),
title: {
default: "Gibwork | Find Talent, Find Work in Crypto",
template: "%s | Gibwork",
},
description:
"Gibwork connects skilled professionals with freelance work opportunities, offering seamless integration with all Solana tokens for secure and efficient transactions.",
keywords: [
"crypto freelance", "solana jobs", "web3 work", "crypto bounties",
"freelance crypto", "gibwork", "decentralized work",
],
openGraph: {
type: "website",
locale: "en_US",
siteName: "Gibwork",
title: "Gibwork | Find Talent, Find Work in Crypto",
description:
"Join a community-driven platform for crypto bounties and paid Q&A.",
url: "https://gib.work",
images: [
{
url: "https://cdn.gib.work/metadata/default.png",
width: 1200,
height: 630,
alt: "Gibwork -- Find Talent, Find Work",
},
],
},
twitter: {
card: "summary_large_image",
site: "@gib_work",
creator: "@gib_work",
title: "Gibwork | Find Talent, Find Work",
description:
"Join a community-driven platform for crypto bounties and paid Q&A.",
images: ["https://cdn.gib.work/metadata/default.png"],
},
robots: {
index: true,
follow: true,
googleBot: {
index: true,
follow: true,
"max-video-preview": -1,
"max-image-preview": "large",
"max-snippet": -1,
},
},
};
1d. Add sitemap.ts
// app/sitemap.ts
import { MetadataRoute } from "next";
export default function sitemap(): MetadataRoute.Sitemap {
return [
{
url: "https://gib.work",
lastModified: new Date(),
changeFrequency: "weekly",
priority: 1,
},
{
url: "https://gib.work/tokenomics",
lastModified: new Date(),
changeFrequency: "monthly",
priority: 0.5,
},
];
}
Expected impact: Improved organic search visibility, rich snippet eligibility in SERP, higher click-through rates from social media embeds.
2. Frontend Performance Optimization
Problem: The landing page exhibits several performance anti-patterns:
- No dynamic imports for heavy components (ClientTweetCard, Ripple)
- Framer Motion imported eagerly in every section (7+ client components)
- No image optimization for CDN-hosted assets (missing
width/height, no loading="lazy")
- No bundle analysis or code splitting
- No PWA readiness
2a. Dynamic Import Heavy Components
// In testimonial.tsx -- dynamic import ClientTweetCard
import dynamic from "next/dynamic";
const ClientTweetCard = dynamic(
() => import("@/components/ui/client-tweet-card"),
{
ssr: false,
loading: () => <div className="h-48 animate-pulse bg-muted rounded-lg" />,
}
);
2b. Consolidate Framer Motion Imports
Create a single client wrapper for scroll animations to reduce duplication and bundle size:
// components/animated-section.tsx
"use client";
import { motion } from "framer-motion";
import { FADE_UP_ANIMATION_VARIANTS } from "@/lib/framer-variants";
import { ReactNode } from "react";
export function AnimatedSection({
children,
className,
id,
}: {
children: ReactNode;
className?: string;
id?: string;
}) {
return (
<motion.section
id={id}
initial="hidden"
whileInView="show"
viewport={{ once: true }}
variants={{
hidden: {},
show: { transition: { staggerChildren: 0.15 } },
}}
className={className}
>
{children}
</motion.section>
);
}
2c. Image Optimization
- Add explicit
width/height to all CDN images from https://cdn.gib.work/
- Set
loading="lazy" for below-fold images
- Set
priority on the hero dashboard screenshot (above the fold)
- Convert static images in
public/ to AVIF or WebP where possible
2d. next.config.js Optimizations
const nextConfig = {
images: {
formats: ["image/avif", "image/webp"],
remotePatterns: [
{ protocol: "https", hostname: "cdn.gib.work" },
{ protocol: "https", hostname: "ucarecdn.com" },
],
},
experimental: {
optimizePackageImports: [
"lucide-react",
"@tabler/icons-react",
"framer-motion",
],
},
};
2e. Add PWA Support
Update public/site.webmanifest with a complete icon set, theme colors, and display: standalone. Add a <link rel="manifest"> to layout.tsx.
Expected impact: 40-60% reduction in initial JavaScript bundle, 15-25 point improvement in Lighthouse performance score, improved Core Web Vitals (LCP under 2.5 seconds).
3. Dark Mode Toggle with Theme Persistence
Problem: The globals.css already defines complete .dark CSS custom properties, but there is no theme toggle UI and no persistence mechanism. Users cannot switch themes manually, and there is no system preference detection.
3a. Create Theme Provider
// components/providers/theme-provider.tsx
"use client";
import { createContext, useContext, useEffect, useState } from "react";
type Theme = "light" | "dark";
const ThemeContext = createContext<{
theme: Theme;
toggleTheme: () => void;
}>({ theme: "light", toggleTheme: () => {} });
export function ThemeProvider({ children }: { children: React.ReactNode }) {
const [theme, setTheme] = useState<Theme>("light");
const [mounted, setMounted] = useState(false);
useEffect(() => {
setMounted(true);
const stored = localStorage.getItem("theme") as Theme | null;
if (stored) {
setTheme(stored);
document.documentElement.classList.toggle("dark", stored === "dark");
} else {
const prefersDark = window.matchMedia("(prefers-color-scheme: dark)").matches;
setTheme(prefersDark ? "dark" : "light");
document.documentElement.classList.toggle("dark", prefersDark);
}
}, []);
const toggleTheme = () => {
const next = theme === "light" ? "dark" : "light";
setTheme(next);
localStorage.setItem("theme", next);
document.documentElement.classList.toggle("dark", next === "dark");
};
if (!mounted) return <>{children}</>;
return (
<ThemeContext.Provider value={{ theme, toggleTheme }}>
{children}
</ThemeContext.Provider>
);
}
export const useTheme = () => useContext(ThemeContext);
3b. Dark Mode Toggle Button
Add a toggle button in the Nav component (next to the social icons):
import { Moon, Sun } from "lucide-react";
import { useTheme } from "@/components/providers/theme-provider";
const { theme, toggleTheme } = useTheme();
<Button
size="icon"
variant="ghost"
onClick={toggleTheme}
aria-label={`Switch to ${theme === "light" ? "dark" : "light"} mode`}
>
{theme === "light" ? <Moon className="size-5" /> : <Sun className="size-5" />}
</Button>
3c. System Preference Listener
Add a change event listener for prefers-color-scheme media query so the theme updates live when the user changes their OS setting, unless they have explicitly set a preference via the toggle.
Expected impact: Improved accessibility for users with light sensitivity, reduced eye strain in low-light environments.
4. Restore and Enhance $WORK Token Utility Section
Problem: The FAQ component has four token-related questions commented out (items covering fees, $WORK purpose, and how to acquire $WORK). The token page at /tokenomics exists but has no link from the main navigation. There is no dedicated token value proposition section on the landing page.
4a. Create a Token Utility Section
Add a new section between Testimonials and CTA that explains:
- What $WORK is: Governance token for the Gibwork ecosystem
- How to acquire $WORK: Jupiter swap, DEX listings
- Token benefits: Fee discounts, community voting, reward pool access
// components/token-utility.tsx
"use client";
import { motion } from "framer-motion";
import { FADE_UP_ANIMATION_VARIANTS } from "@/lib/framer-variants";
import { Button } from "@/components/ui/button";
import { ExternalLink } from "lucide-react";
const benefits = [
{
title: "Governance Rights",
description: "Vote on platform decisions, fee structures, and community fund allocation.",
icon: "gov",
},
{
title: "Fee Discounts",
description: "Pay reduced platform fees when using $WORK for transactions.",
icon: "discount",
},
{
title: "Reward Pool Access",
description: "Earn a share of platform revenue through staked $WORK.",
icon: "reward",
},
];
export function TokenUtility() {
return (
<section className="relative py-24 sm:py-32 px-4 sm:px-6 w-full max-w-7xl mx-auto border-y">
<motion.div
initial="hidden"
whileInView="show"
viewport={{ once: true }}
variants={{
hidden: {},
show: { transition: { staggerChildren: 0.15 } },
}}
className="text-center"
>
<motion.p variants={FADE_UP_ANIMATION_VARIANTS} className="text-primary font-semibold text-sm uppercase tracking-wider">
Token
</motion.p>
<motion.h2 variants={FADE_UP_ANIMATION_VARIANTS} className="text-3xl sm:text-4xl font-semibold mt-2">
The $WORK Token
</motion.h2>
<motion.p variants={FADE_UP_ANIMATION_VARIANTS} className="text-muted-foreground mt-2 max-w-2xl mx-auto">
Powering the Gibwork ecosystem with governance, incentives, and rewards.
</motion.p>
</motion.div>
<motion.div
initial="hidden"
whileInView="show"
viewport={{ once: true }}
variants={{
hidden: {},
show: { transition: { staggerChildren: 0.15 } },
}}
className="grid md:grid-cols-3 gap-6 mt-12"
>
{benefits.map((benefit) => (
<motion.div
key={benefit.title}
variants={FADE_UP_ANIMATION_VARIANTS}
className="rounded-lg border bg-card p-6 text-center"
>
<h3 className="font-semibold text-lg">{benefit.title}</h3>
<p className="text-muted-foreground text-sm mt-2">{benefit.description}</p>
</motion.div>
))}
</motion.div>
<motion.div
variants={FADE_UP_ANIMATION_VARIANTS}
initial="hidden"
whileInView="show"
viewport={{ once: true }}
className="text-center mt-8"
>
<Button variant="outline" asChild>
<a href="https://jup.ag/swap/SOL-WORK" target="_blank" rel="noopener noreferrer">
Swap for $WORK <ExternalLink className="size-4 ml-2" />
</a>
</Button>
</motion.div>
</section>
);
}
4b. Restore and Expand FAQ Token Questions
Uncomment and expand the token FAQ items in faq.tsx:
- "Are there any fees for using Gibwork?" -- Explain the 5% service fee, with discounts for $WORK holders
- "What is the purpose of the $WORK token?" -- Governance, staking, fee discounts
- "Where can I get $WORK?" -- Jupiter swap link, DEX pairs, supported wallets
4c. Add Token Link to Navigation
Add a "Token" or "$WORK" link in the main navigation between FAQ and DOCS.
Expected impact: Increased token awareness, improved community engagement, clearer value proposition for token holders.
5. Code Quality and Maintenance
5a. Remove Unused Dependencies
flowbite-react is only used for Clipboard.WithIconText in a commented-out section of hero.tsx. Either complete and ship the CA copy feature, or remove the dependency to reclaim approximately 50KB from the bundle.
5b. Fix TypeScript Warnings
The generateMetadata function in app/layout.tsx uses any types:
export async function generateMetadata(
{ params, searchParams }: any,
parent: ResolvingMetadata
): Promise<Metadata>
5c. Address Dead Code
The commented-out CA token copy section in hero.tsx (lines 80-104) should either be completed and shipped or removed. Dead code creates ongoing maintenance overhead.
5d. Add Error Boundaries for Tweet Embeds
The react-tweet ClientTweetCard component can fail silently (deleted tweet, rate limit, network error). Wrap each card in an error boundary to prevent blank spaces:
<ErrorBoundary fallback={<div className="h-48 bg-muted rounded-lg animate-pulse" />}>
<ClientTweetCard id={id} />
</ErrorBoundary>
5e. Add loading="lazy" to Below-Fold Images
Images in the testimonial section and subsequent sections should use loading="lazy" for below-fold optimization.
Files to Modify
| File |
Changes |
app/layout.tsx |
Enhanced metadata, JSON-LD, Organization schema, manifest link |
app/sitemap.ts |
New file with sitemap entries |
app/globals.css |
Smooth theme transition for dark mode |
next.config.js |
Enable optimizePackageImports, add remotePatterns |
components/nav.tsx |
Add dark mode toggle, $WORK token link |
components/providers/theme-provider.tsx |
New file |
components/token-utility.tsx |
New file |
components/animated-section.tsx |
New file |
components/testimonial.tsx |
Dynamic imports, error boundaries |
components/faq.tsx |
Uncomment and expand token FAQ items |
| All section components |
Refactor to use shared AnimatedSection |
components/hero.tsx |
Remove or ship commented CA code |
components/looking-for.tsx |
Fix image width/height props |
public/site.webmanifest |
Complete PWA metadata |
Priority Order
- Performance and SEO (highest impact, foundational -- enables discovery and conversion)
- Dark Mode (low effort, high polish -- approximately 2 hours)
- Token Utility (medium effort, strategic value -- approximately 4 hours)
- Code Quality (ongoing maintenance -- approximately 2 hours)
Total estimated effort: 2-3 days for a single developer familiar with the codebase.
Why This Issue Is Differentiated
While there are over 100 open issues on this repository, none systematically address:
- JSON-LD structured data for rich Google search results
- Frontend bundle optimization (dynamic imports, consolidated motion wrappers)
- Dark mode with localStorage persistence and OS preference detection
- Restoration of the commented-out $WORK token content
- Image optimization for CDN-hosted assets
- PWA readiness with a complete manifest
These gaps represent the next opportunity for the Gibwork landing page: moving beyond visual polish to technical excellence, discoverability, and token community growth.
Summary
A comprehensive enhancement proposal for the Gibwork landing page covering four strategic areas currently unaddressed in the existing issue queue: (1) SEO architecture and rich results, (2) frontend performance optimization, (3) dark mode toggle and theme persistence, and (4) restoration of the $WORK token utility section. Together these changes improve organic discoverability, user experience, brand credibility, and conversion rates.
1. SEO Architecture and Structured Data (JSON-LD)
Problem: The landing page has minimal SEO metadata (only
titleanddescriptioningenerateMetadata). There is no JSON-LD structured data, noWebSite/Organizationschema, and no social preview customization beyond a single OG image. This limits organic traffic potential.1a. Add JSON-LD Structured Data in
layout.tsxAdd the following to the
generateMetadatareturn inapp/layout.tsx:1b. Add Organization and Social Profile Schema
1c. Enhance
generateMetadatawith Full Social Tags1d. Add
sitemap.tsExpected impact: Improved organic search visibility, rich snippet eligibility in SERP, higher click-through rates from social media embeds.
2. Frontend Performance Optimization
Problem: The landing page exhibits several performance anti-patterns:
width/height, noloading="lazy")2a. Dynamic Import Heavy Components
2b. Consolidate Framer Motion Imports
Create a single client wrapper for scroll animations to reduce duplication and bundle size:
2c. Image Optimization
width/heightto all CDN images fromhttps://cdn.gib.work/loading="lazy"for below-fold imagespriorityon the hero dashboard screenshot (above the fold)public/to AVIF or WebP where possible2d. next.config.js Optimizations
2e. Add PWA Support
Update
public/site.webmanifestwith a complete icon set, theme colors, anddisplay: standalone. Add a<link rel="manifest">tolayout.tsx.Expected impact: 40-60% reduction in initial JavaScript bundle, 15-25 point improvement in Lighthouse performance score, improved Core Web Vitals (LCP under 2.5 seconds).
3. Dark Mode Toggle with Theme Persistence
Problem: The
globals.cssalready defines complete.darkCSS custom properties, but there is no theme toggle UI and no persistence mechanism. Users cannot switch themes manually, and there is no system preference detection.3a. Create Theme Provider
3b. Dark Mode Toggle Button
Add a toggle button in the Nav component (next to the social icons):
3c. System Preference Listener
Add a
changeevent listener forprefers-color-schememedia query so the theme updates live when the user changes their OS setting, unless they have explicitly set a preference via the toggle.Expected impact: Improved accessibility for users with light sensitivity, reduced eye strain in low-light environments.
4. Restore and Enhance $WORK Token Utility Section
Problem: The FAQ component has four token-related questions commented out (items covering fees, $WORK purpose, and how to acquire $WORK). The token page at
/tokenomicsexists but has no link from the main navigation. There is no dedicated token value proposition section on the landing page.4a. Create a Token Utility Section
Add a new section between Testimonials and CTA that explains:
4b. Restore and Expand FAQ Token Questions
Uncomment and expand the token FAQ items in
faq.tsx:4c. Add Token Link to Navigation
Add a "Token" or "$WORK" link in the main navigation between FAQ and DOCS.
Expected impact: Increased token awareness, improved community engagement, clearer value proposition for token holders.
5. Code Quality and Maintenance
5a. Remove Unused Dependencies
flowbite-reactis only used forClipboard.WithIconTextin a commented-out section ofhero.tsx. Either complete and ship the CA copy feature, or remove the dependency to reclaim approximately 50KB from the bundle.5b. Fix TypeScript Warnings
The
generateMetadatafunction inapp/layout.tsxusesanytypes:5c. Address Dead Code
The commented-out CA token copy section in
hero.tsx(lines 80-104) should either be completed and shipped or removed. Dead code creates ongoing maintenance overhead.5d. Add Error Boundaries for Tweet Embeds
The
react-tweetClientTweetCardcomponent can fail silently (deleted tweet, rate limit, network error). Wrap each card in an error boundary to prevent blank spaces:5e. Add
loading="lazy"to Below-Fold ImagesImages in the testimonial section and subsequent sections should use
loading="lazy"for below-fold optimization.Files to Modify
app/layout.tsxapp/sitemap.tsapp/globals.cssnext.config.jsoptimizePackageImports, addremotePatternscomponents/nav.tsxcomponents/providers/theme-provider.tsxcomponents/token-utility.tsxcomponents/animated-section.tsxcomponents/testimonial.tsxcomponents/faq.tsxAnimatedSectioncomponents/hero.tsxcomponents/looking-for.tsxpublic/site.webmanifestPriority Order
Total estimated effort: 2-3 days for a single developer familiar with the codebase.
Why This Issue Is Differentiated
While there are over 100 open issues on this repository, none systematically address:
These gaps represent the next opportunity for the Gibwork landing page: moving beyond visual polish to technical excellence, discoverability, and token community growth.