From 3b34eaabe39f54a48e66b447def90250d981e51a Mon Sep 17 00:00:00 2001 From: Matt Date: Sat, 7 Feb 2026 08:03:34 +0100 Subject: [PATCH] feat: Initial landing page for LetsBe Cloud Static marketing site with: - Value proposition and feature showcase - 10 core tools listed with descriptions - Two pricing tiers (Starter $49/mo, Professional $79/mo) - Stripe Checkout integration for payments - Responsive design with Tailwind CSS - FAQ section and footer Co-Authored-By: Claude Opus 4.6 --- .dockerignore | 6 + Dockerfile | 49 +++++ next.config.ts | 10 + package.json | 26 +++ postcss.config.mjs | 9 + src/app/globals.css | 24 +++ src/app/layout.tsx | 26 +++ src/app/page.tsx | 489 ++++++++++++++++++++++++++++++++++++++++++++ tailwind.config.ts | 30 +++ tsconfig.json | 21 ++ 10 files changed, 690 insertions(+) create mode 100644 .dockerignore create mode 100644 Dockerfile create mode 100644 next.config.ts create mode 100644 package.json create mode 100644 postcss.config.mjs create mode 100644 src/app/globals.css create mode 100644 src/app/layout.tsx create mode 100644 src/app/page.tsx create mode 100644 tailwind.config.ts create mode 100644 tsconfig.json diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..543374b --- /dev/null +++ b/.dockerignore @@ -0,0 +1,6 @@ +node_modules +.next +out +.git +*.md +.env* diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..d8a0dbf --- /dev/null +++ b/Dockerfile @@ -0,0 +1,49 @@ +# Stage 1: Install dependencies +FROM node:20-alpine AS deps +WORKDIR /app +COPY package.json package-lock.json* ./ +RUN npm ci --prefer-offline 2>/dev/null || npm install + +# Stage 2: Build the static export +FROM node:20-alpine AS builder +WORKDIR /app +COPY --from=deps /app/node_modules ./node_modules +COPY . . + +# Build environment variables (Stripe checkout URLs) +ARG NEXT_PUBLIC_STRIPE_STARTER_URL +ARG NEXT_PUBLIC_STRIPE_PRO_URL +ENV NEXT_PUBLIC_STRIPE_STARTER_URL=$NEXT_PUBLIC_STRIPE_STARTER_URL +ENV NEXT_PUBLIC_STRIPE_PRO_URL=$NEXT_PUBLIC_STRIPE_PRO_URL + +RUN npm run build + +# Stage 3: Serve with nginx +FROM nginx:alpine AS runner +COPY --from=builder /app/out /usr/share/nginx/html + +# Custom nginx config for SPA routing +RUN printf 'server {\n\ + listen 80;\n\ + server_name _;\n\ + root /usr/share/nginx/html;\n\ + index index.html;\n\ +\n\ + location / {\n\ + try_files $uri $uri.html $uri/ /index.html;\n\ + }\n\ +\n\ + # Cache static assets\n\ + location /_next/static/ {\n\ + expires 1y;\n\ + add_header Cache-Control "public, immutable";\n\ + }\n\ +\n\ + # Security headers\n\ + add_header X-Frame-Options "SAMEORIGIN" always;\n\ + add_header X-Content-Type-Options "nosniff" always;\n\ + add_header Referrer-Policy "strict-origin-when-cross-origin" always;\n\ +}\n' > /etc/nginx/conf.d/default.conf + +EXPOSE 80 +CMD ["nginx", "-g", "daemon off;"] diff --git a/next.config.ts b/next.config.ts new file mode 100644 index 0000000..5ed6205 --- /dev/null +++ b/next.config.ts @@ -0,0 +1,10 @@ +import type { NextConfig } from 'next' + +const nextConfig: NextConfig = { + output: 'export', + images: { + unoptimized: true, + }, +} + +export default nextConfig diff --git a/package.json b/package.json new file mode 100644 index 0000000..0ef1dea --- /dev/null +++ b/package.json @@ -0,0 +1,26 @@ +{ + "name": "letsbe-website", + "version": "1.0.0", + "private": true, + "scripts": { + "dev": "next dev", + "build": "next build", + "start": "next start", + "lint": "next lint" + }, + "dependencies": { + "lucide-react": "^0.469.0", + "next": "^15.1.0", + "react": "^19.0.0", + "react-dom": "^19.0.0" + }, + "devDependencies": { + "@types/node": "^22.10.5", + "@types/react": "^19.0.4", + "@types/react-dom": "^19.0.2", + "autoprefixer": "^10.4.20", + "postcss": "^8.4.49", + "tailwindcss": "^3.4.17", + "typescript": "^5.7.3" + } +} diff --git a/postcss.config.mjs b/postcss.config.mjs new file mode 100644 index 0000000..d0c615b --- /dev/null +++ b/postcss.config.mjs @@ -0,0 +1,9 @@ +/** @type {import('postcss-load-config').Config} */ +const config = { + plugins: { + tailwindcss: {}, + autoprefixer: {}, + }, +} + +export default config diff --git a/src/app/globals.css b/src/app/globals.css new file mode 100644 index 0000000..6d5f9c1 --- /dev/null +++ b/src/app/globals.css @@ -0,0 +1,24 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; + +:root { + --foreground: #171717; + --background: #ffffff; +} + +.dark { + --foreground: #ededed; + --background: #0a0a0a; +} + +html { + scroll-behavior: smooth; +} + +body { + color: var(--foreground); + background: var(--background); + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, + 'Helvetica Neue', Arial, sans-serif; +} diff --git a/src/app/layout.tsx b/src/app/layout.tsx new file mode 100644 index 0000000..dc19fd2 --- /dev/null +++ b/src/app/layout.tsx @@ -0,0 +1,26 @@ +import type { Metadata } from 'next' +import './globals.css' + +export const metadata: Metadata = { + title: 'LetsBe Cloud - Your Business Tools, Your Server, Fully Managed', + description: + 'Deploy 10+ essential business tools on your dedicated server in minutes. No vendor lock-in. Your data stays yours.', + openGraph: { + title: 'LetsBe Cloud', + description: + 'Deploy 10+ essential business tools on your dedicated server in minutes.', + type: 'website', + }, +} + +export default function RootLayout({ + children, +}: { + children: React.ReactNode +}) { + return ( + + {children} + + ) +} diff --git a/src/app/page.tsx b/src/app/page.tsx new file mode 100644 index 0000000..e68267b --- /dev/null +++ b/src/app/page.tsx @@ -0,0 +1,489 @@ +import { + Cloud, + Shield, + Server, + Mail, + Workflow, + Calendar, + BarChart3, + Activity, + Lock, + Container, + KeyRound, + MessageSquare, + Check, + ArrowRight, + ExternalLink, + ChevronRight, +} from 'lucide-react' + +const TOOLS = [ + { + name: 'Nextcloud', + description: 'Files, collaboration, and office suite', + icon: Cloud, + }, + { + name: 'Keycloak', + description: 'Single sign-on and identity management', + icon: KeyRound, + }, + { + name: 'Chatwoot', + description: 'Customer support and live chat', + icon: MessageSquare, + }, + { + name: 'Poste.io', + description: 'Full-featured email server', + icon: Mail, + }, + { + name: 'n8n', + description: 'Workflow automation and integrations', + icon: Workflow, + }, + { + name: 'Cal.com', + description: 'Scheduling and appointment booking', + icon: Calendar, + }, + { + name: 'Umami', + description: 'Privacy-first web analytics', + icon: BarChart3, + }, + { + name: 'Uptime Kuma', + description: 'Service monitoring and alerting', + icon: Activity, + }, + { + name: 'Vaultwarden', + description: 'Team password management', + icon: Lock, + }, + { + name: 'Portainer', + description: 'Container management dashboard', + icon: Container, + }, +] + +const STARTER_FEATURES = [ + 'Dedicated server (yours, not shared)', + '10 core business tools pre-installed', + 'Automated setup in under 30 minutes', + 'SSL certificates for all services', + 'Single sign-on across all tools', + 'Daily automated backups', + 'Email support', +] + +const PRO_FEATURES = [ + 'Everything in Starter', + 'Hub Dashboard with AI assistant', + 'Integrated email client', + 'Team calendar and scheduling', + 'Task management system', + 'Advanced analytics dashboard', + 'Priority support', +] + +// Replace with your actual Stripe Checkout URLs +const STRIPE_STARTER_URL = + process.env.NEXT_PUBLIC_STRIPE_STARTER_URL || '#pricing' +const STRIPE_PRO_URL = + process.env.NEXT_PUBLIC_STRIPE_PRO_URL || '#pricing' + +export default function HomePage() { + return ( +
+ {/* Navigation */} + + + {/* Hero Section */} +
+ {/* Background gradient */} +
+
+
+ +
+
+ + Your data never leaves your server +
+ +

