DEV Community

Cover image for Building a High‑Tech Vue + Tailwind One‑Page with Claude Code + Gemini Design MCP"
A0mineTV
A0mineTV

Posted on

Building a High‑Tech Vue + Tailwind One‑Page with Claude Code + Gemini Design MCP"

Context: I wanted a polished, “high‑tech” portfolio one‑pager in Vue 3 + TypeScript + Tailwind without spending days hand‑tweaking spacing, cards, and section layouts.

With Claude Code as the main agent and Gemini Design MCP as the “frontend designer”, I could iterate fast and keep the code in my repo.


Source code (GitHub)

The full project is available here:

To run it locally:

git clone https://github.com/VincentCapek/portfolio-gemini-design.git
cd portfolio-gemini-design
pnpm install
pnpm dev
Enter fullscreen mode Exit fullscreen mode

What you’ll build

A one‑page portfolio landing that feels modern and “techy”:

  • Sticky glassy navbar (scroll + section highlight)
  • Hero with subtle grid background and glowing accents
  • Stats/metrics row
  • Services, resume/timeline, works grid, skills, testimonials slider, contact form
  • Responsive + accessible by default

Prerequisites

  • Node.js >= 18
  • A Gemini Design MCP API key
  • A Vue 3 + TypeScript + Tailwind project (Vite)
  • Package manager: pnpm

1) Install Gemini Design MCP in Claude Code (local mode)

Gemini Design MCP can run locally (recommended). In your project folder, run:

claude mcp add gemini-design-mcp --env API_KEY=your_api_key_here -- npx -y gemini-design-mcp@latest
Enter fullscreen mode Exit fullscreen mode

That’s it—Claude Code can now call Gemini Design tools for UI work.

Why local mode?

  • Faster (no network latency)
  • Simple: no remote auth headers to maintain
  • Works even if your environment restricts remote connections

2) Keep secrets out of your repo (two safe approaches)

You can make the MCP config project-scoped (shareable) without committing secrets.

Option A (recommended): project .mcp.json without secrets + local key in Claude config

1) Commit a minimal .mcp.json that describes how to run the server:

{
  "mcpServers": {
    "gemini-design-mcp": {
      "type": "stdio",
      "command": "npx",
      "args": ["-y", "gemini-design-mcp@latest"]
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

2) Store the API key in Claude Code local scope (not in the repo):

claude mcp add --scope local gemini-design-mcp --env API_KEY=your_api_key_here -- npx -y gemini-design-mcp@latest
Enter fullscreen mode Exit fullscreen mode

This way:

  • .mcp.json can be committed safely
  • your API key stays private in your local Claude config

Option B: environment variable expansion in .mcp.json

If you’re fine using env vars:

{
  "mcpServers": {
    "gemini-design-mcp": {
      "type": "stdio",
      "command": "npx",
      "args": ["-y", "gemini-design-mcp@latest"],
      "env": {
        "API_KEY": "${GEMINI_DESIGN_MCP_API_KEY}"
      }
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Then set it on your machine:

export GEMINI_DESIGN_MCP_API_KEY="your_api_key_here"
Enter fullscreen mode Exit fullscreen mode

Tip: If you accidentally committed your key, rotate it immediately (revoke + regenerate).


3) Add “rules” so Claude always delegates UI work to Gemini

Create a CLAUDE.md at the project root.

This file is where you teach Claude when to use Gemini Design MCP and how to structure requests.

Here’s the exact version I use for a fresh Vue 3 + TS + Tailwind repo.

# CLAUDE.md

This file guides Claude Code (claude.ai/code) when working in this repository.
This is a **fresh Vue 3 + TypeScript + Tailwind** project.

---

## General rules

- Keep changes **small and focused** (minimal diffs).
- Prefer **readability** over cleverness.
- Do not introduce new dependencies unless necessary.
- Always consider **accessibility** (labels, keyboard navigation, focus states).
- Keep UI **responsive** (mobile-first).

---

## Tech stack (baseline)

- Vue 3 + Vite + TypeScript
- Tailwind CSS
- Composition API + `<script setup lang="ts">`
- Package manager: **pnpm**

---

## Package manager: pnpm (required)

- Use **pnpm** for installs and scripts.
- Do **not** use `npm` or `yarn` (unless explicitly requested).

Common commands:
Enter fullscreen mode Exit fullscreen mode


bash
pnpm install
pnpm dev
pnpm build
pnpm lint
pnpm test
pnpm add
pnpm remove


---

## Gemini Design MCP (MCP server): rules

Gemini is your frontend developer. For all UI/design work, use this MCP.

### Before writing any UI code, ask yourself:

- Is it a **NEW** visual component (popup, card, section, etc.)? → `snippet_frontend` or `create_frontend`
- Is it a **REDESIGN** of an existing element? → `modify_frontend`
- Is it just text/logic, or a trivial change? → Do it yourself

### Critical rules

1. If UI already exists and you need to redesign/restyle it → use `modify_frontend`, NOT `snippet_frontend`.
2. Tasks can be mixed (logic + UI). Mentally separate them:
   - Do the logic yourself
   - Delegate UI to Gemini

### Which MCP tool to call

- `create_frontend`: generate a full page/view
- `snippet_frontend`: generate a reusable UI block/snippet
- `modify_frontend`: targeted redesign of an existing component (surgical edits)

### Required brief format (always include)

When calling Gemini Design MCP, include:

1) **Target**
- File path(s) to create/modify
- Purpose of the UI

2) **Layout & content**
- Sections/blocks + hierarchy
- Copy/text placeholders

3) **States**
- Loading / empty / error / success / disabled

4) **Interactions**
- Primary/secondary actions
- Keyboard/focus expectations

