Skip to content

Commit 5ce285e

Browse files
committed
roda structure
1 parent 65a7330 commit 5ce285e

30 files changed

+941
-493
lines changed

.github/copilot-instructions.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,16 @@ Search these pages before using them. Find examples, plugins, UI components, and
4343
-**CSS**: Use frontend styles in `frontend/public/styles.css`. Water.css for fallback.
4444
-**Specs**: RSpec for Ruby, build tests for frontend.
4545

46+
## Roda Large Applications Structure
47+
48+
This project follows [Roda Large Applications conventions](https://roda.jeremyevans.net/rdoc/files/doc/conventions_rdoc.html#label-Large+Applications):
49+
50+
- **Use `hash_branches` plugin** (not `hash_branch_view_subdir` since we have no views)
51+
- **Route modules** go in `routes/` directory (one file per prefix)
52+
- **Helper modules** go in `helpers/` directory with `module_function`
53+
- **Core app modules** stay in `app/` directory
54+
- **Load routes/helpers** with `Dir['routes/*.rb'].each { |f| require_relative f }`
55+
4656
## Don't
4757

4858
- ❌ Don't depend on JS for core flows.
@@ -77,6 +87,11 @@ Search these pages before using them. Find examples, plugins, UI components, and
7787
- `HEALTH_CHECK_USERNAME`, `HEALTH_CHECK_PASSWORD`
7888
- `SENTRY_DSN` (optional)
7989

90+
### Verification Steps
91+
- Run `ruby -c app.rb` to check syntax
92+
- Run `bundle exec rspec` to verify tests
93+
- Check `bundle install` removes unused dependencies
94+
8095
## Style
8196

8297
- Add `# frozen_string_literal: true`

app.rb

Lines changed: 48 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,14 @@
77
require 'html2rss'
88
require_relative 'app/environment_validator'
99
require_relative 'app/roda_config'
10-
require_relative 'app/app_routes'
1110
require_relative 'app/auth'
1211
require_relative 'app/auto_source'
1312
require_relative 'app/feeds'
1413
require_relative 'app/health_check'
15-
require_relative 'app/api_routes'
16-
require_relative 'app/response_helpers'
17-
require_relative 'app/static_file_helpers'
14+
require_relative 'app/response_context'
15+
require_relative 'app/request_context'
16+
require_relative 'app/base_route_handler'
1817
require_relative 'app/xml_builder'
19-
require_relative 'app/auto_source_routes'
20-
require_relative 'app/health_check_routes'
2118
require_relative 'app/security_logger'
2219

2320
module Html2rss
@@ -27,12 +24,6 @@ module Web
2724
#
2825
# It is built with [Roda](https://roda.jeremyevans.net/).
2926
class App < Roda
30-
include ApiRoutes
31-
include ResponseHelpers
32-
include StaticFileHelpers
33-
include AutoSourceRoutes
34-
include HealthCheckRoutes
35-
3627
CONTENT_TYPE_RSS = 'application/xml'
3728

3829
def self.development? = ENV['RACK_ENV'] == 'development'
@@ -45,10 +36,53 @@ def development? = self.class.development?
4536
# Configure Roda app
4637
RodaConfig.configure(self)
4738

39+
# Load hash_branches plugin for Large Applications
40+
plugin :hash_branches
41+
42+
# Load all route files
43+
Dir['routes/*.rb'].each { |f| require_relative f }
44+
4845
@show_backtrace = development? && !ENV['CI']
4946

50-
# Define all routes
51-
AppRoutes.define_routes(self)
47+
# Load all routes
48+
AppRoutes.load_routes(self)
49+
50+
route do |r|
51+
r.public
52+
r.hash_branches('')
53+
54+
r.root do
55+
# Handle root path
56+
index_path = 'public/frontend/index.html'
57+
response['Content-Type'] = 'text/html'
58+
59+
if File.exist?(index_path)
60+
File.read(index_path)
61+
else
62+
fallback_html
63+
end
64+
end
65+
end
66+
67+
def fallback_html
68+
<<~HTML
69+
<!DOCTYPE html>
70+
<html>
71+
<head>
72+
<title>html2rss-web</title>
73+
<link rel="stylesheet" href="/water.css">
74+
</head>
75+
<body>
76+
<h1>html2rss-web</h1>
77+
<p>Convert websites to RSS feeds</p>
78+
<p>API available at <code>/api/</code></p>
79+
</body>
80+
</html>
81+
HTML
82+
end
83+
84+
# Load all helper files
85+
Dir['helpers/*.rb'].each { |f| require_relative f }
5286
end
5387
end
5488
end

app/app_routes.rb

Lines changed: 0 additions & 73 deletions
This file was deleted.

app/auto_source.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,8 @@ def create_empty_feed_warning(url, strategy)
127127
end
128128

129129
def call_strategy(url, strategy) # rubocop:disable Metrics/MethodLength
130+
return error_feed('URL parameter required') if url.nil? || url.empty?
131+
130132
global_config = LocalConfig.global
131133

132134
config = {

app/auto_source_routes.rb

Lines changed: 0 additions & 192 deletions
This file was deleted.

0 commit comments

Comments
 (0)