example-content plugin, project website with screenshot
Example-content: footer button creates 20 realistic demo cards in a "Project Alpha" bucket for screenshots and first-time exploration. Website: full-page sections with large watermark labels, screenshot hero with typing animation, email/spam section, Gitea detail, relay encryption flow, keyboard keycaps, deploy options. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
b9345a410f
commit
9f85e484c4
8 files changed
+1207
-3
No files matched your search
@@ -0,0 +1,487 @@
|
||||
// ── Example content plugin — one-click demo data ──
|
||||
|
||||
const h = window.hyprcrd;
|
||||
const api = h?.api || window._exampleApi;
|
||||
|
||||
const COLORS = {
|
||||
blue: '#38bdf8', purple: '#a78bfa', pink: '#f472b6', red: '#fb7185',
|
||||
green: '#34d399', yellow: '#fbbf24', orange: '#fb923c', slate: '#64748b',
|
||||
};
|
||||
|
||||
const CARDS = [
|
||||
{
|
||||
title: 'Architecture RFC',
|
||||
color: COLORS.blue,
|
||||
body: `## System Architecture
|
||||
|
||||
The new microservice layout separates auth, data, and notification layers.
|
||||
|
||||
### Key decisions
|
||||
- PostgreSQL for persistent state
|
||||
- Redis for session cache + pub/sub
|
||||
- gRPC between internal services
|
||||
- REST + WebSocket for client API
|
||||
|
||||
### Open questions
|
||||
- [ ] Rate limiting strategy
|
||||
- [ ] Multi-region failover
|
||||
- [x] Auth token rotation scheme
|
||||
- [x] Database migration tooling
|
||||
|
||||
See also: [[Deploy checklist]]
|
||||
|
||||
#project/api #architecture`,
|
||||
},
|
||||
{
|
||||
title: 'Sprint Planning Q3',
|
||||
color: COLORS.purple,
|
||||
body: `## Goals
|
||||
|
||||
1. Finish API v3 migration
|
||||
2. Launch mobile auth flow
|
||||
3. Load testing at 10k concurrent
|
||||
4. Cut staging→prod deploy time to <5min
|
||||
|
||||
**Deadline:** 2026-07-01
|
||||
**Owner:** @alice
|
||||
|
||||
### Capacity
|
||||
| Team | Points | Allocated |
|
||||
|----------|--------|-----------|
|
||||
| Backend | 34 | 30 |
|
||||
| Frontend | 21 | 18 |
|
||||
| Infra | 13 | 13 |
|
||||
|
||||
#meeting #project`,
|
||||
},
|
||||
{
|
||||
title: 'Auth timeout on mobile',
|
||||
color: COLORS.red,
|
||||
body: `Users on iOS Safari report being logged out after ~3 minutes of inactivity.
|
||||
|
||||
### Repro
|
||||
1. Login on iPhone 15 (Safari 18)
|
||||
2. Switch to another app for 3 min
|
||||
3. Return → "session expired"
|
||||
|
||||
### Investigation
|
||||
- Cookie \`SameSite=Strict\` might be too aggressive
|
||||
- Safari's ITP may be purging the session cookie
|
||||
- Backend session TTL is 24h — not the issue
|
||||
|
||||
### Fix
|
||||
Try \`SameSite=Lax\` + short-lived refresh token.
|
||||
|
||||
#bug #urgent #project/frontend/auth`,
|
||||
},
|
||||
{
|
||||
title: 'Deploy checklist',
|
||||
color: COLORS.green,
|
||||
body: `- [x] Run full test suite
|
||||
- [x] Update CHANGELOG.md
|
||||
- [x] Bump version in config
|
||||
- [ ] Tag release in git
|
||||
- [ ] Build Docker image
|
||||
- [ ] Push to registry
|
||||
- [ ] Roll out to staging
|
||||
- [ ] Smoke test staging
|
||||
- [ ] Promote to production
|
||||
- [ ] Monitor Grafana for 30min
|
||||
|
||||
> Last deploy: 2026-04-08 by @bob
|
||||
> Rollback: \`git revert HEAD && ./deploy.sh\`
|
||||
|
||||
#ops #deploy`,
|
||||
},
|
||||
{
|
||||
title: 'Meeting 2026-04-15 — Retro',
|
||||
color: COLORS.yellow,
|
||||
due_date: '2026-04-15',
|
||||
body: `**Zeit:** 14:00-15:00
|
||||
**Ort:** Room 42
|
||||
**Teilnehmer:** Alice, Bob, Carol
|
||||
|
||||
---
|
||||
|
||||
### What went well
|
||||
- Deploy frequency improved (3x/week → daily)
|
||||
- Zero P1 incidents this sprint
|
||||
- New search feature got good feedback
|
||||
|
||||
### What to improve
|
||||
- PR review turnaround still >24h
|
||||
- Flaky integration tests causing false alarms
|
||||
- Documentation gaps in relay module
|
||||
|
||||
### Action items
|
||||
- [ ] @alice: set up PR review SLA
|
||||
- [ ] @bob: fix top 5 flaky tests
|
||||
- [ ] @carol: write relay onboarding doc
|
||||
|
||||
#meeting #termin #retro`,
|
||||
},
|
||||
{
|
||||
title: 'Reading list',
|
||||
color: COLORS.slate,
|
||||
body: `Papers and articles to read:
|
||||
|
||||
- [Designing Data-Intensive Applications](https://dataintensive.net/) — Ch. 7-9
|
||||
- [The Twelve-Factor App](https://12factor.net/)
|
||||
- \`CAP theorem revisited\` — Brewer 2012
|
||||
- Local-first software — Kleppmann et al.
|
||||
|
||||
### Notes
|
||||
> "The truth is the log. The database is a cache."
|
||||
> — Pat Helland
|
||||
|
||||
#personal #research`,
|
||||
},
|
||||
{
|
||||
title: 'API v3 migration',
|
||||
color: COLORS.blue,
|
||||
body: `### Endpoints to migrate
|
||||
|
||||
| v2 | v3 | Status |
|
||||
|----|-----|--------|
|
||||
| GET /users | GET /api/v3/users | done |
|
||||
| POST /auth | POST /api/v3/auth/token | done |
|
||||
| GET /cards | GET /api/v3/cards | in progress |
|
||||
| WS /stream | WS /api/v3/events | planned |
|
||||
|
||||
### Breaking changes
|
||||
- Auth header: \`Bearer\` instead of \`X-Token\`
|
||||
- Pagination: cursor-based instead of offset
|
||||
- Error format: \`{"error": {"code": ..., "message": ...}}\`
|
||||
|
||||
[[Architecture RFC]]
|
||||
|
||||
#project/api #migration`,
|
||||
},
|
||||
{
|
||||
title: 'Infra cost review',
|
||||
color: COLORS.orange,
|
||||
body: `### Monthly breakdown (April)
|
||||
|
||||
\`\`\`
|
||||
Compute (k8s) €340 ████████░░ 68%
|
||||
Storage (S3) €85 ██░░░░░░░░ 17%
|
||||
Database (RDS) €52 █░░░░░░░░░ 10%
|
||||
CDN + DNS €18 ░░░░░░░░░░ 4%
|
||||
Monitoring €8 ░░░░░░░░░░ 2%
|
||||
─────────────────────────────────────
|
||||
Total €503
|
||||
\`\`\`
|
||||
|
||||
Budget: €600 → **€97 headroom**
|
||||
|
||||
Next action: evaluate spot instances for batch workers.
|
||||
|
||||
#ops #infra #finance`,
|
||||
},
|
||||
{
|
||||
title: 'Birthday Alice',
|
||||
color: COLORS.pink,
|
||||
due_date: '2026-06-12',
|
||||
body: `#geburtstag`,
|
||||
},
|
||||
{
|
||||
title: 'Onboarding: new developer',
|
||||
color: COLORS.green,
|
||||
body: `## First week checklist
|
||||
|
||||
- [ ] Laptop + accounts provisioned
|
||||
- [ ] SSH key added to Gitea
|
||||
- [ ] Access to staging cluster
|
||||
- [x] Slack channels joined
|
||||
- [x] 1:1 with team lead
|
||||
- [ ] Read [[Architecture RFC]]
|
||||
- [ ] First PR: fix a good-first-issue
|
||||
|
||||
### Contacts
|
||||
| Role | Person |
|
||||
|------|--------|
|
||||
| Buddy | @carol |
|
||||
| Team lead | @alice |
|
||||
| Infra | @dave |
|
||||
|
||||
#onboarding #ops`,
|
||||
},
|
||||
{
|
||||
title: 'Competitive analysis',
|
||||
color: COLORS.purple,
|
||||
body: `### Landscape
|
||||
|
||||
| Product | Self-hosted | Offline | E2E encryption |
|
||||
|---------|:-----------:|:-------:|:--------------:|
|
||||
| Notion | no | no | no |
|
||||
| Obsidian| yes | yes | paid |
|
||||
| Logseq | yes | yes | no |
|
||||
| **hyprcrd** | **yes** | **yes** | **yes** |
|
||||
|
||||
### Differentiators
|
||||
- Tag extraction from body (zero-friction categorization)
|
||||
- Relay model: multi-tenant sync without cloud dependency
|
||||
- Plugin system: extensible without forking
|
||||
- CalDAV native (not just ical export)
|
||||
|
||||
#research #strategy`,
|
||||
},
|
||||
{
|
||||
title: 'Security audit notes',
|
||||
color: COLORS.red,
|
||||
body: `## Audit 2026-Q1 findings
|
||||
|
||||
### Critical
|
||||
~~1. Session token in URL parameter~~ → fixed in v1.2.1
|
||||
|
||||
### High
|
||||
2. CSRF token not rotated on privilege change → [[Auth timeout on mobile]]
|
||||
|
||||
### Medium
|
||||
3. Upload directory allows .svg (XSS vector)
|
||||
4. Rate limiter not applied to /api/export
|
||||
|
||||
### Low
|
||||
5. Server version exposed in HTTP headers
|
||||
6. No CSP header on main app
|
||||
|
||||
> Next audit scheduled: 2026-07-15
|
||||
|
||||
#security #audit #urgent`,
|
||||
},
|
||||
{
|
||||
title: 'Design system tokens',
|
||||
color: COLORS.purple,
|
||||
body: `### Color palette
|
||||
|
||||
\`\`\`
|
||||
--t-bg: #0f172a base background
|
||||
--t-surface: #1e293b card/panel surface
|
||||
--t-border: #334155 borders
|
||||
--t-text: #94a3b8 body text
|
||||
--t-bright: #e2e8f0 headlines
|
||||
--t-accent: #38bdf8 primary accent
|
||||
--t-accent2: #a78bfa secondary accent
|
||||
--t-danger: #fb7185 errors/destructive
|
||||
\`\`\`
|
||||
|
||||
### Typography
|
||||
- **UI:** Silkscreen (pixel font)
|
||||
- **Content:** JetBrains Mono
|
||||
- **Sizes:** 9px labels, 11px body, 13px headings
|
||||
|
||||
### Radius scale
|
||||
\`--ui-radius-card\`, \`--ui-radius-modal\`, \`--ui-radius-input\`
|
||||
|
||||
All overridable per theme preset.
|
||||
|
||||
#design #frontend`,
|
||||
},
|
||||
{
|
||||
title: 'Customer feedback digest',
|
||||
color: COLORS.yellow,
|
||||
body: `### Week of 2026-04-07
|
||||
|
||||
**Positive:**
|
||||
- "Search is blazing fast" — 3 mentions
|
||||
- "CalDAV sync just works" — 2 mentions
|
||||
- "Love the keyboard shortcuts" — @user42
|
||||
|
||||
**Requests:**
|
||||
- Mobile app (→ Electron PWA?)
|
||||
- Shared boards without relay (→ collab-buckets?)
|
||||
- Dark mode for relay UI (→ already shipped!)
|
||||
|
||||
**Issues:**
|
||||
- Image upload fails >5MB on shared hosting
|
||||
- Calendar popup overlaps on 13" screens
|
||||
|
||||
#feedback #product`,
|
||||
},
|
||||
{
|
||||
title: 'Database schema notes',
|
||||
color: COLORS.slate,
|
||||
body: `### Core tables
|
||||
|
||||
\`\`\`sql
|
||||
cards (id, title, body, color, tags,
|
||||
bucket_id, parent_id, position,
|
||||
due_date, relay_uid,
|
||||
created_at, updated_at)
|
||||
|
||||
buckets (id, name, color, parent_id,
|
||||
collab_uid, position)
|
||||
|
||||
settings (key, value)
|
||||
\`\`\`
|
||||
|
||||
### Indexes
|
||||
- \`cards.bucket_id\` — bucket filter
|
||||
- \`cards.parent_id\` — group lookup
|
||||
- \`buckets.collab_uid UNIQUE\` — relay sync
|
||||
|
||||
SQLite WAL mode for concurrent reads.
|
||||
|
||||
#architecture #database`,
|
||||
},
|
||||
{
|
||||
title: 'Release notes v1.3',
|
||||
color: COLORS.green,
|
||||
body: `## What's new
|
||||
|
||||
### Features
|
||||
- **Tooltip system** — custom styled tooltips replace all native titles
|
||||
- **Asset picker** — thumbnail grid in the editor toolbar
|
||||
- **Super-bucket split** — click activates, caret opens dropdown
|
||||
- **Watch plugin** — analog clock overlay with SVG watchface
|
||||
- **Card peek** — hover preview with rendered markdown
|
||||
|
||||
### Fixes
|
||||
- Shortcuts no longer fire when typing in inputs
|
||||
- Gallery opens even if API fetch fails
|
||||
- Relay poll suppressed during user actions
|
||||
- Find/replace integrated into search overlay
|
||||
|
||||
### Breaking
|
||||
- All \`title=""\` attributes migrated to \`data-tip=""\`
|
||||
|
||||
#release #changelog`,
|
||||
},
|
||||
{
|
||||
title: '2026-04-12',
|
||||
color: COLORS.slate,
|
||||
body: `## Journal
|
||||
|
||||
Started the day reviewing PRs. Merged the tooltip system and the asset picker.
|
||||
|
||||
Spent the afternoon on the Electron build — static PHP binary works but the WAL/SHM files caused issues. Fixed by deleting stale lock files.
|
||||
|
||||
Had a good session on the watch plugin. The wobble animation on the second hand is a nice touch.
|
||||
|
||||
**Tomorrow:**
|
||||
- [ ] Test relay collab-buckets with two instances
|
||||
- [ ] Write release notes
|
||||
- [ ] Screenshot for website
|
||||
|
||||
#journal`,
|
||||
},
|
||||
{
|
||||
title: 'Backup strategy',
|
||||
color: COLORS.orange,
|
||||
body: `### Current
|
||||
|
||||
Daily cron:
|
||||
\`\`\`bash
|
||||
#!/bin/bash
|
||||
DATE=$(date +%Y-%m-%d)
|
||||
cp data/hyprcrd.db "/backup/hyprcrd-$DATE.db"
|
||||
tar czf "/backup/uploads-$DATE.tar.gz" public/uploads/
|
||||
find /backup -mtime +30 -delete
|
||||
\`\`\`
|
||||
|
||||
### Planned
|
||||
- [ ] Automated export ZIP via API
|
||||
- [ ] Offsite copy to S3-compatible storage
|
||||
- [ ] Test restore monthly
|
||||
- [ ] Document in runbook
|
||||
|
||||
> WAL checkpoint before copy:
|
||||
> \`sqlite3 data/hyprcrd.db "PRAGMA wal_checkpoint(TRUNCATE);"\`
|
||||
|
||||
#ops #backup #infra`,
|
||||
},
|
||||
{
|
||||
title: 'Plugin ideas',
|
||||
color: COLORS.pink,
|
||||
body: `### Brainstorm
|
||||
|
||||
- **Kanban columns** — cards as swimlanes per bucket
|
||||
- **Time tracking** — start/stop timer per card, weekly report
|
||||
- **AI summary** — auto-generate card summaries with local LLM
|
||||
- **RSS reader** — fetch feeds into cards
|
||||
- **Webhook triggers** — POST on card create/update/delete
|
||||
- **PDF export** — render card as styled PDF
|
||||
- **Voice memo** — record audio, attach to card, transcribe
|
||||
|
||||
### Criteria for inclusion
|
||||
1. Does it help *find* information?
|
||||
2. Can it be a drop-in plugin (no core changes)?
|
||||
3. Is it useful without an internet connection?
|
||||
|
||||
#idea #plugins #brainstorm`,
|
||||
},
|
||||
{
|
||||
title: 'Monitoring setup',
|
||||
color: COLORS.green,
|
||||
body: `### Stack
|
||||
|
||||
- **Uptime:** UptimeRobot (free tier, 5min interval)
|
||||
- **Errors:** Sentry self-hosted → \`sentry.internal\`
|
||||
- **Metrics:** Grafana + Prometheus
|
||||
- **Logs:** Loki + promtail on each node
|
||||
|
||||
### Alerts
|
||||
| Metric | Threshold | Channel |
|
||||
|--------|-----------|---------|
|
||||
| HTTP 5xx rate | >1% for 5min | Slack #ops-alerts |
|
||||
| Response time p95 | >2s for 10min | Slack #ops-alerts |
|
||||
| Disk usage | >85% | Email + Slack |
|
||||
| SSL expiry | <14 days | Email |
|
||||
|
||||
Dashboard: \`grafana.internal/d/hyprcrd\`
|
||||
|
||||
#ops #monitoring #infra`,
|
||||
},
|
||||
];
|
||||
|
||||
async function generate() {
|
||||
const bucket = await api('api/buckets', { method: 'POST', body: { name: 'Project Alpha' } });
|
||||
const bid = bucket?.id;
|
||||
if (!bid) return false;
|
||||
await api(`api/buckets/${bid}`, { method: 'PATCH', body: { color: COLORS.blue } });
|
||||
|
||||
for (const c of CARDS) {
|
||||
await api('api/cards', {
|
||||
method: 'POST',
|
||||
body: { title: c.title, body: c.body, color: c.color, bucket_id: bid, due_date: c.due_date || null },
|
||||
});
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function init() {
|
||||
const footer = document.getElementById('main-footer');
|
||||
if (!footer) return;
|
||||
|
||||
const btn = document.createElement('button');
|
||||
btn.className = 'flex items-center gap-1.5 px-2.5 py-1 text-xs border border-t-border text-t-muted hover:border-t-accent hover:text-t-accent transition-colors';
|
||||
btn.innerHTML = '<i class="ph ph-flask text-sm"></i><span class="font-pixel text-[10px]">Demo</span>';
|
||||
btn.dataset.tip = 'Create example bucket with demo cards';
|
||||
|
||||
btn.addEventListener('click', async () => {
|
||||
btn.disabled = true;
|
||||
btn.innerHTML = '<i class="ph ph-spinner text-sm"></i><span class="font-pixel text-[10px]">creating...</span>';
|
||||
const ok = await generate();
|
||||
if (ok) {
|
||||
btn.innerHTML = '<i class="ph ph-check text-sm"></i><span class="font-pixel text-[10px]">Done</span>';
|
||||
await window._reloadAll?.();
|
||||
} else {
|
||||
btn.innerHTML = '<i class="ph ph-x text-sm"></i><span class="font-pixel text-[10px]">Failed</span>';
|
||||
}
|
||||
setTimeout(() => {
|
||||
btn.innerHTML = '<i class="ph ph-flask text-sm"></i><span class="font-pixel text-[10px]">Demo</span>';
|
||||
btn.disabled = false;
|
||||
}, 2000);
|
||||
});
|
||||
|
||||
const firstChild = footer.querySelector('div');
|
||||
if (firstChild) firstChild.appendChild(btn);
|
||||
|
||||
h?.registerPlugin({ name: 'example-content', version: '1.0.0' });
|
||||
}
|
||||
|
||||
if (document.readyState === 'loading') {
|
||||
document.addEventListener('DOMContentLoaded', init);
|
||||
} else {
|
||||
init();
|
||||
}
|
||||
Reference in new issue
Block a user