5) **Constraints**
- Responsive (mobile/tablet/desktop)
- Accessibility requirements
- **Vue 3 SFC + Tailwind** output

---

## MCP configuration & secrets (important)

- **Never commit API keys or tokens** in any versioned file.
- Do **not** store keys inside committed `.mcp.json`.
- Preferred: commit `.mcp.json` without secrets, store the key in Claude’s local scope config.

---

## Output rule

When you finish a task, provide:
- A short summary of what changed
- The files touched
- Any follow-up suggestions (non-blocking)

Enter fullscreen mode Exit fullscreen mode

That’s the whole “secret sauce”: Claude reliably routes anything visual to Gemini Design MCP.


4) Build the one‑page: break it into sections

Gemini Design MCP works best when you iterate in small steps, like you would with a real designer:

  1. Scaffold the page sections (basic layout)
  2. Make the hero “feel right” (spacing, grid, glow, typography)
  3. Add cards/grids (services, works, testimonials)
  4. Polish interactions (scrollspy, hover states, focus rings)

5) The prompt I used to recreate a similar template structure

I wanted a structure close to this demo layout (same “vibe” and section order, without copying text/images):
https://theme-land.com/relome/demo/index.html

Here is a copy‑paste prompt you can use in Claude Code.

Because of the rules above, Claude should automatically pick Gemini Design MCP and call create_frontend.

Use Gemini Design MCP.

Tool: create_frontend

Goal:
Create a one-page high-tech portfolio landing in Vue 3 + TypeScript + Tailwind inspired by:
https://theme-land.com/relome/demo/index.html
IMPORTANT: Do NOT copy exact text, brand names, or images. Use original copy + placeholders, but keep a very similar overall layout, spacing, and section order.

Project stack:
- Vue 3 + Vite + TypeScript
- Tailwind CSS
- pnpm
- Composition API + <script setup lang="ts">
- No extra UI libraries unless necessary (prefer inline SVG icons).

Output files:
- src/App.vue (page composition + anchors)
- src/components/layout/Navbar.vue (sticky header + mobile menu + active link)
- src/components/sections/HeroSection.vue
- src/components/sections/ServicesSection.vue
- src/components/sections/ResumeSection.vue
- src/components/sections/WorksSection.vue (filterable portfolio grid)
- src/components/sections/SkillsSection.vue
- src/components/sections/ApproachSection.vue
- src/components/sections/TestimonialsSection.vue (simple slider)
- src/components/sections/InsightsSection.vue
- src/components/sections/ContactSection.vue (form + contact info)
- src/components/layout/FooterSection.vue
- src/composables/useScrollSpy.ts (active section highlight)
- src/data/content.ts + src/data/portfolio.ts (content arrays)

