|
| 1 | +# Frontend Rebuild Design |
| 2 | + |
| 3 | +**Goal:** Replace the eye-bleeding Blade+Mix frontend with a clean, atomic, Vue 3 + Tailwind 4 + Vite stack. The OAuth login pages are mandatory (mobile auth flow); the rest is polish. |
| 4 | + |
| 5 | +**Architecture:** Thin Blade shells mount Vue page components. Server data is injected as JSON props via `@json()`. No client-side router, no Inertia — standard multi-page Laravel with a proper component system on top. |
| 6 | + |
| 7 | +**Tech Stack:** Vue 3 (Composition API), Tailwind CSS 4 (Vite plugin, CSS-first), Vite + `laravel-vite-plugin` + `@vitejs/plugin-vue` |
| 8 | + |
| 9 | +--- |
| 10 | + |
| 11 | +## What gets deleted |
| 12 | + |
| 13 | +- `laravel-mix` and `webpack.mix.js` |
| 14 | +- `resources/js/bootstrap.js` |
| 15 | +- All inline Tailwind utility soup in existing Blade views |
| 16 | +- The doubled-up GitHub button on the login page |
| 17 | +- `public/css/` and `public/js/` (compiled Mix output, replaced by Vite) |
| 18 | +- `tailwind.config.js` (Tailwind 4 is CSS-first, no config file) |
| 19 | + |
| 20 | +## What stays untouched |
| 21 | + |
| 22 | +- All backend routes (`routes/web.php`, `routes/api.php`) |
| 23 | +- All controllers (FrontEnd + LoginController + API) |
| 24 | +- Passport OAuth logic |
| 25 | +- `.env`, migrations, models |
| 26 | + |
| 27 | +--- |
| 28 | + |
| 29 | +## Component Structure |
| 30 | + |
| 31 | +``` |
| 32 | +resources/ |
| 33 | + css/ |
| 34 | + app.css ← @import "tailwindcss"; only |
| 35 | + js/ |
| 36 | + components/ |
| 37 | + atoms/ |
| 38 | + AppButton.vue ← variant prop: primary | ghost | danger |
| 39 | + AppAvatar.vue ← src + name fallback to initials |
| 40 | + AppBadge.vue ← count display |
| 41 | + AppIcon.vue ← wraps SVG slot |
| 42 | + molecules/ |
| 43 | + OAuthButton.vue ← provider name + icon + href |
| 44 | + ThreadCard.vue ← subject + participants + last activity |
| 45 | + MessageBubble.vue ← body + sender + timestamp |
| 46 | + organisms/ |
| 47 | + AppHeader.vue ← logo + auth nav (login/logout/username) |
| 48 | + ThreadList.vue ← list of ThreadCard |
| 49 | + MessageFeed.vue ← list of MessageBubble |
| 50 | + pages/ |
| 51 | + Welcome.vue ← landing: hero + CTA |
| 52 | + Login.vue ← OAuth provider buttons (GitHub mandatory) |
| 53 | + Dashboard.vue ← authenticated: thread list |
| 54 | + Thread.vue ← thread detail: message feed |
| 55 | + app.js ← createApp, register page component, mount |
| 56 | + views/ |
| 57 | + layout.blade.php ← <head> + @vite + AppHeader organism + <div id="app"> + footer |
| 58 | + welcome.blade.php ← passes {} to Welcome.vue |
| 59 | + login.blade.php ← passes { params } to Login.vue |
| 60 | + dashboard.blade.php ← passes { threads } to Dashboard.vue |
| 61 | + thread.blade.php ← passes { thread } to Thread.vue |
| 62 | +``` |
| 63 | + |
| 64 | +## Data flow |
| 65 | + |
| 66 | +Each Blade view renders a `<script>` tag with page props and identifies which Vue page to mount: |
| 67 | + |
| 68 | +```blade |
| 69 | +<script>window.__PAGE__ = "Dashboard"; window.__PROPS__ = @json($data);</script> |
| 70 | +``` |
| 71 | + |
| 72 | +`app.js` reads `window.__PAGE__`, imports the matching page component, and mounts it with `window.__PROPS__` as props. One bundle, zero client-side routing. |
| 73 | + |
| 74 | +## Build config |
| 75 | + |
| 76 | +- `vite.config.js`: `laravel-vite-plugin` (entry: `resources/js/app.js`, `resources/css/app.css`) + `@vitejs/plugin-vue` |
| 77 | +- `layout.blade.php`: `@vite(['resources/css/app.css', 'resources/js/app.js'])` |
| 78 | +- No `tailwind.config.js` — Tailwind 4 auto-detects template files via `@source` in CSS |
| 79 | + |
| 80 | +## Design tokens (Tailwind 4 CSS vars) |
| 81 | + |
| 82 | +Defined in `app.css` under `@theme`: |
| 83 | +- Brand red: `--color-brand: oklch(...)` |
| 84 | +- Neutral scale via Tailwind defaults |
| 85 | +- Font: system stack (no external font load) |
0 commit comments