Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 34 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,12 @@

## Current state

This repository contains the live Marianas Open digital platform built and maintained by Shimizu Technology. The earlier planning/POC framing in this README was stale and no longer described the implemented product.
This repository contains the live Marianas Open digital platform built and maintained by Shimizu Technology. It combines a public event, media, rankings, results, travel, sponsor, and impact experience with an invite-only tournament administration console.

The public website is live and currently receives **3,000+ visitors per month** according to the project owner as of July 2026.

The product helps Marianas Open grow beyond a once-a-year event website: athletes can discover and follow the circuit, while the operating team can manage yearly seasons, events, results, galleries, livestreams, content, sponsors, and user access without requiring a developer for routine changes.

## Documentation

| Document | Description |
Expand All @@ -24,6 +26,8 @@ The public website is live and currently receives **3,000+ visitors per month**
| [COMPETITIVE-ANALYSIS.md](./docs/COMPETITIVE-ANALYSIS.md) | FloGrappling, Smoothcomp, UFC Fight Pass, and related platforms |
| [QUESTIONS.md](./docs/QUESTIONS.md) | Historical discovery questions |
| [local-prod-like-uploads.md](./docs/local-prod-like-uploads.md) | Production-like local S3/Solid Queue gallery upload testing |
| [ADMIN-OPERATIONS.md](./docs/ADMIN-OPERATIONS.md) | Yearly rollover, readiness, and publishing operations |
| [AUTH-SYSTEM.md](./docs/AUTH-SYSTEM.md) | Administration roles and authentication behavior |

## What the platform supports

Expand All @@ -34,7 +38,7 @@ The public website is live and currently receives **3,000+ visitors per month**
- Rules, impact, organization, and sponsor content
- Global search and social/QR sharing
- Multilingual content, including English, Japanese, Korean, Portuguese, Tagalog, Simplified Chinese, and Traditional Chinese
- Administrative management for events, competitors, academies, results, videos, images, sponsors, announcements, settings, and site content
- Administrative management for seasons, yearly rollover, events, competitors, academies, results, videos, images, sponsor placements, announcements, settings, and site content
- Role-protected administration and managed media uploads
- Analytics/SEO-oriented public experience

Expand All @@ -49,6 +53,8 @@ marianas-open/

The documents that refer to a POC or potential future build are retained as historical planning artifacts. They are not the current product status.

The frontend is configured for Netlify and the API for a managed Rails/PostgreSQL environment. Public visitors do not download the admin application bundle.

## Stack

- React, Vite, and TypeScript
Expand All @@ -59,10 +65,34 @@ The documents that refer to a POC or potential future build are retained as hist
- PostHog analytics
- Internationalization and structured SEO support

## Local development

```bash
cd api
bundle install
bin/rails db:prepare
bin/rails server
```

In another terminal:

```bash
cd web
npm install
npm run dev
```

## Public-proof boundary

The public site and public tournament content can be demonstrated. Do not expose administrative credentials, unpublished content, private contact information, analytics details, or upload/storage configuration in portfolio demos.

---
Copy environment values from `web/.env.example`; the primary integration variables are `VITE_API_URL`, the Clerk keys, PostgreSQL, Active Storage, and optional translation/analytics services.

## Verification

```bash
cd api && bin/rails test
cd web && npm run lint && npm run build
```

*Shimizu Technology — Building for the Marianas*
See [Admin operations](./docs/ADMIN-OPERATIONS.md) for yearly rollover and publishing, [Authentication](./docs/AUTH-SYSTEM.md) for roles, and [PRD](./docs/PRD.md) for the original product rationale.
33 changes: 16 additions & 17 deletions api/README.md
Original file line number Diff line number Diff line change
@@ -1,24 +1,23 @@
# README
# Marianas Open API

This README would normally document whatever steps are necessary to get the
application up and running.
Rails 8 JSON API for the public platform and invite-only administration console.

Things you may want to cover:
## Setup

