@@ -1,48 +1,385 @@
// 3rd-party
import React from "react";
import type { ReactView } from "@ethicdevs/react-monolith";
-import styled from "styled-components";
+// import styled from "styled-components";
// app
import type { CommonProps } from "../types";
import { AppRoute } from "../routes.defs";
-import { ButtonAnchor, Layout, PageWrapper } from "../components";
+import { Button } from "../components/Button.styled";
+import { Card } from "../components/Card.styled";
+import { Grid } from "../components/Grid";
+import { Layout } from "../components/Layout";
+import { PageWrapper } from "../components/PageWrapper";
+import {} from "../components";
import { buildRouteLink } from "../utils/shared";
export interface HomeViewProps extends CommonProps {
foo?: boolean;
}
+// ReadMe tagline for consistency
+const tagline =
+ "GitFOSS is a small and simple, free and open-source Git Forge built w/ Node.JS, Fastify, Prisma and React!";
+
+type FeatureCard = {
+ title: string;
+ description: string;
+ icon?: string;
+ image?: string;
+};
+
+const features: FeatureCard[] = [
+ {
+ title: "Free hosted or self-hosted",
+ description:
+ "Free hosting for everyone, or self-hosted deployments, both free.",
+ icon: "π ",
+ },
+ {
+ title: "MIT Licensed Open Source",
+ description: "Fully Open Source Software licensed under the MIT License.",
+ icon: "βοΈ",
+ },
+ {
+ title: "Modern tech stack",
+ description:
+ "Written with React, TypeScript, Prisma, and MVC architecture.",
+ icon: "π§°",
+ },
+ {
+ title: "Git repo browser",
+ description: "Files, branches, and tags are browsable in the UI.",
+ icon: "ποΈ",
+ },
+ {
+ title: "PRs & merges",
+ description: "Comment, review, merge, and delete source branches.",
+ icon: "π",
+ image: "https://i.ibb.co/xp1bfGG/image.png",
+ },
+ {
+ title: "Fork repositories",
+ description: "Fork repository workflow support for collaboration.",
+ icon: "π΄",
+ image: "https://i.ibb.co/1Ghq4j73/image.png",
+ },
+ {
+ title: "Tests & Coverage UI",
+ description: "Browser-based tests and coverage details.",
+ icon: "β
",
+ image: "https://i.ibb.co/bgvkWwFh/image.png",
+ },
+ {
+ title: "Builds & CI",
+ description: "Pipelines, actions, and a GitFOSS runner for CI.",
+ icon: "ποΈ",
+ image: "https://i.ibb.co/bgvkWwFh/image.png",
+ },
+ {
+ title: "Deploy",
+ description: "Pipelines and continuous deployment capabilities.",
+ icon: "π",
+ image: "https://i.ibb.co/bgvkWwFh/image.png",
+ },
+ {
+ title: "API Reference",
+ description: "Auto-generated API reference from repos and docs.",
+ icon: "π",
+ image: "https://i.ibb.co/bgvkWwFh/image.png",
+ },
+ {
+ title: "AI assistant",
+ description:
+ "Small no-context model leveraging repo docs, API reference, and docs to assist.",
+ icon: "π€",
+ image: "https://i.ibb.co/bgvkWwFh/image.png",
+ },
+ {
+ title: "SSH Keys management",
+ description: "SSH keys management for secure access to repos.",
+ icon: "π",
+ image: "https://i.ibb.co/bgvkWwFh/image.png",
+ },
+ {
+ title: "User profiles",
+ description:
+ "Profiles with starred/followed repos, followers, and user readmes/links.",
+ icon: "π§βπ»",
+ image: "https://i.ibb.co/bgvkWwFh/image.png",
+ },
+];
+
+// Helper to generate a richer description for "rest" features
+function generateDescription(base: string, idx: number): string {
+ const extras = [
+ "This feature is integrated with a modern, scalable workflow.",
+ "Discover how this can accelerate your teamβs productivity.",
+ "Includes settings and CLI for automation.",
+ ];
+ const extra = extras[idx % extras.length];
+ return `${base} ${extra}`;
+}
+
const HomeView: ReactView<HomeViewProps> = (props) => {
const { commonProps } = props;
+ const primary = features.slice(0, 4); // top 4 features in cards
+ const rest = features.slice(4); // remaining features in sections
+
return (
<Layout {...commonProps}>
- <PageWrapper>
- <StyledButtonsRow>
- <ButtonAnchor href={buildRouteLink(AppRoute.REPOSITORY_EXPLORE, {})}>
- Explore
- </ButtonAnchor>
- <ButtonAnchor href={buildRouteLink(AppRoute.AUTH_REGISTER, {})}>
- Register
- </ButtonAnchor>
- <ButtonAnchor href={buildRouteLink(AppRoute.AUTH_LOGIN, {})}>
- Login
- </ButtonAnchor>
- </StyledButtonsRow>
+ <PageWrapper style={{ maxWidth: 960, margin: "0 auto" }}>
+ {/* Hero Section */}
+ <Grid.Row fluid style={{ minHeight: "72vh", alignItems: "center" }}>
+ <Grid.Col
+ fluid
+ nowrap
+ justifyContent={"center"}
+ style={{
+ marginTop: 80,
+ paddingRight: 20,
+ minWidth: 420,
+ }}
+ >
+ <h1 style={{ fontSize: "3rem", margin: 0, lineHeight: 1.05 }}>
+ GitFOSS
+ </h1>
+ <p style={{ fontSize: "1.15rem", color: "#555", maxWidth: 600 }}>
+ {tagline}
+ </p>
+ <Grid.Row fluid gap={16} style={{ marginTop: 20 }}>
+ <Button as="a" href={buildRouteLink(AppRoute.AUTH_REGISTER, {})}>
+ Register
+ </Button>
+ <Button as="a" href={buildRouteLink(AppRoute.AUTH_LOGIN, {})}>
+ Login
+ </Button>
+ <Button
+ as="a"
+ href={buildRouteLink(AppRoute.REPOSITORY_EXPLORE, {})}
+ >
+ Explore
+ </Button>
+ </Grid.Row>
+ </Grid.Col>
+ <img
+ src="https://i.ibb.co/6cCs4VgG/image.png"
+ alt="GitFOSS hero illustration"
+ style={{
+ width: "100%",
+ maxWidth: 500,
+ minWidth: 400,
+ height: "auto",
+ marginTop: 24,
+ objectFit: "contain",
+ borderRadius: 24,
+ }}
+ />
+ </Grid.Row>
+
+ {/* Primary features: 4 cards in a row, using Card component */}
+ <Grid.Row fluid gap={16} style={{ padding: "10vh 0 20vh 0" }}>
+ {primary.map((f, idx) => (
+ <Grid.Col key={idx} fluid nowrap>
+ <Card
+ themeScheme={commonProps.themeScheme}
+ style={{ minHeight: 238, minWidth: 210 }}
+ >
+ <div
+ style={{
+ display: "flex",
+ flexDirection: "column",
+ gap: 12,
+ }}
+ >
+ <div
+ className="icon"
+ aria-label={f.title}
+ style={{ fontSize: 48 }}
+ >
+ {f.icon ?? "β¨"}
+ </div>
+ <div
+ className="feature-title"
+ style={{ fontWeight: 700, fontSize: 20 }}
+ >
+ {f.title}
+ </div>
+ <div className="feature-desc" style={{ color: "#777777" }}>
+ {f.description}
+ </div>
+ </div>
+ </Card>
+ </Grid.Col>
+ ))}
+ </Grid.Row>
+
+ {/* Rest features: as sections with alternating image/text */}
+ {rest.map((f, idx) => {
+ const genDesc = generateDescription(f.description, idx);
+ const isEven = idx % 2 === 0;
+ const imageSrc = f.image ?? `/assets/feature-${idx + 4}.png`;
+
+ return (
+ <section
+ key={idx}
+ aria-label={`Feature: ${f.title}`}
+ style={{ padding: "40px 0", minHeight: "80vh" }}
+ >
+ <div
+ style={{
+ display: "flex",
+ alignItems: "center",
+ gap: 48,
+ flexWrap: "wrap",
+ }}
+ >
+ {isEven && (
+ <>
+ <div style={{ flex: 1, minWidth: 260 }}>
+ <img
+ src={imageSrc}
+ alt={`${f.title} illustration`}
+ style={{
+ width: "100%",
+ height: "auto",
+ borderRadius: 24,
+ }}
+ />
+ </div>
+ <div style={{ flex: 1, minWidth: 260 }}>
+ <h1 style={{ margin: 0, fontSize: 48 }}>{f.title}</h1>
+ <h3
+ className="feature-desc"
+ style={{
+ color: "#777777",
+ lineHeight: 1.4,
+ fontWeight: "normal",
+ }}
+ >
+ {genDesc}
+ </h3>
+ <div
+ className="cta"
+ style={{ display: "flex", gap: 16, marginTop: 16 }}
+ >
+ <Button
+ as="a"
+ href={buildRouteLink(AppRoute.AUTH_REGISTER, {})}
+ >
+ Register
+ </Button>
+ <Button
+ as="a"
+ href={buildRouteLink(AppRoute.AUTH_LOGIN, {})}
+ >
+ Login
+ </Button>
+ </div>
+ </div>
+ </>
+ )}
+ {!isEven && (
+ <>
+ <div style={{ flex: 1, minWidth: 260 }}>
+ <h1 style={{ margin: 0, fontSize: 48 }}>{f.title}</h1>
+ <h3
+ className="feature-desc"
+ style={{
+ color: "#777777",
+ lineHeight: 1.4,
+ fontWeight: "normal",
+ }}
+ >
+ {genDesc}
+ </h3>
+ <div
+ className="cta"
+ style={{ display: "flex", gap: 16, marginTop: 16 }}
+ >
+ <Button
+ as="a"
+ href={buildRouteLink(AppRoute.AUTH_REGISTER, {})}
+ >
+ Register
+ </Button>
+ <Button
+ as="a"
+ href={buildRouteLink(AppRoute.AUTH_LOGIN, {})}
+ >
+ Login
+ </Button>
+ </div>
+ </div>
+ <div style={{ flex: 1, minWidth: 260 }}>
+ <img
+ src={imageSrc}
+ alt={`${f.title} illustration`}
+ style={{
+ width: "100%",
+ height: "auto",
+ borderRadius: 24,
+ }}
+ />
+ </div>
+ </>
+ )}
+ </div>
+ </section>
+ );
+ })}
+
+ {/* Contribute section outside loop */}
+ <section
+ aria-label="Contribute to GitFOSS"
+ style={{
+ padding: "48px 0",
+ borderTop: "2px dashed #4e7b50",
+ borderBottom: "2px dashed #4e7b50",
+ width: "100%",
+ }}
+ >
+ <Grid.Col
+ fluid
+ nowrap
+ justifyContent={"center"}
+ alignItems={"center"}
+ >
+ <h1
+ style={{
+ margin: "0 0 8px",
+ maxWidth: 400,
+ fontSize: 48,
+ textAlign: "center",
+ }}
+ >
+ Contribute to GitFOSS
+ </h1>
+ <h3
+ style={{
+ color: "#555",
+ margin: "16px 0",
+ maxWidth: 400,
+ textAlign: "center",
+ fontWeight: "normal",
+ }}
+ >
+ Help grow GitFOSS by contributing code, docs, and governance. Your
+ involvement keeps the project open, fast, and secure.
+ </h3>
+ <Button
+ as="a"
+ href="/ethicdevs/gitfoss"
+ style={{ width: 300, height: 60, fontSize: 24, marginTop: 24 }}
+ >
+ Contribute Now
+ </Button>
+ </Grid.Col>
+ </section>
</PageWrapper>
</Layout>
);
};
-const StyledButtonsRow = styled.div`
- display: flex;
- flex-flow: row wrap;
- align-items: center;
- justify-content: center;
- gap: 16px;
- margin-top: 24px;
- width: 100%;
-`;
-
HomeView.displayName = "HomeView";
export default HomeView;