{ "name": "tanstack_start_ts", "private": true, "sideEffects": false, "type": "module", "scripts": { "dev": "vite dev", "build": "vite build", "build:dev": "vite build --mode development", "preview": "vite preview", "lint": "eslint .", "format": "prettier --write ." }, "dependencies": { "@hookform/resolvers": "^5.2.2", "@radix-ui/react-accordion": "^1.2.12", "@radix-ui/react-alert-dialog": "^1.1.15", "@radix-ui/react-aspect-ratio": "^1.1.8", "@radix-ui/react-avatar": "^1.1.11", "@radix-ui/react-checkbox": "^1.3.3", "@radix-ui/react-collapsible": "^1.1.12", "@radix-ui/react-context-menu": "^2.2.16", "@radix-ui/react-dialog": "^1.1.15", "@radix-ui/react-dropdown-menu": "^2.1.16", "@radix-ui/react-hover-card": "^1.1.15", "@radix-ui/react-label": "^2.1.8", "@radix-ui/react-menubar": "^1.1.16", "@radix-ui/react-navigation-menu": "^1.2.14", "@radix-ui/react-popover": "^1.1.15", "@radix-ui/react-progress": "^1.1.8", "@radix-ui/react-radio-group": "^1.3.8", "@radix-ui/react-scroll-area": "^1.2.10", "@radix-ui/react-select": "^2.2.6", "@radix-ui/react-separator": "^1.1.8", "@radix-ui/react-slider": "^1.3.6", "@radix-ui/react-slot": "^1.2.4", "@radix-ui/react-switch": "^1.2.6", "@radix-ui/react-tabs": "^1.1.13", "@radix-ui/react-toggle": "^1.1.10", "@radix-ui/react-toggle-group": "^1.1.11", "@radix-ui/react-tooltip": "^1.2.8", "@tailwindcss/vite": "^4.2.1", "@tanstack/react-query": "^5.83.0", "@tanstack/react-router": "^1.168.25", "@tanstack/react-start": "^1.167.50", "@tanstack/router-plugin": "^1.167.28", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", "cmdk": "^1.1.1", "date-fns": "^4.1.0", "embla-carousel-react": "^8.6.0", "input-otp": "^1.4.2", "lucide-react": "^0.575.0", "react": "^19.2.0", "react-day-picker": "^9.14.0", "react-dom": "^19.2.0", "react-hook-form": "^7.71.2", "react-resizable-panels": "^4.6.5", "recharts": "^2.15.4", "sonner": "^2.0.7", "tailwind-merge": "^3.5.0", "tailwindcss": "^4.2.1", "tw-animate-css": "^1.3.4", "vaul": "^1.1.2", "vite-tsconfig-paths": "^6.0.2", "zod": "^3.24.2" }, "devDependencies": { "@eslint/js": "^9.32.0", "@lovable.dev/vite-tanstack-config": "2.7.6", "@types/node": "^22.16.5", "@types/react": "^19.2.0", "@types/react-dom": "^19.2.0", "@vitejs/plugin-react": "^5.2.0", "eslint": "^9.32.0", "eslint-config-prettier": "^10.1.1", "eslint-plugin-prettier": "^5.2.6", "eslint-plugin-react-hooks": "^5.2.0", "eslint-plugin-react-refresh": "^0.4.20", "globals": "^15.15.0", "nitro": "3.0.260603-beta", "prettier": "^3.7.3", "typescript": "^5.8.3", "typescript-eslint": "^8.56.1", "vite": "^8.0.16" } } vite.config.ts // @lovable.dev/vite-tanstack-config already includes the following — do NOT add them manually // or the app will break with duplicate plugins: // - tanstackStart, viteReact, tailwindcss, tsConfigPaths, nitro (build-only using cloudflare as a default target), // componentTagger (dev-only), VITE_* env injection, @ path alias, React/TanStack dedupe, // error logger plugins, and sandbox detection (port/host/strictPort). // You can pass additional config via defineConfig({ vite: { ... }, etc... }) if needed. import { defineConfig } from "@lovable.dev/vite-tanstack-config"; export default defineConfig({ tanstackStart: { // Redirect TanStack Start's bundled server entry to src/server.ts (our SSR error wrapper). // nitro/vite builds from this server: { entry: "server" }, }, }); tsconfig.json { "include": ["src/**/*.ts", "src/**/*.tsx", "vite.config.ts", "eslint.config.js"], "compilerOptions": { "target": "ES2022", "jsx": "react-jsx", "module": "ESNext", "lib": ["ES2022", "DOM", "DOM.Iterable"], "types": ["vite/client"], /* Bundler mode */ "moduleResolution": "Bundler", "allowImportingTsExtensions": true, "verbatimModuleSyntax": false, "noEmit": true, /* Linting */ "skipLibCheck": true, "strict": true, "noUnusedLocals": false, "noUnusedParameters": false, "noFallthroughCasesInSwitch": true, "noUncheckedSideEffectImports": true, "paths": { "@/*": ["./src/*"] } } } eslint.config.js import js from "@eslint/js"; import eslintPluginPrettier from "eslint-plugin-prettier/recommended"; import globals from "globals"; import reactHooks from "eslint-plugin-react-hooks"; import reactRefresh from "eslint-plugin-react-refresh"; import tseslint from "typescript-eslint"; export default tseslint.config( { ignores: ["dist", ".output", ".vinxi"] }, { extends: [js.configs.recommended, ...tseslint.configs.recommended], files: ["**/*.{ts,tsx}"], languageOptions: { ecmaVersion: 2020, globals: globals.browser, }, plugins: { "react-hooks": reactHooks, "react-refresh": reactRefresh, }, rules": { ...reactHooks.configs.recommended.rules, "no-restricted-imports": [ "error", { paths: [ { name: "server-only", message: "TanStack Start does not use the Next.js `server-only` package. Rename the module to `*.server.ts` or mark it with `@tanstack/react-start/server-only`.", }, ], }, ], "react-refresh/only-export-components": ["warn", { allowConstantExport: true }], "@typescript-eslint/no-unused-vars": "off", }, }, eslintPluginPrettier, ); components.json { "$schema": "https://ui.shadcn.com/schema.json", "style": "new-york", "rsc": false, "tsx": true, "tailwind": { "css": "src/styles.css", "baseColor": "slate", "cssVariables": true, "prefix": "" }, "iconLibrary": "lucide", "rtl": false, "aliases": { "components": "@/components", "utils": "@/lib/utils", "ui": "@/components/ui", "lib": "@/lib", "hooks": "@/hooks" }, "registries": {} } .prettierrc { "printWidth": 100, "semi": true, "singleQuote": false, "trailingComma": "all" } .prettierignore node_modules dist .output .vinxi pnpm-lock.yaml package-lock.json bun.lock routeTree.gen.ts bunfig.toml [ install ] # 24h supply-chain guard: skip package versions published less than a day ago. minimumReleaseAge = 86400 # Each entry bypasses the 24h guard for one package — confirm with the user # before adding any. minimumReleaseAgeExcludes = ["@lovable.dev/vite-tanstack-config", "@lovable.dev/mcp-js", "@lovable.dev/vite-plugin-dev-server-bridge", "@lovable.dev/vite-plugin-hmr-gate"] .gitignore # Logs logs *.log npm-debug.log* yarn-debug.log* yarn-error.log* pnpm-debug.log* lerna-debug.log* node_modules dist dist-ssr .output .vinxi .tanstack/** .nitro *.local # Wrangler / Cloudflare .wrangler/ .dev.vars # Editor directories and files .vscode/* !.vscode/extensions.json .idea .DS_Store *.suo *.ntvs* *.njsproj *.sln *.sw? .lovable/project.json { "schemaVersion": 1, "template": "tanstack_start_ts_2026-06-08-vite-8" } .lovable/plan.md Revert the single-passport hero image back to its previous design while keeping the bilingual stack image unchanged. ## Plan 1. Regenerate `src/assets/passport-eu.jpg` to match its previous design: a single burgundy European passport with **EUROPEAN UNION** at the top, the EU circle-of-stars emblem, and **PASSPORT** at the bottom, placed on a marble desk with a golden key beside it. 2. Leave `src/assets/passports-stack.jpg` untouched — it keeps the bilingual "EUROPEAN COMMUNITY / COMMUNAUTÉ EUROPÉENNE / PASSPORT / PASSEPORT" cover design. 3. Verify the preview renders both images correctly: the hero should show the single EU passport, and the family/section further down should still show the bilingual stack. No other files or copy will change. Source files src/styles.css @import "tailwindcss" source(none); @source "../src"; @import "tw-animate-css"; @custom-variant dark (&:is(.dark *)); @theme inline { --font-display: "Cormorant Garamond", ui-serif, Georgia, serif; --font-sans: "Inter", ui-sans-serif, system-ui, sans-serif; --radius-sm: calc(var(--radius) - 4px); --radius-md: calc(var(--radius) - 2px); --radius-lg: var(--radius); --radius-xl: calc(var(--radius) + 4px); --color-background: var(--background); --color-foreground: var(--foreground); --color-card: var(--card); --color-card-foreground: var(--card-foreground); --color-popover: var(--popover); --color-popover-foreground: var(--popover-foreground); --color-primary: var(--primary); --color-primary-foreground: var(--primary-foreground); --color-secondary: var(--secondary); --color-secondary-foreground: var(--secondary-foreground); --color-muted: var(--muted); --color-muted-foreground: var(--muted-foreground); --color-accent: var(--accent); --color-accent-foreground: var(--accent-foreground); --color-gold: var(--gold); --color-gold-soft: var(--gold-soft); --color-destructive: var(--destructive); --color-destructive-foreground: var(--destructive-foreground); --color-border: var(--border); --color-input: var(--input); --color-ring: var(--ring); } :root { --radius: 0.25rem; /* Deep navy / cream / gold editorial palette */ --background: oklch(0.98 0.005 80); --foreground: oklch(0.18 0.03 250); --card: oklch(1 0 0); --card-foreground: oklch(0.18 0.03 250); --popover: oklch(1 0 0); --popover-foreground: oklch(0.18 0.03 250); --primary: oklch(0.22 0.05 255); /* deep navy */ --primary-foreground: oklch(0.97 0.01 80); --secondary: oklch(0.94 0.015 80); --secondary-foreground: oklch(0.22 0.05 255); --muted: oklch(0.95 0.012 80); --muted-foreground: oklch(0.45 0.02 250); --accent: oklch(0.78 0.13 80); /* warm gold accent */ --accent-foreground: oklch(0.18 0.03 250); --gold: oklch(0.74 0.14 78); --gold-soft: oklch(0.88 0.07 82); --destructive: oklch(0.55 0.22 27); --destructive-foreground: oklch(0.98 0.01 80); --border: oklch(0.88 0.015 80); --input: oklch(0.88 0.015 80); --ring: oklch(0.74 0.14 78); --gradient-hero: linear-gradient(135deg, oklch(0.18 0.04 255 / 0.85), oklch(0.18 0.04 255 / 0.35)); --gradient-gold: linear-gradient(135deg, oklch(0.82 0.12 82), oklch(0.66 0.15 70)); --shadow-elegant: 0 30px 80px -30px oklch(0.18 0.04 255 / 0.35); --shadow-gold: 0 20px 60px -20px oklch(0.74 0.14 78 / 0.5); } .dark { --background: oklch(0.12 0.02 255); --foreground: oklch(0.97 0.01 80); --card: oklch(0.16 0.03 255); --card-foreground: oklch(0.97 0.01 80); --primary: oklch(0.78 0.13 80); --primary-foreground: oklch(0.12 0.02 255); --border: oklch(1 0 0 / 10%); } @layer base { * { border-color: var(--color-border); } html { scroll-behavior: smooth; } body { background-color: var(--color-background); color: var(--color-foreground); font-family: var(--font-sans); font-feature-settings: "ss01", "cv11"; } h1, h2, h3, h4 { font-family: var(--font-display); font-weight: 500; letter-spacing: -0.015em; } } @layer utilities { .text-gold { color: var(--gold); } .bg-gold { background-color: var(--gold); } .border-gold { border-color: var(--gold); } .gradient-gold { background-image: var(--gradient-gold); } .gradient-hero { background-image: var(--gradient-hero); } .shadow-elegant { box-shadow: var(--shadow-elegant); } .shadow-gold { box-shadow: var(--shadow-gold); } .eyebrow { font-family: var(--font-sans); text-transform: uppercase; letter-spacing: 0.28em; font-size: 0.72rem; font-weight: 500; } } src/routes/index.tsx import { createFileRoute } from "@tanstack/react-router"; import heroCoast from "@/assets/hero-coast.jpg"; import passportEu from "@/assets/passport-eu.jpg"; import beachGreece from "@/assets/beach-greece.jpg"; import coastPortugal from "@/assets/coast-portugal.jpg"; import coastItaly from "@/assets/coast-italy.jpg"; import passportsStack from "@/assets/passports-stack.jpg"; import algarveImg from "@/assets/algarve.jpg"; import capriImg from "@/assets/capri-new.jpg"; import meganisiImg from "@/assets/meganisi.jpg"; import mykonosImg from "@/assets/mykonos-new.jpg"; import ibizaImg from "@/assets/ibiza.png"; import santoriniImg from "@/assets/santorini.jpg"; import logoWave from "@/assets/logo-wave.png"; export const Route = createFileRoute("/")({ head: () => ({ meta: [ { title: "Blue Ports Foundation — Golden Passport to European Citizenship" }, { name: "description", content: "Secure a European residence permit and passport through curated property acquisition. Trusted golden passport advisory for clients in Russia, Asia, the Middle East, Africa and the USA.", }, { property: "og:title", content: "Blue Ports Foundation — Golden Passport to European Citizenship" }, { property: "og:description", content: "Residence and citizenship by investment. One application — your entire family included.", }, { property: "og:type", content: "website" }, { property: "og:url", content: "/" }, { property: "og:image", content: heroCoast }, ], links: [{ rel: "canonical", href: "/" }], }), component: Landing, }); function Landing() { return (
); } function Nav() { return (
Blue Ports Foundation Blue Ports Foundation Private Consultation
); } function Hero() { return (
Aerial view of a luxurious Mediterranean coastline at golden hour

Residence & Citizenship by Investment

A European passport,
earned in stone & coastline.

We open the door to European Union residence — and onward to full citizenship — through curated property acquisition. One application. Intact families. A future with freedom of movement.

Begin Your Application How it works
); } function Stat({ n, label }: { n: string; label: string }) { return (
{n}
{label}
); } function Trust() { const items = ["Lisbon", "Valletta", "Athens", "Nicosia", "Rome", "Madrid"]; return (

Counsel across

{items.map((c) => ( {c} ))}
); } function Program() { return (
A European Union passport beside a golden key on a marble desk

The Golden Passport

Citizenship is no longer a matter of birth. It is a matter of vision.

The Golden Passport program allows qualifying investors to obtain a long-term residence permit in the European Community by acquiring real property within an EU member state. After the statutory holding period, that residence converts into full European citizenship — and a passport that opens 180+ countries without a visa.

); } function Pillar({ n, title, body }: { n: string; title: string; body: string }) { return (
{n}
{title}

{body}

); } function LandInvestment() { return (
Aerial of the Portuguese Atlantic coast at golden hour

Land — the Qualifying Asset

Own a piece of Europe.
Inherit new culture.

Our advisors source pre-qualified parcels of land across the European Community — coastal estates in Portugal, olive groves in Greece, vineyards in Italy, agricultural holdings in Cyprus and Spain. Each parcel is structured to satisfy the minimum investment threshold required for a long-term EU residence permit.

You acquire a real asset that grows in equity. We secure the residence. The land remains yours; the passport, in time, becomes yours as well.

    {[ "Pre-vetted, title-clear parcels", "Threshold-compliant valuations", "End-to-end legal structuring", "Discreet escrow & settlement", ].map((i) => (
  • {i}
  • ))}
); } function Family() { return (

One Application. Your Entire Family.

When you arrive, they arrive with you.

A single qualifying application extends to your spouse, dependent children, and — in many jurisdictions — your parents and adult dependents. One investment. One passport file. A multi-generational inheritance of mobility.

{[ { l: "Spouse", v: "Included" }, { l: "Children", v: "Up to 26 years of age" }, { l: "Parents", v: "Eligible" }, { l: "Future heirs", v: "By descent" }, ].map((x) => (
{x.l}
{x.v}
))}
A stack of European passports on a walnut desk with gold coins and a fountain pen
); } function Destinations() { const places = [ { name: "Portugal", img: coastPortugal }, { name: "Greece", img: beachGreece }, { name: "Italy", img: coastItaly }, ]; return (

Where We Place You

Coastlines that hold the keys.

Each destination is vetted for legal stability, investment integrity, and the quality of the European life it confers.

{places.map((p) => (
{`${p.name}
))}
); } function Lifestyle() { const places = [ { name: "Algarve", img: algarveImg }, { name: "Isle of Capri", img: capriImg }, { name: "Meganisi", img: meganisiImg }, { name: "Mykonos", img: mykonosImg }, { name: "Ibiza", img: ibizaImg }, { name: "Santorini", img: santoriniImg }, ]; return (

A Glimpse of What Awaits

The world your passport unlocks.

From the cliffs of Capri to the white domes of Santorini — these are the places our clients call home once their citizenship is secured.

{places.map((p) => (
{p.name}
))}
); } function Audience() { const regions = [ { r: "Russia & CIS", c: "Moscow · St Petersburg · Almaty" }, { r: "Middle East", c: "Dubai · Riyadh · Doha" }, { r: "Africa", c: "Lagos · Cairo · Johannesburg" }, { r: "Asia", c: "Hong Kong · Singapore · Shanghai" }, { r: "United States", c: "New York · Miami · Los Angeles" }, ]; return (

Whom We Serve

A clientele as global as the passport itself.

We work discreetly with private clients from five continents who are seeking the certainty and freedom of European citizenship.

{regions.map((x) => (
{x.r}
{x.c}
))}
); } function Process() { const steps = [ { n: "I", t: "Private Consultation", b: "A confidential briefing to understand your goals, family, and timeline." }, { n: "II", t: "Jurisdiction Selection", b: "We match you with the EU member state best suited to your file." }, { n: "III", t: "Property Acquisition", b: "We source, vet, and structure your qualifying property purchase." }, { n: "IV", t: "Residence Permit", b: "Your residence card is issued — for you and your family." }, { n: "V", t: "European Passport", b: "Upon naturalisation, your family receives full EU citizenship." }, ]; return (

The Pathway

Five steps. One passport.

    {steps.map((s) => (
  1. {s.n}
    {s.t}

    {s.b}

  2. ))}
); } function CTA() { const fieldClass = "w-full bg-primary-foreground/10 border border-primary-foreground/25 text-primary-foreground placeholder:text-primary-foreground/50 px-4 py-3 focus:outline-none focus:border-gold"; const labelClass = "block text-xs uppercase tracking-[0.2em] text-gold/90 mb-2"; return (
Italian coastal village above the sea

Begin

Your European life
starts with a single conversation.

Share a few details with our advisors. Every enquiry is private, complimentary, and answered within 24 hours.

{/* FormSubmit configuration (hidden) */}