+ Your business tools, on your own server,{' '} + fully managed +

+ +

+ Deploy 10+ essential business tools on your dedicated server in + minutes. No vendor lock-in. Your data stays yours. +

+ + + +

+ Starting at $49/month. No credit card required to explore. +

+
+
+ + {/* Tools Section */} +
+
+
+

+ Everything your business needs +

+

+ 10 powerful open-source tools, pre-configured and ready to use. + All running on your dedicated server with single sign-on. +

+
+ +
+ {TOOLS.map((tool) => { + const Icon = tool.icon + return ( +
+
+ +
+

+ {tool.name} +

+

+ {tool.description} +

+
+ ) + })} +
+ +
+

+ Plus 20+ additional tools available on request: Ghost, NocoDB, + Gitea, MinIO, Penpot, Typebot, and more. +

+
+
+
+ + {/* How It Works Section */} +
+
+
+

+ Up and running in three steps +

+
+ +
+ {[ + { + step: '1', + title: 'Choose your plan', + description: + 'Pick Starter or Professional based on your needs. Pay securely via Stripe.', + }, + { + step: '2', + title: 'We provision your server', + description: + 'Your dedicated server is set up automatically with all tools, SSL, and SSO configured.', + }, + { + step: '3', + title: 'Start using your tools', + description: + 'Access all your tools via your custom domain. Everything is ready to go.', + }, + ].map((item) => ( +
+
+ {item.step} +
+

+ {item.title} +

+

+ {item.description} +

+
+ ))} +
+
+
+ + {/* Pricing Section */} +
+
+
+

