From 7eba24ea274e0ca18712f3677816b82a5c7eaf76 Mon Sep 17 00:00:00 2001 From: logikonline Date: Thu, 8 Jan 2026 10:16:33 -0500 Subject: [PATCH] docs: add feature enhancement specifications MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add two specification documents for planned Gitea enhancements: - enhancements.md: Organization public profile pages and Gitea Pages (repository landing pages with custom domains) - ai_enhancements.md: AI and developer experience improvements including structured API errors, Scalar API docs, batch operations, AI-powered wiki generation, and SDK tooling πŸ€– Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- ai_enhancements.md | 1328 ++++++++++++++++++++++++++++++++++++++++++++ enhancements.md | 983 ++++++++++++++++++++++++++++++++ 2 files changed, 2311 insertions(+) create mode 100644 ai_enhancements.md create mode 100644 enhancements.md diff --git a/ai_enhancements.md b/ai_enhancements.md new file mode 100644 index 0000000000..e680164447 --- /dev/null +++ b/ai_enhancements.md @@ -0,0 +1,1328 @@ +# AI & Developer Experience Enhancements + +**Version:** 1.0 +**Date:** January 2026 +**Status:** Draft - Awaiting Review + +--- + +## Table of Contents + +1. [AI-Friendly API Improvements](#1-ai-friendly-api-improvements) +2. [AI-Powered Wiki System](#2-ai-powered-wiki-system) +3. [User Experience Improvements](#3-user-experience-improvements) +4. [Developer Tooling](#4-developer-tooling) +5. [Data Integrity & Optimization](#5-data-integrity--optimization) +6. [Implementation Phases](#6-implementation-phases) + +--- + +## 1. AI-Friendly API Improvements + +### Overview + +Modern AI assistants (Claude, GPT, etc.) need predictable, well-structured APIs to effectively interact with Gitea. These improvements make Gitea a first-class citizen for AI-assisted development workflows. + +### 1.1 Structured JSON Error Responses + +Current error responses are often plain text or inconsistently formatted. AI agents need structured errors to handle failures gracefully. + +#### Current Problem + +```json +// Current: Inconsistent +{"message": "Not found"} +{"error": "unauthorized"} +"Something went wrong" +``` + +#### Proposed Standard + +```json +{ + "error": { + "code": "REPO_NOT_FOUND", + "message": "Repository 'owner/repo' does not exist or you don't have access", + "status": 404, + "details": { + "owner": "acme", + "repo": "missing-repo", + "suggestion": "Did you mean 'acme/missing-repos'?" + }, + "documentation_url": "https://docs.gitea.com/api/errors#REPO_NOT_FOUND", + "request_id": "req_abc123xyz" + } +} +``` + +#### Error Code Categories + +| Prefix | Category | Examples | +|--------|----------|----------| +| `AUTH_` | Authentication | `AUTH_TOKEN_EXPIRED`, `AUTH_INVALID_SCOPE` | +| `PERM_` | Permissions | `PERM_REPO_READ_DENIED`, `PERM_ORG_ADMIN_REQUIRED` | +| `REPO_` | Repository | `REPO_NOT_FOUND`, `REPO_ARCHIVED`, `REPO_TRANSFER_PENDING` | +| `FILE_` | File operations | `FILE_TOO_LARGE`, `FILE_NOT_FOUND`, `FILE_CONFLICT` | +| `GIT_` | Git operations | `GIT_REF_NOT_FOUND`, `GIT_MERGE_CONFLICT` | +| `RATE_` | Rate limiting | `RATE_LIMIT_EXCEEDED`, `RATE_QUOTA_EXHAUSTED` | +| `VAL_` | Validation | `VAL_INVALID_NAME`, `VAL_MISSING_FIELD` | + +#### Implementation + +```go +// modules/structs/api_error.go +type APIError struct { + Code string `json:"code"` + Message string `json:"message"` + Status int `json:"status"` + Details map[string]any `json:"details,omitempty"` + DocumentationURL string `json:"documentation_url,omitempty"` + RequestID string `json:"request_id"` + Suggestions []string `json:"suggestions,omitempty"` +} + +// Usage +func (ctx *Context) APIError(code string, status int, details map[string]any) { + ctx.JSON(status, APIErrorResponse{ + Error: APIError{ + Code: code, + Message: errorMessages[code], + Status: status, + Details: details, + DocumentationURL: fmt.Sprintf("%s/api/errors#%s", setting.AppURL, code), + RequestID: ctx.RequestID(), + }, + }) +} +``` + +### 1.2 OpenAPI Schema & Scalar API Documentation + +Enhance the existing OpenAPI spec and replace Swagger UI with Scalar for a modern API documentation experience. + +#### Why Scalar over Swagger UI + +| Feature | Swagger UI | Scalar | +|---------|-----------|--------| +| UI Design | Dated, cluttered | Modern, clean | +| Dark Mode | Limited | Native support | +| Search | Basic | Full-text across endpoints | +| Try It | Yes | Yes, with better UX | +| Code Examples | Limited | Auto-generated for multiple languages | +| Performance | Heavier | Lighter, faster loading | +| Customization | Complex | Theme-friendly, CSS variables | +| AI-Friendly | Basic | Better structured for LLM consumption | + +#### Scalar Integration + +```go +// routers/api/v1/swagger.go +package v1 + +import ( + "code.gitea.io/gitea/modules/context" + "code.gitea.io/gitea/modules/setting" +) + +// RegisterScalarUI serves the Scalar API documentation UI +func RegisterScalarUI(m *web.Router) { + m.Get("/api/v1/docs", func(ctx *context.Context) { + ctx.HTML(200, tplScalar) + }) +} + +// Scalar HTML template +const tplScalar = ` + + + + {{AppName}} API Reference + + + + + + + + + +` +``` + +#### Self-Hosted Scalar (No CDN) + +```go +// For air-gapped installations, bundle Scalar assets +// assets/scalar/api-reference.min.js + +m.Get("/api/v1/docs/assets/*", func(ctx *context.Context) { + ctx.ServeFile(path.Join(setting.StaticRootPath, "assets/scalar", ctx.Params("*"))) +}) +``` + +#### OpenAPI Schema Improvements + +| Area | Enhancement | +|------|-------------| +| **Descriptions** | Detailed field descriptions with examples | +| **Examples** | Request/response examples for every endpoint | +| **Deprecation** | Clear deprecation notices with migration paths | +| **Schemas** | Reusable schema components with validation rules | +| **Tags** | Logical grouping with descriptions | +| **x-scalar-** | Scalar-specific extensions for enhanced docs | + +#### Example Enhancement + +```yaml +# Before +/repos/{owner}/{repo}/contents/{filepath}: + get: + summary: Get file contents + +# After +/repos/{owner}/{repo}/contents/{filepath}: + get: + operationId: getRepositoryContents + summary: Get file or directory contents + description: | + Retrieves the contents of a file or directory in a repository. + + For files, returns the content (base64 encoded if binary). + For directories, returns a list of entries. + + **Rate limit:** 5000 requests/hour (authenticated) + + **AI Usage Notes:** + - Use `ref` parameter for specific branches/commits + - Large files (>1MB) return download_url instead of content + - Check `type` field: "file", "dir", "symlink", "submodule" + parameters: + - name: filepath + description: | + Path to the file or directory. + Use empty string or "/" for repository root. + example: "src/main.go" + responses: + 200: + description: File or directory contents + content: + application/json: + schema: + oneOf: + - $ref: '#/components/schemas/ContentsResponse' + - type: array + items: + $ref: '#/components/schemas/ContentsResponse' + examples: + file: + summary: Single file + value: + type: file + name: main.go + path: src/main.go + size: 1234 + encoding: base64 + content: cGFja2FnZSBtYWluCg== + directory: + summary: Directory listing + value: + - type: file + name: main.go + path: src/main.go + - type: dir + name: utils + path: src/utils +``` + +### 1.3 Batch Operations Endpoints + +AI agents often need to perform multiple operations efficiently. Batch endpoints reduce API calls and improve performance. + +#### New Batch Endpoints + +``` +POST /api/v1/batch/files +POST /api/v1/batch/issues +POST /api/v1/batch/labels +POST /api/v1/batch/webhooks +GET /api/v1/batch/status/{batch_id} +``` + +#### Batch Files API + +```json +// POST /api/v1/repos/{owner}/{repo}/batch/files +{ + "branch": "main", + "message": "Update configuration files", + "operations": [ + { + "operation": "create", + "path": "config/app.yaml", + "content": "base64-encoded-content" + }, + { + "operation": "update", + "path": "README.md", + "content": "base64-encoded-content", + "sha": "abc123" // Required for updates + }, + { + "operation": "delete", + "path": "old-config.json", + "sha": "def456" + }, + { + "operation": "move", + "path": "docs/old-name.md", + "new_path": "docs/new-name.md" + } + ], + "author": { + "name": "AI Assistant", + "email": "ai@example.com" + } +} + +// Response +{ + "commit": { + "sha": "xyz789", + "message": "Update configuration files", + "url": "https://gitea.example.com/owner/repo/commit/xyz789" + }, + "results": [ + {"path": "config/app.yaml", "status": "created", "sha": "new-sha-1"}, + {"path": "README.md", "status": "updated", "sha": "new-sha-2"}, + {"path": "old-config.json", "status": "deleted"}, + {"path": "docs/new-name.md", "status": "moved", "sha": "new-sha-3"} + ] +} +``` + +#### Batch Issues API + +```json +// POST /api/v1/repos/{owner}/{repo}/batch/issues +{ + "operations": [ + { + "operation": "create", + "title": "Fix login bug", + "body": "Description...", + "labels": ["bug", "priority:high"] + }, + { + "operation": "update", + "issue": 123, + "state": "closed", + "labels": {"add": ["resolved"], "remove": ["in-progress"]} + }, + { + "operation": "comment", + "issue": 124, + "body": "This is being tracked in #123" + } + ] +} +``` + +### 1.4 Streaming Responses for Large Results + +For large queries (repo tree, search results, activity feeds), streaming prevents timeouts and allows incremental processing. + +#### Streaming Endpoints + +``` +GET /api/v1/repos/{owner}/{repo}/git/trees/{sha}?stream=true +GET /api/v1/repos/{owner}/{repo}/search?stream=true +GET /api/v1/repos/{owner}/{repo}/commits?stream=true +``` + +#### Response Format (NDJSON) + +```jsonl +{"type":"meta","total":15000,"estimated":true} +{"type":"item","data":{"path":"src/main.go","type":"file","sha":"abc123"}} +{"type":"item","data":{"path":"src/utils/","type":"dir","sha":"def456"}} +{"type":"item","data":{"path":"src/utils/helpers.go","type":"file","sha":"ghi789"}} +... +{"type":"done","count":15000,"truncated":false} +``` + +#### Server-Sent Events Alternative + +``` +GET /api/v1/repos/{owner}/{repo}/git/trees/{sha} +Accept: text/event-stream + +event: meta +data: {"total":15000} + +event: item +data: {"path":"src/main.go","type":"file"} + +event: item +data: {"path":"src/utils/","type":"dir"} + +event: done +data: {"count":15000} +``` + +### 1.5 AI Context Endpoints + +New endpoints specifically designed for AI assistants to quickly understand a repository. + +#### Repository Summary + +``` +GET /api/v1/repos/{owner}/{repo}/ai/summary +``` + +```json +{ + "overview": { + "name": "myproject", + "description": "A tool for doing X", + "primary_language": "Go", + "languages": {"Go": 75.5, "TypeScript": 20.3, "Shell": 4.2}, + "size_bytes": 15234567, + "file_count": 342, + "last_commit": "2026-01-08T10:30:00Z" + }, + "structure": { + "has_readme": true, + "has_license": true, + "license_type": "MIT", + "has_contributing": true, + "has_ci": true, + "ci_system": "gitea-actions", + "package_managers": ["go.mod", "package.json"], + "frameworks_detected": ["gin", "react"] + }, + "activity": { + "commits_last_30d": 47, + "contributors_last_30d": 5, + "open_issues": 12, + "open_prs": 3, + "stars": 234, + "forks": 45 + }, + "key_files": [ + {"path": "README.md", "description": "Project documentation"}, + {"path": "go.mod", "description": "Go module definition"}, + {"path": "Makefile", "description": "Build commands"}, + {"path": ".gitea/workflows/ci.yaml", "description": "CI pipeline"} + ], + "entry_points": [ + {"path": "cmd/server/main.go", "description": "Main application entry"}, + {"path": "cmd/cli/main.go", "description": "CLI tool entry"} + ] +} +``` + +#### Code Navigation Hints + +``` +GET /api/v1/repos/{owner}/{repo}/ai/navigation +``` + +```json +{ + "architecture": "monorepo", + "modules": [ + { + "name": "api", + "path": "services/api/", + "description": "REST API service", + "entry_point": "services/api/main.go", + "dependencies": ["database", "auth"] + }, + { + "name": "worker", + "path": "services/worker/", + "description": "Background job processor", + "entry_point": "services/worker/main.go" + } + ], + "common_patterns": { + "handlers": "services/*/handlers/*.go", + "models": "internal/models/*.go", + "tests": "**/*_test.go", + "configs": "configs/*.yaml" + }, + "important_files": [ + { + "path": "internal/config/config.go", + "reason": "Central configuration" + }, + { + "path": "internal/database/migrations/", + "reason": "Database schema history" + } + ] +} +``` + +--- + +## 2. AI-Powered Wiki System + +### Overview + +Enable AI assistants to automatically generate and maintain wiki documentation by analyzing the repository, while keeping humans in control through a review workflow. + +### 2.1 Wiki Generation from Repository + +AI can analyze the codebase and generate comprehensive wiki pages. + +#### Trigger Methods + +1. **Manual:** Repo admin requests wiki generation +2. **Scheduled:** Regenerate on release or milestone +3. **API:** External AI service calls generation endpoint + +#### Generation API + +``` +POST /api/v1/repos/{owner}/{repo}/wiki/ai/generate +``` + +```json +{ + "scope": "full", // full | incremental | section + "sections": [ + "architecture", + "api-reference", + "getting-started", + "contributing", + "configuration", + "deployment", + "troubleshooting" + ], + "options": { + "include_code_examples": true, + "include_diagrams": true, // Mermaid diagrams + "language": "en", + "detail_level": "comprehensive", // brief | standard | comprehensive + "source_refs": true // Link back to source files + }, + "ai_provider": "internal", // internal | openai | anthropic | custom + "review_required": true +} +``` + +#### Response + +```json +{ + "generation_id": "gen_abc123", + "status": "processing", + "estimated_pages": 15, + "webhook_url": "/api/v1/repos/{owner}/{repo}/wiki/ai/generations/gen_abc123", + "review_url": "https://gitea.example.com/owner/repo/wiki/_review/gen_abc123" +} +``` + +### 2.2 Generated Wiki Structure + +``` +wiki/ +β”œβ”€β”€ Home.md # Auto-generated overview +β”œβ”€β”€ Architecture.md # System design, components +β”œβ”€β”€ Getting-Started/ +β”‚ β”œβ”€β”€ Installation.md +β”‚ β”œβ”€β”€ Quick-Start.md +β”‚ └── Configuration.md +β”œβ”€β”€ API-Reference/ +β”‚ β”œβ”€β”€ Overview.md +β”‚ β”œβ”€β”€ Authentication.md +β”‚ └── Endpoints/ +β”‚ β”œβ”€β”€ Users.md +β”‚ └── Projects.md +β”œβ”€β”€ Development/ +β”‚ β”œβ”€β”€ Setup.md +β”‚ β”œβ”€β”€ Testing.md +β”‚ └── Contributing.md +β”œβ”€β”€ Deployment/ +β”‚ β”œβ”€β”€ Docker.md +β”‚ β”œβ”€β”€ Kubernetes.md +β”‚ └── Configuration.md +└── Troubleshooting.md +``` + +### 2.3 Wiki Review Workflow + +All AI-generated content goes through human review before publishing. + +#### States + +``` +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ Draft │────►│ Review │────►│ Approved │────►│ Published β”‚ +β”‚(AI Gen) β”‚ β”‚ (Human) β”‚ β”‚ β”‚ β”‚ β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + β”‚ + β–Ό + β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” + β”‚ Rejected │──► Edit ──► Back to Review + β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` + +#### Review UI + +``` +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ πŸ“ Wiki Review: Architecture.md [AI Generated] β”‚ +β”‚ β”‚ +β”‚ Generated: Jan 8, 2026 10:30 AM β”‚ +β”‚ Confidence: 87% β”‚ +β”‚ Sources: 15 files analyzed β”‚ +β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ β”‚ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β”‚ AI Generated β”‚ Your Edits β”‚ β”‚ +β”‚ β”‚ β”‚ β”‚ β”‚ +β”‚ β”‚ # Architecture β”‚ # Architecture β”‚ β”‚ +β”‚ β”‚ β”‚ β”‚ β”‚ +β”‚ β”‚ MyProject uses a β”‚ MyProject uses a β”‚ β”‚ +β”‚ β”‚ microservices arch... β”‚ microservices arch... β”‚ β”‚ +β”‚ β”‚ β”‚ β”‚ β”‚ +β”‚ β”‚ ## Components β”‚ ## Core Components β”‚ β”‚ ← Edit +β”‚ β”‚ β”‚ β”‚ β”‚ +β”‚ β”‚ - API Server β”‚ - API Server (Go/Gin) β”‚ β”‚ ← Enhanced +β”‚ β”‚ - Worker β”‚ - Background Worker β”‚ β”‚ +β”‚ β”‚ - Database β”‚ - PostgreSQL Database β”‚ β”‚ +β”‚ β”‚ β”‚ β”‚ β”‚ +β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ +β”‚ β”‚ +β”‚ πŸ“Ž Source References: β”‚ +β”‚ β€’ cmd/server/main.go:15-45 β”‚ +β”‚ β€’ internal/config/config.go β”‚ +β”‚ β€’ docker-compose.yaml β”‚ +β”‚ β”‚ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”β”‚ +β”‚ β”‚ πŸ’¬ Review Comments β”‚β”‚ +β”‚ β”‚ β”‚β”‚ +β”‚ β”‚ @alice: "Component section needs more detail about the worker" β”‚β”‚ +β”‚ β”‚ @bob: "LGTM after Alice's feedback addressed" β”‚β”‚ +β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜β”‚ +β”‚ β”‚ +β”‚ [βœ“ Approve & Publish] [✏️ Request Changes] [❌ Reject] [πŸ’Ύ Save]β”‚ +β”‚ β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` + +### 2.4 Wiki Improvement Suggestions + +AI can continuously analyze wiki pages and suggest improvements. + +#### Suggestion Types + +| Type | Description | Example | +|------|-------------|---------| +| `outdated` | Content doesn't match current code | "Function `doThing()` was renamed to `performAction()`" | +| `incomplete` | Missing documentation | "New endpoint `/api/v1/users/search` is undocumented" | +| `broken_link` | Dead internal/external links | "Link to `#configuration` section doesn't exist" | +| `clarity` | Confusing or unclear content | "This section could be clearer with a code example" | +| `structure` | Organization improvements | "Consider splitting this into multiple pages" | +| `coverage` | Missing topics | "No documentation for error handling patterns" | + +#### Suggestions API + +``` +GET /api/v1/repos/{owner}/{repo}/wiki/ai/suggestions +``` + +```json +{ + "suggestions": [ + { + "id": "sug_001", + "type": "outdated", + "severity": "high", + "page": "API-Reference/Authentication.md", + "line": 45, + "current_text": "Use the `/api/v1/auth/login` endpoint", + "issue": "Endpoint was changed to `/api/v1/users/tokens`", + "suggested_text": "Use the `/api/v1/users/tokens` endpoint to create access tokens", + "evidence": { + "source_file": "routers/api/v1/user/token.go", + "commit": "abc123", + "date": "2026-01-05" + }, + "confidence": 0.95 + }, + { + "id": "sug_002", + "type": "incomplete", + "severity": "medium", + "page": null, + "issue": "New feature 'Webhooks' has no wiki documentation", + "suggested_action": "Generate new page: Webhooks.md", + "evidence": { + "source_files": [ + "routers/api/v1/repo/webhook.go", + "models/webhook.go" + ], + "feature_commits": ["def456", "ghi789"] + }, + "confidence": 0.88 + }, + { + "id": "sug_003", + "type": "clarity", + "severity": "low", + "page": "Getting-Started/Installation.md", + "line": 12, + "current_text": "Run the setup script", + "issue": "Missing information about prerequisites", + "suggested_text": "Before running the setup script, ensure you have:\n- Go 1.21+\n- PostgreSQL 14+\n- Node.js 18+\n\nThen run the setup script:", + "confidence": 0.72 + } + ], + "summary": { + "total": 15, + "by_severity": {"high": 2, "medium": 8, "low": 5}, + "by_type": {"outdated": 3, "incomplete": 5, "clarity": 4, "broken_link": 2, "coverage": 1} + }, + "last_analysis": "2026-01-08T10:00:00Z", + "next_analysis": "2026-01-09T10:00:00Z" +} +``` + +#### Apply Suggestion + +``` +POST /api/v1/repos/{owner}/{repo}/wiki/ai/suggestions/{id}/apply +``` + +```json +{ + "action": "apply", // apply | dismiss | edit_and_apply + "edited_text": "Optional: manually edited version", + "review_required": true +} +``` + +### 2.5 Wiki Sync with Code + +Keep documentation in sync with code changes. + +#### Sync Configuration + +```yaml +# .gitea/wiki-sync.yaml +sync: + enabled: true + trigger: + - on_release + - on_milestone_close + - weekly + + watch_paths: + - "routers/api/**" # API changes + - "models/**" # Data model changes + - "docs/**" # Inline documentation + - "*.md" # Root markdown files + + notifications: + - type: issue + title: "Wiki Update Required" + assignees: ["docs-team"] + + - type: webhook + url: "https://example.com/wiki-updates" +``` + +#### Sync Status + +``` +GET /api/v1/repos/{owner}/{repo}/wiki/ai/sync/status +``` + +```json +{ + "last_sync": "2026-01-07T15:00:00Z", + "last_code_change": "2026-01-08T09:30:00Z", + "status": "outdated", + "drift_score": 0.15, // 0 = fully synced, 1 = completely outdated + "changed_areas": [ + { + "code_path": "routers/api/v1/repo/release.go", + "wiki_page": "API-Reference/Releases.md", + "change_type": "api_signature_changed", + "details": "New parameter 'prerelease' added to create endpoint" + } + ], + "pending_updates": 3 +} +``` + +--- + +## 3. User Experience Improvements + +### 3.1 Progress Reporting for Long Operations + +Real-time progress for uploads, clones, and other long-running operations. + +#### Progress API + +``` +GET /api/v1/operations/{operation_id}/progress +Accept: text/event-stream +``` + +``` +event: progress +data: {"phase":"uploading","current":52428800,"total":104857600,"percent":50,"speed_bps":5242880,"eta_seconds":10} + +event: progress +data: {"phase":"uploading","current":78643200,"total":104857600,"percent":75,"speed_bps":5500000,"eta_seconds":5} + +event: progress +data: {"phase":"processing","message":"Verifying checksums..."} + +event: complete +data: {"status":"success","result":{"id":123,"name":"release.zip"}} +``` + +#### Progress Response Schema + +```json +{ + "operation_id": "op_abc123", + "type": "chunked_upload", + "status": "in_progress", + "phases": [ + {"name": "uploading", "status": "complete", "progress": 100}, + {"name": "assembling", "status": "in_progress", "progress": 45}, + {"name": "verifying", "status": "pending", "progress": 0} + ], + "current": { + "phase": "assembling", + "progress": 45, + "message": "Assembling chunks 23/50", + "bytes_processed": 241172480, + "bytes_total": 524288000 + }, + "timing": { + "started_at": "2026-01-08T10:30:00Z", + "elapsed_seconds": 45, + "estimated_remaining_seconds": 55 + } +} +``` + +### 3.2 Webhook Notifications + +Webhook events for upload and long operation completion. + +#### New Webhook Events + +```json +{ + "event": "upload_complete", + "payload": { + "type": "release_attachment", + "release": { + "id": 123, + "tag_name": "v1.0.0" + }, + "attachment": { + "id": 456, + "name": "myapp-v1.0.0.zip", + "size": 524288000, + "download_url": "https://..." + }, + "upload_method": "chunked", + "duration_seconds": 120, + "uploader": { + "id": 1, + "login": "developer" + } + } +} +``` + +```json +{ + "event": "wiki_updated", + "payload": { + "action": "ai_generated", + "pages_affected": ["Architecture.md", "API-Reference.md"], + "generation_id": "gen_abc123", + "status": "pending_review", + "review_url": "https://..." + } +} +``` + +### 3.3 Web UI for Chunked Uploads + +Browser-based chunked upload with pause/resume capability. + +#### UI Features + +``` +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ Upload Release Assets β”‚ +β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ β”‚ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”β”‚ +β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β” β”‚β”‚ +β”‚ β”‚ β”‚ β”‚ Drop files here or click to browse β”‚β”‚ +β”‚ β”‚ β”‚ + β”‚ β”‚β”‚ +β”‚ β”‚ β”‚ β”‚ Maximum file size: 2GB β”‚β”‚ +β”‚ β”‚ β””β”€β”€β”€β”€β”€β”˜ β”‚β”‚ +β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜β”‚ +β”‚ β”‚ +β”‚ Uploading: β”‚ +β”‚ β”‚ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β”‚ πŸ“¦ myapp-linux-amd64.tar.gz 245 MB / 500 MBβ”‚ β”‚ +β”‚ β”‚ β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘ 49% β”‚ β”‚ +β”‚ β”‚ Speed: 5.2 MB/s β€’ ETA: 49 seconds [⏸ Pause] β”‚ β”‚ +β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ +β”‚ β”‚ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β”‚ πŸ“¦ myapp-darwin-arm64.tar.gz ⏸️ β”‚ β”‚ +β”‚ β”‚ β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘ 25% β”‚ β”‚ +β”‚ β”‚ Paused β€’ 125 MB uploaded [β–Ά Resume] β”‚ β”‚ +β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ +β”‚ β”‚ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β”‚ βœ… myapp-windows-amd64.zip Done! β”‚ β”‚ +β”‚ β”‚ 450 MB β€’ Uploaded in 1m 32s β”‚ β”‚ +β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ +β”‚ β”‚ +β”‚ ⚠️ Uploads will resume automatically if you close this page β”‚ +β”‚ and return within 24 hours. β”‚ +β”‚ β”‚ +β”‚ [Cancel All] [Upload More] β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` + +#### LocalStorage Persistence + +```javascript +// Persist upload state for resume +const uploadState = { + sessionId: "sess_abc123", + fileName: "myapp.tar.gz", + fileSize: 524288000, + chunkSize: 10485760, + completedChunks: [0, 1, 2, 3, 4, 5], + fileHash: "sha256:abc123...", // For integrity verification + expiresAt: 1704931200 +}; +localStorage.setItem(`upload_${sessionId}`, JSON.stringify(uploadState)); +``` + +--- + +## 4. Developer Tooling + +### 4.1 CLI Tool for Chunked Uploads + +A dedicated CLI tool for reliable large file uploads. + +#### Installation + +```bash +# Via go install +go install code.gitea.io/gitea-cli@latest + +# Via package managers +brew install gitea-cli +apt install gitea-cli +``` + +#### Usage + +```bash +# Basic upload +gitea-cli upload release-asset \ + --repo owner/repo \ + --release v1.0.0 \ + --file ./dist/app.tar.gz + +# With options +gitea-cli upload release-asset \ + --repo owner/repo \ + --release v1.0.0 \ + --file ./dist/app.tar.gz \ + --chunk-size 50MB \ + --parallel 4 \ + --verify-checksum \ + --progress + +# Resume interrupted upload +gitea-cli upload resume --session sess_abc123 + +# List pending uploads +gitea-cli upload list --repo owner/repo +``` + +#### Output + +``` +Uploading app-v1.0.0.tar.gz (524 MB) +Creating upload session... done (sess_abc123) +Uploading chunks (4 parallel workers): + + [β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ] 100% + + Chunks: 50/50 complete + Speed: 8.5 MB/s (avg) + Time: 1m 02s + +Finalizing... done +Verifying checksum... βœ“ SHA256 matches + +βœ… Upload complete! + Asset ID: 456 + Download: https://gitea.example.com/attachments/xyz789 +``` + +### 4.2 SDK Client Libraries + +Official SDK support for popular languages. + +#### Go SDK + +```go +import "code.gitea.io/sdk/gitea" + +client, _ := gitea.NewClient("https://gitea.example.com", + gitea.SetToken("your_token")) + +// Chunked upload +upload, _ := client.CreateChunkedUpload(ctx, "owner", "repo", 123, + gitea.ChunkedUploadOptions{ + FileName: "app.tar.gz", + ChunkSize: 10 * 1024 * 1024, + }) + +file, _ := os.Open("app.tar.gz") +result, _ := upload.Upload(ctx, file, + gitea.WithProgress(func(p gitea.Progress) { + fmt.Printf("\r%d%%", p.Percent) + }), + gitea.WithParallel(4)) +``` + +#### Python SDK + +```python +from gitea import GiteaClient, ChunkedUpload + +client = GiteaClient("https://gitea.example.com", token="your_token") + +# Chunked upload with progress +with open("app.tar.gz", "rb") as f: + result = client.upload_release_asset( + owner="myorg", + repo="myrepo", + release_id=123, + file=f, + filename="app.tar.gz", + chunk_size=10*1024*1024, + parallel=4, + progress_callback=lambda p: print(f"{p.percent}%") + ) + +print(f"Uploaded: {result.browser_download_url}") +``` + +#### JavaScript/TypeScript SDK + +```typescript +import { GiteaClient } from '@gitea/sdk'; + +const client = new GiteaClient({ + baseUrl: 'https://gitea.example.com', + token: 'your_token' +}); + +// Chunked upload with progress +const file = new File([...], 'app.tar.gz'); +const result = await client.releases.uploadAssetChunked({ + owner: 'myorg', + repo: 'myrepo', + releaseId: 123, + file, + chunkSize: 10 * 1024 * 1024, + parallel: 4, + onProgress: (progress) => { + console.log(`${progress.percent}%`); + } +}); +``` + +--- + +## 5. Data Integrity & Optimization + +### 5.1 Checksum Verification + +End-to-end integrity verification using SHA256. + +#### Client-Side + +```bash +# Calculate before upload +SHA256=$(sha256sum app.tar.gz | cut -d' ' -f1) + +# Include in upload session creation +curl -X POST ".../upload-session?name=app.tar.gz&size=524288000&sha256=$SHA256" +``` + +#### Server Verification + +```json +// Create session with checksum +POST /api/v1/repos/{owner}/{repo}/releases/{id}/assets/upload-session +{ + "name": "app.tar.gz", + "size": 524288000, + "checksum": { + "algorithm": "sha256", + "value": "abc123def456..." + } +} + +// Complete response includes verification +POST /api/v1/repos/{owner}/{repo}/uploads/{session}/complete +{ + "id": 456, + "name": "app.tar.gz", + "size": 524288000, + "checksum_verified": true, + "checksum": { + "algorithm": "sha256", + "value": "abc123def456..." + } +} +``` + +### 5.2 Compression Support + +Optional server-side compression for text-based files. + +#### Request Compression + +``` +PUT /api/v1/repos/{owner}/{repo}/uploads/{session}/chunks/0 +Content-Encoding: gzip +X-Original-Size: 10485760 + +[gzip-compressed chunk data] +``` + +#### Response + +```json +{ + "chunk_number": 0, + "received_size": 3145728, // Compressed size + "original_size": 10485760, // Uncompressed size + "compression_ratio": 0.30 +} +``` + +### 5.3 Deduplication + +Detect and reuse identical chunks across uploads. + +#### How It Works + +1. Client sends chunk hash before upload +2. Server checks if chunk exists in storage +3. If exists, skip upload and reference existing chunk +4. Reduces storage and upload time for similar files + +#### API + +```json +// Check if chunks exist +POST /api/v1/repos/{owner}/{repo}/uploads/{session}/chunks/check +{ + "chunks": [ + {"number": 0, "sha256": "abc123..."}, + {"number": 1, "sha256": "def456..."}, + {"number": 2, "sha256": "ghi789..."} + ] +} + +// Response +{ + "existing": [ + {"number": 0, "sha256": "abc123...", "exists": true}, + {"number": 1, "sha256": "def456...", "exists": false}, + {"number": 2, "sha256": "ghi789...", "exists": true} + ], + "upload_required": [1], + "bytes_saved": 20971520 +} +``` + +--- + +## 6. Implementation Phases + +### Phase 1: API Foundation (4-5 weeks) + +1. **Week 1-2:** Structured error responses + - Define error code taxonomy + - Implement APIError type + - Migrate existing endpoints + +2. **Week 2-3:** OpenAPI improvements + - Add detailed descriptions + - Add request/response examples + - Generate improved client SDKs + +3. **Week 3-4:** Batch operations + - Batch files endpoint + - Batch issues endpoint + - Transaction handling + +4. **Week 4-5:** AI context endpoints + - Repository summary + - Navigation hints + +### Phase 2: Wiki AI System (6-8 weeks) + +1. **Week 1-2:** Wiki generation infrastructure + - Generation queue and workers + - Template system for different page types + - Source code analysis integration + +2. **Week 3-4:** Review workflow + - Review UI components + - State machine for page lifecycle + - Diff viewer for AI vs human edits + +3. **Week 5-6:** Suggestions system + - Outdated content detection + - Missing documentation detection + - Suggestion management API + +4. **Week 7-8:** Code sync + - Watch path configuration + - Drift detection algorithm + - Notification system + +### Phase 3: User Experience (3-4 weeks) + +1. **Week 1:** Progress reporting + - SSE endpoint implementation + - Progress aggregation for multi-step operations + +2. **Week 2:** Webhooks + - New event types + - Payload schemas + - Delivery reliability + +3. **Week 3-4:** Web UI uploads + - Drag-and-drop component + - Progress visualization + - Pause/resume functionality + - LocalStorage persistence + +### Phase 4: Developer Tools (3-4 weeks) + +1. **Week 1-2:** CLI tool + - Upload command implementation + - Progress display + - Resume functionality + +2. **Week 3-4:** SDK libraries + - Go SDK updates + - Python SDK + - JavaScript/TypeScript SDK + +### Phase 5: Data Integrity (2-3 weeks) + +1. **Week 1:** Checksum verification + - SHA256 calculation + - Verification flow + - Error handling for mismatches + +2. **Week 2:** Compression + - Gzip support + - Content-Encoding handling + - Size tracking + +3. **Week 3:** Deduplication + - Chunk hash storage + - Lookup optimization + - Storage savings reporting + +--- + +## Appendix A: Error Code Reference + +### Authentication Errors (AUTH_) + +| Code | Status | Description | +|------|--------|-------------| +| `AUTH_TOKEN_MISSING` | 401 | No authentication token provided | +| `AUTH_TOKEN_INVALID` | 401 | Token is malformed or invalid | +| `AUTH_TOKEN_EXPIRED` | 401 | Token has expired | +| `AUTH_SCOPE_INSUFFICIENT` | 403 | Token lacks required scope | +| `AUTH_2FA_REQUIRED` | 401 | Two-factor authentication required | + +### Permission Errors (PERM_) + +| Code | Status | Description | +|------|--------|-------------| +| `PERM_REPO_READ_DENIED` | 403 | Cannot read repository | +| `PERM_REPO_WRITE_DENIED` | 403 | Cannot write to repository | +| `PERM_REPO_ADMIN_REQUIRED` | 403 | Repository admin access required | +| `PERM_ORG_MEMBER_REQUIRED` | 403 | Must be organization member | + +### Repository Errors (REPO_) + +| Code | Status | Description | +|------|--------|-------------| +| `REPO_NOT_FOUND` | 404 | Repository does not exist | +| `REPO_ARCHIVED` | 403 | Repository is archived | +| `REPO_DISABLED` | 403 | Repository is disabled | +| `REPO_TRANSFER_PENDING` | 409 | Repository has pending transfer | + +### File Errors (FILE_) + +| Code | Status | Description | +|------|--------|-------------| +| `FILE_NOT_FOUND` | 404 | File does not exist | +| `FILE_TOO_LARGE` | 413 | File exceeds size limit | +| `FILE_CONFLICT` | 409 | File was modified (SHA mismatch) | +| `FILE_BINARY` | 400 | Cannot perform text operation on binary file | + +### Upload Errors (UPLOAD_) + +| Code | Status | Description | +|------|--------|-------------| +| `UPLOAD_SESSION_NOT_FOUND` | 404 | Upload session does not exist | +| `UPLOAD_SESSION_EXPIRED` | 410 | Upload session has expired | +| `UPLOAD_CHUNK_INVALID` | 400 | Chunk number out of range | +| `UPLOAD_CHUNK_SIZE_MISMATCH` | 400 | Chunk size doesn't match expected | +| `UPLOAD_CHECKSUM_MISMATCH` | 400 | File checksum verification failed | +| `UPLOAD_INCOMPLETE` | 400 | Not all chunks have been uploaded | + +--- + +*End of Specification* diff --git a/enhancements.md b/enhancements.md new file mode 100644 index 0000000000..23233c40b9 --- /dev/null +++ b/enhancements.md @@ -0,0 +1,983 @@ +# Feature Enhancements Specification + +**Version:** 1.0 +**Date:** January 2026 +**Status:** Approved for Development + +--- + +## Table of Contents + +1. [Organization Public Profile Page](#1-organization-public-profile-page) +2. [Repository Landing Pages (Gitea Pages)](#2-repository-landing-pages-gitea-pages) +3. [Database Schema Changes](#3-database-schema-changes) +4. [API Endpoints](#4-api-endpoints) +5. [Implementation Phases](#5-implementation-phases) + +--- + +## 1. Organization Public Profile Page + +### Overview + +A new **Overview** tab becomes the default landing page for organizations, replacing the Repositories tab as the first view. This page showcases the organization's identity, featured projects, and public members. + +### Tab Structure + +``` +[Overview] [Repositories] [Projects] [Packages] [People] [Settings] + ↑ + DEFAULT +``` + +### 1.1 Pinned Repositories + +Organizations can pin and group unlimited repositories to highlight on their profile. + +#### Features + +| Feature | Specification | +|---------|---------------| +| **Count** | Unlimited pinned repos | +| **Grouping** | Repos can be organized into named groups | +| **Ordering** | Drag-and-drop reordering within groups | +| **Metadata Displayed** | Stars, forks, primary language badge, description | + +#### Data Model + +```go +// models/organization/pinned_repo.go +type OrgPinnedRepo struct { + ID int64 `xorm:"pk autoincr"` + OrgID int64 `xorm:"INDEX NOT NULL"` + RepoID int64 `xorm:"INDEX NOT NULL"` + GroupName string `xorm:"DEFAULT ''"` // Empty = ungrouped + DisplayOrder int `xorm:"DEFAULT 0"` + CreatedUnix timeutil.TimeStamp `xorm:"created"` +} + +type OrgPinnedGroup struct { + ID int64 `xorm:"pk autoincr"` + OrgID int64 `xorm:"INDEX NOT NULL"` + Name string `xorm:"NOT NULL"` + DisplayOrder int `xorm:"DEFAULT 0"` + Collapsed bool `xorm:"DEFAULT false"` // Allow collapsible groups +} +``` + +#### UI Layout + +``` +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ πŸ“Œ Featured Projects β”‚ +β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ β”‚ +β”‚ β–Ό Core Products β”‚ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β”‚ [icon] β”‚ β”‚ [icon] β”‚ β”‚ [icon] β”‚ β”‚ +β”‚ β”‚ main-app β”‚ β”‚ api-server β”‚ β”‚ web-client β”‚ β”‚ +β”‚ β”‚ ⭐ 2.1k 🍴 432β”‚ β”‚ ⭐ 1.8k 🍴 289β”‚ β”‚ ⭐ 956 🍴 178 β”‚ β”‚ +β”‚ β”‚ ● TypeScript β”‚ β”‚ ● Go β”‚ β”‚ ● React β”‚ β”‚ +β”‚ β”‚ "Our flagship β”‚ β”‚ "Backend API β”‚ β”‚ "Frontend β”‚ β”‚ +β”‚ β”‚ application" β”‚ β”‚ services" β”‚ β”‚ application" β”‚ β”‚ +β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ +β”‚ β”‚ +β”‚ β–Ό Libraries & Tools β”‚ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β”‚ [icon] β”‚ β”‚ [icon] β”‚ β”‚ +β”‚ β”‚ shared-utils β”‚ β”‚ cli-tool β”‚ β”‚ +β”‚ β”‚ ⭐ 445 🍴 67 β”‚ β”‚ ⭐ 312 🍴 45 β”‚ β”‚ +β”‚ β”‚ ● TypeScript β”‚ β”‚ ● Rust β”‚ β”‚ +β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ +β”‚ β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` + +### 1.2 Public Members Display + +Members can opt-in to be displayed publicly on the organization profile. + +#### Features + +| Feature | Specification | +|---------|---------------| +| **Visibility** | Member chooses to be displayed (opt-in) | +| **Roles Shown** | Owner, Admin, Member | +| **Overflow** | "and X more" with link to People tab | +| **Layout** | Avatar grid with username and role | + +#### Data Model + +```go +// Add to existing OrgUser model +type OrgUser struct { + // ... existing fields + IsPublic bool `xorm:"DEFAULT false"` // Member opts in to public display +} +``` + +#### UI Layout + +``` +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ πŸ‘₯ Public Members [View All β†’]β”‚ +β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ β”‚ +β”‚ β”Œβ”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β” β”‚ +β”‚ β”‚ πŸ‘€ β”‚ β”‚ πŸ‘€ β”‚ β”‚ πŸ‘€ β”‚ β”‚ πŸ‘€ β”‚ β”‚ πŸ‘€ β”‚ β”‚ πŸ‘€ β”‚ ... and 18 more β”‚ +β”‚ β””β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”˜ β”‚ +β”‚ @alice @bob @carol @david @emma @frank β”‚ +β”‚ Owner Admin Admin Member Member Member β”‚ +β”‚ β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` + +### 1.3 Promotional Region / About Section + +Organizations can create a rich profile page with custom content. + +#### Storage + +Content is stored in a **private repository** within the organization: + +``` +Repository: {org}/.profile (private) +Files: + - README.md # Main profile content (Markdown) + - assets/ # Images, videos, badges + - logo.png + - banner.jpg + - team-photo.jpg + - style.css # Optional custom CSS (sandboxed) +``` + +#### Features + +| Feature | Specification | +|---------|---------------| +| **Content Format** | Markdown (README.md) | +| **Editor** | Markdown editor + optional WYSIWYG toggle | +| **Media** | Images, videos, badges stored in `.profile` repo | +| **Custom CSS** | Allowed within sandboxed constraints | +| **Version Control** | Full Git history via `.profile` repo | + +#### Content Capabilities + +```markdown +# Allowed in README.md: + +## Standard Markdown +- Headers, lists, links, code blocks +- Tables, blockquotes +- Task lists + +## Extended Features +- ![Images](./assets/logo.png) +- ![Badges](https://img.shields.io/badge/...) +- Embedded videos (iframe allowlist: YouTube, Vimeo) +- HTML subset (safe tags only) + +## Organization-specific +- {{MEMBER_COUNT}} - Dynamic member count +- {{REPO_COUNT}} - Dynamic repo count +- {{PINNED_REPOS}} - Renders pinned repos widget +``` + +#### CSS Sandboxing + +```css +/* style.css - Allowed properties */ +.profile-content { + /* Typography */ + font-family: ...; /* From approved list */ + font-size: ...; + color: ...; + + /* Layout */ + margin: ...; + padding: ...; + + /* Backgrounds */ + background-color: ...; + background-image: url('./assets/...'); /* Local only */ + + /* Borders */ + border: ...; + border-radius: ...; +} + +/* Blocked: position:fixed, z-index manipulation, external URLs, + animations (except approved), JavaScript injection */ +``` + +#### UI Layout + +``` +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β”‚ β”‚ Acme Corporation β”‚ +β”‚ β”‚ [LOGO] β”‚ ━━━━━━━━━━━━━━━━ β”‚ +β”‚ β”‚ β”‚ "Building the future, one commit at a time" β”‚ +β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ +β”‚ β”‚ +β”‚ 🌐 acme.com πŸ“ San Francisco, CA πŸ“§ hello@acme.com β”‚ +β”‚ 🐦 @acmecorp πŸ’Ό 500+ employees β”‚ +β”‚ β”‚ +β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ β”‚ +β”‚ ## About Us β”‚ +β”‚ β”‚ +β”‚ We are a team of passionate developers building open source β”‚ +β”‚ tools that empower developers worldwide. Founded in 2015, β”‚ +β”‚ we've grown to become a leader in developer productivity. β”‚ +β”‚ β”‚ +β”‚ ### What We Do β”‚ +β”‚ β”‚ +β”‚ πŸš€ **Developer Tools** - IDE plugins, CLI utilities β”‚ +β”‚ πŸ”§ **Infrastructure** - Deployment, monitoring, scaling β”‚ +β”‚ πŸ“š **Education** - Tutorials, documentation, courses β”‚ +β”‚ β”‚ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β”‚ [TEAM PHOTO] β”‚ β”‚ +β”‚ β”‚ β”‚ β”‚ +β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ +β”‚ β”‚ +β”‚ ### Join Us β”‚ +β”‚ We're always looking for talented people! Check out our β”‚ +β”‚ [careers page](https://acme.com/careers). β”‚ +β”‚ β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` + +--- + +## 2. Repository Landing Pages (Gitea Pages) + +### Overview + +Repository owners can create a **standalone landing page** that acts as a public-facing project website. This page is independent of the repository's visibilityβ€”a private repo can have a public landing page. + +### Key Characteristics + +| Aspect | Specification | +|--------|---------------| +| **Independence** | Landing page visibility separate from repo visibility | +| **Domain** | Custom domain OR auto-generated subdomain | +| **SSL/TLS** | Automatic via Let's Encrypt | +| **Templates** | 4 built-in templates, switchable without data loss | +| **Configuration** | `.gitea/landing.yaml` (precedence) + DB fallback | + +### 2.1 Domain Mapping + +#### Option 1: Auto-Generated Subdomain + +``` +Format: {repo}.{owner}.pages.{gitea-domain} +Example: myproject.acme.pages.gitea.example.com +``` + +- Automatically available when landing page is enabled +- No DNS configuration required +- SSL certificate auto-provisioned + +#### Option 2: Custom Domain + +``` +User Configuration: +1. Add CNAME record: myproject.com β†’ pages.gitea.example.com +2. Configure domain in repo settings +3. SSL certificate auto-provisioned via Let's Encrypt +``` + +#### DNS Verification + +```go +// Verify domain ownership before enabling +type PagesDomain struct { + ID int64 `xorm:"pk autoincr"` + RepoID int64 `xorm:"INDEX NOT NULL"` + Domain string `xorm:"UNIQUE NOT NULL"` + Verified bool `xorm:"DEFAULT false"` + VerificationTXT string // TXT record for verification + SSLCertID string // Reference to cert storage + CreatedUnix timeutil.TimeStamp + VerifiedUnix timeutil.TimeStamp +} +``` + +### 2.2 Templates + +Four built-in templates with consistent configuration: + +#### Template 1: Simple + +Clean, minimal design focused on the README. + +``` +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ β”‚ +β”‚ [PROJECT LOGO] β”‚ +β”‚ β”‚ +β”‚ MyProject β”‚ +β”‚ "A better way to do things" β”‚ +β”‚ β”‚ +β”‚ [⬇️ Download v2.1.0] [πŸ“– View Docs] β”‚ +β”‚ β”‚ +β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ β”‚ +β”‚ # MyProject β”‚ +β”‚ β”‚ +β”‚ MyProject is a tool that helps you accomplish X faster and β”‚ +β”‚ more reliably than ever before. β”‚ +β”‚ β”‚ +β”‚ ## Installation β”‚ +β”‚ ```bash β”‚ +β”‚ npm install myproject β”‚ +β”‚ ``` β”‚ +β”‚ β”‚ +β”‚ ## Quick Start β”‚ +β”‚ ... β”‚ +β”‚ β”‚ +β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ ⭐ 2,341 stars β”‚ 🍴 456 forks β”‚ πŸ“ MIT License β”‚ v2.1.0 β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` + +#### Template 2: Documentation + +Sidebar navigation with documentation pages from `/docs` folder. + +``` +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ β”‚ β”‚ +β”‚ [Logo] β”‚ Getting Started β”‚ +β”‚ MyProject β”‚ ══════════════════════════════════════════════════ β”‚ +β”‚ β”‚ β”‚ +β”‚ πŸ” Search β”‚ Welcome to MyProject! This guide will walk you β”‚ +β”‚ β”‚ through installation and basic usage. β”‚ +β”‚ ────────── β”‚ β”‚ +β”‚ β”‚ ## Prerequisites β”‚ +β”‚ πŸ“– DOCS β”‚ β”‚ +β”‚ Getting β”‚ Before you begin, ensure you have: β”‚ +β”‚ Started ● β”‚ - Node.js 18+ β”‚ +β”‚ Install β”‚ - npm or yarn β”‚ +β”‚ Config β”‚ β”‚ +β”‚ Usage β”‚ ## Installation β”‚ +β”‚ β”‚ β”‚ +β”‚ πŸ“š API β”‚ ```bash β”‚ +β”‚ Overview β”‚ npm install -g myproject β”‚ +β”‚ Reference β”‚ ``` β”‚ +β”‚ Examples β”‚ β”‚ +β”‚ β”‚ ## Verify Installation β”‚ +β”‚ ────────── β”‚ β”‚ +β”‚ πŸ“¦ v2.1.0 β”‚ ```bash β”‚ +β”‚ ⭐ 2,341 β”‚ myproject --version β”‚ +β”‚ β”‚ ``` β”‚ +β”‚ [GitHub] β”‚ β”‚ +β”‚ [Discord] β”‚ [Next: Configuration β†’] β”‚ +β”‚ β”‚ β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` + +#### Template 3: Product + +Marketing-style landing page with features, screenshots, and CTAs. + +``` +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β”‚ +β”‚β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β”‚ +β”‚β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘ [HERO BACKGROUND] β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β”‚ +β”‚β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β”‚ +β”‚β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘ MyProject β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β”‚ +β”‚β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘ "Ship faster with confidence" β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β”‚ +β”‚β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β”‚ +β”‚β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘ [Get Started] [View Source] β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β”‚ +β”‚β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β”‚ +β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ β”‚ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β”‚ πŸš€ β”‚ β”‚ πŸ”’ β”‚ β”‚ πŸ”Œ β”‚ β”‚ +β”‚ β”‚ Blazing Fast β”‚ β”‚ Secure β”‚ β”‚ Extensible β”‚ β”‚ +β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ +β”‚ β”‚ Built on Rust β”‚ β”‚ SOC2 compliant β”‚ β”‚ Plugin system β”‚ β”‚ +β”‚ β”‚ for maximum β”‚ β”‚ with E2E β”‚ β”‚ with 200+ β”‚ β”‚ +β”‚ β”‚ performance β”‚ β”‚ encryption β”‚ β”‚ integrations β”‚ β”‚ +β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ +β”‚ β”‚ +β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ β”‚ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β”‚ β”‚ β”‚ +β”‚ β”‚ [SCREENSHOT/DEMO] β”‚ β”‚ +β”‚ β”‚ β”‚ β”‚ +β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ +β”‚ β”‚ +β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ β”‚ +β”‚ Latest Releases Contributors β”‚ +β”‚ ──────────────── ──────────── β”‚ +β”‚ πŸ“¦ v2.1.0 - Jan 8, 2026 [πŸ‘€][πŸ‘€][πŸ‘€][πŸ‘€][πŸ‘€] +47 β”‚ +β”‚ πŸ“¦ v2.0.2 - Dec 15, 2025 β”‚ +β”‚ πŸ“¦ v2.0.1 - Dec 1, 2025 Trusted by 10,000+ developers β”‚ +β”‚ β”‚ +β”‚ [⭐ Star on Gitea] β”‚ +β”‚ β”‚ +β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ [Home] [Docs] [Blog] [GitHub] [Discord] Β© 2026 Acme Corp β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` + +#### Template 4: Portfolio/Gallery + +Visual showcase for design, art, or media projects. + +``` +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ β”‚ +β”‚ Design System β”‚ +β”‚ "A visual component library" β”‚ +β”‚ β”‚ +β”‚ [View Components] [Download] β”‚ +β”‚ β”‚ +β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ β”‚ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ +β”‚ β”‚ [img 1] β”‚ β”‚ [img 2] β”‚ β”‚ [img 3] β”‚ β”‚ [img 4] β”‚ β”‚ +β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ +β”‚ β”‚ Buttons β”‚ β”‚ Forms β”‚ β”‚ Cards β”‚ β”‚ Modals β”‚ β”‚ +β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ +β”‚ β”‚ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ +β”‚ β”‚ [img 5] β”‚ β”‚ [img 6] β”‚ β”‚ [img 7] β”‚ β”‚ [img 8] β”‚ β”‚ +β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ +β”‚ β”‚ Tables β”‚ β”‚ Nav β”‚ β”‚ Icons β”‚ β”‚ Colors β”‚ β”‚ +β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ +β”‚ β”‚ +β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ β”‚ +β”‚ ## About This Project β”‚ +β”‚ β”‚ +β”‚ A comprehensive design system built for modern web applications. β”‚ +β”‚ Includes 50+ components, dark mode support, and full β”‚ +β”‚ accessibility compliance. β”‚ +β”‚ β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` + +### 2.3 Configuration + +Configuration lives in `.gitea/landing.yaml` with DB fallback. File takes precedence. + +#### Full Configuration Schema + +```yaml +# .gitea/landing.yaml +# Landing Page Configuration for Gitea Pages + +#────────────────────────────────────────────────────────────────────── +# BASIC SETTINGS +#────────────────────────────────────────────────────────────────────── + +enabled: true +template: product # simple | documentation | product | portfolio + +# Custom domain (optional - subdomain is always available) +domain: myproject.com + +#────────────────────────────────────────────────────────────────────── +# BRANDING +#────────────────────────────────────────────────────────────────────── + +branding: + logo: ./assets/logo.png + logo_dark: ./assets/logo-dark.png # Optional dark mode variant + favicon: ./assets/favicon.ico + + # Color scheme + primary_color: "#4a90d9" + secondary_color: "#2ecc71" + accent_color: "#e74c3c" + + # Theme + dark_mode: auto # auto | light | dark | both (toggle) + + # Custom fonts (from approved list) + heading_font: "Inter" + body_font: "system-ui" + +#────────────────────────────────────────────────────────────────────── +# HERO SECTION +#────────────────────────────────────────────────────────────────────── + +hero: + title: "MyProject" + tagline: "The best thing since sliced bread" + + # Background options + background: ./assets/hero-bg.jpg + # OR gradient: "linear-gradient(135deg, #667eea 0%, #764ba2 100%)" + # OR color: "#1a1a2e" + + # Call-to-action buttons + cta_primary: + text: "Get Started" + link: "#installation" + # OR link: releases/latest (auto-resolves to latest release) + + cta_secondary: + text: "View Documentation" + link: /docs + style: outline # outline | ghost + +#────────────────────────────────────────────────────────────────────── +# FEATURES (for product template) +#────────────────────────────────────────────────────────────────────── + +features: + - icon: rocket # Built-in icons: rocket, shield, puzzle, zap, etc. + title: "Blazingly Fast" + description: "Built with performance in mind from day one." + + - icon: shield + title: "Secure by Default" + description: "Enterprise-grade security out of the box." + + - icon: ./assets/custom-icon.svg # Custom icon + title: "Extensible" + description: "Plugin system for unlimited customization." + + - icon: puzzle + title: "Easy Integration" + description: "Works with your existing tools and workflows." + +#────────────────────────────────────────────────────────────────────── +# SECTIONS +#────────────────────────────────────────────────────────────────────── + +sections: + - type: features # Renders features array above + + - type: screenshot + image: ./assets/screenshot.png + caption: "MyProject in action" + + - type: readme + file: README.md # Default + + - type: releases + limit: 3 + show_notes: true # Show release notes excerpt + + - type: contributors + limit: 12 + show_count: true # "and 47 more contributors" + + - type: custom + file: ./docs/features.md + title: "Why MyProject?" + +#────────────────────────────────────────────────────────────────────── +# DOCUMENTATION (for documentation template) +#────────────────────────────────────────────────────────────────────── + +documentation: + source: ./docs # Folder containing markdown files + + # Search + search: true + + # Table of contents in each page + toc: true + + # Sidebar navigation + sidebar: + - title: "Getting Started" + items: + - intro.md + - installation.md + - quick-start.md + + - title: "Guides" + items: + - configuration.md + - deployment.md + - troubleshooting.md + + - title: "API Reference" + collapsed: true # Collapsed by default + items: + - api/overview.md + - api/authentication.md + - api/endpoints.md + + # "Edit this page" links + edit_links: + enabled: true + text: "Edit this page" + # Link auto-generated to repo file + +#────────────────────────────────────────────────────────────────────── +# GALLERY (for portfolio template) +#────────────────────────────────────────────────────────────────────── + +gallery: + source: ./gallery # Folder containing images + columns: 4 # 2, 3, or 4 + lightbox: true # Click to enlarge + captions: true # Show image filename as caption + + # Or explicit items: + items: + - image: ./gallery/buttons.png + title: "Button Components" + link: /docs/buttons + + - image: ./gallery/forms.png + title: "Form Elements" + link: /docs/forms + +#────────────────────────────────────────────────────────────────────── +# FOOTER +#────────────────────────────────────────────────────────────────────── + +footer: + # Link columns + links: + - title: "Resources" + items: + - text: "Documentation" + url: /docs + - text: "API Reference" + url: /docs/api + - text: "Examples" + url: /examples + + - title: "Community" + items: + - text: "Discord" + url: https://discord.gg/xxx + - text: "Twitter" + url: https://twitter.com/myproject + - text: "GitHub Discussions" + url: https://github.com/org/repo/discussions + + - title: "Company" + items: + - text: "About" + url: https://company.com/about + - text: "Blog" + url: https://company.com/blog + - text: "Careers" + url: https://company.com/careers + + # Copyright + copyright: "Β© 2026 Acme Corporation. Released under MIT License." + + # Show "Powered by Gitea" badge + show_powered_by: true + +#────────────────────────────────────────────────────────────────────── +# SEO & SOCIAL +#────────────────────────────────────────────────────────────────────── + +seo: + title: "MyProject - Ship Faster with Confidence" + description: "MyProject helps development teams ship code faster and more reliably." + keywords: + - developer tools + - productivity + - open source + + # Open Graph / Social sharing + og_image: ./assets/og-image.png + twitter_card: summary_large_image + twitter_site: "@myproject" + +#────────────────────────────────────────────────────────────────────── +# ANALYTICS (optional) +#────────────────────────────────────────────────────────────────────── + +analytics: + # Privacy-friendly options + plausible: myproject.com + # OR + umami: + website_id: "xxx" + url: "https://analytics.example.com" + # OR + google_analytics: "G-XXXXXXXXXX" + +#────────────────────────────────────────────────────────────────────── +# ADVANCED +#────────────────────────────────────────────────────────────────────── + +advanced: + # Custom CSS file + custom_css: ./assets/custom.css + + # Custom head content (limited HTML) + custom_head: | + + + # Redirects + redirects: + /old-docs: /docs + /github: https://github.com/org/repo +``` + +### 2.4 URL Structure & Routing + +#### Standalone Architecture + +Landing pages are **completely independent** of the repository view: + +``` +Landing Page: https://myproject.com + https://repo.owner.pages.gitea.example.com + +Repository: https://gitea.example.com/owner/repo + (May be private - landing page still accessible) +``` + +#### Routing Flow + +``` + β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” + Request ──────► β”‚ Gitea Router β”‚ + β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + β”‚ + β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” + β”‚ β”‚ β”‚ + β–Ό β–Ό β–Ό + β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” + β”‚ pages.gitea.com β”‚ β”‚ Custom β”‚ β”‚ gitea.example.com β”‚ + β”‚ *.pages.gitea.. β”‚ β”‚ Domain β”‚ β”‚ (main app) β”‚ + β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + β”‚ β”‚ + β–Ό β–Ό + β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” + β”‚ Pages Handler β”‚ + β”‚ - Lookup repo by domain β”‚ + β”‚ - Load .gitea/landing.yaml β”‚ + β”‚ - Render template β”‚ + β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` + +#### Navigation Between Landing and Repo + +The landing page is responsible for providing links to the source repository: + +```yaml +# In landing.yaml +hero: + cta_secondary: + text: "View Source" + link: https://gitea.example.com/owner/repo + +footer: + links: + - title: "Developers" + items: + - text: "Source Code" + url: https://gitea.example.com/owner/repo + - text: "Issues" + url: https://gitea.example.com/owner/repo/issues +``` + +--- + +## 3. Database Schema Changes + +### New Tables + +```sql +-- Organization pinned repositories +CREATE TABLE org_pinned_repo ( + id BIGINT PRIMARY KEY AUTO_INCREMENT, + org_id BIGINT NOT NULL, + repo_id BIGINT NOT NULL, + group_id BIGINT DEFAULT NULL, + display_order INT DEFAULT 0, + created_unix BIGINT, + FOREIGN KEY (org_id) REFERENCES organization(id), + FOREIGN KEY (repo_id) REFERENCES repository(id), + FOREIGN KEY (group_id) REFERENCES org_pinned_group(id), + UNIQUE KEY (org_id, repo_id) +); + +-- Organization pinned repo groups +CREATE TABLE org_pinned_group ( + id BIGINT PRIMARY KEY AUTO_INCREMENT, + org_id BIGINT NOT NULL, + name VARCHAR(255) NOT NULL, + display_order INT DEFAULT 0, + collapsed BOOLEAN DEFAULT FALSE, + FOREIGN KEY (org_id) REFERENCES organization(id) +); + +-- Pages domain mapping +CREATE TABLE pages_domain ( + id BIGINT PRIMARY KEY AUTO_INCREMENT, + repo_id BIGINT NOT NULL, + domain VARCHAR(255) NOT NULL UNIQUE, + verified BOOLEAN DEFAULT FALSE, + verification_token VARCHAR(64), + ssl_status VARCHAR(32) DEFAULT 'pending', + ssl_cert_expiry BIGINT, + created_unix BIGINT, + verified_unix BIGINT, + FOREIGN KEY (repo_id) REFERENCES repository(id) +); + +-- Pages configuration cache (parsed from .gitea/landing.yaml) +CREATE TABLE pages_config ( + id BIGINT PRIMARY KEY AUTO_INCREMENT, + repo_id BIGINT NOT NULL UNIQUE, + enabled BOOLEAN DEFAULT FALSE, + template VARCHAR(32) DEFAULT 'simple', + config_json TEXT, -- Cached parsed config + config_hash VARCHAR(64), -- For invalidation + updated_unix BIGINT, + FOREIGN KEY (repo_id) REFERENCES repository(id) +); +``` + +### Modified Tables + +```sql +-- Add to org_user table +ALTER TABLE org_user ADD COLUMN is_public BOOLEAN DEFAULT FALSE; + +-- Add to repository table +ALTER TABLE repository ADD COLUMN pages_enabled BOOLEAN DEFAULT FALSE; +ALTER TABLE repository ADD COLUMN pages_subdomain VARCHAR(255); +``` + +--- + +## 4. API Endpoints + +### Organization Profile API + +``` +# Pinned repos +GET /api/v1/orgs/{org}/pinned +POST /api/v1/orgs/{org}/pinned +PUT /api/v1/orgs/{org}/pinned/reorder +DELETE /api/v1/orgs/{org}/pinned/{repo} + +# Pinned groups +GET /api/v1/orgs/{org}/pinned/groups +POST /api/v1/orgs/{org}/pinned/groups +PUT /api/v1/orgs/{org}/pinned/groups/{id} +DELETE /api/v1/orgs/{org}/pinned/groups/{id} + +# Public members +GET /api/v1/orgs/{org}/public_members +PUT /api/v1/orgs/{org}/public_members/{username} # Opt-in +DELETE /api/v1/orgs/{org}/public_members/{username} # Opt-out + +# Profile content (via .profile repo) +# Uses standard repo file API +``` + +### Pages API + +``` +# Pages configuration +GET /api/v1/repos/{owner}/{repo}/pages +PUT /api/v1/repos/{owner}/{repo}/pages +DELETE /api/v1/repos/{owner}/{repo}/pages + +# Custom domains +GET /api/v1/repos/{owner}/{repo}/pages/domains +POST /api/v1/repos/{owner}/{repo}/pages/domains +DELETE /api/v1/repos/{owner}/{repo}/pages/domains/{domain} +POST /api/v1/repos/{owner}/{repo}/pages/domains/{domain}/verify + +# SSL certificates +GET /api/v1/repos/{owner}/{repo}/pages/domains/{domain}/ssl +POST /api/v1/repos/{owner}/{repo}/pages/domains/{domain}/ssl/renew +``` + +--- + +## 5. Implementation Phases + +### Phase 1: Organization Profile (4-6 weeks) + +1. **Week 1-2:** Database schema, models, migrations +2. **Week 2-3:** Pinned repos API and UI +3. **Week 3-4:** Public members opt-in system +4. **Week 4-5:** Profile content from `.profile` repo +5. **Week 5-6:** WYSIWYG editor integration, CSS sandboxing + +### Phase 2: Gitea Pages Foundation (6-8 weeks) + +1. **Week 1-2:** Pages router, subdomain handling +2. **Week 2-3:** Configuration parser (`.gitea/landing.yaml`) +3. **Week 3-4:** Simple template implementation +4. **Week 4-6:** Documentation template with sidebar +5. **Week 6-7:** Product and Portfolio templates +6. **Week 7-8:** Settings UI, template switching + +### Phase 3: Custom Domains & SSL (3-4 weeks) + +1. **Week 1:** Domain verification system +2. **Week 2:** Let's Encrypt integration +3. **Week 3:** DNS routing and Host header handling +4. **Week 4:** SSL certificate renewal, monitoring + +### Phase 4: Polish & Advanced Features (2-3 weeks) + +1. Analytics integration +2. Search functionality (docs template) +3. Image optimization +4. CDN integration options +5. Performance optimization + +--- + +## Appendix: File Structure + +### Organization `.profile` Repository + +``` +{org}/.profile/ +β”œβ”€β”€ README.md # Main profile content +β”œβ”€β”€ style.css # Optional custom CSS +└── assets/ + β”œβ”€β”€ logo.png + β”œβ”€β”€ logo-dark.png + β”œβ”€β”€ banner.jpg + └── team-photo.jpg +``` + +### Repository Landing Page + +``` +{repo}/ +β”œβ”€β”€ .gitea/ +β”‚ └── landing.yaml # Landing page configuration +β”œβ”€β”€ docs/ # Documentation (for docs template) +β”‚ β”œβ”€β”€ intro.md +β”‚ β”œβ”€β”€ installation.md +β”‚ └── api/ +β”‚ └── endpoints.md +β”œβ”€β”€ gallery/ # Images (for portfolio template) +β”‚ β”œβ”€β”€ screenshot1.png +β”‚ └── screenshot2.png +└── assets/ # Landing page assets + β”œβ”€β”€ logo.png + β”œβ”€β”€ favicon.ico + β”œβ”€β”€ hero-bg.jpg + β”œβ”€β”€ og-image.png + └── custom.css +``` + +--- + +*End of Specification*