Files
hyprcrd/public/plugins/example-content/example-content.js
T
thandClaude Opus 4.6 9f85e484c4 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>
2026-04-12 23:54:43 +02:00

488 lines
13 KiB
JavaScript

// ── 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();
}