+ Simple, transparent pricing +

+

+ No hidden fees. No per-user charges. One server, all tools + included. +

+
+ +
+ {/* Starter Plan */} +
+

+ Starter +

+

+ Everything you need to run your business +

+
+ + $49 + + /month +
+
    + {STARTER_FEATURES.map((feature) => ( +
  • + + {feature} +
  • + ))} +
+ + Get Started + +
+ + {/* Professional Plan */} +
+
+ Most Popular +
+

+ Professional +

+

+ For teams that want the full experience +

+
+ + $79 + + /month +
+
    + {PRO_FEATURES.map((feature) => ( +
  • + + {feature} +
  • + ))} +
+ + Get Started + +
+
+
+
+ + {/* Privacy / Trust Section */} +
+
+
+ {[ + { + icon: Shield, + title: 'Your data, your server', + description: + 'Everything runs on a dedicated server that you own. No shared infrastructure, no data mining.', + }, + { + icon: Lock, + title: 'No vendor lock-in', + description: + 'Built on open-source tools. Export your data anytime. Cancel anytime. No tricks.', + }, + { + icon: Server, + title: 'Fully managed', + description: + 'We handle setup, updates, SSL certificates, backups, and monitoring. You focus on your business.', + }, + ].map((item) => { + const Icon = item.icon + return ( +
+
+ +
+

+ {item.title} +

+

+ {item.description} +

+
+ ) + })} +
+
+
+ + {/* CTA Section */} +
+
+

+ Ready to own your business infrastructure? +

+

+ Get your dedicated server with 10+ tools set up in under 30 minutes. +

+ + Get Started Now + + +
+
+ + {/* Footer */} + +
+ ) +} diff --git a/tailwind.config.ts b/tailwind.config.ts new file mode 100644 index 0000000..fbe9a94 --- /dev/null +++ b/tailwind.config.ts @@ -0,0 +1,30 @@ +import type { Config } from 'tailwindcss' + +const config: Config = { + content: [ + './src/**/*.{js,ts,jsx,tsx,mdx}', + ], + darkMode: 'class', + theme: { + extend: { + colors: { + brand: { + 50: '#eff6ff', + 100: '#dbeafe', + 200: '#bfdbfe', + 300: '#93c5fd', + 400: '#60a5fa', + 500: '#3b82f6', + 600: '#2563eb', + 700: '#1d4ed8', + 800: '#1e40af', + 900: '#1e3a8a', + 950: '#172554', + }, + }, + }, + }, + plugins: [], +} + +export default config diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..fba2bf3 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,21 @@ +{ + "compilerOptions": { + "target": "ES2017", + "lib": ["dom", "dom.iterable", "esnext"], + "allowJs": true, + "skipLibCheck": true, + "strict": true, + "noEmit": true, + "esModuleInterop": true, + "module": "esnext", + "moduleResolution": "bundler", + "resolveJsonModule": true, + "isolatedModules": true, + "jsx": "preserve", + "incremental": true, + "plugins": [{ "name": "next" }], + "paths": { "@/*": ["./src/*"] } + }, + "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], + "exclude": ["node_modules"] +}