Design requirements:
- Dark modern look with subtle grid background and soft glows.
- Hero: headline, subtitle, CTA, avatar placeholder, stats row (4 metrics).
- Services: 4 feature cards with icon + title + description.
- Resume: experience + education timeline blocks.
- Works: category pills + responsive project card grid.
- Skills: 6 skills with percentages (progress bars or radial).
- Approach: 3 steps (01 Define, 02 Develop, 03 Deliver).
- Testimonials: cards + prev/next + dots, keyboard accessible.
- Insights: 2–3 blog cards with date, read time, tags.
- Contact: left side info + right side form (checkboxes, budget pills, validation, loading state).
- Footer: simple.

UX:
- Smooth scrolling to anchors (respect prefers-reduced-motion).
- ScrollSpy highlights active nav link.
- Visible focus styles and accessible labels.

Tailwind:
- Utility-first. Minimal scoped CSS.
- Consistent container (max-w-6xl mx-auto px-4) and typography hierarchy.

Deliverables:
- Production-ready Vue SFC components with typed props where needed.
- Keep logic lightweight and content data-driven.
- Summarize created files and anchor IDs.
Enter fullscreen mode Exit fullscreen mode

6) My iteration loop (this is what makes the result “high‑end”)

Once the scaffold is there, I iterate in tiny design requests instead of one giant prompt:

Make the hero feel more “high‑tech”

Use Gemini Design MCP.
Tool: modify_frontend

Target file: src/components/sections/HeroSection.vue

Redesign goals:
- Stronger grid background + subtle vignette
- Softer glow behind the avatar
- Better typography hierarchy (headline + name emphasis)
- CTA button with premium hover/active states
- Improve spacing on mobile

Keep the current structure and content.
Only change visuals and classes.
Enter fullscreen mode Exit fullscreen mode

Upgrade the metric cards

Use Gemini Design MCP.
Tool: modify_frontend

Target file: src/components/sections/HeroSection.vue (metrics row)

Make the metric cards look more premium:
- glassmorphism, subtle borders, faint noise
- better number styling (tabular nums), label alignment
- hover effect and focus ring for accessibility

No new dependencies.
Enter fullscreen mode Exit fullscreen mode

Add a new UI block without touching existing layout

Use Gemini Design MCP.
Tool: snippet_frontend

Add a "Trusted by" strip under the hero:
- 5 logo placeholders (SVG or simple text marks)
- subtle separators, matches the dark theme
- responsive (wrap on mobile)
Insert location: directly under the metrics row.
Enter fullscreen mode Exit fullscreen mode

7) Common gotchas (and how to avoid them)

“Gemini generated React, but my repo is Vue”

Gemini Design MCP often defaults to React + Tailwind. If that happens:

  • Treat it as a layout reference
  • Ask Claude to convert it to Vue SFC
  • Or explicitly remind: “Output Vue 3 SFC + <script setup lang="ts">

“It looks good on desktop but not on mobile”

Always ask for mobile fixes explicitly:

  • “Fix mobile spacing and reduce visual clutter”
  • “Make the nav menu comfortable on small screens”
  • “Adjust typography scale for sm and md breakpoints”

“I’m afraid it will break my logic”

That’s exactly why modify_frontend exists: it’s a surgical restyle tool.

Use it whenever the component already exists.


8) Final checklist before shipping

  • pnpm dev and verify hot reload
  • Keyboard navigation works (tab through buttons/links/inputs)
  • Contrast is readable on the dark background
  • Each section has a stable anchor ID for nav links
  • No secrets are committed (.mcp.json clean, API key stored locally)

Conclusion

This workflow feels like pairing with a designer who can also code:

  • Claude Code orchestrates the work
  • Gemini Design MCP handles the visual layer
  • Your repo stays clean, typed, and maintainable

If you’re building Vue + Tailwind UIs and you want “polish” without a week of pixel pushing, this setup is a huge win.


Handy links (add as you like)

Top comments (0)