diff --git a/apps/api/package.json b/apps/api/package.json index a880b10..ca45e16 100644 --- a/apps/api/package.json +++ b/apps/api/package.json @@ -19,14 +19,14 @@ "@types/express": "^4.17.21", "@types/jsonwebtoken": "^9.0.7", "@types/node": "^24.5.1", - "prisma": "^5.22.0", + "prisma": "^6.19.0", "tsx": "^4.20.3", "typescript": "^5.9.2" }, "dependencies": { "@octokit/graphql": "^9.0.1", "@opensox/shared": "workspace:*", - "@prisma/client": "^5.22.0", + "@prisma/client": "^6.19.0", "@trpc/server": "^11.5.1", "cors": "^2.8.5", "dotenv": "^16.5.0", diff --git a/apps/web/next.config.js b/apps/web/next.config.js index fdebc20..df699c6 100644 --- a/apps/web/next.config.js +++ b/apps/web/next.config.js @@ -6,8 +6,13 @@ const nextConfig = { protocol: "https", hostname: "avatars.githubusercontent.com", }, + { + protocol: "https", + hostname: "images.pexels.com", + pathname: "/**", // optional but recommended + }, ], }, }; -module.exports = nextConfig; \ No newline at end of file +module.exports = nextConfig; diff --git a/apps/web/package.json b/apps/web/package.json index 7848f7c..214a6ec 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -33,8 +33,10 @@ "posthog-js": "^1.203.1", "react": "^18.2.0", "react-dom": "^18.2.0", + "react-markdown": "^10.1.0", "react-qr-code": "^2.0.18", "react-tweet": "^3.2.1", + "remark-gfm": "^4.0.1", "superjson": "^2.2.5", "tailwind-merge": "^2.5.4", "tailwindcss-animate": "^1.0.7", diff --git a/apps/web/src/app/(main)/dashboard/newsletters/[slug]/page.tsx b/apps/web/src/app/(main)/dashboard/newsletters/[slug]/page.tsx new file mode 100644 index 0000000..d1507dc --- /dev/null +++ b/apps/web/src/app/(main)/dashboard/newsletters/[slug]/page.tsx @@ -0,0 +1,135 @@ +"use client"; + +import { NEWSLETTERS } from "@/data/newsletters"; +import NewsletterContent from "@/components/newsletters/NewsletterContent"; +import { CalendarIcon, ArrowLeftIcon, ClockIcon, BookmarkIcon } from "@heroicons/react/24/outline"; +import { BookmarkIcon as BookmarkSolid } from "@heroicons/react/24/solid"; +import Link from "next/link"; +import { useState } from "react"; + +export default function Page({ params }: { params: { slug: string } }) { + const n = NEWSLETTERS.find((x) => x.slug === params.slug); + const [isSaved, setIsSaved] = useState(false); + + if (!n) { + return ( +
+
+

Newsletter not found

+ + + Back to newsletters + +
+
+ ); + } + + const wordCount = n.body.split(/\s+/).length; + const readingTime = Math.ceil(wordCount / 200); + + return ( +
+ + {/* Back Navigation */} +
+
+ + + Newsletters + +
+
+ + {/* Article Content */} +
+ + {/* Article Header */} +
+ {n.featured && ( +
+ + Featured + +
+ )} + +

+ {n.title} +

+ +

+ {n.excerpt} +

+ + {/* Meta Information */} +
+
+
+ + {new Date(n.date).toLocaleDateString('en-US', { + year: 'numeric', + month: 'short', + day: 'numeric' + })} +
+ +
+ + {readingTime} min +
+
+ + {/* Save Button */} + +
+
+ + {/* Article Body */} +
+
+ +
+
+ + {/* Article Footer */} + +
+
+ ); +} \ No newline at end of file diff --git a/apps/web/src/app/(main)/dashboard/newsletters/page.tsx b/apps/web/src/app/(main)/dashboard/newsletters/page.tsx new file mode 100644 index 0000000..dccff06 --- /dev/null +++ b/apps/web/src/app/(main)/dashboard/newsletters/page.tsx @@ -0,0 +1,9 @@ +import NewsletterContainer from '@/components/newsletters/NewsletterContainer' + +export default function Page() { + return ( +
+ +
+ ) +} \ No newline at end of file diff --git a/apps/web/src/components/dashboard/Sidebar.tsx b/apps/web/src/components/dashboard/Sidebar.tsx index eabb046..2f924ee 100644 --- a/apps/web/src/components/dashboard/Sidebar.tsx +++ b/apps/web/src/components/dashboard/Sidebar.tsx @@ -17,6 +17,7 @@ import { StarIcon, HeartIcon, EnvelopeIcon, + NewspaperIcon, } from "@heroicons/react/24/outline"; import { useShowSidebar } from "@/store/useShowSidebar"; import { signOut } from "next-auth/react"; @@ -138,6 +139,16 @@ export default function Sidebar() { icon={} collapsed={isCollapsed} /> + + } + collapsed={isCollapsed} + /> + ("all"); + const [isDropdownOpen, setIsDropdownOpen] = useState(false); + + const monthFilters = useMemo(() => { + const months = [ + { value: "all", label: "All months" }, + { value: "2025-11", label: "November 2025" }, + { value: "2025-10", label: "October 2025" }, + { value: "2025-09", label: "September 2025" }, + ]; + return months; + }, []); + + const selectedFilterLabel = monthFilters.find(filter => filter.value === selectedMonth)?.label || "All months"; + + return ( +
+
+ + {/* Header */} +
+
+ + Pro Access + +
+ +

+ Newsletters +

+ +

+ Curated insights and platform updates +

+
+ + {/* Controls */} +
+ + {/* Search */} +
+ + setQ(e.target.value)} + placeholder="Search" + className="w-full pl-7 pr-4 py-3 bg-transparent border-b border-zinc-800 text-white placeholder:text-zinc-600 focus:outline-none focus:border-zinc-600 transition-colors text-sm font-light" + /> +
+ + {/* Filter */} +
+ + + {isDropdownOpen && ( + <> +
setIsDropdownOpen(false)} + /> + +
+ {monthFilters.map((filter) => ( + + ))} +
+ + )} +
+
+ + {/* Active Filter */} + {selectedMonth !== "all" && ( +
+ FILTERED BY + +
+ )} + + {/* Newsletter List */} + + + {/* Footer */} +
+

