2
0

feat(socialcard): add unsplash integration and improve image cards
Some checks failed
Build and Release / Create Release (push) Successful in 0s
Build and Release / Integration Tests (PostgreSQL) (push) Successful in 2m36s
Build and Release / Lint (push) Successful in 5m19s
Build and Release / Unit Tests (push) Successful in 5m24s
Build and Release / Build Binaries (amd64, linux, linux-latest) (push) Successful in 2m56s
Build and Release / Build Binaries (amd64, windows, windows-latest) (push) Successful in 9h4m44s
Build and Release / Build Binaries (arm64, darwin, macos) (push) Successful in 8m5s
Build and Release / Build Binaries (amd64, darwin, macos) (push) Successful in 8m29s
Build and Release / Build Binary (linux/arm64) (push) Has been cancelled

Add Unsplash API integration documentation to README with setup instructions. Adjust image card gradient scrim to cover bottom 50% with increased opacity (240) for better text readability. Set correct OpenGraph image dimensions (1080x1350) for portrait card formats. Improve Unsplash selection UX with status messages and page reload after successful image download.
This commit is contained in:
2026-01-31 00:39:46 -05:00
parent 3c98948218
commit d3aa4508e7
4 changed files with 41 additions and 12 deletions

View File

@@ -32,6 +32,7 @@ The AI-native Git platform. Self-hosted, fast, and designed for the age of AI-as
- [AI Features Configuration](#ai-features-configuration)
- [Authentication Sources](#authentication-sources)
- [Email/SMTP Setup](#emailsmtp-setup)
- [Unsplash Integration](#unsplash-integration)
- [Usage](#usage)
- [Repository Operations](#repository-operations)
- [Project Management](#project-management)
@@ -549,6 +550,25 @@ USER = your-email@gmail.com
PASSWD = your-app-password
```
### Unsplash Integration
Enable Unsplash image search for repository social card backgrounds (Media Kit). This allows repository admins to search and select high-quality background images directly from Unsplash.
```ini
[unsplash]
; Enable Unsplash integration for Media Kit background images
ENABLED = true
; Unsplash API access key (get one at https://unsplash.com/developers)
ACCESS_KEY = your_unsplash_access_key
```
To obtain an access key:
1. Create an account at [unsplash.com/developers](https://unsplash.com/developers)
2. Create a new application
3. Copy the **Access Key** (the Secret Key is not needed)
When enabled, repository admins can search Unsplash from **Settings > Media Kit** when using the "Background Image" social card style. Attribution is handled automatically per Unsplash API guidelines.
## Usage
### Repository Operations

View File

@@ -378,9 +378,9 @@ func (r *Renderer) renderImageCard(data CardData) ([]byte, error) {
fillRect(img, img.Bounds(), ThemeDark.Background)
}
// Strong gradient scrim over bottom 45%
scrimStartY := h * 55 / 100
drawGradientScrim(img, scrimStartY, h, 220)
// Strong gradient scrim over bottom 50%
scrimStartY := h * 50 / 100
drawGradientScrim(img, scrimStartY, h, 240)
// White text on scrim
titleColor := color.RGBA{R: 255, G: 255, B: 255, A: 255}

View File

@@ -33,8 +33,13 @@
{{end}}
<meta property="og:type" content="object">
<meta property="og:image" content="{{AppUrl}}{{.Repository.OwnerName}}/{{.Repository.Name}}/social-preview">
{{if or (eq .Repository.SocialCardTheme "solid") (eq .Repository.SocialCardTheme "image")}}
<meta property="og:image:width" content="1080">
<meta property="og:image:height" content="1350">
{{else}}
<meta property="og:image:width" content="1200">
<meta property="og:image:height" content="630">
{{end}}
<meta property="og:image:type" content="image/png">
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:image" content="{{AppUrl}}{{.Repository.OwnerName}}/{{.Repository.Name}}/social-preview">

View File

@@ -200,6 +200,11 @@
el.style.borderColor = 'var(--color-primary)';
el.style.opacity = '0.7';
el.style.pointerEvents = 'none';
// Show a status message
const statusEl = document.createElement('div');
statusEl.textContent = 'Downloading image…';
statusEl.style.cssText = 'padding:8px;color:var(--color-text);font-size:13px;';
resultsDiv.parentNode.insertBefore(statusEl, resultsDiv.nextSibling);
try {
const csrf = document.querySelector('input[name="_csrf"]').value;
const fd = new FormData();
@@ -209,16 +214,15 @@
fd.append('url', photo.regular);
const resp = await fetch('{{.Link}}/unsplash/select', {method: 'POST', body: fd});
if (resp.ok) {
// Switch radio to "image" and update UI
const imageRadio = document.querySelector('.style-radio[value="image"]');
if (imageRadio) {
imageRadio.checked = true;
updateButtonStyles();
solidOpts.style.display = 'none';
imageOpts.style.display = '';
}
updatePreview();
statusEl.textContent = 'Image saved! Reloading…';
window.location.reload();
} else {
statusEl.textContent = 'Failed to save image. Please try again.';
statusEl.style.color = 'var(--color-error)';
}
} catch (e) {
statusEl.textContent = 'Network error. Please try again.';
statusEl.style.color = 'var(--color-error)';
} finally {
el.style.opacity = '1';
el.style.pointerEvents = '';