Skip to content

Commit 5a17944

Browse files
committed
feat: add changelog and case studies features with live views
- Introduced ChangelogLive and CaseStudyLive modules for displaying changelog entries and case studies. - Added routes for changelog and case studies in the router. - Implemented rendering logic for both features, including navigation and content display.
1 parent af6ddd2 commit 5a17944

File tree

8 files changed

+293
-6
lines changed

8 files changed

+293
-6
lines changed

lib/algora/content.ex

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,10 @@ defmodule Algora.Content do
77

88
defstruct [:slug, :title, :date, :tags, :authors, :content]
99

10+
defp base_path, do: Path.join([:code.priv_dir(:algora), "content"])
11+
1012
def load_content(directory, slug) do
11-
with {:ok, content} <- File.read(Path.join(directory, "#{slug}.md")),
13+
with {:ok, content} <- [base_path(), directory, "#{slug}.md"] |> Path.join() |> File.read(),
1214
[frontmatter, markdown] <- content |> String.split("---\n", parts: 3) |> Enum.drop(1),
1315
{:ok, parsed_frontmatter} <- YamlElixir.read_from_string(frontmatter) do
1416
{:ok,
@@ -24,7 +26,8 @@ defmodule Algora.Content do
2426
end
2527

2628
def list_content(directory) do
27-
directory
29+
[base_path(), directory]
30+
|> Path.join()
2831
|> File.ls!()
2932
|> Enum.filter(&String.ends_with?(&1, ".md"))
3033
|> Enum.map(fn filename ->

lib/algora_web/live/blog_live.ex

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,9 @@ defmodule AlgoraWeb.BlogLive do
55
alias AlgoraWeb.Components.Footer
66
alias AlgoraWeb.Components.Header
77

8-
defp blog_path, do: Path.join([:code.priv_dir(:algora), "blog"])
9-
108
@impl true
119
def mount(%{"slug" => slug}, _session, socket) do
12-
case Algora.Content.load_content(blog_path(), slug) do
10+
case Algora.Content.load_content("blog", slug) do
1311
{:ok, content} ->
1412
{:ok,
1513
assign(socket,
@@ -24,7 +22,7 @@ defmodule AlgoraWeb.BlogLive do
2422

2523
@impl true
2624
def mount(_params, _session, socket) do
27-
posts = Algora.Content.list_content(blog_path())
25+
posts = Algora.Content.list_content("blog")
2826
{:ok, assign(socket, posts: posts, page_title: "Blog")}
2927
end
3028

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
defmodule AlgoraWeb.CaseStudyLive do
2+
@moduledoc false
3+
use AlgoraWeb, :live_view
4+
5+
alias AlgoraWeb.Components.Footer
6+
alias AlgoraWeb.Components.Header
7+
8+
@impl true
9+
def mount(%{"slug" => slug}, _session, socket) do
10+
case Algora.Content.load_content("case_studies", slug) do
11+
{:ok, content} ->
12+
{:ok,
13+
assign(socket,
14+
content: content,
15+
page_title: content.title
16+
)}
17+
18+
{:error, _reason} ->
19+
{:ok, push_navigate(socket, to: ~p"/case-studies")}
20+
end
21+
end
22+
23+
@impl true
24+
def mount(_params, _session, socket) do
25+
posts = Algora.Content.list_content("case_studies")
26+
{:ok, assign(socket, posts: posts, page_title: "Case Studies")}
27+
end
28+
29+
@impl true
30+
def render(assigns) do
31+
~H"""
32+
<div>
33+
<Header.header />
34+
<div class="max-w-5xl mx-auto px-4 pt-32 pb-16 sm:pb-24">
35+
<%= if @live_action == :index do %>
36+
<h1 class="text-3xl font-bold mb-8">Case Studies</h1>
37+
<div class="space-y-6">
38+
<%= for post <- @posts do %>
39+
<div class="border border-border p-6 rounded-lg hover:border-border/80">
40+
<.link navigate={~p"/case-studies/#{post.slug}"} class="block space-y-2">
41+
<h2 class="text-3xl font-bold hover:text-success font-display">
42+
{post.title}
43+
</h2>
44+
<div class="flex items-center gap-4 text-sm text-muted-foreground">
45+
<time datetime={post.date}>{Algora.Content.format_date(post.date)}</time>
46+
</div>
47+
</.link>
48+
</div>
49+
<% end %>
50+
</div>
51+
<% else %>
52+
<article class="prose dark:prose-invert max-w-none">
53+
<header class="mb-8 not-prose">
54+
<h1 class="text-5xl font-display font-extrabold tracking-tight mb-4 bg-clip-text text-transparent bg-gradient-to-r from-emerald-400 to-emerald-300">
55+
{@content.title}
56+
</h1>
57+
58+
<div class="flex items-center gap-4 text-muted-foreground mb-4">
59+
<time datetime={@content.date}>{Algora.Content.format_date(@content.date)}</time>
60+
</div>
61+
</header>
62+
63+
{raw(@content.content)}
64+
</article>
65+
<% end %>
66+
</div>
67+
<Footer.footer />
68+
</div>
69+
"""
70+
end
71+
end
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
defmodule AlgoraWeb.ChangelogLive do
2+
@moduledoc false
3+
use AlgoraWeb, :live_view
4+
5+
alias AlgoraWeb.Components.Footer
6+
alias AlgoraWeb.Components.Header
7+
8+
@impl true
9+
def mount(%{"slug" => slug}, _session, socket) do
10+
case Algora.Content.load_content("changelog", slug) do
11+
{:ok, content} ->
12+
{:ok,
13+
assign(socket,
14+
content: content,
15+
page_title: content.title
16+
)}
17+
18+
{:error, _reason} ->
19+
{:ok, push_navigate(socket, to: ~p"/changelog")}
20+
end
21+
end
22+
23+
@impl true
24+
def mount(_params, _session, socket) do
25+
posts = Algora.Content.list_content("changelog")
26+
{:ok, assign(socket, posts: posts, page_title: "Changelog")}
27+
end
28+
29+
@impl true
30+
def render(assigns) do
31+
~H"""
32+
<div>
33+
<Header.header />
34+
<div class="max-w-5xl mx-auto px-4 pt-32 pb-16 sm:pb-24">
35+
<%= if @live_action == :index do %>
36+
<h1 class="text-3xl font-bold mb-8">Changelog</h1>
37+
<div class="space-y-6">
38+
<%= for post <- @posts do %>
39+
<div class="border border-border p-6 rounded-lg hover:border-border/80">
40+
<.link navigate={~p"/changelog/#{post.slug}"} class="block space-y-2">
41+
<h2 class="text-3xl font-bold hover:text-success font-display">
42+
{post.title}
43+
</h2>
44+
<div class="flex items-center gap-4 text-sm text-muted-foreground">
45+
<time datetime={post.date}>{Algora.Content.format_date(post.date)}</time>
46+
</div>
47+
</.link>
48+
</div>
49+
<% end %>
50+
</div>
51+
<% else %>
52+
<article class="prose dark:prose-invert max-w-none">
53+
<header class="mb-8 not-prose">
54+
<h1 class="text-5xl font-display font-extrabold tracking-tight mb-4 bg-clip-text text-transparent bg-gradient-to-r from-emerald-400 to-emerald-300">
55+
{@content.title}
56+
</h1>
57+
58+
<div class="flex items-center gap-4 text-muted-foreground mb-4">
59+
<time datetime={@content.date}>{Algora.Content.format_date(@content.date)}</time>
60+
</div>
61+
</header>
62+
63+
{raw(@content.content)}
64+
</article>
65+
<% end %>
66+
</div>
67+
<Footer.footer />
68+
</div>
69+
"""
70+
end
71+
end

lib/algora_web/router.ex

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,10 @@ defmodule AlgoraWeb.Router do
140140
live "/swift", SwiftBountiesLive
141141
live "/blog/:slug", BlogLive, :show
142142
live "/blog", BlogLive, :index
143+
live "/changelog/:slug", ChangelogLive, :show
144+
live "/changelog", ChangelogLive, :index
145+
live "/case-studies/:slug", CaseStudyLive, :show
146+
live "/case-studies", CaseStudyLive, :index
143147
end
144148

145149
live_session :root,

priv/blog/2024-03-building-a-globally-distributed-livestreaming-app.md renamed to priv/content/blog/2024-03-building-a-globally-distributed-livestreaming-app.md

File renamed without changes.

priv/content/case_studies/acme.md

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
---
2+
title: "How ACME Corp Migrated 100+ Microservices to Elixir"
3+
date: "2024-03-20"
4+
company: "ACME Corporation"
5+
industry: "E-commerce"
6+
logo: "/images/case-studies/acme-logo.png"
7+
summary: "Learn how ACME Corp successfully migrated their entire microservices architecture to Elixir, improving performance by 300% and reducing infrastructure costs by 60%."
8+
---
9+
10+
# How ACME Corp Migrated 100+ Microservices to Elixir
11+
12+
## Company Overview
13+
14+
ACME Corporation is a leading e-commerce platform handling millions of transactions daily. With over 1000 employees and 10 million active users, maintaining system performance and reliability is crucial to their success.
15+
16+
## The Challenge
17+
18+
- Legacy microservices architecture built with Node.js and Python
19+
- High infrastructure costs due to service redundancy
20+
- Complex deployment and maintenance procedures
21+
- Scalability issues during peak shopping seasons
22+
23+
## Why Elixir?
24+
25+
After evaluating several options, ACME chose Elixir for its:
26+
27+
- Excellent concurrency model
28+
- Built-in fault tolerance
29+
- Lower infrastructure requirements
30+
- Strong developer productivity
31+
- Growing ecosystem
32+
33+
## Implementation
34+
35+
The migration was completed in phases over 8 months:
36+
37+
1. **Planning & Training (1 month)**
38+
39+
- Team training on Elixir and OTP
40+
- Architecture design
41+
- Migration strategy development
42+
43+
2. **Initial Migration (3 months)**
44+
45+
- Core services migration
46+
- Development of shared libraries
47+
- Setup of monitoring and deployment pipelines
48+
49+
3. **Bulk Migration (3 months)**
50+
51+
- Systematic migration of remaining services
52+
- Performance optimization
53+
- Integration testing
54+
55+
4. **Optimization (1 month)**
56+
- Fine-tuning
57+
- Documentation
58+
- Knowledge transfer
59+
60+
## Results
61+
62+
The migration to Elixir delivered impressive results:
63+
64+
- **300%** improvement in overall system performance
65+
- **60%** reduction in infrastructure costs
66+
- **90%** decrease in system failures
67+
- **50%** reduction in deployment complexity
68+
69+
## Key Learnings
70+
71+
1. Invest in team training early
72+
2. Migrate incrementally
73+
3. Build strong testing practices
74+
4. Leverage the BEAM's built-in features
75+
76+
## Testimonial
77+
78+
> "Migrating to Elixir was one of the best technical decisions we've made. The performance improvements and cost savings have been remarkable, and our team loves working with the language."
79+
>
80+
> — Sarah Chen, CTO at ACME Corp
81+
82+
## Tools Used
83+
84+
- Phoenix Framework
85+
- Broadway for data processing
86+
- LiveView for real-time features
87+
- Oban for background jobs
88+
- Commanded for event sourcing
89+
90+
## Looking Forward
91+
92+
ACME continues to expand their use of Elixir, with plans to:
93+
94+
- Build more real-time features with LiveView
95+
- Implement event sourcing across all services
96+
- Contribute back to the Elixir community
97+
98+
Want to learn more about how Algora can help with your Elixir migration? [Contact us](/contact) today.
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
---
2+
title: "AI-Powered Code Reviews"
3+
date: "2024-03-25"
4+
summary: "Introducing AI-powered code reviews to help developers catch issues early and maintain high code quality."
5+
---
6+
7+
# AI-Powered Code Reviews
8+
9+
We're excited to announce the launch of AI-powered code reviews in Algora! This new feature helps developers catch potential issues early and maintain high code quality across their projects.
10+
11+
## Key Features
12+
13+
- **Automated Code Analysis**: Our AI analyzes your code for common issues, best practices, and potential bugs
14+
- **Performance Insights**: Get recommendations for improving code performance
15+
- **Security Scanning**: Identify potential security vulnerabilities
16+
- **Style Guide Enforcement**: Ensure consistent code style across your team
17+
18+
## How It Works
19+
20+
1. Push your code to any repository connected to Algora
21+
2. Our AI automatically analyzes the changes
22+
3. Review suggestions appear directly in your PR
23+
4. Accept or dismiss recommendations with one click
24+
25+
## Getting Started
26+
27+
Enable AI code reviews in your project settings:
28+
29+
1. Go to Project Settings > Integrations
30+
2. Enable "AI Code Review"
31+
3. Configure your preferences
32+
4. Start pushing code!
33+
34+
## What's Next
35+
36+
We're continuously improving our AI models and adding new features. Coming soon:
37+
38+
- Custom rule creation
39+
- Team-specific style guides
40+
- Integration with more CI/CD platforms
41+
42+
Try it out and let us know what you think!

0 commit comments

Comments
 (0)