+ More insights coming soon +

+
+
+
+ ); +} \ No newline at end of file diff --git a/apps/web/src/components/newsletters/NewsletterContent.tsx b/apps/web/src/components/newsletters/NewsletterContent.tsx new file mode 100644 index 0000000..2207c3a --- /dev/null +++ b/apps/web/src/components/newsletters/NewsletterContent.tsx @@ -0,0 +1,177 @@ +/* eslint-disable @typescript-eslint/no-unused-vars */ +"use client"; + +import React from "react"; +import ReactMarkdown from "react-markdown"; +import remarkGfm from "remark-gfm"; +import { useState } from "react"; +import { DocumentDuplicateIcon, CheckIcon } from "@heroicons/react/24/outline"; +import Image from "next/image"; + +const CodeBlock = ({ children, className }: { children: React.ReactNode; className?: string }) => { + const [copied, setCopied] = useState(false); + + const handleCopy = async () => { + const text = String(children).replace(/\n$/, ''); + await navigator.clipboard.writeText(text); + setCopied(true); + setTimeout(() => setCopied(false), 2000); + }; + + return ( +
+
+        {children}
+      
+ + {/* Copy Button */} + +
+ ); +}; + +export default function NewsletterContent({ body }: { body: string }) { + return ( + ( +

+ {children} +

+ ), + h3: ({ children }: any) => ( +

+ {children} +

+ ), + + // Paragraphs + p: ({ children }: any) => ( +

+ {children} +

+ ), + + // Lists + ul: ({ children }: any) => ( +
    + {children} +
+ ), + ol: ({ children }: any) => ( +
    + {children} +
+ ), + li: ({ children }: any) => ( +
  • {children}
  • + ), + + // Code blocks - using our custom CodeBlock component + code: ({ node, inline, className, children, ...props }: any) => { + if (inline) { + return ( + + {children} + + ); + } + return {children}; + }, + + // Blockquotes + blockquote: ({ children }: any) => ( +
    + {children} +
    + ), + + // Links + a: ({ children, href }: any) => ( + + {children} + + ), + + // Images + img: ({ src, alt }: any) => ( +
    +
    + {alt} +
    + {alt && alt !== "undefined" && ( +

    + {alt} +

    + )} +
    + ), + + // Strong/bold + strong: ({ children }: any) => ( + {children} + ), + + // Emphasis/italic + em: ({ children }: any) => ( + {children} + ), + + // Horizontal rule + hr: () => ( +
    + ), + + // Table + table: ({ children }: any) => ( +
    + + {children} +
    +
    + ), + th: ({ children }: any) => ( + + {children} + + ), + td: ({ children }: any) => ( + + {children} + + ), + }} + > + {body} +
    + ); +} \ No newline at end of file diff --git a/apps/web/src/components/newsletters/NewsletterCrad.tsx b/apps/web/src/components/newsletters/NewsletterCrad.tsx new file mode 100644 index 0000000..3910955 --- /dev/null +++ b/apps/web/src/components/newsletters/NewsletterCrad.tsx @@ -0,0 +1,55 @@ +import Link from "next/link"; +import Image from "next/image"; +import { Newsletter } from "@/data/newsletters"; +import { CalendarIcon } from "@heroicons/react/24/outline"; + +export default function NewsletterCard({ n }: { n: Newsletter }) { + return ( +
    + + {/* Hero Image */} + {n.hero && ( +
    + {n.title} +
    +
    + )} + + {/* Content */} +
    + {n.featured && ( +
    + + Featured + +
    + )} + +

    + {n.title} +

    + +

    + {n.excerpt} +

    + +
    + + + {new Date(n.date).toLocaleDateString("en-US", { + year: "numeric", + month: "short", + day: "numeric", + })} + +
    +
    + +
    + ); +} \ No newline at end of file diff --git a/apps/web/src/components/newsletters/NewsletterList.tsx b/apps/web/src/components/newsletters/NewsletterList.tsx new file mode 100644 index 0000000..9a02f1c --- /dev/null +++ b/apps/web/src/components/newsletters/NewsletterList.tsx @@ -0,0 +1,91 @@ +import { NEWSLETTERS, Newsletter } from "@/data/newsletters"; +import NewsletterCard from "./NewsletterCrad"; +import { DocumentMagnifyingGlassIcon } from "@heroicons/react/24/outline"; + +export default function NewsletterList({ + query = "", + monthFilter = "all", +}: { + query?: string; + monthFilter?: string; +}) { + const filtered = NEWSLETTERS + .sort((a, b) => +new Date(b.date) - +new Date(a.date)) + .filter((newsletter) => { + const matchesSearch = query + ? newsletter.title.toLowerCase().includes(query.toLowerCase()) || + newsletter.excerpt.toLowerCase().includes(query.toLowerCase()) + : true; + + const matchesMonth = + monthFilter === "all" ? true : newsletter.date.startsWith(monthFilter); + + return matchesSearch && matchesMonth; + }); + + const groupedNewsletters = filtered.reduce((acc, newsletter) => { + const date = new Date(newsletter.date); + const year = date.getFullYear(); + const month = date.toLocaleDateString("en-US", { month: "long" }); + + const key = `${year}-${month}`; + if (!acc[key]) { + acc[key] = { + year, + month, + newsletters: [], + }; + } + acc[key].newsletters.push(newsletter); + return acc; + }, {} as Record); + + const groupedArray = Object.values(groupedNewsletters); + + if (!filtered.length) { + return ( +
    + + +

    + {query || monthFilter !== "all" + ? "No newsletters found" + : "No newsletters yet"} +

    + +

    + {query || monthFilter !== "all" + ? "Try adjusting your search or filter" + : "New content coming soon"} +

    +
    + ); + } + + return ( +
    + {groupedArray.map((group) => ( +
    + {/* Month/Year Header */} +
    +

    + {group.month} {group.year} +

    + +

    + {group.newsletters.length}{" "} + {group.newsletters.length === 1 ? "article" : "articles"} +

    +
    + + {/* Newsletter Grid */} +
    + {group.newsletters.map((n) => ( + + ))} +
    +
    + ))} +
    + ); +} \ No newline at end of file diff --git a/apps/web/src/data/newsletters.ts b/apps/web/src/data/newsletters.ts new file mode 100644 index 0000000..a9e3fdc --- /dev/null +++ b/apps/web/src/data/newsletters.ts @@ -0,0 +1,445 @@ +// data/newsletters.ts +export type Newsletter = { + title: string; + date: string; + slug: string; + excerpt: string; + hero?: string; + body: string; + featured?: boolean; +}; + +export const NEWSLETTERS: Newsletter[] = [ + { + title: "Scaling Open Source Collaboration: November 2025 Platform Updates", + date: "2025-11-15", + slug: "opensox-november-2025", + excerpt: "Major platform updates, community growth metrics, and what's next for OpenSox", + hero: "https://images.pexels.com/photos/12662811/pexels-photo-12662811.jpeg", + featured: true, + body: `# Scaling Open Source Collaboration: November 2025 Platform Updates + +![Platform Dashboard](https://images.pexels.com/photos/1779487/pexels-photo-1779487.jpeg) + +The past month has been transformative for OpenSox as we continue building the most efficient platform for open source collaboration. + +## Major Platform Updates + +### Newsletter System for Pro Users +We launched our comprehensive newsletter system designed specifically for pro users, delivering: + +- Technical deep dives into platform architecture +- Exclusive interviews with top open source maintainers +- Advanced contribution strategies from industry experts +- Early access to upcoming features and beta programs + +### Enhanced Contributor Onboarding +Our redesigned onboarding process reduced time-to-first-contribution by 62%. Key improvements include: + +- Intelligent project matching based on technical background +- Interactive tutorials that adapt to learning style +- Personalized milestone tracking +- Mentor matching system connecting new contributors with experienced maintainers + +### Performance Optimizations +We achieved a 40% reduction in dashboard load times through strategic optimizations: + +\`\`\`typescript +// Parallel data fetching with caching +const [userData, projectData, activityData] = await Promise.all([ + trpc.user.profile.useQuery({ cache: 'force-cache' }), + trpc.project.list.useQuery({ + take: 50, + cache: 'force-cache', + staleTime: 5 * 60 * 1000 + }), + trpc.activity.recent.useQuery({ cache: 'force-cache' }) +]); +\`\`\` + +Additional wins: lazy loading non-critical components, optimized database queries reducing response times by 200ms, and CDN implementation for global assets. + +## Community Growth Metrics + +November delivered our strongest engagement yet: + +- 2,847 new contributors joined +- 15,632 daily search queries +- 45% quarter-over-quarter growth in active repositories +- 280+ quality PRs from top contributors + +Geographic distribution: North America (42%), Europe (31%), Asia (18%), Other regions (9%). + +## Technical Deep Dive: Database Optimization + +As our user base grew, we noticed increasing latency in project discovery. We implemented a denormalized data model with strategic indexing: + +\`\`\`sql +CREATE INDEX idx_projects_tech_stack ON projects USING gin(tech_stack); +CREATE INDEX idx_projects_activity ON projects(last_activity_at DESC); + +SELECT p.id, p.name, p.tech_stack, p.star_count +FROM projects p +WHERE p.tech_stack @> '{"javascript","typescript"}' + AND p.last_activity_at > NOW() - INTERVAL '30 days' +ORDER BY p.star_count DESC LIMIT 50; +\`\`\` + +Results: 300% query performance improvement, 40% reduction in database CPU utilization. + +## Q1 2026 Roadmap + +### AI-Powered Contribution Matching +Our ML team is developing an advanced recommendation system that analyzes your code style, predicts project compatibility, and suggests optimal contribution opportunities. + +### Enhanced Project Analytics +Pro users will gain access to contribution impact scoring, project health metrics, community engagement insights, and personal growth tracking. + +### Mobile App Development +Native iOS and Android apps for reviewing PRs on the go, receiving real-time notifications, and tracking contribution progress. + +## Pro Tips for Maximum Impact + +\`\`\`javascript +// Use compound filters for better results +const optimalFilters = { + languages: ['typescript', 'javascript'], + experienceLevel: 'intermediate', + projectSize: 'medium', + activityLevel: 'high', + hasGoodFirstIssues: true +}; +\`\`\` + +Contribution workflow: start with documentation, fix existing issues before proposing features, write comprehensive tests, and follow each project's communication style. + +--- + +*Questions? Join our [community Discord](https://discord.gg/UuJjwbfz) or reply to this newsletter.*` + }, + { + title: "The Complete Guide to Open Source Contribution Excellence", + date: "2025-10-28", + slug: "contributor-best-practices-2025", + excerpt: "Comprehensive strategies and workflows for becoming an exceptional contributor", + hero: "https://images.pexels.com/photos/11034131/pexels-photo-11034131.jpeg", + body: `# The Complete Guide to Open Source Contribution Excellence + +![Collaborative Coding](https://images.pexels.com/photos/1181671/pexels-photo-1181671.jpeg) + +Becoming an effective contributor requires more than technical skills—it demands strategic thinking, clear communication, and understanding of community dynamics. + +## Mindset and Preparation + +### Developing the Right Mindset +Successful contributors approach open source with: + +- Growth orientation—viewing every PR as learning +- Community focus—prioritizing project health +- Patience and persistence +- Empathy for maintainers' perspectives + +### Technical Preparation +\`\`\`bash +# Environment setup checklist +node --version && npm --version && git --version + +git config --global user.name "Your Name" +git config --global user.email "your.email@example.com" +git config --global init.defaultBranch main + +npm install -g typescript prettier eslint +\`\`\` + +## Getting Started Efficiently + +### Project Selection Strategy +Choose projects that align with your skill level, show recent activity, have responsive maintainers, and offer learning potential. + +### The Fork & Clone Workflow +\`\`\`bash +git clone https://github.com/your-username/project.git +cd project +git remote add upstream https://github.com/original/project.git +git checkout -b feature/your-feature +git fetch upstream && git merge upstream/main +\`\`\` + +## Writing Exceptional Code + +### Code Quality Standards +\`\`\`typescript +interface UserProfile { + id: string; + username: string; + email: string; + avatarUrl?: string; +} + +/** + * Updates user profile with validation + */ +async function updateUserProfile(profile: UserProfile): Promise { + if (!isValidEmail(profile.email)) { + throw new Error('Invalid email format'); + } + + const updated = await userRepository.update(profile); + await auditLogger.logProfileUpdate(profile.id); + + return updated; +} +\`\`\` + +### Testing Strategy +\`\`\`typescript +describe('UserProfile', () => { + it('should validate email format', () => { + expect(isValidEmail('test@example.com')).toBe(true); + expect(isValidEmail('invalid')).toBe(false); + }); + + it('should handle updates with audit logging', async () => { + const updated = await updateUserProfile(mockProfile); + expect(updated.updatedAt).toBeDefined(); + expect(auditLogger.logProfileUpdate).toHaveBeenCalled(); + }); +}); +\`\`\` + +## Communication Mastery + +### PR Description Template +\`\`\`markdown +## Changes Made +- Added newsletter subscription system +- Implemented email validation and rate limiting +- Added comprehensive test coverage + +## Technical Details +- Chosen SendGrid for reliability +- Implemented Redis for rate limiting +- Used Zod for input validation + +## Testing Performed +- [x] Unit tests (95% coverage) +- [x] Integration tests +- [x] Load testing with 1000 concurrent users + +## Related Issues +Closes #123, #124 + +## Deployment Notes +- Requires SENDGRID_API_KEY env variable +- Database migration included +\`\`\` + +## Advanced Contribution Strategies + +### Building Maintainer Trust +1. Start small with documentation and bug fixes +2. Be reliable—follow through on commitments +3. Understand the project vision +4. Help other contributors + +### Time Management +\`\`\`yaml +weekly_goals: + primary_focus: "Newsletter feature" + time_allocation: + coding: 15 hours + code_review: 5 hours + community_engagement: 3 hours + learning_research: 2 hours +\`\`\` + +## Common Pitfalls to Avoid + +**Technical**: Over-engineering, ignoring conventions, poor test coverage +**Communication**: Assuming context, being defensive, incomplete information + +## Continuous Learning + +### Skill Development Roadmap +1. Months 1-3: Master basic workflow +2. Months 4-6: Develop technical expertise +3. Months 7-12: Complex features and bug fixes +4. Year 2: Begin mentoring and maintenance + +--- + +*Ready to start? Explore [recommended projects](https://opensox.ai/projects) tailored to your skills.*` + }, + { + title: "AI-Powered Open Source: The Next Evolution", + date: "2025-10-12", + slug: "ai-open-source-future", + excerpt: "How AI is transforming open source development and contribution workflows", + hero: "https://images.pexels.com/photos/2599244/pexels-photo-2599244.jpeg", + body: `# AI-Powered Open Source: The Next Evolution + +![AI and Development](https://images.pexels.com/photos/8386440/pexels-photo-8386440.jpeg) + +AI integration into open source development is fundamentally changing how we build, maintain, and contribute to software. + +## The New Development Landscape + +### AI-Assisted Contributor Lifecycle +Modern contributors access tools that transform every stage: + +- Project discovery through intelligent matching +- Context analysis for issue understanding +- Code generation assistance +- Automated testing and review +- Knowledge sharing and community integration + +## Intelligent Project Matching + +### How Advanced Matching Works +Our AI analyzes multiple dimensions for optimal matches: + +\`\`\`python +def analyze_technical_fit(contributor_skills, project_requirements): + primary_match = calculate_skill_overlap( + contributor_skills.primary, + project_requirements.essential_skills + ) + + learning_opportunities = identify_skill_gaps( + contributor_skills.current, + project_requirements.desired_skills + ) + + complexity_match = assess_complexity_fit( + contributor_skills.experience_level, + project_requirements.complexity + ) + + return calculate_weighted_score( + primary_match, learning_opportunities, complexity_match + ) +\`\`\` + +Results: 89% higher retention, 3.2x faster time-to-first-contribution, 45% reduction in abandoned PRs. + +## AI-Powered Code Review + +### Beyond Basic Linting +Modern AI review systems understand code intent, architectural patterns, performance implications, and security considerations. + +\`\`\`typescript +class AIReviewAssistant { + async analyzePullRequest(pr: PullRequest) { + const analysis = await this.comprehensiveAnalysis(pr); + + return { + criticalIssues: this.identifyCriticalProblems(analysis), + suggestions: this.generateImprovements(analysis), + performanceOptimizations: this.analyzePerformance(analysis), + securityConsiderations: this.checkSecurity(analysis), + knowledgeSharing: this.provideEducation(analysis) + }; + } +} +\`\`\` + +Recent analysis of 15,000 PRs showed AI-assisted reviews reduced review time by 60% while identifying 35% more potential issues. + +## Intelligent Issue Triage + +### Smart Issue Assignment +\`\`\`python +def optimize_issue_assignment(issue, contributors): + scores = [] + + for contributor in contributors: + technical_score = calculate_technical_match( + contributor.skills, issue.requirements + ) + availability_score = assess_availability( + contributor.workload, issue.effort + ) + performance_score = analyze_historical_performance( + contributor.past_issues, issue.type + ) + + overall = weighted_average([ + (technical_score, 0.4), + (availability_score, 0.3), + (performance_score, 0.3) + ]) + + scores.append({'contributor': contributor, 'score': overall}) + + return sorted(scores, key=lambda x: x['score'], reverse=True) +\`\`\` + +## Predictive Community Analytics + +### Project Health Forecasting +Our AI models predict maintainer burnout risk, contribution pipeline health, community growth trajectories, and technical debt accumulation. + +\`\`\`python +def generate_health_alerts(metrics): + alerts = [] + + if is_maintainer_overload_imminent(metrics.maintainer_activity): + alerts.append({ + 'type': 'MAINTAINER_OVERLOAD', + 'severity': 'HIGH', + 'suggested_actions': [ + 'Recruit additional maintainers', + 'Implement issue triage automation' + ] + }) + + return alerts +\`\`\` + +## Ethical AI Implementation + +We're committed to transparency, bias mitigation, user control, and data privacy. Our AI features are built with community input using open source models where possible. + +## Getting Started + +### For New Contributors +1. Enable smart recommendations in profile settings +2. Complete skill assessment for personalized matching +3. Set learning goals to guide recommendations +4. Use AI review assistant for first PRs + +### For Projects +\`\`\`yaml +ai_features: + matching: + enabled: true + required_skills: ["javascript", "react", "testing"] + + review: + automated_checks: true + educational_feedback: true + + analytics: + health_monitoring: true + predictive_insights: true +\`\`\` + +## Real Impact + +**React Community**: 75% increase in contributor retention, time-to-first-contribution reduced from 3 weeks to 4 days. + +**VS Code Extensions**: 45% faster development, higher code quality across ecosystem. + +## The Future + +Short-term (2026): Context-aware code generation, predictive conflict detection, automated dependency management. + +Long-term (2030): Autonomous maintenance of code areas, AI-mediated cross-project collaboration, self-documenting codebases. + +The future isn't about AI replacing humans—it's about AI augmenting human capabilities through better collaboration tools. + +--- + +*Experience AI-powered open source. [Enable smart features](https://opensox.ai/ai-features) in your dashboard today.*` + } +]; \ No newline at end of file diff --git a/apps/web/tsconfig.json b/apps/web/tsconfig.json index cafc424..5c8c370 100644 --- a/apps/web/tsconfig.json +++ b/apps/web/tsconfig.json @@ -41,6 +41,6 @@ "**/*.tsx", ".next/types/**/*.ts", "types/**/*" - ], +, "src/app/(main)/dashboard/newsletters/[slug]" ], "exclude": ["node_modules", "../api/node_modules"] }