# Public Pages Restructuring Implementation Plan
> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
**Goal:** Restructure public pages — update homepage hero, extract reusable ContactForm, clean up Contact page (form + sidebar), create Support page (knowledge base categories, remote tools, FAQ, contact form fallback).
**Architecture:** Extract shared ContactForm from PublicContactView into `features/support/components/`. Rewrite PublicContactView as focused two-column contact page. Rewrite PublicSupportView as self-service hub. Update HeroSection text. Add `/support` route.
**Tech Stack:** Next.js 15, React 19, Tailwind CSS, shadcn/ui atoms, Zod validation, lucide-react icons
---
### Task 1: Update Homepage Hero Text
**Files:**
- Modify: `apps/portal/src/features/landing-page/components/HeroSection.tsx:42-49`
**Step 1: Update the hero heading and subtitle**
Change lines 42-49 in `HeroSection.tsx`:
```tsx
// OLD:
English IT Supportfor Expats in Japan
No Japanese required. Get reliable internet, mobile, and VPN services with full English
support. Serving expats and international businesses for over 20 years.
// NEW:
A One Stop Solutionfor Your IT Needs
From internet and mobile to VPN and on-site tech support — we handle it all in English so you don't have to.
```
**Step 2: Verify no lint errors**
Run: `pnpm lint --filter @customer-portal/portal`
**Step 3: Commit**
```
feat: update homepage hero text to "A One Stop Solution for Your IT Needs"
```
---
### Task 2: Extract Reusable ContactForm Component
**Files:**
- Create: `apps/portal/src/features/support/components/ContactForm.tsx`
- Create: `apps/portal/src/features/support/components/index.ts`
**Step 1: Create the ContactForm component**
Create `apps/portal/src/features/support/components/ContactForm.tsx`:
```tsx
"use client";
import { useState, useCallback } from "react";
import Link from "next/link";
import { Button, Input } from "@/components/atoms";
import { FormField } from "@/components/molecules/FormField/FormField";
import { AlertBanner } from "@/components/molecules/AlertBanner/AlertBanner";
import { useZodForm } from "@/shared/hooks";
import { CheckCircle } from "lucide-react";
import {
publicContactRequestSchema,
type PublicContactRequest,
} from "@customer-portal/domain/support";
import { apiClient, ApiError, isApiError } from "@/core/api";
import { cn } from "@/shared/utils";
interface ContactFormProps {
className?: string;
}
export function ContactForm({ className }: ContactFormProps) {
const [isSubmitted, setIsSubmitted] = useState(false);
const [submitError, setSubmitError] = useState(null);
const handleSubmit = useCallback(async (data: PublicContactRequest) => {
setSubmitError(null);
try {
await apiClient.POST("/api/support/contact", { body: data });
setIsSubmitted(true);
} catch (error) {
if (isApiError(error)) {
setSubmitError(error.message || "Failed to send message");
return;
}
if (error instanceof ApiError) {
setSubmitError(error.message || "Failed to send message");
return;
}
setSubmitError(error instanceof Error ? error.message : "Failed to send message");
}
}, []);
const form = useZodForm({
schema: publicContactRequestSchema,
initialValues: {
name: "",
email: "",
phone: "",
subject: "",
message: "",
},
onSubmit: handleSubmit,
});
if (isSubmitted) {
return (
Message Sent!
Thank you for contacting us. We'll get back to you within 24 hours.
);
}
return (
{submitError && (
{submitError}
)}
By submitting, you agree to our{" "}
Privacy Policy
. We typically respond within 24 hours.
);
}
```
**Step 2: Create barrel export**
Create `apps/portal/src/features/support/components/index.ts`:
```ts
export { ContactForm } from "./ContactForm";
```
**Step 3: Verify no lint errors**
Run: `pnpm lint --filter @customer-portal/portal`
**Step 4: Commit**
```
feat: extract reusable ContactForm component from PublicContactView
```
---
### Task 3: Rewrite Contact Page (Two-Column Layout)
**Files:**
- Modify: `apps/portal/src/features/support/views/PublicContactView.tsx` (full rewrite)
**Step 1: Rewrite PublicContactView**
Replace the entire content of `apps/portal/src/features/support/views/PublicContactView.tsx` with:
```tsx
"use client";
import { Mail, MapPin, Phone, MessageSquare, Clock, Send, ExternalLink } from "lucide-react";
import { ContactForm } from "@/features/support/components";
/**
* PublicContactView - Focused contact page with form + sidebar info
*/
export function PublicContactView() {
return (
{/* Header */}
Get in Touch
Our English-speaking team is here to help. Fill out the form below or reach us through any
of the channels listed.
);
}
export default PublicContactView;
```
**Step 2: Verify no lint errors**
Run: `pnpm lint --filter @customer-portal/portal`
**Step 3: Commit**
```
feat: rewrite contact page with two-column layout using shared ContactForm
```
---
### Task 4: Rewrite Support Page as Self-Service Hub
**Files:**
- Modify: `apps/portal/src/features/support/views/PublicSupportView.tsx` (full rewrite)
**Step 1: Rewrite PublicSupportView**
Replace the entire content of `apps/portal/src/features/support/views/PublicSupportView.tsx` with:
```tsx
"use client";
import { useState } from "react";
import Image from "next/image";
import Link from "next/link";
import {
HelpCircle,
Wifi,
Smartphone,
Lock,
Building2,
CreditCard,
Wrench,
Download,
ChevronDown,
Send,
} from "lucide-react";
import { ContactForm } from "@/features/support/components";
import { supportDownloads } from "@/features/landing-page/data";
import { cn } from "@/shared/utils";
// =============================================================================
// DATA
// =============================================================================
const KNOWLEDGE_BASE_CATEGORIES = [
{
title: "Internet & Wi-Fi",
description: "Router setup, connection issues, speed troubleshooting",
icon: Wifi,
color: "text-blue-500",
bgColor: "bg-blue-500/10",
hoverBorder: "hover:border-blue-500/40",
},
{
title: "Phone & SIM",
description: "SIM activation, plan changes, number porting",
icon: Smartphone,
color: "text-green-500",
bgColor: "bg-green-500/10",
hoverBorder: "hover:border-green-500/40",
},
{
title: "VPN & Streaming",
description: "VPN router setup, streaming access, configuration",
icon: Lock,
color: "text-purple-500",
bgColor: "bg-purple-500/10",
hoverBorder: "hover:border-purple-500/40",
},
{
title: "Business Solutions",
description: "Office networks, dedicated lines, enterprise support",
icon: Building2,
color: "text-orange-500",
bgColor: "bg-orange-500/10",
hoverBorder: "hover:border-orange-500/40",
},
{
title: "Billing & Account",
description: "Invoices, payments, account changes, contracts",
icon: CreditCard,
color: "text-pink-500",
bgColor: "bg-pink-500/10",
hoverBorder: "hover:border-pink-500/40",
},
{
title: "General Tech Support",
description: "Device help, software issues, general troubleshooting",
icon: Wrench,
color: "text-amber-500",
bgColor: "bg-amber-500/10",
hoverBorder: "hover:border-amber-500/40",
},
];
const FAQ_ITEMS = [
{
question: "How do I set up my internet router?",
answer:
"After your installation appointment, connect the provided router to the NTT ONU device using the included LAN cable. Power on the router and connect to the Wi-Fi network using the credentials on the router label. If you need help, contact our support team or use our remote support tools.",
},
{
question: "How do I activate my SIM card?",
answer:
"Insert the SIM card into your unlocked phone. You should receive a confirmation email with APN settings. Go to Settings > Mobile Data > APN and enter the provided settings. Restart your phone and you should be connected within a few minutes.",
},
{
question: "What payment methods do you accept?",
answer:
"We accept major credit cards (Visa, Mastercard, American Express), bank transfers, and convenience store payments. Foreign credit cards are accepted for all our services.",
},
{
question: "How do I contact support outside business hours?",
answer:
"You can send us an email or submit a contact form at any time — we'll respond within 24 hours on the next business day. For urgent issues, our live chat may have extended availability.",
},
{
question: "Can I change my plan after signing up?",
answer:
"Yes, you can change your plan at any time. Contact our support team and we'll help you switch to a plan that better fits your needs. Changes typically take effect from the next billing cycle.",
},
];
// =============================================================================
// COMPONENT
// =============================================================================
/**
* PublicSupportView - Self-service support hub
*/
export function PublicSupportView() {
const [expandedFaq, setExpandedFaq] = useState(null);
return (
{/* Header */}
How Can We Help?
Find answers, download remote support tools, or send us a message. Our English-speaking
team is ready to assist.
Send us a message and we'll get back to you within 24 hours.
{/* Existing Customer CTA */}
Already have an account?{" "}
Sign in
{" "}
to access your dashboard and support tickets.
);
}
export default PublicSupportView;
```
**Step 2: Verify no lint errors**
Run: `pnpm lint --filter @customer-portal/portal`
**Step 3: Commit**
```
feat: rewrite support page as self-service hub with knowledge base, remote tools, FAQ
```
---
### Task 5: Add Support Page Route
**Files:**
- Create: `apps/portal/src/app/(public)/(site)/support/page.tsx`
**Step 1: Create the support route page**
Create `apps/portal/src/app/(public)/(site)/support/page.tsx`:
```tsx
/**
* Public Support Page
*
* Self-service support hub with knowledge base categories,
* remote support tools, FAQ, and contact form fallback.
*/
import type { Metadata } from "next";
import { PublicSupportView } from "@/features/support/views/PublicSupportView";
export const metadata: Metadata = {
title: "Support - Self-Service Help Center | Assist Solutions",
description:
"Find answers to common questions, download remote support tools, or contact our English-speaking team. No Japanese required.",
keywords: [
"IT support Japan",
"English tech support Tokyo",
"remote support Japan",
"expat tech help",
"Assist Solutions support",
],
openGraph: {
title: "Support - Help Center | Assist Solutions",
description:
"Self-service support hub for expats in Japan. FAQ, remote support tools, and direct contact options.",
type: "website",
},
};
export default function SupportPage() {
return ;
}
```
**Step 2: Verify no lint errors**
Run: `pnpm lint --filter @customer-portal/portal`
**Step 3: Verify type checking passes**
Run: `pnpm type-check`
**Step 4: Commit**
```
feat: add /support route for public support page
```
---
### Task 6: Update Support Views Barrel Export
**Files:**
- Modify: `apps/portal/src/features/support/views/index.ts`
**Step 1: Add PublicSupportView and PublicContactView to the barrel export**
The current `views/index.ts` only exports authenticated views. Add the public views:
```ts
// Current content:
export * from "./NewSupportCaseView";
export * from "./SupportCasesView";
export * from "./SupportCaseDetailView";
export * from "./SupportHomeView";
// Add these:
export * from "./PublicContactView";
export * from "./PublicSupportView";
```
Note: The contact page currently imports directly from the view file (`@/features/support/views/PublicContactView`), not from the barrel. After adding to barrel, update the contact page import in `apps/portal/src/app/(public)/(site)/contact/page.tsx` to use the barrel:
```tsx
// OLD:
import { PublicContactView } from "@/features/support/views/PublicContactView";
// NEW:
import { PublicContactView } from "@/features/support/views";
```
And update the new support page import in `apps/portal/src/app/(public)/(site)/support/page.tsx`:
```tsx
// OLD:
import { PublicSupportView } from "@/features/support/views/PublicSupportView";
// NEW:
import { PublicSupportView } from "@/features/support/views";
```
**Step 2: Verify no lint errors**
Run: `pnpm lint --filter @customer-portal/portal`
**Step 3: Verify type checking passes**
Run: `pnpm type-check`
**Step 4: Commit**
```
refactor: add public views to support barrel exports
```
---
### Task 7: Final Verification
**Step 1: Run full lint check**
Run: `pnpm lint`
**Step 2: Run type check**
Run: `pnpm type-check`
**Step 3: Verify all pages render** (manual or dev server if permitted)
Check these routes work:
- `/` — homepage with new hero text
- `/contact` — two-column contact page
- `/support` — self-service support hub
- `/help` — still redirects to `/contact`