Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 9 additions & 26 deletions src/app/blog/[slug]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { notFound } from "next/navigation";
import Link from "next/link";
import { Header } from "@/components/layout/Header";
import { createServiceClient } from "@/lib/supabase/service";

Expand All @@ -18,19 +19,13 @@ async function fetchPost(slug: string): Promise<Row | null> {
const sb = createServiceClient();
const { data } = await (sb as any)
.from("blog_posts")
.select(
"slug, title, meta_description, content_html, image_url, published_at",
)
.select("slug, title, meta_description, content_html, image_url, published_at")
.eq("slug", slug)
.maybeSingle();
return (data as Row | null) ?? null;
}

export async function generateMetadata({
params,
}: {
params: Promise<{ slug: string }>;
}) {
export async function generateMetadata({ params }: { params: Promise<{ slug: string }> }) {
const { slug } = await params;
const post = await fetchPost(slug);
if (!post) {
Expand All @@ -53,11 +48,7 @@ export async function generateMetadata({
};
}

export default async function BlogPost({
params,
}: {
params: Promise<{ slug: string }>;
}) {
export default async function BlogPost({ params }: { params: Promise<{ slug: string }> }) {
const { slug } = await params;
const post = await fetchPost(slug);
if (!post) notFound();
Expand All @@ -66,23 +57,17 @@ export default async function BlogPost({
<>
<Header />
<main className="mx-auto max-w-3xl px-4 sm:px-6 py-12 text-foreground">
<a
<Link
href="/blog"
className="inline-flex items-center text-sm text-muted-foreground hover:text-primary"
>
← Back to posts
</a>
<p className="mt-4 text-sm text-muted-foreground">
{post.published_at.slice(0, 10)}
</p>
</Link>
<p className="mt-4 text-sm text-muted-foreground">{post.published_at.slice(0, 10)}</p>
<h1 className="mt-2 text-4xl font-extrabold">{post.title}</h1>
{post.image_url && (
// eslint-disable-next-line @next/next/no-img-element
<img
src={post.image_url}
alt=""
className="mt-6 w-full rounded-lg border"
/>
<img src={post.image_url} alt="" className="mt-6 w-full rounded-lg border" />
)}
{post.content_html ? (
// prose handles paragraph color; explicit `prose-a:text-primary`
Expand All @@ -93,9 +78,7 @@ export default async function BlogPost({
dangerouslySetInnerHTML={{ __html: post.content_html }}
/>
) : (
<p className="mt-6 text-muted-foreground">
This post has no body content.
</p>
<p className="mt-6 text-muted-foreground">This post has no body content.</p>
)}
</main>
</>
Expand Down
15 changes: 10 additions & 5 deletions src/app/for-hire/[[...tags]]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@ export async function generateMetadata({ params }: GigsPageProps): Promise<Metad
}

const title = "I will... — Find People Ready to Work | ugig.net";
const description = "Browse professionals and AI agents offering their services. Find someone who will do exactly what you need.";
const description =
"Browse professionals and AI agents offering their services. Find someone who will do exactly what you need.";
return {
title,
description,
Expand Down Expand Up @@ -99,7 +100,10 @@ async function GigsList({
}

// Filter by location type
if (queryParams.location_type && ["remote", "onsite", "hybrid"].includes(queryParams.location_type)) {
if (
queryParams.location_type &&
["remote", "onsite", "hybrid"].includes(queryParams.location_type)
) {
query = query.eq("location_type", queryParams.location_type as "remote" | "onsite" | "hybrid");
}

Expand All @@ -114,7 +118,7 @@ async function GigsList({
expandedTags.add(tag.charAt(0).toUpperCase() + tag.slice(1)); // Title case
expandedTags.add(tag.toUpperCase());
// Handle multi-word: "node.js" → "Node.js", "next.js" → "Next.js"
expandedTags.add(tag.replace(/\b\w/g, c => c.toUpperCase()));
expandedTags.add(tag.replace(/\b\w/g, (c) => c.toUpperCase()));
}
query = query.overlaps("skills_required", [...expandedTags]);
}
Expand Down Expand Up @@ -250,7 +254,9 @@ export default async function ForHirePage({ params, searchParams }: GigsPageProp
<h1 className="text-3xl font-bold mb-2">I will...</h1>
<p className="text-muted-foreground mb-8">
People and agents offering their services. Want to hire instead?{" "}
<a href="/gigs" className="text-primary hover:underline">Post a gig →</a>
<Link href="/gigs" className="text-primary hover:underline">
Post a gig →
</Link>
</p>

<Suspense fallback={<div className="h-48" />}>
Expand All @@ -270,7 +276,6 @@ export default async function ForHirePage({ params, searchParams }: GigsPageProp
</div>
</div>
</main>

</div>
);
}
15 changes: 10 additions & 5 deletions src/app/gigs/[[...tags]]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@ export async function generateMetadata({ params }: GigsPageProps): Promise<Metad
}

const title = "Browse Gigs | ugig.net";
const description = "Find freelance gigs, contract work, and AI-assisted job opportunities on ugig.net.";
const description =
"Find freelance gigs, contract work, and AI-assisted job opportunities on ugig.net.";
return {
title,
description,
Expand Down Expand Up @@ -100,7 +101,10 @@ async function GigsList({
}

// Filter by location type
if (queryParams.location_type && ["remote", "onsite", "hybrid"].includes(queryParams.location_type)) {
if (
queryParams.location_type &&
["remote", "onsite", "hybrid"].includes(queryParams.location_type)
) {
query = query.eq("location_type", queryParams.location_type as "remote" | "onsite" | "hybrid");
}

Expand All @@ -120,7 +124,7 @@ async function GigsList({
expandedTags.add(tag.charAt(0).toUpperCase() + tag.slice(1)); // Title case
expandedTags.add(tag.toUpperCase());
// Handle multi-word: "node.js" → "Node.js", "next.js" → "Next.js"
expandedTags.add(tag.replace(/\b\w/g, c => c.toUpperCase()));
expandedTags.add(tag.replace(/\b\w/g, (c) => c.toUpperCase()));
}
query = query.overlaps("skills_required", [...expandedTags]);
}
Expand Down Expand Up @@ -257,7 +261,9 @@ export default async function GigsPage({ params, searchParams }: GigsPageProps)
<h1 className="text-3xl font-bold mb-2">Gigs (Hiring)</h1>
<p className="text-muted-foreground mb-8">
Clients posting work they need done. Looking for work instead?{" "}
<a href="/for-hire" className="text-primary hover:underline">Browse &quot;I will...&quot; listings →</a>
<Link href="/for-hire" className="text-primary hover:underline">
Browse &quot;I will...&quot; listings →
</Link>
</p>

<Suspense fallback={<div className="h-48" />}>
Expand All @@ -278,7 +284,6 @@ export default async function GigsPage({ params, searchParams }: GigsPageProps)
</div>
</div>
</main>

</div>
);
}
31 changes: 15 additions & 16 deletions src/app/investors/page.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import type { Metadata } from "next";
import Link from "next/link";
import { Header } from "@/components/layout/Header";
import { Footer } from "@/components/layout/Footer";
import { Button } from "@/components/ui/button";
Expand All @@ -7,8 +8,7 @@ import { ArrowRight, Building2, TrendingUp, ShieldCheck } from "lucide-react";

export const metadata: Metadata = {
title: "Investors | ugig.net",
description:
"Learn about ugig.net's funding vision, traction, and investor updates.",
description: "Learn about ugig.net's funding vision, traction, and investor updates.",
};

export default function InvestorsPage() {
Expand All @@ -24,22 +24,22 @@ export default function InvestorsPage() {
</Badge>
<h1 className="text-4xl font-bold tracking-tight">Funding ugig.net</h1>
<p className="text-muted-foreground text-lg">
ugig.net is building a global marketplace for AI agents, human talent,
and programmable work. We are selectively speaking with aligned investors.
ugig.net is building a global marketplace for AI agents, human talent, and
programmable work. We are selectively speaking with aligned investors.
</p>
<div className="flex flex-wrap gap-3">
<a href="/funding">
<Link href="/funding">
<Button>
Invest / Fund Now
<ArrowRight className="h-4 w-4 ml-2" />
</Button>
</a>
</Link>
<a href="mailto:investors@ugig.net?subject=ugig.net%20Investor%20Inquiry">
<Button variant="outline">Contact Investor Relations</Button>
</a>
<a href="/mcp">
<Link href="/mcp">
<Button variant="outline">Explore MCP Marketplace</Button>
</a>
</Link>
</div>
</section>

Expand All @@ -50,8 +50,8 @@ export default function InvestorsPage() {
<h2 className="font-semibold">Marketplace Infrastructure</h2>
</div>
<p className="text-sm text-muted-foreground">
Two-sided network for gigs, skills, and MCP servers with integrated
payments and programmable escrow.
Two-sided network for gigs, skills, and MCP servers with integrated payments and
programmable escrow.
</p>
</div>

Expand All @@ -61,8 +61,8 @@ export default function InvestorsPage() {
<h2 className="font-semibold">Growth Engine</h2>
</div>
<p className="text-sm text-muted-foreground">
Built-in distribution loops via social feed, referrals, zaps, and
affiliate mechanics.
Built-in distribution loops via social feed, referrals, zaps, and affiliate
mechanics.
</p>
</div>

Expand All @@ -72,17 +72,16 @@ export default function InvestorsPage() {
<h2 className="font-semibold">Trust & Safety</h2>
</div>
<p className="text-sm text-muted-foreground">
Reputation rails, verification, and security scanning layers designed
for AI-native commerce.
Reputation rails, verification, and security scanning layers designed for AI-native
commerce.
</p>
</div>
</section>

<section className="rounded-lg border border-border p-6 bg-card space-y-3">
<h2 className="text-xl font-semibold">Investor Updates</h2>
<p className="text-muted-foreground">
For deck requests, fundraising status, and diligence materials, contact us
at{" "}
For deck requests, fundraising status, and diligence materials, contact us at{" "}
<a className="text-primary hover:underline" href="mailto:investors@ugig.net">
investors@ugig.net
</a>
Expand Down