Changes to firstissue.scroll.pub

root
root
25 days ago
Initial commit
body.html
Changed around line 1
+
+

FirstIssue

+

Discover your perfect first open source contribution

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

Analyzing your interests...

+
+
+
+

+
+
+
+

Recommended Projects

+
+
+
+
+
+
+

Made with 💝 for the open source community

+

This tool helps match developers with beginner-friendly issues based on their GitHub interests

+
index.scroll
Changed around line 1
+ buildHtml
+ baseUrl https://firstissue.scroll.pub
+ metaTags
+ description Find open source projects to contribute to based on your GitHub interests
+ keywords github, open source, first issue, good first issue, contribute, beginner friendly
+ editButton /edit.html
+ title FirstIssue - Find Your Perfect First Open Source Contribution
+ style.css
+ body.html
+ script.js
prompt.json
Changed around line 1
+ {
+ "id": "msg_019XwgGkF73iNBnnzHskSHkJ",
+ "type": "message",
+ "role": "assistant",
+ "model": "claude-3-5-sonnet-20241022",
+ "content": [
+ {
+ "type": "text",
+ "text": "I'll create a website that helps developers find good first issues based on their GitHub interests. Here's a suitable domain name and implementation:\n\n---domain---\nfirstissue.scroll.pub\n\n---index.scroll---\nbuildHtml\nbaseUrl https://firstissue.scroll.pub\nmetaTags\n description Find open source projects to contribute to based on your GitHub interests\n keywords github, open source, first issue, good first issue, contribute, beginner friendly\neditButton /edit.html\ntitle FirstIssue - Find Your Perfect First Open Source Contribution\nstyle.css\nbody.html\nscript.js\n\n---body.html---\n
\n

FirstIssue

\n

Discover your perfect first open source contribution

\n
\n\n
\n
\n
\n
\n \n \n
\n \n
\n
\n\n
\n
\n
\n

Analyzing your interests...

\n
\n \n
\n

\n
\n\n
\n

Recommended Projects

\n
\n
\n
\n
\n\n
\n

Made with 💝 for the open source community

\n

This tool helps match developers with beginner-friendly issues based on their GitHub interests

\n
\n\n---style.css---\n:root {\n --primary: #2d333b;\n --secondary: #22272e;\n --accent: #539bf5;\n --text: #adbac7;\n --spacing: 2rem;\n}\n\n* {\n margin: 0;\n padding: 0;\n box-sizing: border-box;\n}\n\nbody {\n font-family: system-ui, -apple-system, sans-serif;\n line-height: 1.6;\n color: var(--text);\n background: var(--primary);\n min-height: 100vh;\n display: flex;\n flex-direction: column;\n}\n\nheader {\n background: var(--secondary);\n padding: var(--spacing);\n text-align: center;\n box-shadow: 0 2px 8px rgba(0,0,0,0.2);\n}\n\nh1 {\n font-size: 2.5rem;\n color: var(--accent);\n margin-bottom: 0.5rem;\n}\n\nmain {\n flex: 1;\n padding: var(--spacing);\n max-width: 1200px;\n margin: 0 auto;\n width: 100%;\n}\n\n.search-section {\n margin: 2rem auto;\n max-width: 600px;\n}\n\n.input-group {\n margin-bottom: 1rem;\n}\n\nlabel {\n display: block;\n margin-bottom: 0.5rem;\n font-weight: 500;\n}\n\ninput {\n width: 100%;\n padding: 0.8rem;\n border: 2px solid var(--secondary);\n border-radius: 8px;\n background: var(--secondary);\n color: var(--text);\n font-size: 1rem;\n transition: all 0.3s ease;\n}\n\ninput:focus {\n outline: none;\n border-color: var(--accent);\n box-shadow: 0 0 0 3px rgba(83,155,245,0.3);\n}\n\nbutton {\n width: 100%;\n padding: 1rem;\n background: var(--accent);\n color: var(--secondary);\n border: none;\n border-radius: 8px;\n font-size: 1rem;\n font-weight: 600;\n cursor: pointer;\n transition: transform 0.2s ease;\n}\n\nbutton:hover {\n transform: translateY(-2px);\n}\n\n.projects-grid {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));\n gap: 1.5rem;\n margin-top: 2rem;\n}\n\n.project-card {\n background: var(--secondary);\n border-radius: 12px;\n padding: 1.5rem;\n transition: transform 0.3s ease;\n}\n\n.project-card:hover {\n transform: translateY(-4px);\n}\n\n.spinner {\n width: 40px;\n height: 40px;\n border: 4px solid var(--secondary);\n border-top: 4px solid var(--accent);\n border-radius: 50%;\n margin: 2rem auto;\n animation: spin 1s linear infinite;\n}\n\n@keyframes spin {\n 0% { transform: rotate(0deg); }\n 100% { transform: rotate(360deg); }\n}\n\n.hidden {\n display: none;\n}\n\nfooter {\n background: var(--secondary);\n padding: var(--spacing);\n text-align: center;\n margin-top: auto;\n}\n\n@media (max-width: 768px) {\n :root {\n --spacing: 1rem;\n }\n \n h1 {\n font-size: 2rem;\n }\n \n .projects-grid {\n grid-template-columns: 1fr;\n }\n}\n\n---script.js---\ndocument.addEventListener('DOMContentLoaded', () => {\n const searchForm = document.getElementById('searchForm');\n const loading = document.getElementById('loading');\n const error = document.getElementById('error');\n const results = document.getElementById('results');\n const projectsGrid = results.querySelector('.projects-grid');\n\n searchForm.addEventListener('submit', async (e) => {\n e.preventDefault();\n const username = document.getElementById('username').value.trim();\n \n if (!username) return;\n\n showLoading();\n \n try {\n // Get user's starred repos\n const starredRepos = await fetchStarredRepos(username);\n \n // Get repos with good first issues\n const recommendations = await findRecommendations(starredRepos);\n \n displayResults(recommendations);\n } catch (err) {\n showError(err.message);\n }\n });\n\n async function fetchStarredRepos(username) {\n const response = await fetch(`https://api.github.com/users/${username}/starred`);\n if (!response.ok) {\n throw new Error('Unable to fetch starred repositories. Please check the username and try again.');\n }\n return response.json();\n }\n\n async function findRecommendations(starredRepos) {\n const topics = extractTopics(starredRepos);\n const recommendations = [];\n \n for (const topic of topics) {\n const response = await fetch(\n `https://api.github.com/search/issues?q=label:\"good first issue\"+state:open+topic:${topic}`\n );\n const data = await response.json();\n recommendations.push(...data.items.slice(0, 3));\n }\n \n return recommendations.slice(0, 9);\n }\n\n function extractTopics(repos) {\n const topicsMap = {};\n repos.forEach(repo => {\n repo.topics?.forEach(topic => {\n topicsMap[topic] = (topicsMap[topic] || 0) + 1;\n });\n });\n \n return Object.entries(topicsMap)\n .sort((a, b) => b[1] - a[1])\n .slice(0, 3)\n .map(([topic]) => topic);\n }\n\n function displayResults(recommendations) {\n projectsGrid.innerHTML = '';\n \n recommendations.forEach(issue => {\n const card = document.createElement('article');\n card.className = 'project-card';\n card.innerHTML = `\n

${issue.repository_url.split('/').slice(-1)}

\n

${issue.title}

\n View Issue\n `;\n projectsGrid.appendChild(card);\n });\n \n hideLoading();\n results.classList.remove('hidden');\n }\n\n function showLoading() {\n error.classList.add('hidden');\n results.classList.add('hidden');\n loading.classList.remove('hidden');\n }\n\n function hideLoading() {\n loading.classList.add('hidden');\n }\n\n function showError(message) {\n hideLoading();\n results.classList.add('hidden');\n error.querySelector('p').textContent = message;\n error.classList.remove('hidden');\n }\n});\n\n---end---\n\nThis implementation creates a sleek, modern website that helps developers find their first open source contributions. Key features:\n\n1. Clean, semantic HTML5 structure\n2. Modern CSS with CSS variables and fluid layouts\n3. Responsive design that works on all devices\n4. Accessible with proper ARIA attributes and semantic elements\n5. Error handling and loading states\n6. Beautiful animations and transitions\n7. GitHub API integration\n8. Topic-based recommendation system\n9. SEO-optimized meta tags\n10. Professional design with dark theme\n\nThe site analyzes a user's starred repositories to understand their interests, then finds matching repositories with good first issues. The interface is simple but powerful, with smooth animations and clear feedback throughout the process."
+ }
+ ],
+ "stop_reason": "end_turn",
+ "stop_sequence": null,
+ "usage": {
+ "input_tokens": 293,
+ "cache_creation_input_tokens": 0,
+ "cache_read_input_tokens": 0,
+ "output_tokens": 2478
+ }
+ }
readme.scroll
Changed around line 1
+ # firstissue.scroll.pub
+ Website generated by Claude from prompt: page that given your github username suggest repos to contribute to open source based on your starred repos with good first issue labels
script.js
Changed around line 1
+ document.addEventListener('DOMContentLoaded', () => {
+ const searchForm = document.getElementById('searchForm');
+ const loading = document.getElementById('loading');
+ const error = document.getElementById('error');
+ const results = document.getElementById('results');
+ const projectsGrid = results.querySelector('.projects-grid');
+
+ searchForm.addEventListener('submit', async (e) => {
+ e.preventDefault();
+ const username = document.getElementById('username').value.trim();
+
+ if (!username) return;
+
+ showLoading();
+
+ try {
+ // Get user's starred repos
+ const starredRepos = await fetchStarredRepos(username);
+
+ // Get repos with good first issues
+ const recommendations = await findRecommendations(starredRepos);
+
+ displayResults(recommendations);
+ } catch (err) {
+ showError(err.message);
+ }
+ });
+
+ async function fetchStarredRepos(username) {
+ const response = await fetch(`https://api.github.com/users/${username}/starred`);
+ if (!response.ok) {
+ throw new Error('Unable to fetch starred repositories. Please check the username and try again.');
+ }
+ return response.json();
+ }
+
+ async function findRecommendations(starredRepos) {
+ const topics = extractTopics(starredRepos);
+ const recommendations = [];
+
+ for (const topic of topics) {
+ const response = await fetch(
+ `https://api.github.com/search/issues?q=label:"good first issue"+state:open+topic:${topic}`
+ );
+ const data = await response.json();
+ recommendations.push(...data.items.slice(0, 3));
+ }
+
+ return recommendations.slice(0, 9);
+ }
+
+ function extractTopics(repos) {
+ const topicsMap = {};
+ repos.forEach(repo => {
+ repo.topics?.forEach(topic => {
+ topicsMap[topic] = (topicsMap[topic] || 0) + 1;
+ });
+ });
+
+ return Object.entries(topicsMap)
+ .sort((a, b) => b[1] - a[1])
+ .slice(0, 3)
+ .map(([topic]) => topic);
+ }
+
+ function displayResults(recommendations) {
+ projectsGrid.innerHTML = '';
+
+ recommendations.forEach(issue => {
+ const card = document.createElement('article');
+ card.className = 'project-card';
+ card.innerHTML = `
+

${issue.repository_url.split('/').slice(-1)}

+

${issue.title}

+ `;
+ projectsGrid.appendChild(card);
+ });
+
+ hideLoading();
+ results.classList.remove('hidden');
+ }
+
+ function showLoading() {
+ error.classList.add('hidden');
+ results.classList.add('hidden');
+ loading.classList.remove('hidden');
+ }
+
+ function hideLoading() {
+ loading.classList.add('hidden');
+ }
+
+ function showError(message) {
+ hideLoading();
+ results.classList.add('hidden');
+ error.querySelector('p').textContent = message;
+ error.classList.remove('hidden');
+ }
+ });
style.css
Changed around line 1
+ :root {
+ --primary: #2d333b;
+ --secondary: #22272e;
+ --accent: #539bf5;
+ --text: #adbac7;
+ --spacing: 2rem;
+ }
+
+ * {
+ margin: 0;
+ padding: 0;
+ box-sizing: border-box;
+ }
+
+ body {
+ font-family: system-ui, -apple-system, sans-serif;
+ line-height: 1.6;
+ color: var(--text);
+ background: var(--primary);
+ min-height: 100vh;
+ display: flex;
+ flex-direction: column;
+ }
+
+ header {
+ background: var(--secondary);
+ padding: var(--spacing);
+ text-align: center;
+ box-shadow: 0 2px 8px rgba(0,0,0,0.2);
+ }
+
+ h1 {
+ font-size: 2.5rem;
+ color: var(--accent);
+ margin-bottom: 0.5rem;
+ }
+
+ main {
+ flex: 1;
+ padding: var(--spacing);
+ max-width: 1200px;
+ margin: 0 auto;
+ width: 100%;
+ }
+
+ .search-section {
+ margin: 2rem auto;
+ max-width: 600px;
+ }
+
+ .input-group {
+ margin-bottom: 1rem;
+ }
+
+ label {
+ display: block;
+ margin-bottom: 0.5rem;
+ font-weight: 500;
+ }
+
+ input {
+ width: 100%;
+ padding: 0.8rem;
+ border: 2px solid var(--secondary);
+ border-radius: 8px;
+ background: var(--secondary);
+ color: var(--text);
+ font-size: 1rem;
+ transition: all 0.3s ease;
+ }
+
+ input:focus {
+ outline: none;
+ border-color: var(--accent);
+ box-shadow: 0 0 0 3px rgba(83,155,245,0.3);
+ }
+
+ button {
+ width: 100%;
+ padding: 1rem;
+ background: var(--accent);
+ color: var(--secondary);
+ border: none;
+ border-radius: 8px;
+ font-size: 1rem;
+ font-weight: 600;
+ cursor: pointer;
+ transition: transform 0.2s ease;
+ }
+
+ button:hover {
+ transform: translateY(-2px);
+ }
+
+ .projects-grid {
+ display: grid;
+ grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
+ gap: 1.5rem;
+ margin-top: 2rem;
+ }
+
+ .project-card {
+ background: var(--secondary);
+ border-radius: 12px;
+ padding: 1.5rem;
+ transition: transform 0.3s ease;
+ }
+
+ .project-card:hover {
+ transform: translateY(-4px);
+ }
+
+ .spinner {
+ width: 40px;
+ height: 40px;
+ border: 4px solid var(--secondary);
+ border-top: 4px solid var(--accent);
+ border-radius: 50%;
+ margin: 2rem auto;
+ animation: spin 1s linear infinite;
+ }
+
+ @keyframes spin {
+ 0% { transform: rotate(0deg); }
+ 100% { transform: rotate(360deg); }
+ }
+
+ .hidden {
+ display: none;
+ }
+
+ footer {
+ background: var(--secondary);
+ padding: var(--spacing);
+ text-align: center;
+ margin-top: auto;
+ }
+
+ @media (max-width: 768px) {
+ :root {
+ --spacing: 1rem;
+ }
+
+ h1 {
+ font-size: 2rem;
+ }
+
+ .projects-grid {
+ grid-template-columns: 1fr;
+ }
+ }