* Ruby version
```bash
bundle install
bin/rails db:prepare
bin/rails server
```

* System dependencies
Ruby `3.3.7` is declared in `.ruby-version`. PostgreSQL and an Active Storage service are required. Clerk protects admin endpoints; public event, sponsor, ranking, video, and content endpoints remain unauthenticated.

* Configuration
## Test and safety checks

* Database creation
```bash
bin/rails test
bin/rails zeitwerk:check
bundle exec brakeman -q --no-pager
```

* Database initialization

* How to run the test suite

* Services (job queues, cache servers, search engines, etc.)

* Deployment instructions

* ...
Database migrations create seasons, safe event lineage, sponsor placements, publishing constraints, and audit logs. Deployments must run `bin/rails db:migrate` before serving the new admin console.
2 changes: 1 addition & 1 deletion api/app/controllers/api/v1/admin/academies_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ module Admin
class AcademiesController < ApplicationController
include ClerkAuthenticatable

before_action :require_staff!
before_action :require_admin_access!
before_action :set_academy, only: [:show, :update, :destroy, :upload_logo]

def index
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ module Admin
class AnnouncementsController < ApplicationController
include ClerkAuthenticatable

before_action :require_staff!
before_action :require_admin_access!
before_action :set_announcement, only: [:show, :update, :destroy, :upload_image, :remove_image]

def index
Expand Down
16 changes: 16 additions & 0 deletions api/app/controllers/api/v1/admin/audit_logs_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
module Api
module V1
module Admin
class AuditLogsController < ApplicationController
include ClerkAuthenticatable

before_action :require_staff!

def index
logs = AuditLog.includes(:actor).recent.limit(params.fetch(:limit, 50).to_i.clamp(1, 100))
render json: { audit_logs: logs.as_json }
end
end
end
end
end
2 changes: 1 addition & 1 deletion api/app/controllers/api/v1/admin/competitors_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ module Admin
class CompetitorsController < ApplicationController
include ClerkAuthenticatable

before_action :require_staff!
before_action :require_admin_access!
before_action :set_competitor, only: [:show, :update, :destroy, :upload_photo]

def index
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ module Admin
class EventAccommodationsController < ApplicationController
include ClerkAuthenticatable

before_action :require_staff!
before_action :require_admin_access!
before_action :set_event
before_action :set_accommodation, only: [:update, :destroy, :upload]

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ class EventGalleryImagesController < ApplicationController
UploadAlreadyUsed = Class.new(StandardError)
UNCATEGORIZED_FILTER = "__uncategorized__".freeze

before_action :require_staff!
before_action :require_admin_access!
before_action :set_event
before_action :set_gallery_image, only: [ :update, :destroy, :upload ]

Expand Down Expand Up @@ -177,8 +177,17 @@ def bulk_update
return render json: { error: "Category must be #{EventGalleryImage::CATEGORY_MAX_LENGTH} characters or fewer" }, status: :unprocessable_entity
end

updated = @event.event_gallery_images.where(id: ids).update_all(attrs.merge(updated_at: Time.current))
render json: { updated: updated }
images = @event.event_gallery_images.where(id: ids).to_a
EventGalleryImage.transaction do
images.each { |image| image.update!(attrs) }
end
render json: { updated: images.size }
rescue ActiveRecord::RecordInvalid => e
render json: {
updated: 0,
image_id: e.record.id,
errors: e.record.errors.full_messages
}, status: :unprocessable_entity
end

def bulk_destroy
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ module Admin
class EventGalleryUploadBatchesController < ApplicationController
include ClerkAuthenticatable

before_action :require_staff!
before_action :require_admin_access!
before_action :set_event
before_action :set_batch, only: [:show, :update, :destroy]

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ module Admin
class EventResultsController < ApplicationController
include ClerkAuthenticatable
before_action :authenticate_user!
before_action :require_staff!
before_action :require_admin_access!
before_action :set_event
before_action :set_result, only: [:update, :destroy]

Expand Down
Loading