diff --git a/apps/portal/public/assets/images/About us.png b/apps/portal/public/assets/images/About us.png
new file mode 100644
index 00000000..7efb3367
Binary files /dev/null and b/apps/portal/public/assets/images/About us.png differ
diff --git a/apps/portal/src/app/(public)/(site)/about/page.tsx b/apps/portal/src/app/(public)/(site)/about/page.tsx
index f95bf359..81ec50cb 100644
--- a/apps/portal/src/app/(public)/(site)/about/page.tsx
+++ b/apps/portal/src/app/(public)/(site)/about/page.tsx
@@ -4,8 +4,27 @@
* Corporate profile and company information.
*/
+import type { Metadata } from "next";
import { AboutUsView } from "@/features/marketing/views/AboutUsView";
+export const metadata: Metadata = {
+ title: "About Us - Assist Solutions Corp. | Company Profile",
+ description:
+ "Learn about Assist Solutions Corp., established in 2002. A registered telecom carrier (A-19-9538) providing IT services to Japan's international community with bilingual support.",
+ keywords: [
+ "Assist Solutions",
+ "IT company Tokyo",
+ "expat services Japan",
+ "telecom carrier Japan",
+ ],
+ openGraph: {
+ title: "About Assist Solutions Corp.",
+ description:
+ "Established in 2002, serving Japan's international community with reliable IT solutions and English support.",
+ type: "website",
+ },
+};
+
export default function AboutPage() {
return ;
}
diff --git a/apps/portal/src/app/(public)/(site)/contact/page.tsx b/apps/portal/src/app/(public)/(site)/contact/page.tsx
index cea3eeee..d767b2c8 100644
--- a/apps/portal/src/app/(public)/(site)/contact/page.tsx
+++ b/apps/portal/src/app/(public)/(site)/contact/page.tsx
@@ -4,8 +4,21 @@
* Contact form for unauthenticated users.
*/
+import type { Metadata } from "next";
import { PublicContactView } from "@/features/support/views/PublicContactView";
+export const metadata: Metadata = {
+ title: "Contact Us - Assist Solutions | Get Support",
+ description:
+ "Contact Assist Solutions for internet, mobile, and IT support inquiries. Call toll-free 0120-660-470 or reach us online. English and Japanese support available.",
+ keywords: ["contact Assist Solutions", "IT support Tokyo", "customer service"],
+ openGraph: {
+ title: "Contact Assist Solutions",
+ description: "Get in touch with our bilingual support team. Toll-free: 0120-660-470",
+ type: "website",
+ },
+};
+
export default function ContactPage() {
return ;
}
diff --git a/apps/portal/src/app/(public)/(site)/page.tsx b/apps/portal/src/app/(public)/(site)/page.tsx
index bae0be3d..c0764b2e 100644
--- a/apps/portal/src/app/(public)/(site)/page.tsx
+++ b/apps/portal/src/app/(public)/(site)/page.tsx
@@ -1,5 +1,27 @@
+import type { Metadata } from "next";
import { PublicLandingView } from "@/features/landing-page";
+export const metadata: Metadata = {
+ title: "Assist Solutions - Internet, Mobile & IT Services for Expats in Japan",
+ description:
+ "One stop IT solution for Japan's international community. Reliable fiber internet, mobile SIM cards, VPN, TV services and bilingual tech support since 2002.",
+ keywords: [
+ "internet Japan",
+ "expat internet Tokyo",
+ "SIM card Japan",
+ "English support IT",
+ "fiber optic Japan",
+ "VPN Japan",
+ ],
+ openGraph: {
+ title: "Assist Solutions - IT Services for Expats in Japan",
+ description:
+ "Reliable internet, mobile, VPN and tech support with English service. Serving Japan's international community since 2002.",
+ type: "website",
+ locale: "en_US",
+ },
+};
+
export default function PublicHomePage() {
return ;
}
diff --git a/apps/portal/src/app/(public)/(site)/services/business/page.tsx b/apps/portal/src/app/(public)/(site)/services/business/page.tsx
index dbef92a9..61f40a9d 100644
--- a/apps/portal/src/app/(public)/(site)/services/business/page.tsx
+++ b/apps/portal/src/app/(public)/(site)/services/business/page.tsx
@@ -1,6 +1,26 @@
+import type { Metadata } from "next";
import { Button } from "@/components/atoms";
import { Server, Monitor, Wrench, Globe } from "lucide-react";
+export const metadata: Metadata = {
+ title: "Business Solutions - Enterprise IT Services | Assist Solutions",
+ description:
+ "Comprehensive business IT solutions: Dedicated Internet Access with SLA, office LAN setup, data center services at Equinix Tokyo, and ongoing tech support.",
+ keywords: [
+ "business internet Japan",
+ "dedicated internet access",
+ "office LAN setup Tokyo",
+ "data center Japan",
+ "enterprise IT Tokyo",
+ ],
+ openGraph: {
+ title: "Business Solutions - Assist Solutions",
+ description:
+ "Enterprise-grade IT services with dedicated bandwidth, data center hosting, and bilingual support.",
+ type: "website",
+ },
+};
+
export default function BusinessSolutionsPage() {
return (
@@ -75,6 +95,58 @@ export default function BusinessSolutionsPage() {
+ {/* FAQ Section */}
+
+
+ Frequently Asked Questions
+
+
+
+
+ What is Dedicated Internet Access (DIA) and how is it different from regular internet?
+
+
+ DIA provides a dedicated, unshared connection with guaranteed bandwidth and uptime
+ SLA. Unlike shared business internet, your speeds are consistent regardless of network
+ congestion, making it ideal for businesses with critical online operations.
+
+
+
+
+
+ Do you offer support contracts for ongoing IT maintenance?
+
+
+ Yes, we offer flexible support contracts ranging from ad-hoc support to comprehensive
+ managed IT services. Our team can handle network monitoring, security updates, and
+ regular maintenance to keep your systems running smoothly.
+
+
+
+
+
+ Can you set up a network for a new office or relocating business?
+
+
+ Absolutely. We specialize in complete office network setups including cable
+ installation, switch configuration, firewall setup, and Wi-Fi deployment. We can also
+ coordinate with NTT and building management for new line installations.
+
+
+
+
+
+ What data center facilities do you use?
+
+
+ We partner with Equinix (Tokyo Tennozu Isle) and GDC (Gotenyama) for colocation and
+ data center services. Both facilities offer enterprise-grade security, power
+ redundancy, and connectivity options.
+
+
+
+
+
{/* CTA */}
diff --git a/apps/portal/src/app/(public)/(site)/services/internet/page.tsx b/apps/portal/src/app/(public)/(site)/services/internet/page.tsx
index 2e23ef80..8255bcbd 100644
--- a/apps/portal/src/app/(public)/(site)/services/internet/page.tsx
+++ b/apps/portal/src/app/(public)/(site)/services/internet/page.tsx
@@ -4,9 +4,29 @@
* Displays internet plans for unauthenticated users.
*/
+import type { Metadata } from "next";
import { PublicInternetPlansView } from "@/features/services/views/PublicInternetPlans";
import { RedirectAuthenticatedToAccountServices } from "@/features/services/components/common/RedirectAuthenticatedToAccountServices";
+export const metadata: Metadata = {
+ title: "Internet Plans - Fiber Optic Internet in Japan | Assist Solutions",
+ description:
+ "Get reliable NTT fiber optic internet up to 10Gbps with English support. IPv6/IPoE connections, no long-term contracts, monthly billing. Serving expats in Tokyo.",
+ keywords: [
+ "fiber internet Japan",
+ "NTT fiber optic",
+ "internet for expats",
+ "10Gbps internet Tokyo",
+ "IPv6 Japan",
+ ],
+ openGraph: {
+ title: "Internet Plans - Assist Solutions",
+ description:
+ "High-speed NTT fiber optic internet with English support. Up to 10Gbps, no long-term contracts.",
+ type: "website",
+ },
+};
+
export default function PublicInternetPlansPage() {
return (
<>
diff --git a/apps/portal/src/app/(public)/(site)/services/onsite/page.tsx b/apps/portal/src/app/(public)/(site)/services/onsite/page.tsx
index ded38d14..f9a6f1d1 100644
--- a/apps/portal/src/app/(public)/(site)/services/onsite/page.tsx
+++ b/apps/portal/src/app/(public)/(site)/services/onsite/page.tsx
@@ -1,6 +1,25 @@
+import type { Metadata } from "next";
import { Button } from "@/components/atoms";
import { Users, Monitor, Tv, Headset } from "lucide-react";
+export const metadata: Metadata = {
+ title: "Onsite Support - Tech Support in Tokyo | Assist Solutions",
+ description:
+ "Professional onsite and remote tech support in Tokyo, Saitama, and Kanagawa. Wi-Fi setup, network troubleshooting, computer repair. English-speaking technicians.",
+ keywords: [
+ "tech support Tokyo",
+ "IT support expats",
+ "computer repair Japan",
+ "Wi-Fi setup Tokyo",
+ "English IT support",
+ ],
+ openGraph: {
+ title: "Onsite Tech Support - Assist Solutions",
+ description: "English-speaking technicians for home and office IT support in Tokyo area.",
+ type: "website",
+ },
+};
+
export default function OnsiteSupportPage() {
return (
diff --git a/apps/portal/src/app/(public)/(site)/services/page.tsx b/apps/portal/src/app/(public)/(site)/services/page.tsx
index f3d8cb70..3009101f 100644
--- a/apps/portal/src/app/(public)/(site)/services/page.tsx
+++ b/apps/portal/src/app/(public)/(site)/services/page.tsx
@@ -1,5 +1,24 @@
+import type { Metadata } from "next";
import { ServicesGrid } from "@/features/services/components/common/ServicesGrid";
+export const metadata: Metadata = {
+ title: "Services - Internet, Mobile, VPN & IT Support | Assist Solutions",
+ description:
+ "Explore our comprehensive IT services: fiber optic internet up to 10Gbps, mobile SIM cards, VPN access, TV services, and professional onsite support in Tokyo.",
+ keywords: [
+ "internet service Japan",
+ "SIM card Tokyo",
+ "VPN service",
+ "IT support expats",
+ "fiber internet",
+ ],
+ openGraph: {
+ title: "Our Services - Assist Solutions",
+ description: "Internet, mobile, VPN, TV and tech support services for expats in Japan.",
+ type: "website",
+ },
+};
+
interface ServicesPageProps {
basePath?: string;
}
diff --git a/apps/portal/src/app/(public)/(site)/services/sim/page.tsx b/apps/portal/src/app/(public)/(site)/services/sim/page.tsx
index 365bfbbb..726e2806 100644
--- a/apps/portal/src/app/(public)/(site)/services/sim/page.tsx
+++ b/apps/portal/src/app/(public)/(site)/services/sim/page.tsx
@@ -4,9 +4,29 @@
* Displays SIM plans for unauthenticated users.
*/
+import type { Metadata } from "next";
import { PublicSimPlansView } from "@/features/services/views/PublicSimPlans";
import { RedirectAuthenticatedToAccountServices } from "@/features/services/components/common/RedirectAuthenticatedToAccountServices";
+export const metadata: Metadata = {
+ title: "SIM Card Plans - Mobile Service in Japan | Assist Solutions",
+ description:
+ "Get affordable SIM cards using NTT Docomo's network. Voice + Data and Data-only plans, eSIM available. First month free, no credit check for foreigners.",
+ keywords: [
+ "SIM card Japan",
+ "mobile service expats",
+ "Docomo MVNO",
+ "eSIM Japan",
+ "prepaid SIM Tokyo",
+ ],
+ openGraph: {
+ title: "Mobile SIM Card Plans - Assist Solutions",
+ description:
+ "Affordable mobile plans on Docomo's network with English support. SIM and eSIM available.",
+ type: "website",
+ },
+};
+
export default function PublicSimPlansPage() {
return (
<>
diff --git a/apps/portal/src/app/(public)/(site)/services/tv/page.tsx b/apps/portal/src/app/(public)/(site)/services/tv/page.tsx
index 7cd0c8ad..a416d3ef 100644
--- a/apps/portal/src/app/(public)/(site)/services/tv/page.tsx
+++ b/apps/portal/src/app/(public)/(site)/services/tv/page.tsx
@@ -1,3 +1,4 @@
+import type { Metadata } from "next";
import { Button } from "@/components/atoms";
import {
Tv,
@@ -11,6 +12,25 @@ import {
Globe,
} from "lucide-react";
+export const metadata: Metadata = {
+ title: "TV Services - Satellite & Cable TV in Japan | Assist Solutions",
+ description:
+ "Access premium TV services including Sky PerfecTV, iTSCOM, and J:COM. We arrange your TV service at no extra fee. English support available.",
+ keywords: [
+ "cable TV Japan",
+ "satellite TV Tokyo",
+ "Sky PerfecTV",
+ "JCOM English",
+ "TV service expats",
+ ],
+ openGraph: {
+ title: "TV Services - Assist Solutions",
+ description:
+ "Premium cable and satellite TV options in Japan. Free consultation and arrangement service.",
+ type: "website",
+ },
+};
+
export default function TVServicesPage() {
return (
diff --git a/apps/portal/src/app/(public)/(site)/services/vpn/page.tsx b/apps/portal/src/app/(public)/(site)/services/vpn/page.tsx
index abb231d5..282f80df 100644
--- a/apps/portal/src/app/(public)/(site)/services/vpn/page.tsx
+++ b/apps/portal/src/app/(public)/(site)/services/vpn/page.tsx
@@ -4,9 +4,23 @@
* Displays VPN plans for unauthenticated users.
*/
+import type { Metadata } from "next";
import { PublicVpnPlansView } from "@/features/services/views/PublicVpnPlans";
import { RedirectAuthenticatedToAccountServices } from "@/features/services/components/common/RedirectAuthenticatedToAccountServices";
+export const metadata: Metadata = {
+ title: "VPN Service - Secure VPN Access from Japan | Assist Solutions",
+ description:
+ "Reliable VPN service with servers in San Francisco and London. Static routing from Tokyo, optional VPN Wi-Fi router rental. Perfect for streaming and privacy.",
+ keywords: ["VPN Japan", "VPN service Tokyo", "streaming VPN", "secure internet Japan"],
+ openGraph: {
+ title: "VPN Service - Assist Solutions",
+ description:
+ "Secure VPN access from Tokyo with servers in US and UK. Static routing and router rental available.",
+ type: "website",
+ },
+};
+
export default function PublicVpnPlansPage() {
return (
<>
diff --git a/apps/portal/src/app/layout.tsx b/apps/portal/src/app/layout.tsx
index 01601e36..4762b115 100644
--- a/apps/portal/src/app/layout.tsx
+++ b/apps/portal/src/app/layout.tsx
@@ -5,8 +5,65 @@ import { QueryProvider } from "@/core/providers";
import { SessionTimeoutWarning } from "@/features/auth/components/SessionTimeoutWarning";
export const metadata: Metadata = {
- title: "Assist Solutions Portal",
- description: "Manage your subscriptions, billing, and support with Assist Solutions",
+ title: {
+ default: "Assist Solutions - IT Services for Expats in Japan",
+ template: "%s | Assist Solutions",
+ },
+ description:
+ "One stop IT solution for Japan's international community. Internet, mobile, VPN, and tech support with English service since 2002.",
+ metadataBase: new URL(process.env.NEXT_PUBLIC_SITE_URL || "https://portal.asolutions.co.jp"),
+ alternates: {
+ canonical: "/",
+ },
+ openGraph: {
+ type: "website",
+ locale: "en_US",
+ siteName: "Assist Solutions",
+ },
+ twitter: {
+ card: "summary_large_image",
+ },
+ robots: {
+ index: true,
+ follow: true,
+ },
+};
+
+// Organization structured data for rich search results
+const organizationJsonLd = {
+ "@context": "https://schema.org",
+ "@type": "Organization",
+ name: "Assist Solutions Corp.",
+ alternateName: "Assist Solutions",
+ url: "https://asolutions.co.jp",
+ logo: "https://portal.asolutions.co.jp/assets/images/logo.png",
+ foundingDate: "2002-03-08",
+ description:
+ "IT and telecom services for Japan's international community with bilingual English/Japanese support.",
+ address: {
+ "@type": "PostalAddress",
+ streetAddress: "3F Azabu Maruka Bldg., 3-8-2 Higashi Azabu",
+ addressLocality: "Minato-ku",
+ addressRegion: "Tokyo",
+ postalCode: "106-0044",
+ addressCountry: "JP",
+ },
+ contactPoint: [
+ {
+ "@type": "ContactPoint",
+ telephone: "+81-3-3560-1006",
+ contactType: "customer service",
+ availableLanguage: ["English", "Japanese"],
+ },
+ {
+ "@type": "ContactPoint",
+ telephone: "0120-660-470",
+ contactType: "customer service",
+ areaServed: "JP",
+ availableLanguage: ["English", "Japanese"],
+ },
+ ],
+ sameAs: ["https://www.asolutions.co.jp"],
};
// Disable static generation for the entire app since it uses dynamic features extensively
@@ -24,6 +81,12 @@ export default async function RootLayout({
return (
+
+
+
{children}
diff --git a/apps/portal/src/app/robots.ts b/apps/portal/src/app/robots.ts
new file mode 100644
index 00000000..a6157906
--- /dev/null
+++ b/apps/portal/src/app/robots.ts
@@ -0,0 +1,22 @@
+import type { MetadataRoute } from "next";
+
+/**
+ * Robots.txt configuration
+ *
+ * Controls search engine crawler access.
+ * Allows all public pages, blocks account/authenticated areas.
+ */
+export default function robots(): MetadataRoute.Robots {
+ const baseUrl = process.env.NEXT_PUBLIC_SITE_URL || "https://portal.asolutions.co.jp";
+
+ return {
+ rules: [
+ {
+ userAgent: "*",
+ allow: "/",
+ disallow: ["/account/", "/api/", "/auth/", "/_next/", "/order/"],
+ },
+ ],
+ sitemap: `${baseUrl}/sitemap.xml`,
+ };
+}
diff --git a/apps/portal/src/app/sitemap.ts b/apps/portal/src/app/sitemap.ts
new file mode 100644
index 00000000..277de3e3
--- /dev/null
+++ b/apps/portal/src/app/sitemap.ts
@@ -0,0 +1,33 @@
+import type { MetadataRoute } from "next";
+
+/**
+ * Sitemap for SEO
+ *
+ * Generates a sitemap.xml for search engine crawlers.
+ * Only includes public pages that should be indexed.
+ */
+export default function sitemap(): MetadataRoute.Sitemap {
+ const baseUrl = process.env.NEXT_PUBLIC_SITE_URL || "https://portal.asolutions.co.jp";
+
+ // Public pages that should be indexed
+ const publicPages = [
+ { path: "", priority: 1.0, changeFrequency: "weekly" as const },
+ { path: "/about", priority: 0.8, changeFrequency: "monthly" as const },
+ { path: "/services", priority: 0.9, changeFrequency: "weekly" as const },
+ { path: "/services/internet", priority: 0.8, changeFrequency: "weekly" as const },
+ { path: "/services/sim", priority: 0.8, changeFrequency: "weekly" as const },
+ { path: "/services/vpn", priority: 0.7, changeFrequency: "monthly" as const },
+ { path: "/services/tv", priority: 0.7, changeFrequency: "monthly" as const },
+ { path: "/services/onsite", priority: 0.7, changeFrequency: "monthly" as const },
+ { path: "/services/business", priority: 0.7, changeFrequency: "monthly" as const },
+ { path: "/contact", priority: 0.8, changeFrequency: "monthly" as const },
+ { path: "/help", priority: 0.6, changeFrequency: "monthly" as const },
+ ];
+
+ return publicPages.map(page => ({
+ url: `${baseUrl}${page.path}`,
+ lastModified: new Date(),
+ changeFrequency: page.changeFrequency,
+ priority: page.priority,
+ }));
+}
diff --git a/apps/portal/src/components/templates/PublicShell/PublicShell.tsx b/apps/portal/src/components/templates/PublicShell/PublicShell.tsx
index ae917f49..42e3ea08 100644
--- a/apps/portal/src/components/templates/PublicShell/PublicShell.tsx
+++ b/apps/portal/src/components/templates/PublicShell/PublicShell.tsx
@@ -7,11 +7,21 @@
"use client";
import type { ReactNode } from "react";
-import { useEffect } from "react";
+import { useEffect, useState } from "react";
import Link from "next/link";
import { Logo } from "@/components/atoms/logo";
import { SiteFooter } from "@/components/organisms/SiteFooter";
import { useAuthStore } from "@/features/auth/stores/auth.store";
+import {
+ Wifi,
+ Smartphone,
+ Building2,
+ Lock,
+ Tv,
+ Wrench,
+ ChevronDown,
+ ArrowRight,
+} from "lucide-react";
export interface PublicShellProps {
children: ReactNode;
@@ -21,6 +31,7 @@ export function PublicShell({ children }: PublicShellProps) {
const isAuthenticated = useAuthStore(state => state.isAuthenticated);
const hasCheckedAuth = useAuthStore(state => state.hasCheckedAuth);
const checkAuth = useAuthStore(state => state.checkAuth);
+ const [servicesOpen, setServicesOpen] = useState(false);
useEffect(() => {
if (!hasCheckedAuth) {
@@ -47,12 +58,117 @@ export function PublicShell({ children }: PublicShellProps) {