diff --git a/docs/CNAME b/docs/CNAME new file mode 100644 index 0000000..e2b44d5 --- /dev/null +++ b/docs/CNAME @@ -0,0 +1 @@ +jcli.tutunak.com diff --git a/docs/assets/favicon.svg b/docs/assets/favicon.svg new file mode 100644 index 0000000..a4478c2 --- /dev/null +++ b/docs/assets/favicon.svg @@ -0,0 +1,4 @@ + + + j> + diff --git a/docs/css/style.css b/docs/css/style.css new file mode 100644 index 0000000..d529510 --- /dev/null +++ b/docs/css/style.css @@ -0,0 +1,494 @@ +:root { + --bg-primary: #0d1117; + --bg-secondary: #161b22; + --bg-tertiary: #21262d; + --text-primary: #e6edf3; + --text-secondary: #8b949e; + --accent: #58a6ff; + --accent-green: #3fb950; + --border: #30363d; +} + +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} + +html { + scroll-behavior: smooth; +} + +body { + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif; + background-color: var(--bg-primary); + color: var(--text-primary); + line-height: 1.6; +} + +.container { + max-width: 900px; + margin: 0 auto; + padding: 0 24px; +} + +/* Header */ +.site-header { + position: fixed; + top: 0; + left: 0; + right: 0; + background: rgba(13, 17, 23, 0.9); + backdrop-filter: blur(12px); + border-bottom: 1px solid var(--border); + z-index: 100; +} + +.header-content { + display: flex; + align-items: center; + justify-content: space-between; + height: 60px; +} + +.logo { + font-family: 'SF Mono', 'Fira Code', 'Consolas', monospace; + font-size: 1.25rem; + font-weight: 700; + color: var(--text-primary); + text-decoration: none; +} + +.logo:hover { + color: var(--accent); +} + +.site-header nav { + display: flex; + align-items: center; + gap: 24px; +} + +.nav-link { + color: var(--text-secondary); + text-decoration: none; + font-size: 0.9rem; + transition: color 0.2s; +} + +.nav-link:hover { + color: var(--text-primary); +} + +.nav-home { + color: var(--accent); +} + +.nav-home:hover { + color: var(--accent-green); +} + +/* Hero Section */ +.hero { + padding: 140px 0 80px; + text-align: center; +} + +.hero h1 { + font-size: clamp(2rem, 5vw, 3rem); + font-weight: 600; + margin-bottom: 16px; + letter-spacing: -0.02em; +} + +.tagline { + font-size: 1.25rem; + color: var(--text-secondary); + margin-bottom: 40px; +} + +.install-box { + display: inline-flex; + align-items: center; + background: var(--bg-secondary); + border: 1px solid var(--border); + border-radius: 8px; + padding: 12px 16px; + gap: 12px; +} + +.install-box code { + font-family: 'SF Mono', 'Fira Code', 'Consolas', monospace; + font-size: 0.95rem; + color: var(--accent-green); +} + +.copy-btn { + background: none; + border: none; + color: var(--text-secondary); + cursor: pointer; + padding: 4px; + display: flex; + align-items: center; + transition: color 0.2s; +} + +.copy-btn:hover { + color: var(--text-primary); +} + +.copy-btn svg { + width: 18px; + height: 18px; +} + +.copy-btn .hidden { + display: none; +} + +.copy-btn.copied .icon-copy { + display: none; +} + +.copy-btn.copied .icon-check { + display: block; + color: var(--accent-green); +} + +/* Problem Section */ +.problem { + padding: 60px 0; + text-align: center; +} + +.problem-text { + font-size: 1.1rem; + color: var(--text-secondary); + line-height: 2; + font-style: italic; +} + +/* Terminal Demo */ +.demo { + padding: 40px 0 80px; +} + +.terminal { + background: var(--bg-secondary); + border: 1px solid var(--border); + border-radius: 12px; + overflow: hidden; + box-shadow: 0 16px 48px rgba(0, 0, 0, 0.4); +} + +.terminal-header { + background: var(--bg-tertiary); + padding: 12px 16px; + display: flex; + align-items: center; + gap: 8px; +} + +.terminal-dot { + width: 12px; + height: 12px; + border-radius: 50%; +} + +.terminal-dot.red { background: #ff5f56; } +.terminal-dot.yellow { background: #ffbd2e; } +.terminal-dot.green { background: #27c93f; } + +.terminal-title { + margin-left: auto; + margin-right: auto; + color: var(--text-secondary); + font-size: 0.85rem; +} + +.terminal-body { + padding: 24px; + font-family: 'SF Mono', 'Fira Code', 'Consolas', monospace; + font-size: 0.9rem; + min-height: 280px; + position: relative; +} + +.terminal-body pre { + margin: 0; + white-space: pre-wrap; +} + +.cursor { + display: inline-block; + width: 8px; + height: 18px; + background: var(--text-primary); + animation: blink 1s step-end infinite; + vertical-align: text-bottom; +} + +@keyframes blink { + 50% { opacity: 0; } +} + +.prompt { color: var(--accent-green); } +.command { color: var(--text-primary); } +.output { color: var(--text-secondary); } +.highlight { color: var(--accent); } +.selected { color: var(--accent-green); } + +/* Features Section */ +.features { + padding: 80px 0; +} + +.feature-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); + gap: 24px; +} + +.feature-card { + background: var(--bg-secondary); + border: 1px solid var(--border); + border-radius: 12px; + padding: 32px 24px; + text-align: center; + transition: border-color 0.2s; +} + +.feature-card:hover { + border-color: var(--accent); +} + +.feature-card h3 { + font-size: 0.85rem; + letter-spacing: 0.1em; + color: var(--accent); + margin-bottom: 16px; +} + +.feature-card p { + color: var(--text-secondary); + margin-bottom: 20px; + font-size: 0.95rem; +} + +.feature-card code { + display: inline-block; + background: var(--bg-primary); + padding: 8px 16px; + border-radius: 6px; + font-family: 'SF Mono', 'Fira Code', 'Consolas', monospace; + font-size: 0.85rem; + color: var(--accent-green); +} + +/* Installation Section */ +.installation { + padding: 80px 0; + background: var(--bg-secondary); +} + +.installation h2 { + text-align: center; + margin-bottom: 32px; + font-size: 1.75rem; +} + +.tabs { + display: flex; + justify-content: center; + gap: 8px; + margin-bottom: 24px; +} + +.tab { + background: none; + border: 1px solid var(--border); + color: var(--text-secondary); + padding: 10px 24px; + border-radius: 6px; + cursor: pointer; + font-size: 0.9rem; + transition: all 0.2s; +} + +.tab:hover { + color: var(--text-primary); + border-color: var(--text-secondary); +} + +.tab.active { + background: var(--accent); + border-color: var(--accent); + color: var(--bg-primary); +} + +.tab-content { + display: none; + background: var(--bg-primary); + border: 1px solid var(--border); + border-radius: 8px; + padding: 24px; + max-width: 600px; + margin: 0 auto; +} + +.tab-content.active { + display: block; +} + +.tab-content pre { + margin: 0; +} + +.tab-content code { + font-family: 'SF Mono', 'Fira Code', 'Consolas', monospace; + font-size: 0.9rem; + line-height: 1.8; +} + +.tab-content .comment { + color: var(--text-secondary); +} + +/* Workflow Section */ +.workflow { + padding: 80px 0; +} + +.workflow h2 { + text-align: center; + margin-bottom: 48px; + font-size: 1.75rem; +} + +.workflow-steps { + display: flex; + flex-direction: column; + gap: 24px; + max-width: 600px; + margin: 0 auto; +} + +.workflow-step { + display: flex; + align-items: flex-start; + gap: 20px; +} + +.step-number { + flex-shrink: 0; + width: 36px; + height: 36px; + background: var(--accent); + color: var(--bg-primary); + border-radius: 50%; + display: flex; + align-items: center; + justify-content: center; + font-weight: 600; + font-size: 0.9rem; +} + +.step-content { + flex: 1; +} + +.step-content p { + color: var(--text-secondary); + margin-bottom: 8px; +} + +.step-content code { + display: inline-block; + background: var(--bg-secondary); + border: 1px solid var(--border); + padding: 8px 16px; + border-radius: 6px; + font-family: 'SF Mono', 'Fira Code', 'Consolas', monospace; + font-size: 0.85rem; + color: var(--accent-green); +} + +/* Footer */ +footer { + padding: 48px 0; + text-align: center; + border-top: 1px solid var(--border); +} + +.footer-links { + display: flex; + align-items: center; + justify-content: center; + gap: 16px; + margin-bottom: 16px; +} + +.footer-link { + display: inline-flex; + align-items: center; + gap: 6px; + color: var(--text-secondary); + text-decoration: none; + font-size: 0.9rem; + transition: color 0.2s; +} + +.footer-link:hover { + color: var(--accent); +} + +.footer-divider { + color: var(--border); +} + +.license { + color: var(--text-secondary); + font-size: 0.8rem; +} + +/* Responsive */ +@media (max-width: 600px) { + .header-content { + height: 52px; + } + + .site-header nav { + gap: 16px; + } + + .nav-link { + font-size: 0.85rem; + } + + .hero { + padding: 100px 0 60px; + } + + .install-box { + flex-direction: column; + width: 100%; + max-width: 320px; + } + + .terminal-body { + font-size: 0.8rem; + padding: 16px; + min-height: 240px; + } + + .feature-grid { + grid-template-columns: 1fr; + } + + .workflow-step { + flex-direction: column; + align-items: center; + text-align: center; + } +} diff --git a/docs/index.html b/docs/index.html new file mode 100644 index 0000000..dbea31c --- /dev/null +++ b/docs/index.html @@ -0,0 +1,174 @@ + + + + + + jcli - Jira without leaving your terminal + + + + + + + + + +
+
+

Jira without leaving your terminal.

+

Select issues. Track work. Generate branches. Stay in flow.

+
+ go install github.com/tutunak/jcli@latest + +
+
+
+ + +
+
+

+ Every browser tab is a broken promise.
+ Open Jira. Find the ticket. Copy the key.
+ Switch back. Remember what you were doing. +

+
+
+ + +
+
+
+
+ + + + terminal +
+
+

+                    
+                
+
+
+
+ + +
+
+
+
+

SELECT

+

Interactive issue selection from your assigned tasks

+ jcli issue select +
+
+

TRACK

+

Current issue tracking persists across sessions

+ jcli issue current +
+
+

BRANCH

+

Smart branch names from issue key and summary

+ jcli issue branch +
+
+
+
+ + +
+
+

Get Started

+
+ + +
+
+
# Install jcli
+go install github.com/tutunak/jcli@latest
+
+# Configure your Jira credentials
+jcli config credentials
+
+# Set your default project
+jcli config project MYPROJ
+
+
+
# Clone the repository
+git clone https://github.com/tutunak/jcli.git
+cd jcli
+
+# Build and install
+make build
+mv jcli /usr/local/bin/
+
+
+
+ + +
+
+

Daily Workflow

+
+
+ 1 +
+

Start your day by selecting an issue

+ jcli issue select +
+
+
+ 2 +
+

Create a branch for your work

+ git checkout -b $(jcli issue branch) +
+
+
+ 3 +
+

Check your current issue anytime

+ jcli issue current +
+
+
+
+
+ + + + + + + diff --git a/docs/js/terminal.js b/docs/js/terminal.js new file mode 100644 index 0000000..d0c3d31 --- /dev/null +++ b/docs/js/terminal.js @@ -0,0 +1,99 @@ +// Terminal typewriter animation +const sequences = [ + { text: '$ ', class: 'prompt', delay: 0 }, + { text: 'jcli issue select', class: 'command', delay: 50 }, + { text: '\n', delay: 400 }, + { text: '? Select an issue\n', class: 'output', delay: 30 }, + { text: '> ', class: 'selected', delay: 0 }, + { text: 'PROJ-123: Implement user authentication\n', class: 'selected', delay: 0 }, + { text: ' PROJ-124: Fix login redirect bug\n', class: 'output', delay: 0 }, + { text: ' PROJ-125: Add password reset flow\n', class: 'output', delay: 0 }, + { text: '\n', delay: 1500 }, + { text: '✓ Selected PROJ-123\n\n', class: 'selected', delay: 0 }, + { text: '$ ', class: 'prompt', delay: 500 }, + { text: 'git checkout -b $(jcli issue branch)', class: 'command', delay: 40 }, + { text: '\n', delay: 400 }, + { text: "Switched to a new branch '", class: 'output', delay: 0 }, + { text: 'PROJ-123-implement-user-authentication-847291', class: 'highlight', delay: 0 }, + { text: "'\n\n", class: 'output', delay: 0 }, + { text: '$ ', class: 'prompt', delay: 800 }, + { text: 'jcli issue current', class: 'command', delay: 50 }, + { text: '\n', delay: 400 }, + { text: 'PROJ-123', class: 'highlight', delay: 0 }, + { text: ': Implement user authentication\n', class: 'output', delay: 0 }, +]; + +const terminalOutput = document.getElementById('terminal-output'); +const cursor = document.querySelector('.cursor'); +let currentSequence = 0; +let currentChar = 0; +let isTyping = false; + +function typeWriter() { + if (currentSequence >= sequences.length) { + // Reset and loop + setTimeout(() => { + terminalOutput.innerHTML = ''; + currentSequence = 0; + currentChar = 0; + typeWriter(); + }, 3000); + return; + } + + const seq = sequences[currentSequence]; + + if (currentChar === 0 && seq.delay > 0) { + setTimeout(() => { + currentChar = 0; + typeCharacter(); + }, seq.delay); + } else { + typeCharacter(); + } +} + +function typeCharacter() { + const seq = sequences[currentSequence]; + + if (currentChar < seq.text.length) { + const span = document.createElement('span'); + span.className = seq.class || ''; + span.textContent = seq.text[currentChar]; + terminalOutput.appendChild(span); + currentChar++; + + const charDelay = seq.delay || 30; + setTimeout(typeCharacter, charDelay); + } else { + currentSequence++; + currentChar = 0; + setTimeout(typeWriter, 100); + } +} + +// Copy to clipboard functionality +function copyInstall() { + const cmd = document.getElementById('install-cmd').textContent; + navigator.clipboard.writeText(cmd).then(() => { + const btn = document.querySelector('.copy-btn'); + btn.classList.add('copied'); + setTimeout(() => btn.classList.remove('copied'), 2000); + }); +} + +// Tab switching +document.querySelectorAll('.tab').forEach(tab => { + tab.addEventListener('click', () => { + document.querySelectorAll('.tab').forEach(t => t.classList.remove('active')); + document.querySelectorAll('.tab-content').forEach(c => c.classList.remove('active')); + + tab.classList.add('active'); + document.getElementById(tab.dataset.tab).classList.add('active'); + }); +}); + +// Start animation when page loads +document.addEventListener('DOMContentLoaded', () => { + setTimeout(typeWriter, 500); +});