{ "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 (
Residence & Citizenship by Investment
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.
Counsel across
The Golden Passport
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.
{body}
Land — the Qualifying Asset
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.
One Application. Your Entire Family.
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.
Where We Place You
Each destination is vetted for legal stability, investment integrity, and the quality of the European life it confers.
A Glimpse of What Awaits
From the cliffs of Capri to the white domes of Santorini — these are the places our clients call home once their citizenship is secured.
Whom We Serve
We work discreetly with private clients from five continents who are seeking the certainty and freedom of European citizenship.
The Pathway
{s.b}
Begin
Share a few details with our advisors. Every enquiry is private, complimentary, and answered within 24 hours.
The page you're looking for doesn't exist or has been moved.
Something went wrong on our end. You can try refreshing or head back home.
Something went wrong on our end. You can try refreshing or head back home.