# Indie — Independent Website Platform A platform that lets anyone create, own, and publish their own static website without social media gatekeeping. Built with a drag-and-drop builder and LLM prompt-to-site generation. Every site is backed by a git repository. Users self-host or use free subdomain hosting. --- ## Tech Stack | Layer | Technology | |-------|-----------| | Backend | Java 17, Spring Boot 3.x, Gradle (Groovy) | | Frontend | Angular 17, Angular Material, Angular CDK (drag-drop) | | Relational DB | PostgreSQL | | Document DB | MongoDB (LLM sessions) | | Object Storage | Cloudflare R2 (S3-compatible) | | LLM | Gemini (primary), OpenAI (fallback), provider-abstraction for future | | Auth | Spring Security + OAuth2 Client — email/password, Google OAuth, GitHub OAuth, OpenID Connect | | Git | JGit — local repo per site, optional GitHub/GitLab remote push | | Infra | Docker Compose (dev), R2 + Cloudflare (hosting), Caddy/nginx (prod reverse proxy) | --- ## Build Phases ### v0.1 — Auth & Foundation (Target: Weeks 1-3) **Goal:** User can register, log in via email or OAuth, and create/manage sites and pages. #### Backend | File | Action | Details | |------|--------|---------| | `backend/build.gradle` | Add | Spring Boot 3.x, deps: web, jpa, security, oauth2-client, oauth2-resource-server, validation, lombok, postgresql, testcontainers, aws-java-sdk-s3 (R2), springdoc-openapi, jgit | | `backend/settings.gradle` | Add | Project name, plugin management | | `backend/src/main/resources/application.yml` | Add | DB configs, JWT keys, OAuth client IDs/secrets, LLM keys, R2 credentials, git config | | `com/indie/IndieApplication.java` | Add | Main class | | `com/indie/config/SecurityConfig.java` | Add | SecurityFilterChain with JWT filter + OAuth2 login + OpenID Connect. Route permissions: `/api/auth/**` public, `/api/**` authenticated | | `com/indie/config/JwtConfig.java` | Add | RS256 signing, access token 15min, refresh token 7d | | `com/indie/config/GitConfig.java` | Add | Repos root path (`/var/git/sites/`), author name/email | | `com/indie/model/User.java` | Add | id(UUID), email, password(bcrypt, nullable), name, avatarUrl, provider(LOCAL/GOOGLE/GITHUB/OPENID), providerId, emailVerified, createdAt, updatedAt | | `com/indie/model/Site.java` | Add | id, userId, name, description, subdomain(unique), themeConfig(JSONB), status(DRAFT/PUBLISHED), publishedAt, createdAt, updatedAt | | `com/indie/model/Page.java` | Add | id, siteId(FK), title, slug, seoTitle, seoDescription, orderIndex, createdAt | | `com/indie/model/Component.java` | Add | id, pageId(FK), type(enum), config(JSONB), styles(JSONB), orderIndex | | `com/indie/repository/*.java` | Add | JPA repositories for User, Site, Page, Component | | `com/indie/service/AuthService.java` | Add | register, login, refreshToken, oauthLogin | | `com/indie/service/OAuth2UserService.java` | Add | Maps Google/GitHub/OpenID user info to User entity | | `com/indie/controller/AuthController.java` | Add | `POST /api/auth/register`, `/login`, `/refresh`, `/logout` | | `com/indie/controller/SiteController.java` | Add | Full CRUD: `GET/POST /api/sites`, `GET/PUT/DELETE /api/sites/{id}` | | `com/indie/controller/PageController.java` | Add | CRUD for pages within a site | #### Frontend | File | Action | Details | |------|--------|---------| | `frontend/` | Init | Angular 17 standalone, Angular Material, lazy routes, Tailwind CSS | | `src/app/auth/` | Add | LoginComponent, RegisterComponent, OAuth callback handler, AuthService, AuthGuard, JWT interceptor | | `src/app/dashboard/` | Add | DashboardComponent (list site cards), CreateSiteDialog, DeleteSiteDialog | #### Infrastructure | File | Action | Details | |------|--------|---------| | `docker-compose.yml` | Add | PostgreSQL, MongoDB, MinIO (local R2 mock), backend (8080), frontend (4200) | --- ### v0.2 — Drag-and-Drop Builder (Target: Weeks 4-6) **Goal:** User can visually build a website by dragging components onto a canvas, editing their properties, styling via theme editor, and previewing live. #### Backend | File | Action | Details | |------|--------|---------| | `com/indie/controller/BuilderController.java` | Add | `GET /api/sites/{id}/pages` (with nested components), `PUT /api/sites/{id}/pages/{pageId}/components` (batch save), `GET/PUT /api/sites/{id}/theme` | | `com/indie/service/BuilderService.java` | Add | Validate component tree (type enum, config schema, max 50/page), save in transaction | #### Frontend | File | Action | Details | |------|--------|---------| | `src/app/builder/builder.component.ts` | Add | 3-panel layout (palette 250px, canvas flex, properties 320px) via CSS Grid or mat-sidenav | | `src/app/builder/services/builder-state.service.ts` | Add | BehaviorSubject store: `components$`, `selectedComponentId$`, `themeConfig$`, `pages$`. Methods: add, remove, update, reorder. Undo/redo stack (50 snapshots) | | `src/app/builder/services/auto-save.service.ts` | Add | 2s debounce → `PUT` batch save. "Saving..."/"Saved" indicator | | `src/app/builder/component-palette/` | Add | PaletteComponent — Material list of 10 draggable component types, organized by category | | `src/app/builder/canvas/` | Add | CanvasComponent — `cdkDropList` accepting drops, renders components in order, highlight on select, delete on hover | | `src/app/builder/property-panel/` | Add | PropertyPanelComponent — dynamic form per type (config + styles sections). Material expansion panels | | `src/app/builder/renderer/` | Add | Render components per type (heading, text, image, button, divider, gallery, video, contact_form, map, custom_html) — each takes `config` + `styles` as `@Input()` | | `src/app/builder/theme-editor/` | Add | ThemeEditorComponent — color pickers, font selectors, spacing slider. Live preview updates | | `src/app/builder/preview/` | Add | PreviewComponent — sandboxed `