Add frontend marketing site and plugin host API package - #3
Merged
Conversation
Introduces fiely-frontend/ — the web UI package for Fiely. Ships a full landing page (hero, features, AI features, audience, tech stack, roadmap, CTA, footer) with a cohesive design system in Tailwind, dark-mode ready tokens, Inter typography and accessible, responsive layouts. Set up with Vite, TypeScript strict mode and a production build that type-checks cleanly.
Expands "Frontend Plugin Mechanism" from a sketch into an actionable contract: goals, bundle layout with content-hashed serving, full manifest schema with hostApiVersion gating, an import-map + native ESM loader (rejecting Module Federation with reasoning), a three-tier trust model (core / first-party in-process / third-party iframe + postMessage), a versioned @fiely/host API surface, typed entry-point props, routing ownership, shared @fiely/ui styling rules, aggregate manifest endpoint, frontend security model per tier, and a DX story with create-fiely-plugin + @fiely/plugin-dev. Updates the Decisions summary and Phase 4 roadmap to match.
Adds packages/fiely-host/ — the contract every Fiely plugin compiles against. The package exposes: - FielyHost interface (files, ui, fetch, events, config, theme, i18n) - Entry-point prop types (PageProps, FileActionProps, SettingsPanelProps, SidebarWidgetProps) - HostEvent union + narrowing helpers - PluginManifest schema with entry-point type guards - HOST_API_VERSION constant and PermissionError class - @fiely/host/mount subpath: loadPluginBundle, entryPointBundleUrl, pluginAssetUrl, and the shared MOUNT_CLASS Plugins run in-process: the core loads the bundle via dynamic import() under the browser's import map, builds a permission-scoped FielyHost, and renders the plugin's exported component as a React child. No iframe, no postMessage RPC — isolation comes from admin review at install time, backend enforcement of AppPermission on every API call, CSP that pins script-src/connect-src to the core origin, and per-plugin CSS scoping inside .fiely-plugin-root. Also updates docs/plugin-architecture.md to drop the iframe trust tier and document the unified in-process model and layered security story.
Move to a root Dockerfile that builds the React frontend with Node, embeds the resulting dist into fiely-core as Spring Boot static resources, and produces one runtime image. - Dockerfile at repo root: frontend (node:22-alpine) -> backend (gradle:8.11-jdk21) -> runtime (eclipse-temurin:21-jre). Frontend assets land under classpath:/static/ and are served by Spring. - SpaWebConfig adds a resource resolver that serves real files, returns 404 for missing assets (extension check), skips /api/ and /actuator/ routes so they behave as before, and otherwise falls back to index.html so React Router deep links work on refresh. - .dockerignore at root covers both frontend and backend build artifacts. - CI: split out a 'frontend' job (Node 22, npm ci + build, dist artifact) alongside the existing backend build; docker-build now uses the root Dockerfile with context '.', depends on both. - Remove the now-redundant fiely-backend/Dockerfile and .dockerignore. - .gitignore excludes the staged static/ directory so a local build never leaks into commits. - README: describe the single-container build/run flow. Smoke-tested locally: /api/ping returns JSON, / and /dashboard and /apps/my-app all return the SPA shell (identical bytes), /assets/* returns the real bundle, /foo.png and /api/unknown return 404.
Add a root-level docker-compose.yml that brings up PostgreSQL (with pgvector, pre-provisioned for the planned semantic search in phase 2) and the Fiely container together with a single 'docker compose up'. - Persistent named volume for the database - pg_isready healthcheck so the Fiely container waits for the DB - Configurable via .env (port, DB name/user/password); defaults are local-only dev values - Database port is not exposed to the host by default - Build targets the root Dockerfile at context '.' .env.example documents the available overrides. README: replace the "coming soon" note with a real quick start section, keep the manual 'docker build' + 'docker run' flow as an alternative.
Previously 'docker compose up' always triggered a full local build (frontend + backend, a few minutes on the first run). Flip the default so the compose file references the image CI publishes to GHCR and only falls back to the local build context if the pull fails. - docker-compose.yml: image defaults to ghcr.io/benjaminledel/fiely:latest, overridable via FIELY_IMAGE; pull_policy: missing; build: stays as a fallback so 'docker compose up' works on a fresh checkout even before the image is published - .env.example: document FIELY_IMAGE with an example of pinning a SHA tag - README: clarify the pull-first / build-fallback behavior and show the 'docker compose pull' / '--build' / 'down -v' commands - ci.yml: clean up IMAGE_NAME from the doubled ghcr.io/<repo>/fiely to ghcr.io/<repo> (the repo already is fiely)
Adds a dev overlay that runs alongside the base compose:
docker compose -f docker-compose.yml -f docker-compose.dev.yml up
- New fiely-frontend-dev service (node:22-alpine) running `vite --host`
with a bind mount to ./fiely-frontend/ so source edits HMR instantly.
node_modules lives in a named volume so host platform differences
(macOS/Windows) don't break native deps.
- File-watch polling enabled (CHOKIDAR_USEPOLLING) so mounts work
reliably on all Linux kernels.
- Vite config now reads VITE_API_PROXY (falls back to localhost:8080)
and proxies /api + /actuator to the backend container, so the dev
frontend talks to a real Spring Boot backend without CORS.
- Dev overlay forces 'fiely' to build locally (pull_policy: never,
tag fiely:dev) rather than pulling the GHCR image.
- @types/node added as a devDependency for vite.config.ts's process
access.
- README documents the dev workflow (port table, HMR behavior, how
to rebuild the backend).
Drop the two-port setup (Vite on :5173, backend on :8080). Everything now lives behind Spring Boot on :8080 in dev too, mirroring how prod works. How it works: - SpaWebConfig now reads spring.web.resources.static-locations instead of hardcoding classpath:/static/. Both the resource handler and the SPA index.html fallback walk the configured locations in order, so operators can prepend a filesystem path without patching code. - docker-compose.dev.yml replaces fiely-frontend-dev (npm run dev with HMR + proxy) with fiely-frontend-watch (vite build --watch) writing into a shared named volume. - The fiely backend mounts that volume read-only at /app/frontend-dist and is told to serve from there first via SPRING_WEB_RESOURCES_STATIC_LOCATIONS=file:/app/frontend-dist/,classpath:/static/. Spring streams the freshest bytes on every request — no backend restart needed after a frontend edit. - A healthcheck on the watcher (tests for /dist-out/index.html) gates the backend's depends_on so users never hit 404 on the first load. - README updated: one port, one URL (localhost:8080), single workflow. Still documents the host-Vite path for users who want real React Fast Refresh with state preservation. Verified locally: started the JAR with a temp file: location, filesystem dist took precedence, classpath fallback worked for assets only present there, overwriting index.html was reflected on the next request without a restart.
Fiely is a self-hosted product container, not a marketing site — the first thing a user should see on localhost:8080 is the Nextcloud-style login, not an eight-section sales pitch. A real marketing site belongs on fiely.cloud and can be built separately. - Remove Hero, Features, AIFeatures, Audience, TechStack, Roadmap, CTA, Header, Footer components. - Add Login.tsx: centered card with username + password (show/hide toggle), "stay signed in" checkbox, forgot-password link, submit button wired to POST /api/auth/login, inline error surface, and a disabled SSO button placeholder for the upcoming OIDC/SAML auth plugin. - Add LegalFooter.tsx: Imprint · Privacy · Terms · "Open source · MIT" shown on unauthenticated pages. Links point at /legal/* routes the settings plugin will own. - App.tsx collapses to the unauthenticated shell that mounts Login. - index.html: title → "Sign in · Fiely", description → product copy. - Design-system tokens in index.css (.btn-primary, .btn-ghost, .gradient-text, brand palette) are preserved so the authenticated surfaces can build on them. Bundle drops: CSS 31.96 → 16.93 kB (-47 %), JS 184.50 → 152.06 kB (-18 %).
After merging origin/main, /api/auth/login is real. Adjust the form:
- Send only { username, password } (backend ignores 'remember').
- Read error messages from body.error (AuthController's ErrorResponse
field) with a fallback to body.message for future providers.
- On success, store TokenPair.accessToken + refreshToken in localStorage
(when 'Stay signed in' is ticked) or sessionStorage otherwise. The
authenticated shell will pick it up; a real cookie-backed session
can replace this later.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
This PR introduces the Fiely frontend marketing site and the foundational
@fiely/hostpackage that defines the plugin contract. It also restructures the Docker build to embed the frontend into the backend as a single container, and updates CI/CD to build both frontend and backend.Key Changes
Frontend (fiely-frontend/)
Plugin Host API (
packages/fiely-host/)@fiely/hostnpm package — the contract plugins compile againstFielyHostinterface with user info, theme tokens, and API surfaceFielyFilesApi— typed wrappers for file operations (get, list, download, upload, delete)FielyUiApi— user-visible effects (toast, confirm, navigate, openFile)PageProps,FileActionProps,SettingsPanelPropshost.on())PermissionErrorfor permission-denied scenariosPluginManifest,EntryPoint,AppPermission)loadPluginBundle,MOUNT_CLASSfor CSS scoping)react,react-dom, and@fiely/host(pinned via import map)Docker & Deployment
Dockerfile— 3-stage build:fiely-frontend/todist/fiely-backend/, embedding frontend dist as Spring Boot static resourcesdocker-compose.yml— quick-start with PostgreSQL (pgvector) + Fiely.dockerignore— excludes build artifacts, docs, and local config.env.example— template for compose environment variablesBackend Integration
SpaWebConfig.kt— Spring Boot web config for SPA fallback/static/as-isindex.htmlfor client-side routing/api/and/actuator/from rewritingCI/CD
.github/workflows/ci.yml— updated to build both frontend and backendDocumentation
docs/plugin-architecture.md— expanded Phase 4 (Third-Party Apps) with detailed frontend plugin mechanismhostApiVersioncompatibility gatingcreate-fiely-pluginscaffold and@fiely/plugin-devVite pluginpackages/fiely-host/README.md— plugin author guide with examples (pages, file actions, events, permissions)https://claude.ai/code/session_01WyDtWm5QXTFa79B1K3L5Wi