Compare commits

...
Author SHA1 Message Date
Tangzixy 0f181f218e Translate zh.json via GitLocalize 2026-04-13 10:47:43 +00:00
Ace06_10010 5472c08cb1 Translate zh.json via GitLocalize 2026-04-13 10:47:41 +00:00
Starystars67 0322221529 Move back to local served installer 2026-04-13 09:52:01 +01:00
Starystars67 9066e31c55 Use nginx:stable, add nginx config, non-root
Switch the runtime stage to nginx:stable (replacing alpine), remove the default static assets, and copy the built app into /usr/share/nginx/html. Add a custom nginx main config (nginx.main.conf → /etc/nginx/nginx.conf) and keep the default site config. Run the container as the non-root nginx user and expose port 80. These changes ensure the image serves the intended build, uses a stable nginx variant, and improves container security.
2026-04-13 00:54:51 +01:00
Starystars67 d19a10c08b correct actions workflows 2026-04-13 00:27:00 +01:00
Starystars67 a90e60ef32 Merge pull request #25 from BeamMP/dev 2026-04-13 00:19:08 +01:00
Starystars67 070fb38709 chang to node lts and correct json structure 2026-04-13 00:17:41 +01:00
Starystars67 ed1cb0e2a8 Cleanup 2026-04-13 00:08:22 +01:00
Starystars67 bedcd0cb50 Merge remote-tracking branch 'origin/main' into dev 2026-04-13 00:05:35 +01:00
Starystars67 2987de52ec 2.4.16 2026-04-12 23:55:03 +01:00
Starystars67 aaf888f182 Update release workflow by removing CA cert step
Removed installation of registry CA certificate and updated image tag from 'prod' to 'latest'.
2026-04-12 23:37:22 +01:00
Starystars67 052da9316c deperation.... 2026-04-02 03:35:42 +01:00
Starystars67 842e229e55 add zip to test download 2026-04-02 03:22:38 +01:00
Starystars67 b2742428d0 Test 2026-04-02 03:09:16 +01:00
Starystars67 48717eeabd Update nginx.conf 2026-04-02 02:53:16 +01:00
Starystars67 5f14414055 trying things at this point 2026-04-02 02:48:57 +01:00
Starystars67 a253919575 server hardening + deperation to tget the installer served 2026-04-02 02:42:55 +01:00
Starystars67 4626a69185 Serve .msi as download and update installer link
Add nginx rule to serve .msi files as application/octet-stream with Content-Disposition: attachment and X-Content-Type-Options: nosniff, returning 404 when missing. Update Home.vue to build the installer download URL from import.meta.env.BASE_URL and bind it to the CTA link (using :href) instead of a hardcoded path, ensuring the installer link respects the app base URL.
2026-04-02 02:13:11 +01:00
Starystars67 44268d076d Use imported images and URL helper
Replace hardcoded asset paths with bundler-friendly imports and a URL helper. Added getFlagUrl in LanguageSelector.vue to resolve flag assets via import.meta.url and replaced string-based src attributes. In Home.vue, import landingLq and landingHq and use them for initial and high-quality hero image loading to avoid direct '/src/...' paths and ensure proper asset resolution.
2026-04-02 01:34:31 +01:00
Starystars67 c2e460b408 Move landing images to src/assets
Rename public/landing-lq.jpg and public/landing_hq.png to src/assets and update Home.vue to use the new asset paths for loading the high-quality hero image (img.src and heroImageSrc). This ensures the images are managed by the app's asset pipeline.
2026-04-02 00:07:19 +01:00
Starystars67 c827c81d28 Fix metrics 2026-04-02 00:02:23 +01:00
Starystars67 5f9aad80ac mv flags 2026-04-01 23:55:16 +01:00
Starystars67 be9bae93de Use backend address. 2026-04-01 23:46:03 +01:00
Starystars67 5295ec664b Add docker-compose and MSI installer; fix paths
Add docker-compose.yml to run the website container (binds 127.0.0.1:3000 -> 80). Add BeamMP_Installer.msi to public/installer. Update src/views/Home.vue to use /landing-lq.jpg for the hero image (instead of /src/assets/landing-lq.jpg) and change the installer download link from BeamMP_Installer.zip to BeamMP_Installer.msi.
2026-04-01 22:28:32 +01:00
Starystars67 f59b5df887 remove mobile details plus try fix image 2026-04-01 22:00:48 +01:00
Starystars67 cf3c3790b5 changes for temp launch 2026-04-01 21:30:37 +01:00
Starystars67 4331a58e50 Update sync text, theme icons, communities link
Add responsive icons for system theme selection (Smartphone, Tablet, Monitor) in ThemeToggle.vue; add an "Explore Communities" CTA to Home.vue that links to the localized communities page. Reduce the advertised sync update rate from ~100 to ~50 times per second across multiple locale files (en, de, es, it, ru). Also update the English freeroam label/description to "Freeroam & Custom Servers" with details about custom scripts/maps/mods. Note: fr.json contains unresolved merge conflict markers for the sync description and needs manual resolution.
2026-02-21 19:07:30 +00:00
Starystars67 214ccd10d1 Update logo URL for Iceline Hosting 2026-01-30 22:00:47 +00:00
3v. c6fb3331c2 Update localisation for French language 2026-01-30 21:46:00 +00:00
Starystars67 391c8bc14e Change Docker tag from 'latest' to 'prod' 2026-01-30 21:38:33 +00:00
Starystars67 84d63cb84d Add condition for prerelease in staging workflow 2026-01-30 21:37:47 +00:00
Starystars67 e95c68165a Update release workflow for Docker registry integration 2026-01-30 21:37:08 +00:00
Starystars67 070e31dbec Update staging workflow for Docker image release 2026-01-30 21:32:58 +00:00
Starystars67 c9fc193aa3 change wording 2025-12-31 15:08:57 +00:00
Starystars67 e7f80d83a6 update server list image + bump version number 2025-12-31 13:02:38 +00:00
Starystars67 9d9c10179c fix: nav not opening on screen sizes between md and xl 2025-12-31 12:51:50 +00:00
Starystars67 e2a1b4a598 fix: white fade on hero image + update landing image + HQ loader after. 2025-12-31 12:49:10 +00:00
Starystars67 ca7b7e9d1b minor style changes 2025-12-29 23:36:46 +00:00
Starystars67 7e53a63455 Correct servers page for darkmode & improve some wording. 2025-12-29 22:37:55 +00:00
Starystars67 f2aec71b6e adjust color for partners on light mode 2025-12-29 19:47:43 +00:00
Starystars67 c317aa4e37 Add Initial Iceline Hosting partner 2025-12-29 19:08:11 +00:00
Starystars67 df371568c7 add GH release points to timeline & fix padding of nav and logo 2025-12-29 18:52:34 +00:00
Starystars67 6ed1bf7352 fixes: various bits fixed / improved based on fedback 2025-12-29 16:16:17 +00:00
Starystars67 31a179bc45 Update README.md 2025-12-24 13:08:35 +00:00
Starystars67 cf3c13c303 Update README.md 2025-12-24 13:07:48 +00:00
Starystars67 476211b220 Update Wabbanode Link 2025-12-24 11:49:54 +00:00
Starystars67 625e5fd596 fix another link 2025-12-23 14:33:23 +00:00
Starystars67 7f8633ab09 other small fixes 2025-12-23 14:24:11 +00:00
Starystars67 176b5c2934 Fix small link issue 2025-12-23 14:19:54 +00:00
Starystars67 cf53167cec Forgot to bump version 2025-12-23 14:08:10 +00:00
Starystars67 171bb3f018 Update Linux Builds 2025-12-23 14:06:44 +00:00
Starystars67 6e6470086e Update Zap-Hosting Link 2025-12-23 14:06:35 +00:00
Starystars67 b171d836ad Update Zap-Hosting Logo 2025-12-23 13:55:39 +00:00
Starystars67 f3315d443f Add Wabbanode 2025-12-23 13:18:36 +00:00
Starystars67 c09b0cc69f randomise partners list using date as the seed 2025-12-23 13:00:33 +00:00
Starystars67 88a3f10192 minor fixes 2025-12-23 12:52:44 +00:00
Starystars67 952d35535f Correct Zap-Hosting spelling 2025-12-23 12:33:43 +00:00
Starystars67 600123dd8b Add noscript site as well 2025-12-23 12:21:44 +00:00
Starystars67 b3d6f59aaf Lots of changes & improvements 2025-12-23 11:51:13 +00:00
Starystars67 07a84f25d5 Fix language selection to persist between pages and allow for sharing of specfic pages in chosen lang 2025-12-20 17:28:21 +00:00
Starystars67 f3269d0bee minor clean up and attempt to fix coloring 2025-12-20 02:34:26 +00:00
Starystars67 cdbf8f991c temp noscript addition 2025-12-20 02:26:44 +00:00
Starystars67 04fb9ba50f stop x scroll.. 2025-12-20 02:16:32 +00:00
Starystars67 2d83ba9dfd fix height to match theme toggle 2025-12-20 02:13:41 +00:00
Starystars67 c0a10c4710 Fix socials and linux icon 2025-12-20 02:09:12 +00:00
Starystars67 1e8489018d missed detail 2025-12-20 01:42:52 +00:00
Starystars67 ab6c93791f Update package.json 2025-12-20 01:22:09 +00:00
Starystars67andTixx acc1377bbb Add initial templates for additional languages
Co-Authored-By: Tixx <83774803+WiserTixx@users.noreply.github.com>
2025-12-20 01:20:03 +00:00
Starystars67andTixx 3873388b48 Added i18n Translation Support
Co-Authored-By: Tixx <83774803+WiserTixx@users.noreply.github.com>
2025-12-20 00:28:36 +00:00
Starystars67 0d4d34634a put correct servers address. 2025-11-30 17:41:15 +00:00
Starystars67 d5b7c52641 various changes 2025-11-30 17:39:52 +00:00
Starystars67 9c85fb2f10 Add GH actions files. 2025-11-30 16:08:36 +00:00
Starystars67 a2d2cb07d4 adjust dockerfile 2025-11-30 16:04:00 +00:00
Starystars67 403489e43c Rebuild website! 2025-11-30 16:01:49 +00:00
Starystars67 d24ec58185 bumped versions 2025-11-30 12:15:19 +00:00
Starystars67 a3f47c5b12 Update versions of launcher 2025-09-14 14:56:01 +01:00
Starystars67 d5c33e56e5 update launcher to 2.5.1 2025-09-13 17:35:10 +01:00
Starystars67 266c1470ba Update package.json 2025-02-10 10:15:53 +00:00
Starystars67 6fcf1d1f6f added build pipelines 2025-02-08 20:58:57 +00:00
Starystars67 30eb6b96e0 add dockerignore 2025-02-08 20:56:42 +00:00
Starystars67 ebb7611a92 update to include installer :( 2025-02-08 20:44:03 +00:00
Starystars67 77c71a501f update served version of launcher 2025-02-08 20:43:14 +00:00
Starystars67 c5988f94b0 Bump version of launcher and update some packages to solve vulnerabilities 2024-11-12 16:35:20 +00:00
Starystars67 1671b775e4 More bits of work 2024-10-22 19:10:46 +01:00
Starystars67 4d8c30f48c New navbar and updated logos & links 2024-10-22 16:57:42 +01:00
alex.ita d1150ed84d Update index.ejs
404 fix
2024-01-17 19:58:07 +00:00
Starystars67 5dfb7b79d7 bump build version 2024-01-17 19:42:09 +00:00
Starystars67 19abd94069 Merge pull request #18 from AlexITA1100/resize-fix
Resize fix
2024-01-17 19:39:58 +00:00
alex.ita c0f96b35de Merge branch 'BeamMP:main' into resize-fix 2024-01-17 20:38:36 +01:00
Starystars67 dedc16fb73 Merge pull request #16 from AlexITA1100/main
Made the website work when Javascript is disabled.
2024-01-17 19:36:38 +00:00
alex.ita f8d4478d35 Merge branch 'main' into main 2024-01-17 20:30:29 +01:00
alex.ita 738721119e Merge branch 'main' into resize-fix 2024-01-17 18:53:17 +01:00
Starystars67 b8a5db6d48 Merge pull request #19 from AlexITA1100/update-docs-link
Updated links to redirect to the docs instead of the wiki.
2024-01-17 12:03:35 +00:00
alex.ita cc48fe2ffc Update nav-nojs.ejs
Keeping the no-JS version in line with the resize fix.
2024-01-16 21:03:06 +01:00
alex.ita a307a3cd9f Updated links to docs. 2024-01-16 20:48:18 +01:00
alex.ita 9a2a10499d Updated links to redirect to the docs instead of the wiki. 2024-01-16 20:43:12 +01:00
alex.ita 3daa559a67 Updated for release.
Updated:
- Updated for v3.2.2 naming scheme changes.
- Made the links in `linux-builds.ejs` comply with [WCAG AAA standards](https://www.w3.org/WAI/WCAG22/quickref/#contrast-enhanced).
2024-01-16 20:31:58 +01:00
alex.ita e459538f18 Removed unused code 2024-01-11 13:50:06 +01:00
alex.ita 0065093ca3 Added route to new page.
Added route to Linux builds download page for JS-free users **ONLY**.
2024-01-09 11:14:16 +01:00
alex.ita 391f634d65 Changed Linux distro download option.
Moved from drop down menu to a new page.
This **will** need a new servlet in the backend.
2024-01-08 23:32:30 +01:00
alex.ita 838a33b4d5 Resize fix
Fixes the resize and zoom issues.
2024-01-06 12:07:56 +01:00
alex.ita 647ab8bda9 Updated to be future ready
Specified the architecture for Linux builds
2024-01-03 10:25:27 +01:00
alex.ita 8b37e854d8 CSS fix
Missed a comma
2023-12-18 10:16:17 +01:00
alex.ita 23ec17460e Made the website work when Javascript is disabled
Added:
- The website can now serve Javascript-free pages for user that have JS disabled or a browser that does not support it. The pages "/stats" and "/servers" cannot work without JS so the JS-fee index does not link to them;
- stats.ejs: if Javascript is disabled, won't serve any data but will prompt the user to enable Javascript.
Fixed:
- stats.ejs: copyright in the footer has been updated from "2021" to "2019 - present";
2023-12-16 19:26:02 +01:00
386 changed files with 81327 additions and 38648 deletions

No files matched your search

+34
View File
@@ -0,0 +1,34 @@
name: Build Docker image and push to release
on:
release:
types: [published]
jobs:
docker:
if: "!github.event.release.prerelease"
runs-on: ubuntu-latest
steps:
- name: Connect to Tailscale
uses: tailscale/github-action@v4
with:
oauth-client-id: ${{ secrets.TS_OAUTH_CLIENT_ID }}
oauth-secret: ${{ secrets.TS_OAUTH_SECRET }}
tags: tag:ci
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
with:
driver: docker
- name: Login to Docker Registry
uses: docker/login-action@v3
with:
registry: ${{ secrets.REGISTRY_URL }}
username: ${{ secrets.REGISTRY_USERNAME }}
password: ${{ secrets.REGISTRY_PASSWORD }}
- name: Build and push
uses: docker/build-push-action@v5
with:
push: true
tags: ${{ secrets.REGISTRY_URL }}/beammp/website:${{ github.REF_NAME }}, ${{ secrets.REGISTRY_URL }}/beammp/website:latest, ${{ secrets.REGISTRY_URL }}/beammp/website:production
+34
View File
@@ -0,0 +1,34 @@
name: Build Docker image and push to prerelease
on:
release:
types: [published]
jobs:
docker:
if: github.event.release.prerelease
runs-on: ubuntu-latest
steps:
- name: Connect to Tailscale
uses: tailscale/github-action@v4
with:
oauth-client-id: ${{ secrets.TS_OAUTH_CLIENT_ID }}
oauth-secret: ${{ secrets.TS_OAUTH_SECRET }}
tags: tag:ci
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
with:
driver: docker
- name: Login to Docker Registry
uses: docker/login-action@v3
with:
registry: ${{ secrets.REGISTRY_URL }}
username: ${{ secrets.REGISTRY_USERNAME }}
password: ${{ secrets.REGISTRY_PASSWORD }}
- name: Build and push
uses: docker/build-push-action@v5
with:
push: true
tags: ${{ secrets.REGISTRY_URL }}/beammp/website:${{ github.REF_NAME }}, ${{ secrets.REGISTRY_URL }}/beammp/website:latest
+1 -1
View File
@@ -102,7 +102,6 @@ dist
# TernJS port file # TernJS port file
.tern-port .tern-port
*.exe
*.zip *.zip
# Logs # Logs
@@ -129,3 +128,4 @@ frontend/*.ntvs*
frontend/*.njsproj frontend/*.njsproj
frontend/*.sln frontend/*.sln
frontend/*.sw? frontend/*.sw?
.DS_Store
+6
View File
@@ -0,0 +1,6 @@
node_modules
dist
*.log
.DS_Store
pnpm-lock.yaml
package-lock.json
+11
View File
@@ -0,0 +1,11 @@
{
"semi": false,
"singleQuote": true,
"tabWidth": 2,
"useTabs": false,
"trailingComma": "es5",
"printWidth": 100,
"arrowParens": "always",
"endOfLine": "lf",
"vueIndentScriptAndStyle": false
}
+27
View File
@@ -0,0 +1,27 @@
{
"cSpell.words": [
"beammp",
"beammpservers",
"beamng",
"Deutsch",
"Español",
"Français",
"freeroam",
"gridlines",
"Italiano",
"Lucide",
"maxplayers",
"modlist",
"modstotal",
"modstotalsize",
"Offroad",
"playerslist",
"reka",
"rels",
"roleplay",
"sdesc",
"sname",
"vueuse",
"Русский"
]
}
+21 -16
View File
@@ -1,25 +1,30 @@
FROM node:18.16.0-alpine3.17 # Step 1: Build stage
FROM node:lts-alpine AS build
# Create app directory
WORKDIR /app WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
ENV NODE_ENV=production
RUN npm run build
RUN apk --no-cache add curl # Step 2: Serve stage
FROM nginx:stable
# Install app dependencies # Remove default nginx static assets
# A wildcard is used to ensure both package.json AND package-lock.json are copied RUN rm -rf /usr/share/nginx/html/*
# where available (npm@5+)
COPY package*.json /app
# General Install of Deps # Copy built files from the previous stage
# RUN npm install COPY --from=build /app/dist /usr/share/nginx/html
# If you are building your code for production
RUN npm ci --only=production
# Bundle app source # Copy secure nginx configs
COPY . /app COPY nginx.main.conf /etc/nginx/nginx.conf
COPY nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 3599 # Use non-root user for security
USER nginx
HEALTHCHECK CMD curl --fail http://localhost:3599/ping || exit 1 # Expose port 80
EXPOSE 80
CMD [ "node", "index.js" ] CMD ["nginx", "-g", "daemon off;"]
+112 -1
View File
@@ -1 +1,112 @@
# BeamMP-Website # BeamMP Website
This repository is home for the BeamMP website. The website features support for translations too now!
**Tech Stack**
- **Framework:** Vue 3 (`vue`, `vue-router`)
- **Build:** Vite 7 (`vite`, `@vitejs/plugin-vue`)
- **Styling:** Tailwind CSS 4 + `tailwindcss-animate`, `tailwind-merge`
- **UI Icons/Utils:** `lucide-vue-next`, `clsx`, `class-variance-authority`
- **Radix-style Components:** `reka-ui` through `shadcn-vue`
- **Composable utilities:** `@vueuse/core`
**Theming and Colour Guide**
- BeamMP Orange `#F36D24`
- BeamMP Blue `#4470B6`
- BeamMP Green `#1D9749`
- Gray `#333333`
- Black `#000000`
- White `#FFFFFF`
## Getting Started
Prerequisites:
- Node.js 22+
- pnpm, npm, or yarn (examples use npm)
Install dependencies and run the dev server:
```powershell
# from this folder (repo root)
npm install
npm run dev
```
Build for production and preview locally:
```powershell
npm run build
npm run preview
```
Vite will print the local dev URL (usually `http://localhost:5173`).
## Project Scripts
- `npm run dev`: Start Vite development server
- `npm run build`: Production build
- `npm run preview`: Preview the production build locally
- `npm run lint`: Lint and auto-fix Vue/JS files with ESLint
- `npm run format`: Format all source files with Prettier
## Directory Overview
- `src/` – App source (styles, components, pages, routing)
- `src/components/ui/` – UI components (e.g., `button`, `navigation-menu`)
- `src/lib/` – Utilities and helpers
- `routes/` - vue-router routes
- `views/` - Pages of the website
- `index.html` – Vite HTML entry
- `tailwind.config.js` – Tailwind configuration
- `vite.config.js` – Vite configuration
- `components.json` – Shadcn-Vue component registry
## Contributing
We welcome contributions! Here’s how to get started.
### 1) Pick an Issue or Open One
- Browse issues or propose an enhancement/bug. Share context and repro steps.
### 2) Create a Branch
- Use a descriptive branch name:
- `feature/<short-description>`
- `fix/<short-description>`
- `docs/<short-description>`
### 3) Dev Environment
- Install deps with `npm install` and run `npm run dev`.
- Keep changes scoped and focused; avoid drive-by refactors unless agreed.
### 4) Code Style & Patterns
- **Vue 3 + `<script setup>`** preferred for new components.
- **Linting**: Run `npm run lint` before committing to catch errors. ESLint is configured for Vue 3 best practices.
- **Formatting**: Run `npm run format` to auto-format code with Prettier (or use an editor extension).
- **Type safety**: If/when TypeScript is introduced, prefer explicit props and emits.
- **Tailwind**: Use utility classes; extract variants with `class-variance-authority` when patterns repeat.
- **Accessibility**: Prefer accessible primitives (e.g., `reka-ui`) and keyboard support.
- **File naming**: `PascalCase.vue` for components; avoid one-letter variable names.
### 5) Testing & Checks
- Run the app locally and verify core flows.
- Ensure components render on both light/dark themes if relevant.
- If you add dependencies, update this README and relevant configs.
### 6) Commit & PR
- Write clear, imperative commit messages, e.g., `feat: add NavigationMenu component`.
- Open a PR describing the problem, solution, screenshots if UI changes, and any follow-ups.
- Link related issues. Keep PRs small; big changes should be split.
# Translations
BeamMP makes an effort to be maintained for multiple languages.
The current progress of this sits at:
[![gitlocalized ](https://gitlocalize.com/repo/10617/whole_project/badge.svg)](https://gitlocalize.com/repo/10617?utm_source=badge)
We use [GitLocalize](https://gitlocalize.com/) for managing this. You can contribute if you wish here: https://gitlocalize.com/repo/10617.
The individual language progress is as follows:
| Language | Badge |
|-----------------------|---------------------------------------------------------------------------------------------------------------------------------|
| French | [![gitlocalized ](https://gitlocalize.com/repo/10617/fr/badge.svg)](https://gitlocalize.com/repo/10617/fr?utm_source=badge) |
| German | [![gitlocalized ](https://gitlocalize.com/repo/10617/de/badge.svg)](https://gitlocalize.com/repo/10617/de?utm_source=badge) |
| Italian | [![gitlocalized ](https://gitlocalize.com/repo/10617/it/badge.svg)](https://gitlocalize.com/repo/10617/it?utm_source=badge) |
| Russian | [![gitlocalized ](https://gitlocalize.com/repo/10617/ru/badge.svg)](https://gitlocalize.com/repo/10617/ru?utm_source=badge) |
| Spanish | [![gitlocalized ](https://gitlocalize.com/repo/10617/es/badge.svg)](https://gitlocalize.com/repo/10617/es?utm_source=badge) |
+21
View File
@@ -0,0 +1,21 @@
{
"$schema": "https://shadcn-vue.com/schema.json",
"style": "new-york",
"typescript": false,
"tailwind": {
"config": "tailwind.config.js",
"css": "src/style.css",
"baseColor": "gray",
"cssVariables": true,
"prefix": ""
},
"iconLibrary": "lucide",
"aliases": {
"components": "@/components",
"utils": "@/lib/utils",
"ui": "@/components/ui",
"lib": "@/lib",
"composables": "@/composables"
},
"registries": {}
}
+8
View File
@@ -0,0 +1,8 @@
services:
website:
build:
dockerfile: Dockerfile
container_name: website
restart: unless-stopped
ports:
- "127.0.0.1:3000:80"
+74
View File
@@ -0,0 +1,74 @@
import pluginVue from 'eslint-plugin-vue'
import js from '@eslint/js'
import prettier from 'eslint-plugin-prettier'
import configPrettier from 'eslint-config-prettier'
export default [
// Ignore patterns (replaces .eslintignore)
{
ignores: ['node_modules', 'dist', '*.log', '.DS_Store'],
},
// Base JavaScript config
js.configs.recommended,
// Vue 3 recommended config
...pluginVue.configs['flat/recommended'],
// Global configuration
{
plugins: {
prettier,
},
languageOptions: {
ecmaVersion: 'latest',
sourceType: 'module',
globals: {
// Browser globals
window: 'readonly',
document: 'readonly',
navigator: 'readonly',
console: 'readonly',
localStorage: 'readonly',
fetch: 'readonly',
alert: 'readonly',
prompt: 'readonly',
getComputedStyle: 'readonly',
// Node globals
process: 'readonly',
__dirname: 'readonly',
__filename: 'readonly',
module: 'readonly',
require: 'readonly',
},
},
rules: {
// Prettier integration
...configPrettier.rules,
'prettier/prettier': 'error',
// Vue-specific rules
'vue/multi-word-component-names': 'off',
'vue/no-v-html': 'warn',
'vue/require-default-prop': 'off',
'vue/require-prop-types': 'warn',
'vue/component-name-in-template-casing': ['error', 'PascalCase'],
'vue/html-self-closing': [
'error',
{
html: {
void: 'always',
normal: 'always',
component: 'always',
},
},
],
// General JavaScript rules
'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off',
'prefer-const': 'error',
'no-var': 'error',
},
},
]
-3
View File
@@ -1,3 +0,0 @@
INSTANCES=3
DEBUG=false
PORT=3000
-7
View File
@@ -1,7 +0,0 @@
# Vue 3 + Vite
This template should help get you started developing with Vue 3 in Vite. The template uses Vue 3 `<script setup>` SFCs, check out the [script setup docs](https://v3.vuejs.org/api/sfc-script-setup.html#sfc-script-setup) to learn more.
## Recommended IDE Setup
- [VS Code](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin).
-13
View File
@@ -1,13 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>BeamMP</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.js"></script>
</body>
</html>
-5395
View File
File diff suppressed because it is too large. Load diff
-30
View File
@@ -1,30 +0,0 @@
{
"name": "beammp-website-frontend",
"private": true,
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite preview"
},
"dependencies": {
"@headlessui/vue": "^1.7.16",
"@heroicons/vue": "^2.0.18",
"@statnett/vue-plotly": "^0.3.2",
"axios": "^1.6.2",
"plotly.js": "^2.27.1",
"plotly.js-dist": "^2.27.1",
"plotly.js-dist-min": "^2.27.1",
"uuid": "^9.0.1",
"vue": "^3.3.8",
"vue-router": "^4.2.5"
},
"devDependencies": {
"@vitejs/plugin-vue": "^4.5.0",
"autoprefixer": "^10.4.16",
"postcss": "^8.4.32",
"tailwindcss": "^3.3.6",
"vite": "^5.0.0"
}
}
-6
View File
@@ -1,6 +0,0 @@
export default {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
}
-1
View File
@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg>

Before

Width:  |  Height:  |  Size: 1.5 KiB

-10
View File
@@ -1,10 +0,0 @@
<script setup>
import Navbar from '@/components/NavBar.vue'
import Footer from '@/components/Footer.vue'
</script>
<template>
<Navbar />
<router-view />
<Footer />
</template>
Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.0 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.2 KiB

-121
View File
@@ -1,121 +0,0 @@
<template>
<div class="bg-gray-800 text-gray-400">
<div class="px-4 pt-16 mx-auto md:max-w-full lg:max-w-screen-xl md:px-24 lg:px-8">
<div class="grid gap-16 row-gap-10 mb-8 lg:grid-cols-6">
<div class="md:max-w-md lg:col-span-2">
<a href="/" aria-label="Go home" title="Company" class="inline-flex items-center">
<img class="h-8 w-auto" src="../assets/beammp-logo.png" alt="BeamMP Logo" />
<span class="ml-4 text-xl font-bold tracking-wide text-gray-200 uppercase">BeamMP</span>
</a>
<div class="mt-4 lg:max-w-sm">
<p class="text-sm text-gray-300">
Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam.
</p>
<p class="mt-4 text-sm text-gray-300">
Eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo.
</p>
</div>
</div>
<div class="grid grid-cols-2 gap-5 row-gap-8 lg:col-span-4 md:grid-cols-4">
<div>
<p class="font-semibold tracking-wide text-gray-200">Sites</p>
<ul class="mt-2 space-y-2">
<li>
<a href="https://patreon.com/beammp" class="text-gray-300 transition-colors duration-300 hover:text-deep-purple-accent-400">Patreon</a>
</li>
<li>
<a href="https://forum.beammp.com/" class="text-gray-300 transition-colors duration-300 hover:text-deep-purple-accent-400">Forum</a>
</li>
<li>
<a href="https://keymaster.beammp.com/" class="text-gray-300 transition-colors duration-300 hover:text-deep-purple-accent-400">Keymaster</a>
</li>
<li>
<a href="https://docs.beammp.com/" class="text-gray-300 transition-colors duration-300 hover:text-deep-purple-accent-400">Docs</a>
</li>
<li>
<a href="https://store.beammp.com/" class="text-gray-300 transition-colors duration-300 hover:text-deep-purple-accent-400">Store</a>
</li>
</ul>
</div>
<div>
<p class="font-semibold tracking-wide text-gray-200">GitHub</p>
<ul class="mt-2 space-y-2">
<li>
<a href="https://github.com/BeamMP/BeamMP" class="text-gray-300 transition-colors duration-300 hover:text-deep-purple-accent-400">Mod</a>
</li>
<li>
<a href="https://github.com/BeamMP/BeamMP-Launcher" class="text-gray-300 transition-colors duration-300 hover:text-deep-purple-accent-400">Launcher</a>
</li>
<li>
<a href="https://github.com/BeamMP/BeamMP-Server" class="text-gray-300 transition-colors duration-300 hover:text-deep-purple-accent-400">Server</a>
</li>
</ul>
</div>
<div>
<p class="font-semibold tracking-wide text-gray-200">?</p>
<ul class="mt-2 space-y-2">
<li>
<a href="/" class="text-gray-300 transition-colors duration-300 hover:text-deep-purple-accent-400">?</a>
</li>
<li>
<a href="/" class="text-gray-300 transition-colors duration-300 hover:text-deep-purple-accent-400">?</a>
</li>
<li>
<a href="/" class="text-gray-300 transition-colors duration-300 hover:text-deep-purple-accent-400">?</a>
</li>
<li>
<a href="/" class="text-gray-300 transition-colors duration-300 hover:text-deep-purple-accent-400">?</a>
</li>
<li>
<a href="/" class="text-gray-300 transition-colors duration-300 hover:text-deep-purple-accent-400">?</a>
</li>
</ul>
</div>
<div>
<p class="font-semibold tracking-wide text-gray-200">Documents</p>
<ul class="mt-2 space-y-2">
<li>
<a href="/rules" class="text-gray-300 transition-colors duration-300 hover:text-deep-purple-accent-400">Rules</a>
</li>
<li>
<a href="/privacy" class="text-gray-300 transition-colors duration-300 hover:text-deep-purple-accent-400">Privacy policy</a>
</li>
<li>
<a href="/terms" class="text-gray-300 transition-colors duration-300 hover:text-deep-purple-accent-400">Terms</a>
</li>
</ul>
</div>
</div>
</div>
<div class="flex flex-col justify-between pt-5 pb-10 border-t sm:flex-row">
<p class="text-sm text-gray-300">
© Copyright 2024 BeamMP. All rights reserved.
</p>
<div class="flex items-center mt-4 space-x-4 sm:mt-0">
<a href="/" class="text-gray-400 transition-colors duration-300 hover:text-deep-purple-accent-400">
<svg viewBox="0 0 24 24" fill="currentColor" class="h-5">
<path
d="M24 4.6c-0.9 0.4-1.8 0.7-2.8 0.8c1-0.6 1.8-1.6 2.2-2.7c-1 0.6-2 1-3.1 1.2c-0.9-1-2.2-1.6-3.6-1.6 c-2.7 0-4.9 2.2-4.9 4.9c0 0.4 0 0.8 0.1 1.1C7.7 8.1 4.1 6.1 1.7 3.1C1.2 3.9 1 4.7 1 5.6c0 1.7 0.9 3.2 2.2 4.1 C2.4 9.7 1.6 9.5 1 9.1c0 0 0 0 0 0.1c0 2.4 1.7 4.4 3.9 4.8c-0.4 0.1-0.8 0.2-1.3 0.2c-0.3 0-0.6 0-0.9-0.1c0.6 2 2.4 3.4 4.6 3.4 c-1.7 1.3-3.8 2.1-6.1 2.1c-0.4 0-0.8 0-1.2-0.1c2.2 1.4 4.8 2.2 7.5 2.2c9.1 0 14-7.5 14-14c0-0.2 0-0.4 0-0.6 C22.5 6.4 23.3 5.5 24 4.6z"
></path>
</svg>
</a>
<a href="/" class="text-gray-400 transition-colors duration-300 hover:text-deep-purple-accent-400">
<svg viewBox="0 0 30 30" fill="currentColor" class="h-6">
<circle cx="15" cy="15" r="4"></circle>
<path
d="M19.999 3h-10C6.14 3 3 6.141 3 10.001v10C3 23.86 6.141 27 10.001 27h10C23.86 27 27 23.859 27 19.999v-10 C27 6.14 23.859 3 19.999 3z M15 21c-3.309 0-6-2.691-6-6s2.691-6 6-6s6 2.691 6 6S18.309 21 15 21z M22 9c-0.552 0-1-0.448-1-1 c0-0.552 0.448-1 1-1s1 0.448 1 1C23 8.552 22.552 9 22 9z"
></path>
</svg>
</a>
<a href="/" class="text-gray-400 transition-colors duration-300 hover:text-deep-purple-accent-400">
<svg viewBox="0 0 24 24" fill="currentColor" class="h-5">
<path
d="M22 0H2C0.895 0 0 0.895 0 2v20c0 1.105 0.895 2 2 2h11v-9h-3v-4h3V8.413c0-3.1 1.893-4.788 4.659-4.788 c1.325 0 2.463 0.099 2.795 0.143v3.24l-1.918 0.001c-1.504 0-1.795 0.715-1.795 1.763V11h4.44l-1 4h-3.44v9H22c1.105 0 2-0.895 2-2 V2C24 0.895 23.105 0 22 0z"
></path>
</svg>
</a>
</div>
</div>
</div>
</div>
</template>
-133
View File
@@ -1,133 +0,0 @@
<template>
<Disclosure as="nav" class="bg-gray-800" v-slot="{ open }">
<div class="mx-auto max-w-7xl px-2 sm:px-6 lg:px-8">
<div class="relative flex h-16 items-center justify-between">
<div class="absolute inset-y-0 left-0 flex items-center sm:hidden">
<!-- Mobile menu button-->
<DisclosureButton
class="relative inline-flex items-center justify-center rounded-md p-2 text-gray-400 hover:bg-gray-700 hover:text-white focus:outline-none focus:ring-2 focus:ring-inset focus:ring-white">
<span class="absolute -inset-0.5" />
<span class="sr-only">Open main menu</span>
<Bars3Icon v-if="!open" class="block h-6 w-6" aria-hidden="true" />
<XMarkIcon v-else class="block h-6 w-6" aria-hidden="true" />
</DisclosureButton>
</div>
<div class="flex flex-1 items-center justify-center sm:items-stretch sm:justify-start">
<div class="flex flex-shrink-0 items-center">
<a href="/"><img class="h-8 w-auto" src="../assets/beammp-logo.png" alt="BeamMP Logo" /></a>
</div>
<div class="hidden sm:ml-6 sm:block">
<div class="flex space-x-4">
<a v-for="item in navigation" :key="item.name" :href="item.href"
:class="[item.current ? 'bg-gray-900 text-white' : 'text-gray-300 hover:bg-gray-700 hover:text-white', 'rounded-md px-3 py-2 text-sm font-medium']"
:aria-current="item.current ? 'page' : undefined">{{ item.name }}</a>
</div>
</div>
</div>
<!-- Mode Switcher Dropdown -->
<div class="flex items-center border-l border-slate-200 ml-6 pl-6 dark:border-slate-800">
<label class="sr-only" id="headlessui-listbox-label-:Rpkcr6:" data-headlessui-state="">Theme</label>
<button type="button" id="headlessui-listbox-button-:R19kcr6:" aria-haspopup="true" aria-expanded="false" data-headlessui-state="" aria-labelledby="headlessui-listbox-label-:Rpkcr6: headlessui-listbox-button-:R19kcr6:" class="">
<span class="dark:hidden">
<svg viewBox="0 0 24 24" fill="none" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="w-6 h-6">
<path d="M15 12a3 3 0 1 1-6 0 3 3 0 0 1 6 0Z" class="stroke-slate-400 dark:stroke-slate-500"></path>
<path
d="M12 4v1M17.66 6.344l-.828.828M20.005 12.004h-1M17.66 17.664l-.828-.828M12 20.01V19M6.34 17.664l.835-.836M3.995 12.004h1.01M6 6l.835.836"
class="stroke-slate-400 dark:stroke-slate-500"></path>
</svg>
</span>
<span class="hidden dark:inline">
<svg viewBox="0 0 24 24" fill="none" class="w-6 h-6">
<path fill-rule="evenodd" clip-rule="evenodd"
d="M17.715 15.15A6.5 6.5 0 0 1 9 6.035C6.106 6.922 4 9.645 4 12.867c0 3.94 3.153 7.136 7.042 7.136 3.101 0 5.734-2.032 6.673-4.853Z"
class="fill-transparent"></path>
<path
d="m17.715 15.15.95.316a1 1 0 0 0-1.445-1.185l.495.869ZM9 6.035l.846.534a1 1 0 0 0-1.14-1.49L9 6.035Zm8.221 8.246a5.47 5.47 0 0 1-2.72.718v2a7.47 7.47 0 0 0 3.71-.98l-.99-1.738Zm-2.72.718A5.5 5.5 0 0 1 9 9.5H7a7.5 7.5 0 0 0 7.5 7.5v-2ZM9 9.5c0-1.079.31-2.082.845-2.93L8.153 5.5A7.47 7.47 0 0 0 7 9.5h2Zm-4 3.368C5 10.089 6.815 7.75 9.292 6.99L8.706 5.08C5.397 6.094 3 9.201 3 12.867h2Zm6.042 6.136C7.718 19.003 5 16.268 5 12.867H3c0 4.48 3.588 8.136 8.042 8.136v-2Zm5.725-4.17c-.81 2.433-3.074 4.17-5.725 4.17v2c3.552 0 6.553-2.327 7.622-5.537l-1.897-.632Z"
class="fill-slate-400 dark:fill-slate-500"></path>
<path fill-rule="evenodd" clip-rule="evenodd"
d="M17 3a1 1 0 0 1 1 1 2 2 0 0 0 2 2 1 1 0 1 1 0 2 2 2 0 0 0-2 2 1 1 0 1 1-2 0 2 2 0 0 0-2-2 1 1 0 1 1 0-2 2 2 0 0 0 2-2 1 1 0 0 1 1-1Z"
class="fill-slate-400 dark:fill-slate-500"></path>
</svg>
</span>
</button>
</div>
<!--<div class="absolute inset-y-0 right-0 flex items-center pr-2 sm:static sm:inset-auto sm:ml-6 sm:pr-0">
<button type="button" class="relative rounded-full bg-gray-800 p-1 text-gray-400 hover:text-white focus:outline-none focus:ring-2 focus:ring-white focus:ring-offset-2 focus:ring-offset-gray-800">
<span class="absolute -inset-1.5" />
<span class="sr-only">View notifications</span>
<BellIcon class="h-6 w-6" aria-hidden="true" />
</button>-->
<!-- Profile dropdown - From the Forum Accounts System -->
<!--<Menu as="div" class="relative ml-3">
<div>
<MenuButton class="relative flex rounded-full bg-gray-800 text-sm focus:outline-none focus:ring-2 focus:ring-white focus:ring-offset-2 focus:ring-offset-gray-800">
<span class="absolute -inset-1.5" />
<span class="sr-only">Open user menu</span>
<img class="h-8 w-8 rounded-full" src="https://images.unsplash.com/photo-1472099645785-5658abf4ff4e?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80" alt="" />
</MenuButton>
</div>
<transition enter-active-class="transition ease-out duration-100" enter-from-class="transform opacity-0 scale-95" enter-to-class="transform opacity-100 scale-100" leave-active-class="transition ease-in duration-75" leave-from-class="transform opacity-100 scale-100" leave-to-class="transform opacity-0 scale-95">
<MenuItems class="absolute right-0 z-10 mt-2 w-48 origin-top-right rounded-md bg-white py-1 shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none">
<MenuItem v-slot="{ active }">
<a href="#" :class="[active ? 'bg-gray-100' : '', 'block px-4 py-2 text-sm text-gray-700']">Your Profile</a>
</MenuItem>
<MenuItem v-slot="{ active }">
<a href="#" :class="[active ? 'bg-gray-100' : '', 'block px-4 py-2 text-sm text-gray-700']">Settings</a>
</MenuItem>
<MenuItem v-slot="{ active }">
<a href="#" :class="[active ? 'bg-gray-100' : '', 'block px-4 py-2 text-sm text-gray-700']">Sign out</a>
</MenuItem>
</MenuItems>
</transition>
</Menu>-->
<!--</div>-->
</div>
</div>
<DisclosurePanel class="sm:hidden">
<div class="space-y-1 px-2 pb-3 pt-2">
<DisclosureButton v-for="item in navigation" :key="item.name" as="a" :href="item.href"
:class="[item.current ? 'bg-gray-900 text-white' : 'text-gray-300 hover:bg-gray-700 hover:text-white', 'block rounded-md px-3 py-2 text-base font-medium']"
:aria-current="item.current ? 'page' : undefined">{{ item.name }}</DisclosureButton>
</div>
</DisclosurePanel>
</Disclosure>
</template>
<script>
export default {
methods: {
setTheme(theme) {
if (theme === 'light') {
document.documentElement.classList.remove('dark');
} else if (theme === 'dark') {
document.documentElement.classList.add('dark');
} else if (theme === 'system') {
document.documentElement.classList.remove('dark');
}
},
},
};
</script>
<script setup>
import { Disclosure, DisclosureButton, DisclosurePanel, Menu, MenuButton, MenuItem, MenuItems } from '@headlessui/vue'
import { Bars3Icon, BellIcon, XMarkIcon } from '@heroicons/vue/24/outline'
const navigation = [
{ name: 'Forum', href: 'https://forum.beammp.com/', current: false },
{ name: 'Docs', href: 'https://docs.beammp.com/', current: false },
{ name: 'Stats', href: '/stats', current: false },
{ name: 'Servers', href: '/servers', current: false },
{ name: 'Hosting', href: '/hosting', current: false },
{ name: 'Events', href: 'https://forum.beammp.com/c/important/events/25', current: false },
{ name: 'Store', href: 'https://store.beammp.com/', current: false },
{ name: 'GitHub', href: 'https://github.com/BeamMP', current: false },
{ name: 'Patreon', href: 'https://patreon.com/BeamMP', current: false },
]
var isOpen = false
</script>
@@ -1,14 +0,0 @@
<template>
<div class="bg-white py-24 sm:py-32">
<div class="mx-auto max-w-7xl px-6 lg:px-8">
<h2 class="text-center text-lg font-semibold leading-8 text-gray-900">Used by some of the largest and most innovative BeamNG communities</h2>
<div class="mx-auto mt-10 grid max-w-lg grid-cols-4 items-center gap-x-8 gap-y-10 sm:max-w-xl sm:grid-cols-6 sm:gap-x-10 lg:mx-0 lg:max-w-none lg:grid-cols-5">
<a href="https://discord.gg/carp"><img class="col-span-2 max-h-10 w-full object-contain lg:col-span-1" src="@/assets/communities/carp-logo.png" alt="CaRP" width="158" height="48" /></a>
<a href="https://discord.2fast.racing/"><img class="col-span-2 max-h-12 w-full object-contain lg:col-span-1" src="@/assets/communities/2fast-logo.png" alt="2FastRacing" width="158" height="48" /></a>
<a href="https://discord.beamcruise.com"><img class="col-span-2 max-h-12 w-full object-contain lg:col-span-1" src="@/assets/communities/beamcruise-logo.png" alt="Beam\\Cruise" width="158" height="48" /></a>
<a href="https://discord.gg/b9G3fXKqpg"><img class="col-span-2 max-h-12 w-full object-contain lg:col-span-1" src="@/assets/communities/nuclear-logo.png" alt="CnR" width="158" height="48" /></a>
<img class="col-span-2 col-start-2 max-h-12 w-full object-contain sm:col-start-auto lg:col-span-1" src="@/assets/beammp-logo.png" alt="Community E" width="158" height="48" />
</div>
</div>
</div>
</template>
-27
View File
@@ -1,27 +0,0 @@
<template>
<div class="bg-white">
<div class="mx-auto max-w-7xl py-24 sm:px-6 sm:py-32 lg:px-8">
<div class="relative isolate overflow-hidden bg-gray-900 px-6 pt-16 shadow-2xl sm:rounded-3xl sm:px-16 md:pt-24 lg:flex lg:gap-x-20 lg:px-24 lg:pt-0">
<svg viewBox="0 0 1024 1024" class="absolute left-1/2 top-1/2 -z-10 h-[64rem] w-[64rem] -translate-y-1/2 [mask-image:radial-gradient(closest-side,white,transparent)] sm:left-full sm:-ml-80 lg:left-1/2 lg:ml-0 lg:-translate-x-1/2 lg:translate-y-0" aria-hidden="true">
<circle cx="512" cy="512" r="512" fill="url(#759c1415-0410-454c-8f7c-9a820de03641)" fill-opacity="0.7" />
<defs>
<radialGradient id="759c1415-0410-454c-8f7c-9a820de03641">
<stop stop-color="#7775D6" />
<stop offset="1" stop-color="#E935C1" />
</radialGradient>
</defs>
</svg>
<div class="mx-auto max-w-md text-center lg:mx-0 lg:flex-auto lg:py-32 lg:text-left">
<h2 class="text-3xl font-bold tracking-tight text-white sm:text-4xl">Looking to write your own mods, plugins or resources?</h2>
<p class="mt-6 text-lg leading-8 text-gray-300">Check out our docs to get you started with developing your own mods and resources.</p>
<div class="mt-10 flex items-center justify-center gap-x-6 lg:justify-start">
<a href="https://docs.beammp.com" class="rounded-md bg-white px-3.5 py-2.5 text-sm font-semibold text-gray-900 shadow-sm hover:bg-gray-100 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-white">Learn more <span aria-hidden="true">→</span></a>
</div>
</div>
<div class="relative mt-16 h-80 lg:mt-8">
<img class="absolute left-0 top-0 w-[57rem] max-w-none rounded-md bg-white/5 ring-1 ring-white/10" src="https://tailwindui.com/img/component-images/dark-project-app-screenshot.png" alt="App screenshot" width="1824" height="1080" />
</div>
</div>
</div>
</div>
</template>
@@ -1,48 +0,0 @@
<template>
<div class="overflow-hidden bg-white py-24 sm:py-32">
<div class="mx-auto max-w-7xl px-6 lg:px-8">
<div class="mx-auto grid max-w-2xl grid-cols-1 gap-x-8 gap-y-16 sm:gap-y-20 lg:mx-0 lg:max-w-none lg:grid-cols-2">
<div class="lg:pr-8 lg:pt-4">
<div class="lg:max-w-lg">
<h2 class="text-base font-semibold leading-7 text-indigo-600">Integrated Server list</h2>
<p class="mt-2 text-3xl font-bold tracking-tight text-gray-900 sm:text-4xl">Choose a server to your liking</p>
<p class="mt-6 text-lg leading-8 text-gray-600">BeamMP has a builtin server list allowing you to select the server that appeals to your liking the most.</p>
<dl class="mt-10 max-w-xl space-y-8 text-base leading-7 text-gray-600 lg:max-w-none">
<div v-for="feature in features" :key="feature.name" class="relative pl-9">
<dt class="inline font-semibold text-gray-900">
<component :is="feature.icon" class="absolute left-1 top-1 h-5 w-5 text-indigo-600" aria-hidden="true" />
{{ feature.name }}
</dt>
{{ ' ' }}
<dd class="inline">{{ feature.description }}</dd>
</div>
</dl>
</div>
</div>
<img src="@/assets/beammp-servers.png" alt="Product screenshot" class="w-[48rem] max-w-none rounded-xl shadow-xl ring-1 ring-gray-400/10 sm:w-[57rem] md:-ml-4 lg:-ml-0" width="2432" height="1442" />
</div>
</div>
</div>
</template>
<script setup>
import { CloudArrowUpIcon, LockClosedIcon, ServerIcon } from '@heroicons/vue/20/solid'
const features = [
{
name: 'Custom mods',
description: 'BeamMP includes resource sharing functionality so that you can share your favorite mods with your friends directly from the same server. This applies with each and every server too!',
icon: CloudArrowUpIcon,
},
{
name: 'Public & Private Servers',
description: 'You have full control over your server including if you want it public for others to join or not.',
icon: LockClosedIcon,
},
{
name: 'Self and Paid Hosting',
description: 'You are free to host your own server or check out one of our parters who can have you up and running in minutes.',
icon: ServerIcon,
},
]
</script>
@@ -1,48 +0,0 @@
<template>
<div class="overflow-hidden bg-white py-24 sm:py-32">
<div class="mx-auto max-w-7xl px-6 lg:px-8">
<div class="mx-auto grid max-w-2xl grid-cols-1 gap-x-8 gap-y-16 sm:gap-y-20 lg:mx-0 lg:max-w-none lg:grid-cols-2">
<div class="lg:pr-8 lg:pt-4">
<div class="lg:max-w-lg">
<h2 class="text-base font-semibold leading-7 text-indigo-600">Integrated Server list</h2>
<p class="mt-2 text-3xl font-bold tracking-tight text-gray-900 sm:text-4xl">Choose a server to your liking</p>
<p class="mt-6 text-lg leading-8 text-gray-600">BeamMP has a builtin server list allowing you to select the server that appeals to your liking the most.</p>
<dl class="mt-10 max-w-xl space-y-8 text-base leading-7 text-gray-600 lg:max-w-none">
<div v-for="feature in features" :key="feature.name" class="relative pl-9">
<dt class="inline font-semibold text-gray-900">
<component :is="feature.icon" class="absolute left-1 top-1 h-5 w-5 text-indigo-600" aria-hidden="true" />
{{ feature.name }}
</dt>
{{ ' ' }}
<dd class="inline">{{ feature.description }}</dd>
</div>
</dl>
</div>
</div>
<img src="@/assets/beammp-servers.png" alt="Product screenshot" class="w-[48rem] max-w-none rounded-xl shadow-xl ring-1 ring-gray-400/10 sm:w-[57rem] md:-ml-4 lg:-ml-0" width="2432" height="1442" />
</div>
</div>
</div>
</template>
<script setup>
import { CloudArrowUpIcon, LockClosedIcon, ServerIcon } from '@heroicons/vue/20/solid'
const features = [
{
name: 'Custom mods',
description: 'BeamMP includes resource sharing functionality so that you can share your favorite mods with your friends directly from the same server. This applies with each and every server too!',
icon: CloudArrowUpIcon,
},
{
name: 'Public & Private Servers',
description: 'You have full control over your server including if you want it public for others to join or not.',
icon: LockClosedIcon,
},
{
name: 'Self and Paid Hosting',
description: 'You are free to host your own server or check out one of our parters who can have you up and running in minutes.',
icon: ServerIcon,
},
]
</script>
-58
View File
@@ -1,58 +0,0 @@
<template>
<header class="main-content" :style="{ 'background-position': 'center center, center 0px' }">
<div class="introduction" style="margin-top: 0px;">
<div class="container mx-auto">
<div class="flex items-center justify-center">
<div class="lg:w-8/12 md:w-8/12 sm:w-8/12 xs:w-full">
<p class="lead">
<b>BeamMP</b> Bringing Multiplayer to BeamNG.drive!<br>
With a smooth and enjoyable experience.
</p>
</div>
<div id="button" class="lg:w-4/12 md:w-4/12 sm:w-4/12 xs:w-full hidden-xs buttons-wrapper">
<div class="buttons mt-3">
<button @click="downloadInstaller" class="download-client js-show-story" href="beamMP.zip" download="">
<img class="os-icon" src="https://raw.githubusercontent.com/devicons/devicon/master/icons/windows8/windows8-original.svg" alt="windows-logo">
<span class="text">Download Client</span>
<span class="description"> BeamMP_Installer.zip</span>
</button>
</div>
<div class="buttons mt-3">
<form action="https://github.com/BeamMP/BeamMP-Server/releases/latest/download/BeamMP-Server.exe">
<button class="download-client js-show-story" style="background: radial-gradient(circle,rgb(255 179 38 / 80%),rgb(255 176 0 / 65%)) center/100%;">
<img class="os-icon" src="https://raw.githubusercontent.com/devicons/devicon/master/icons/windows8/windows8-original.svg" alt="windows-logo">
<span class="text">Download Server</span>
<span class="description"> BeamMP-Server.exe</span>
</button>
</form>
</div>
<div class="buttons mt-3">
<form action="https://github.com/BeamMP/BeamMP-Server/releases/latest">
<button class="download-client js-show-story" style="background: radial-gradient(circle,rgb(255 179 38 / 80%),rgb(255 176 0 / 65%)) center/100%;">
<img class="os-icon" src="https://raw.githubusercontent.com/devicons/devicon/master/icons/linux/linux-plain.svg" alt="linux-logo">
<span class="text">Download Server</span>
<span class="description">Linux builds</span>
</button>
</form>
</div>
</div>
</div>
</div>
</div>
</header>
</template>
<script>
export default {
methods: {
downloadInstaller() {
// Implement your download logic here
// You can use the window.location.href or any other method
}
}
}
</script>
<style scoped>
/* Add your Tailwind CSS styles here */
</style>
-16
View File
@@ -1,16 +0,0 @@
<template>
<div class="bg-white py-24 sm:py-32">
<div class="mx-auto max-w-7xl px-6 lg:px-8">
<h2 class="text-center text-lg font-semibold leading-8 text-gray-900">Proudly partnered with trusted hosting companies</h2>
<div v-for="partner in partners" :key="partner.id" class="mx-auto mt-10 grid max-w-lg grid-cols-4 items-center gap-x-8 gap-y-10 sm:max-w-xl sm:grid-cols-6 sm:gap-x-10 lg:mx-0 lg:max-w-none lg:grid-cols-5">
<a :href="partner.link"><img class="col-span-2 max-h-12 w-full object-contain lg:col-span-1" :src="partner.logo" :alt="partner.alt" width="158" height="48" /></a>
</div>
</div>
</div>
</template>
<script setup>
const partners = [
{ id: 1, logo: 'src/assets/partners/horizon_hosting-logo.png', alt: 'Horizon Hosting', link: 'https://billing.horizonnetworks.uk/store/beammp-server-hosting' },
]
</script>
-21
View File
@@ -1,21 +0,0 @@
<template>
<div class="bg-white dark:bg-slate-800 py-24 sm:py-32">
<div class="mx-auto max-w-7xl px-6 lg:px-8">
<dl class="grid grid-cols-1 gap-x-8 gap-y-16 text-center lg:grid-cols-4">
<div v-for="stat in stats" :key="stat.id" class="mx-auto flex max-w-xs flex-col gap-y-4">
<a :href="stat.link"><dt class="text-base leading-7 text-gray-600 dark:text-white">{{ stat.name }}</dt></a>
<dd class="order-first text-3xl font-semibold tracking-tight text-gray-900 sm:text-5xl dark:text-slate-400">{{ stat.value }}</dd>
</div>
</dl>
</div>
</div>
</template>
<script setup>
const stats = [
{ id: 1, name: 'Players Online', value: '1500', link: '/stats' },
{ id: 2, name: 'Public Servers', value: '1200', link: '/stats' },
{ id: 3, name: 'Users', value: '+760,000', link: 'https://forum.beammp.com' },
{ id: 4, name: 'Discord Members', value: '+190,000', link: 'https://discord.com/servers/beammp-601558901657305098' },
]
</script>
@@ -1,169 +0,0 @@
<template>
<div class="expanded-row-details">
<h1 style="padding-left:10px;display:flex;">
<template v-if="rowData.raw.official">
<img src="/src/assets/beammp-logo.png" alt="" style="height: 23px; padding-right: 10px;"> [Official Server]
</template>
<template v-else>
<img src="/src/assets/beammp-logo.png" alt="" style="height: 23px; padding-right: 10px;">
</template>
<span v-for="(value, name) in rowData.name" :style="value.f">{{ value.s }}</span>
</h1>
<div class="columns-2">
<div>
<h2 class="text-xl">Information:</h2>
<hr/>
<table class="description-table">
<tr>
<td>Owner:</td>
<td>{{rowData.raw.owner|| ""}}</td>
</tr>
<tr>
<td>Map:</td>
<td>{{rowData.map || ""}}</td>
</tr>
</table>
</div>
<div>
<div>
<h2 class="text-xl">Description:</h2>
<hr/>
<p><span v-for="(value, name) in formatDescriptionName(rowData.raw.sdesc)" :style="value.f">{{ value.s }}</span></p>
</div>
<div>
<h2 class="text-xl">Mods ({{modCount(rowData.raw.modlist|| "")}}):</h2>
<hr/>
<p>{{modList(rowData.raw.modlist|| "")}} ({{formatBytes(rowData.raw.modstotalsize) || "0B"}})</p>
</div>
</div>
</div>
<div class="row">
<h1 class="text-xl">Players ({{rowData.players|| "0"}}):</h1>
<hr/>
<p>{{listPlayers(rowData.raw.playerslist|| "")}}</p>
</div>
</div>
</template>
<script>
var descStyleMap = {
'^0': 'color:#000000',
'^1': 'color:#0000AA',
'^2': 'color:#00AA00',
'^3': 'color:#00AAAA',
'^4': 'color:#AA0000',
'^5': 'color:#AA00AA',
'^6': 'color:#FFAA00',
'^7': 'color:#AAAAAA',
'^8': 'color:#555555',
'^9': 'color:#5555FF',
'^a': 'color:#55FF55',
'^b': 'color:#55FFFF',
'^c': 'color:#FF5555',
'^d': 'color:#FF55FF',
'^e': 'color:#FFFF55',
'^f': 'color:#FFFFFF',
'^l': 'font-weight:bold',
'^m': 'text-decoration:line-through',
'^n': 'text-decoration:underline',
'^o': 'font-style:italic',
};
export default {
props: {
rowData: {
type: Object,
required: true,
},
},
methods: {
modCount(s) {
if(s.length==0) return 0;
return s.split(";").length-1;
},
modList(s) {
var modarray = s.split(';');
//console.log(modarray);
s = "";
for (var i=0; i<modarray.length-1; i++){
var modName = modarray[i].split('/').pop();
modName = modName.replace(".zip","");
s += modName;
//if (i<modarray.length-2)
s += ", ";
}
//console.log(s);
s = s.substring(0, s.length -2);
return s
},
formatBytes(bytes = 0, decimals = 2) {
if (bytes == 0 || bytes == undefined) return '0 Bytes';
const k = 1024;
const dm = decimals < 0 ? 0 : decimals;
const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
const i = Math.floor(Math.log(bytes) / Math.log(k));
return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i];
},
listPlayers(s) {
if (s != undefined || s != "") {
var re = new RegExp(";", 'g');
s = s.replace(re, ', ');
s = s.substring(0, s.length -2);
return s
} else {
return "No players..."
}
},
applyCode(string, codes) {
var cssText = ''
string = string.replace(/\x00*/g, '');
for (var i = 0, len = codes.length; i < len; i++) {
cssText += styleMap[codes[i]] + ';';
}
return {s: string, f:cssText};
},
formatDescriptionName(string) {
var codes = string.match(/\^.{1}/g) || [],
indexes = [],
apply = [],
tmpStr,
name = [],
i,
len;
for (i = 0, len = codes.length; i < len; i++) {
indexes.push(string.indexOf(codes[i]));
string = string.replace(codes[i], '\x00\x00');
}
if (indexes[0] !== 0) {
name.push(this.applyCode(string.substring(0, indexes[0]), []))
}
for (i = 0; i < len; i++) {
var indexDelta = indexes[i + 1] - indexes[i];
if (indexDelta === 2) {
while (indexDelta === 2) {
apply.push(codes[i]);
i++;
indexDelta = indexes[i + 1] - indexes[i];
}
apply.push(codes[i]);
} else {
apply.push(codes[i]);
}
if (apply.lastIndexOf('^r') > -1) {
apply = apply.slice(apply.lastIndexOf('^r') + 1);
}
tmpStr = string.substring(indexes[i], indexes[i + 1]);
name.push(this.applyCode(tmpStr, apply))
}
return name
}
}
};
</script>
<style scoped>/* Add styles for the expanded row details */
.expanded-row-details {
padding: 10px;
background-color: #f5f5f5;
}</style>
-84
View File
@@ -1,84 +0,0 @@
<template>
<div class="table-container">
<table class="min-w-full divide-y divide-gray-400">
<thead>
<tr>
<th v-for="column in columns" :key="column.key" class="px-6 py-3 bg-gray-200 text-left text-xs leading-4 font-medium text-gray-500 uppercase tracking-wider">
{{ column.label }}
</th>
</tr>
</thead>
<tbody>
<template v-for="item in data" :key="item.id">
<tr @click="selectRow(item.id)" class="servers-table-row">
<td v-for="column in columns" :key="column.key" class="px-6 py-1 whitespace-no-wrap text-sm leading-5 text-gray-600" :style="item.style" >
<template v-if="column.key == 'location'">
<span style="display:flex;width: 125px;">
<img :src="`/src/assets/flags/${item.cc}.png`" alt="" style="padding-right: 10px;">
<span style="position: absolute;left: 105px;">{{ item[column.key] }}</span>
</span>
</template>
<template v-else-if="column.key == 'name'">
<span v-for="(value, name) in item[column.key]" :style="value.f">{{ value.s }}</span>
</template>
<template v-else>
{{ item[column.key] }}
</template>
</td>
</tr>
<tr v-if="selectedRow == item.id">
<td :colspan="columns.length">
<ExpandedRowDetails :rowData="getExpandedRowData(item)" />
</td>
</tr>
</template>
</tbody>
</table>
</div>
</template>
<script>
import ExpandedRowDetails from "@/components/servers/ExpandedRowDetails.vue";
export default {
components: {
ExpandedRowDetails,
},
props: {
columns: {
type: Array,
required: true,
},
data: {
type: Array,
required: true,
},
},
data() {
return {
selectedRow: null,
};
},
methods: {
selectRow(id) {
if (this.selectedRow === id) {
this.selectedRow = null;
} else {
this.selectedRow = id;
}
},
getExpandedRowData(item) {
return item || {}
},
},
};
</script>
<style scoped>
.table-container {
overflow-x: auto;
}
.servers-table-row:hover {
background-color: rgba(0, 0, 0, 0.25);
}
</style>
-82
View File
@@ -1,82 +0,0 @@
<!-- https://github.com/VanOord/vue3-plotly/pull/10/files -->
<template>
<div :id="plotlyId"></div>
</template>
<script>
let Plotly;
import events from "./events.js";
import { v4 as uuidv4 } from 'uuid';
let timeOutFunctionId;
export default {
name: 'VuePlotly',
data() {
return {
plotlyId: `plotly-${uuidv4()}`,
};
},
props: {
'data' : {
type : Array,
required:false,
},
'layout': {
type : Object,
required:false,
},
'config':{
type : Object,
required:false,
},
'bundle':{
type : String,
default : "full",
required:false
}
},
watch: {
data() { this.setGraph(); },
layout() { this.setGraph(); },
config() { this.setGraph(); },
},
async mounted() {
switch(this.bundle){
//case "basic" : Plotly = await import("plotly.js-basic-dist-min"); break;
//case "cartesian" : Plotly = await import("plotly.js-cartesian-dist-min"); break;
//case "geo" : Plotly = await import("plotly.js-geo-dist-min"); break;
//case "gl3d" : Plotly = await import("plotly.js-gl3d-dist-min"); break;
//case "gl2d" : Plotly = await import("plotly.js-gl2d-dist-min"); break;
//case "mapbox" : Plotly = await import("plotly.js-mapbox-dist-min"); break;
//case "finance" : Plotly = await import("plotly.js-finance-dist-min"); break;
//case "strict" : Plotly = await import("plotly.js-strict-dist-min"); break;
default : Plotly = await import("plotly.js-dist");
}
this.setGraph();
events.forEach(evt => {
this.$el.on(evt.completeName, evt.handler(this));
});
this.resizeObserver = new ResizeObserver(() => {
clearTimeout(timeOutFunctionId); // debounce the reset
timeOutFunctionId = setTimeout(this.setGraph, 100);
});
this.resizeObserver.observe(document.getElementById(this.plotlyId));
},
beforeUnmount() {
events.forEach(event => this.$el.removeAllListeners(event.completeName));
this.resizeObserver.disconnect();
},
methods: {
setGraph() {
Plotly.newPlot(this.plotlyId, this.data, this.layout, this.config);
},
},
};
</script>
-40
View File
@@ -1,40 +0,0 @@
const eventsName = [
"AfterExport",
"AfterPlot",
"Animated",
"AnimatingFrame",
"AnimationInterrupted",
"AutoSize",
"BeforeExport",
"ButtonClicked",
"Click",
"ClickAnnotation",
"Deselect",
"DoubleClick",
"Framework",
"Hover",
"LegendClick",
"LegendDoubleClick",
"Relayout",
"Restyle",
"Redraw",
"Selected",
"Selecting",
"SliderChange",
"SliderEnd",
"SliderStart",
"Transitioning",
"TransitionInterrupted",
"Unhover"
];
const events = eventsName
.map(evt => evt.toLocaleLowerCase())
.map(eventName => ({
completeName: "plotly_" + eventName,
handler: context => (...args) => {
context.$emit.apply(context, [eventName, ...args]);
}
}));
export default events;
-6
View File
@@ -1,6 +0,0 @@
import { createApp } from 'vue'
import './style.css'
import App from './App.vue'
import router from './router'
createApp(App).use(router).mount('#app')
-36
View File
@@ -1,36 +0,0 @@
import { createRouter, createWebHistory } from 'vue-router'
import Home from '@/views/Home.vue'
export default createRouter({
history: createWebHistory(),
routes: [
{
path: '/',
component: Home,
},
{
path: '/stats',
component: () => import('@/views/Stats.vue'),
},
{
path: '/servers',
component: () => import('@/views/Servers.vue'),
},
{
path: '/hosting',
component: () => import('@/views/Hosting.vue'),
},
{
path: '/rules',
component: () => import('@/views/Rules.vue'),
},
{
path: '/privacy',
component: () => import('@/views/Privacy.vue'),
},
{
path: '/terms',
component: () => import('@/views/Terms.vue'),
},
],
})
-118
View File
@@ -1,118 +0,0 @@
@tailwind base;
@tailwind components;
@tailwind utilities;
.main-content {
display: flex;
position: relative;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
width: 100%;
height: calc(100vh - 80px);
overflow: hidden;
background: linear-gradient(-45deg, rgba(22, 25, 35, 0.35) 0%, rgba(22, 25, 35, 0.95) 100%) center center/100%, url(./assets/beamng-mp-landing.png) center top/cover;
color: #fefee1;
}
.main-content .introduction {
width: 100%;
position: absolute;
transition: transform .2s ease;
transform: translateX(0);
}
.main-content .lead {
font-size: 30px;
font-weight: 300;
font-family: verdana;
}
.middle-xs {
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
}
.center-xs {
-webkit-box-pack: center;
-ms-flex-pack: center;
justify-content: center;
text-align: center;
}
.main-content .buttons-wrapper {
display: flex;
flex-direction: column;
align-items: flex-end;
align-content: flex-end;
}
.main-content .buttons-wrapper .buttons .download-client {
display: block;
position: relative;
padding: 15px 25px 15px 25px;
cursor: pointer;
color: #fefee1;
border: none;
text-shadow: 0 0 1px rgba(22, 25, 35, 0.5);
background: radial-gradient(circle, rgba(150, 204, 0, 0.8), rgba(150, 204, 0, 0.65)) center/100%;
transition: box-shadow .2s ease;
font-size: 27px;
font-weight: 300;
line-height: 1;
border-radius: 3px;
text-decoration: none;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
min-width: 297px;
padding-left: 40px;
}
.description {
display: block;
font-size: 12px;
font-weight: 200;
opacity: .9;
}
div.buttons {
min-width: 297px;
}
div.buttons.mt-3 {
min-width: 297px;
}
img.os-icon {
width: 32px !important;
height: 32px !important;
position: absolute;
top: 18px;
left: 15px;
}
@media screen and (max-width: 600px) {
#button {
display: none;
}
}
@media screen and (max-width: 767px) {
.text {
display: none;
}
.logo-link {
display: flex;
height: 100%;
align-items: center;
align-content: center;
}
.logo-text {
margin: 0 auto;
}
}
-19
View File
@@ -1,19 +0,0 @@
<script setup>
import Hero from '@/components/home/Hero.vue'
import Stats from '@/components/home/Stats.vue'
import Communities from '@/components/home/Communities.vue'
import Partners from '@/components/home/Partners.vue'
import Featured2 from '@/components/home/Featured2.vue'
import Docs from '@/components/home/Docs.vue'
</script>
<template>
<Hero />
<Stats />
<Communities />
<Featured2 />
<Partners />
<!-- Coders Portion -->
<Docs />
</template>
-3
View File
@@ -1,3 +0,0 @@
<template>
<h1>BeamMP Privacy Policy</h1>
</template>
-3
View File
@@ -1,3 +0,0 @@
<template>
<h1>BeamMP Privacy Policy</h1>
</template>
-3
View File
@@ -1,3 +0,0 @@
<template>
<h1>BeamMP Rules</h1>
</template>
-440
View File
@@ -1,440 +0,0 @@
<script setup>
import Table from '@/components/servers/Table.vue'
</script>
<template>
<div id="app" class="p-8">
<Table :columns="columns" :data="tableData" />
</div>
</template>
<script>
import axios from 'axios'
var styleMap = {
'^0': 'color:#000000',
'^1': 'color:#0000AA',
'^2': 'color:#00AA00',
'^3': 'color:#00AAAA',
'^4': 'color:#AA0000',
'^5': 'color:#AA00AA',
'^6': 'color:#FFAA00',
'^7': 'color:#AAAAAA',
'^8': 'color:#555555',
'^9': 'color:#5555FF',
'^a': 'color:#55FF55',
'^b': 'color:#55FFFF',
'^c': 'color:#FF5555',
'^d': 'color:#FF55FF',
'^e': 'color:#FFFF55',
'^f': 'color:#FFFFFF',
'^l': 'font-weight:bold',
'^m': 'text-decoration:line-through',
'^n': 'text-decoration:underline',
'^o': 'font-style:italic',
};
const isoCountries = {
'AF': 'Afghanistan',
'AX': 'Aland Islands',
'AL': 'Albania',
'DZ': 'Algeria',
'AS': 'American Samoa',
'AD': 'Andorra',
'AO': 'Angola',
'AI': 'Anguilla',
'AQ': 'Antarctica',
'AG': 'Antigua And Barbuda',
'AR': 'Argentina',
'AM': 'Armenia',
'AW': 'Aruba',
'AU': 'Australia',
'AT': 'Austria',
'AZ': 'Azerbaijan',
'BS': 'Bahamas',
'BH': 'Bahrain',
'BD': 'Bangladesh',
'BB': 'Barbados',
'BY': 'Belarus',
'BE': 'Belgium',
'BZ': 'Belize',
'BJ': 'Benin',
'BM': 'Bermuda',
'BT': 'Bhutan',
'BO': 'Bolivia',
'BA': 'Bosnia And Herzegovina',
'BW': 'Botswana',
'BV': 'Bouvet Island',
'BR': 'Brazil',
'IO': 'British Indian Ocean Territory',
'BN': 'Brunei Darussalam',
'BG': 'Bulgaria',
'BF': 'Burkina Faso',
'BI': 'Burundi',
'KH': 'Cambodia',
'CM': 'Cameroon',
'CA': 'Canada',
'CV': 'Cape Verde',
'KY': 'Cayman Islands',
'CF': 'Central African Republic',
'TD': 'Chad',
'CL': 'Chile',
'CN': 'China',
'CX': 'Christmas Island',
'CC': 'Cocos (Keeling) Islands',
'CO': 'Colombia',
'KM': 'Comoros',
'CG': 'Congo',
'CD': 'Congo, Democratic Republic',
'CK': 'Cook Islands',
'CR': 'Costa Rica',
'CI': 'Cote D\'Ivoire',
'HR': 'Croatia',
'CU': 'Cuba',
'CY': 'Cyprus',
'CZ': 'Czech Republic',
'DK': 'Denmark',
'DJ': 'Djibouti',
'DM': 'Dominica',
'DO': 'Dominican Republic',
'EC': 'Ecuador',
'EG': 'Egypt',
'SV': 'El Salvador',
'GQ': 'Equatorial Guinea',
'ER': 'Eritrea',
'EE': 'Estonia',
'ET': 'Ethiopia',
'FK': 'Falkland Islands (Malvinas)',
'FO': 'Faroe Islands',
'FJ': 'Fiji',
'FI': 'Finland',
'FR': 'France',
'GF': 'French Guiana',
'PF': 'French Polynesia',
'TF': 'French Southern Territories',
'GA': 'Gabon',
'GM': 'Gambia',
'GE': 'Georgia',
'DE': 'Germany',
'GH': 'Ghana',
'GI': 'Gibraltar',
'GR': 'Greece',
'GL': 'Greenland',
'GD': 'Grenada',
'GP': 'Guadeloupe',
'GU': 'Guam',
'GT': 'Guatemala',
'GG': 'Guernsey',
'GN': 'Guinea',
'GW': 'Guinea-Bissau',
'GY': 'Guyana',
'HT': 'Haiti',
'HM': 'Heard Island & Mcdonald Islands',
'VA': 'Holy See (Vatican City State)',
'HN': 'Honduras',
'HK': 'Hong Kong',
'HU': 'Hungary',
'IS': 'Iceland',
'IN': 'India',
'ID': 'Indonesia',
'IR': 'Iran, Islamic Republic Of',
'IQ': 'Iraq',
'IE': 'Ireland',
'IM': 'Isle Of Man',
'IL': 'Israel',
'IT': 'Italy',
'JM': 'Jamaica',
'JP': 'Japan',
'JE': 'Jersey',
'JO': 'Jordan',
'KZ': 'Kazakhstan',
'KE': 'Kenya',
'KI': 'Kiribati',
'KR': 'Korea',
'KW': 'Kuwait',
'KG': 'Kyrgyzstan',
'LA': 'Lao People\'s Democratic Republic',
'LV': 'Latvia',
'LB': 'Lebanon',
'LS': 'Lesotho',
'LR': 'Liberia',
'LY': 'Libyan Arab Jamahiriya',
'LI': 'Liechtenstein',
'LT': 'Lithuania',
'LU': 'Luxembourg',
'MO': 'Macao',
'MK': 'Macedonia',
'MG': 'Madagascar',
'MW': 'Malawi',
'MY': 'Malaysia',
'MV': 'Maldives',
'ML': 'Mali',
'MT': 'Malta',
'MH': 'Marshall Islands',
'MQ': 'Martinique',
'MR': 'Mauritania',
'MU': 'Mauritius',
'YT': 'Mayotte',
'MX': 'Mexico',
'FM': 'Micronesia, Federated States Of',
'MD': 'Moldova',
'MC': 'Monaco',
'MN': 'Mongolia',
'ME': 'Montenegro',
'MS': 'Montserrat',
'MA': 'Morocco',
'MZ': 'Mozambique',
'MM': 'Myanmar',
'NA': 'Namibia',
'NR': 'Nauru',
'NP': 'Nepal',
'NL': 'Netherlands',
'AN': 'Netherlands Antilles',
'NC': 'New Caledonia',
'NZ': 'New Zealand',
'NI': 'Nicaragua',
'NE': 'Niger',
'NG': 'Nigeria',
'NU': 'Niue',
'NF': 'Norfolk Island',
'MP': 'Northern Mariana Islands',
'NO': 'Norway',
'OM': 'Oman',
'PK': 'Pakistan',
'PW': 'Palau',
'PS': 'Palestinian Territory, Occupied',
'PA': 'Panama',
'PG': 'Papua New Guinea',
'PY': 'Paraguay',
'PE': 'Peru',
'PH': 'Philippines',
'PN': 'Pitcairn',
'PL': 'Poland',
'PT': 'Portugal',
'PR': 'Puerto Rico',
'QA': 'Qatar',
'RE': 'Reunion',
'RO': 'Romania',
'RU': 'Russian Federation',
'RW': 'Rwanda',
'BL': 'Saint Barthelemy',
'SH': 'Saint Helena',
'KN': 'Saint Kitts And Nevis',
'LC': 'Saint Lucia',
'MF': 'Saint Martin',
'PM': 'Saint Pierre And Miquelon',
'VC': 'Saint Vincent And Grenadines',
'WS': 'Samoa',
'SM': 'San Marino',
'ST': 'Sao Tome And Principe',
'SA': 'Saudi Arabia',
'SN': 'Senegal',
'RS': 'Serbia',
'SC': 'Seychelles',
'SL': 'Sierra Leone',
'SG': 'Singapore',
'SK': 'Slovakia',
'SI': 'Slovenia',
'SB': 'Solomon Islands',
'SO': 'Somalia',
'ZA': 'South Africa',
'GS': 'South Georgia And Sandwich Isl.',
'ES': 'Spain',
'LK': 'Sri Lanka',
'SD': 'Sudan',
'SR': 'Suriname',
'SJ': 'Svalbard And Jan Mayen',
'SZ': 'Swaziland',
'SE': 'Sweden',
'CH': 'Switzerland',
'SY': 'Syrian Arab Republic',
'TW': 'Taiwan',
'TJ': 'Tajikistan',
'TZ': 'Tanzania',
'TH': 'Thailand',
'TL': 'Timor-Leste',
'TG': 'Togo',
'TK': 'Tokelau',
'TO': 'Tonga',
'TT': 'Trinidad And Tobago',
'TN': 'Tunisia',
'TR': 'Turkey',
'TM': 'Turkmenistan',
'TC': 'Turks And Caicos Islands',
'TV': 'Tuvalu',
'UG': 'Uganda',
'UA': 'Ukraine',
'AE': 'United Arab Emirates',
'GB': 'United Kingdom',
'US': 'United States',
'UM': 'United States Outlying Islands',
'UY': 'Uruguay',
'UZ': 'Uzbekistan',
'VU': 'Vanuatu',
'VE': 'Venezuela',
'VN': 'Viet Nam',
'VG': 'Virgin Islands, British',
'VI': 'Virgin Islands, U.S.',
'WF': 'Wallis And Futuna',
'EH': 'Western Sahara',
'YE': 'Yemen',
'ZM': 'Zambia',
'ZW': 'Zimbabwe'
};
export default {
components: {
Table,
},
data() {
return {
columns: [
{ key: "location", label: "Location" },
{ key: "name", label: "Name" },
{ key: "map", label: "Map" },
{ key: "players", label: "Players" },
],
tableData: [],
};
},
methods: {
getData() {
axios
.get(`https://backend.beammp.com/servers-info`)
.then(res => {
var servers = []
var data = res.data;
var i = 0
var serversArray = new Array();
// Parse the data to a nice looking Array
for (var i = 0; i < data.length; i++) {
var v = data[i]
v.strippedName = this.stripCustomFormatting(v.sname);
serversArray.push(v);
}
// Sort the servers to display official servers first
serversArray.sort(function(a, b) {
if (a.official && b.official) return a.strippedName.localeCompare(b.strippedName)
else if (a.official) return -1;
else if (b.official) return 1;
return 0;
});
serversArray.forEach(s => {
servers.push({id: i, cc: s.location, location: this.getCountryName(s.location), name: this.formatServerName(s.sname), map: this.smoothMapName(s.map), players: `${s.players}/${s.maxplayers}`, raw: s, style: this.getRowStyle(s)})
i++
});
this.tableData = servers//res.data
})
},
getRowStyle(server) {
const s = false ? 'rgba(255, 215, 0, 0.35)!important' : server.featured ? 'rgba(0, 128, 0, 0.25)!important' : server.official ? 'rgba(255, 106, 0, 0.25)!important' : server.partner ? 'rgba(0, 123, 195, 0.3)!important' : 'rgba(0, 0, 0, 0)!important';
return `background: ${s}`
},
stripCustomFormatting(name) {
var serverStyleArray = [
"^0",
"^1",
"^2",
"^3",
"^4",
"^5",
"^6",
"^7",
"^8",
"^9",
"^a",
"^b",
"^c",
"^d",
"^e",
"^f",
"^l",
"^m",
"^n",
"^o",
"^r",
"^p"
];
for (var i = 0; i < serverStyleArray.length; i++){
while (name.includes(serverStyleArray[i])){
name = name.replace(serverStyleArray[i], "");
}
}
return name;
},
getCountryName(countryCode) {
if (isoCountries.hasOwnProperty(countryCode)) {
return isoCountries[countryCode];
} else {
return countryCode;
}
},
toTitleCase(str) {
return str.replace(/\w\S*/g, function (txt) {
return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();
});
},
smoothMapName(map) {
if (map != "Any Map") {
map = map.replace("/info.json", "")
map = map.split('/').pop().replace(/\s*/g, '')
map = map.replace(/_/g, " ")
map = map.replace(/-/g, " ")
map = this.toTitleCase(map)
}
return map
},
applyCode(string, codes) {
var cssText = ''
string = string.replace(/\x00*/g, '');
for (var i = 0, len = codes.length; i < len; i++) {
cssText += styleMap[codes[i]] + ';';
}
return {s: string, f:cssText};
},
formatServerName(string) {
var codes = string.match(/\^.{1}/g) || [],
indexes = [],
apply = [],
tmpStr,
name = [],
i,
len;
for (i = 0, len = codes.length; i < len; i++) {
indexes.push(string.indexOf(codes[i]));
string = string.replace(codes[i], '\x00\x00');
}
if (indexes[0] !== 0) {
name.push(this.applyCode(string.substring(0, indexes[0]), []))
}
for (i = 0; i < len; i++) {
var indexDelta = indexes[i + 1] - indexes[i];
if (indexDelta === 2) {
while (indexDelta === 2) {
apply.push(codes[i]);
i++;
indexDelta = indexes[i + 1] - indexes[i];
}
apply.push(codes[i]);
} else {
apply.push(codes[i]);
}
if (apply.lastIndexOf('^r') > -1) {
apply = apply.slice(apply.lastIndexOf('^r') + 1);
}
tmpStr = string.substring(indexes[i], indexes[i + 1]);
name.push(this.applyCode(tmpStr, apply))
}
return name
}
},
beforeMount() {
this.getData()
}
};
</script>
-129
View File
@@ -1,129 +0,0 @@
<template>
<div class="container mx-auto mt-8">
<h1 class="text-4xl font-bold mb-4">Project Metrics</h1>
<!-- Timeseries Graph -->
<div v-if="dataLoaded">
<Plotly :data="graphData" :layout="graphLayout" />
</div>
<!-- Metrics -->
<div class="mt-8">
<p><strong>Concurrent Players (All Time High):</strong> {{ allTimeHigh }}</p>
<p><strong>Players Online Now:</strong> {{ playersOnlineNow }}</p>
<p><strong>Servers Online Now:</strong> {{ serversOnlineNow }}</p>
</div>
</div>
</template>
<script>
import Plotly from '@/components/stats/Plotly.vue'
import axios from 'axios'
export default {
components: {
Plotly,
},
data() {
return {
// Sample Data
graphData: [
{
x: ['2023-01-01', '2023-01-02', '2023-01-03'],
y: [10, 15, 8],
type: 'scatter',
mode: 'lines+markers',
name: 'Concurrent Players',
},
],
graphLayout: {
title: 'Concurrent Players Over Time',
xaxis: {
autorange: true,
range: ['2015-02-17', '2017-02-16'],
rangeselector: {buttons: [
{
count: 24,
label: '24h',
step: 'hour',
stepmode: 'backward'
},
{
count: 7,
label: '7d',
step: 'day',
stepmode: 'backward'
},
{
count: 1,
label: '1m',
step: 'month',
stepmode: 'backward'
},
{
count: 6,
label: '6m',
step: 'month',
stepmode: 'backward'
},
{
count: 12,
label: '1y',
step: 'month',
stepmode: 'backward'
},
{step: 'all'}
]},
rangeslider: {range: ['2015-02-17', '2017-02-16']},
type: 'date'
},
yaxis: {
title: 'Concurrent Players',
autorange: true,
range: [86.8700008333, 138.870004167],
type: 'linear'
}
},
allTimeHigh: 20,
playersOnlineNow: 12,
serversOnlineNow: 3,
dataLoaded: false,
timePeriod: 'today'
};
},
methods: {
setTimeRange(range) {
// Update graph data based on the selected time range
// You need to implement the logic to fetch data from your backend here
console.log(`Updating graph for ${range}`);
},
getData() {
axios
.get(`https://backend.beammp.com/stats-info?period=${this.timePeriod}`)
.then(res => {
const data = [];
var Labels = [];
var Players = [];
if (res.data.v2history) {
res.data.v2history.forEach(function(item, index) {
Labels.push(item.datetime)
Players.push(item.players)
})
this.graphData[0].x = Labels
this.graphData[0].y = Players
this.allTimeHigh = res.data.maxp
console.log('Data Downloaded & Sorted')
this.dataLoaded = true
}
})
}
},
beforeMount() {
this.getData();
},
};
</script>
<style scoped>
/* Add Tailwind CSS styles as needed */
</style>
-3
View File
@@ -1,3 +0,0 @@
<template>
<h1>BeamMP Terms & Conditions</h1>
</template>
-12
View File
@@ -1,12 +0,0 @@
/** @type {import('tailwindcss').Config} */
export default {
content: [
"./index.html",
"./src/**/*.{vue,js,ts,jsx,tsx}",
],
theme: {
extend: {},
},
plugins: [],
}
+735
View File
@@ -0,0 +1,735 @@
<!doctype html>
<html lang="en" style="overflow-x: hidden;">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/ico+xml" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>BeamMP Website</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.js"></script>
<noscript>
<style>
/* NoScript Styling */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
line-height: 1.6;
color: #333;
background: #f5f5f5;
}
.warning-banner {
background: linear-gradient(135deg, #f36d24 0%, #e85d1f 100%);
color: white;
padding: 1rem;
text-align: center;
font-weight: 600;
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
position: sticky;
top: 0;
z-index: 1000;
}
.warning-banner strong {
display: block;
font-size: 1.1rem;
margin-bottom: 0.5rem;
}
.header {
background: white;
border-bottom: 1px solid #e5e5e5;
padding: 1rem 0;
position: sticky;
top: 94px;
z-index: 999;
box-shadow: 0 1px 3px rgba(0,0,0,0.1);
}
.header-content {
max-width: 1200px;
margin: 0 auto;
padding: 0 1rem;
display: flex;
justify-content: space-between;
align-items: center;
flex-wrap: wrap;
gap: 1rem;
}
.logo {
height: 64px;
width: auto;
}
.nav {
display: flex;
gap: 0.5rem;
flex-wrap: wrap;
}
.nav a {
color: #333;
text-decoration: none;
padding: 0.5rem 1rem;
border-radius: 6px;
transition: background 0.2s;
}
.nav a:hover {
background: #f5f5f5;
}
.hero {
background: linear-gradient(to bottom, rgba(0,0,0,0.5), rgba(0,0,0,0.7)), url('/landing-1.jpg') center/cover;
color: white;
padding: 5rem 1rem;
text-align: center;
}
.hero-content {
max-width: 900px;
margin: 0 auto;
}
.hero h1 {
font-size: 3rem;
font-weight: bold;
margin-bottom: 1rem;
line-height: 1.2;
}
.hero p {
font-size: 1.5rem;
margin-bottom: 2rem;
color: #e5e5e5;
}
.cta-buttons {
display: flex;
gap: 1rem;
justify-content: center;
flex-wrap: wrap;
margin-bottom: 3rem;
}
.btn {
display: inline-flex;
align-items: center;
gap: 0.5rem;
padding: 1rem 2rem;
border-radius: 8px;
text-decoration: none;
font-weight: 600;
font-size: 1.1rem;
transition: transform 0.2s, box-shadow 0.2s;
}
.btn:hover {
transform: scale(1.05);
}
.btn-primary {
background: linear-gradient(135deg, #f36d24 0%, #dc2626 100%);
color: white;
box-shadow: 0 4px 12px rgba(243, 109, 36, 0.3);
}
.btn-secondary {
background: rgba(255,255,255,0.1);
backdrop-filter: blur(10px);
border: 1px solid rgba(255,255,255,0.3);
color: white;
}
.stats {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
gap: 2rem;
max-width: 800px;
margin: 0 auto;
}
.stat {
text-align: center;
}
.stat-value {
font-size: 2.5rem;
font-weight: bold;
color: #f36d24;
}
.stat-label {
color: #e5e5e5;
margin-top: 0.5rem;
}
.container {
max-width: 1200px;
margin: 0 auto;
padding: 4rem 1rem;
}
.section {
padding: 4rem 1rem;
}
.section-alt {
background: white;
}
.section-title {
font-size: 2.5rem;
font-weight: bold;
text-align: center;
margin-bottom: 3rem;
}
.grid {
display: grid;
gap: 1.5rem;
}
.grid-2 {
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
}
.grid-4 {
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
}
.card {
background: white;
border: 1px solid #e5e5e5;
border-radius: 12px;
padding: 2rem;
transition: border-color 0.2s, box-shadow 0.2s;
}
.card:hover {
border-color: #4470b6;
box-shadow: 0 8px 24px rgba(0,0,0,0.1);
}
.card-icon {
width: 48px;
height: 48px;
margin-bottom: 1rem;
color: #f36d24;
}
.card-title {
font-size: 1.25rem;
font-weight: 600;
margin-bottom: 0.75rem;
}
.card-text {
color: #666;
font-size: 0.95rem;
}
.footer {
background: white;
border-top: 1px solid #e5e5e5;
padding: 2rem 1rem;
margin-top: 4rem;
}
.footer-content {
max-width: 1200px;
margin: 0 auto;
display: flex;
justify-content: space-between;
align-items: center;
flex-wrap: wrap;
gap: 1.5rem;
}
.social-links {
display: flex;
gap: 1rem;
align-items: center;
flex-wrap: wrap;
}
.social-links a {
color: #666;
transition: color 0.2s;
}
.social-links a:hover {
color: #4470b6;
}
.footer-info {
text-align: right;
color: #666;
font-size: 0.85rem;
}
.footer-links {
display: flex;
gap: 0.75rem;
margin-top: 0.5rem;
}
.footer-links a {
color: #666;
text-decoration: none;
}
.footer-links a:hover {
color: #4470b6;
}
.two-column {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 3rem;
align-items: center;
}
.feature-list {
list-style: none;
}
.feature-list li {
display: flex;
gap: 1rem;
margin-bottom: 1.5rem;
}
.feature-bullet {
width: 24px;
height: 24px;
border-radius: 50%;
background: rgba(68, 112, 182, 0.2);
flex-shrink: 0;
margin-top: 4px;
position: relative;
}
.feature-bullet::after {
content: '';
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 8px;
height: 8px;
border-radius: 50%;
background: #4470b6;
}
.feature-title {
font-weight: 600;
margin-bottom: 0.25rem;
}
.screenshot {
width: 100%;
border-radius: 12px;
border: 1px solid #e5e5e5;
box-shadow: 0 8px 24px rgba(0,0,0,0.15);
}
.cta-section {
background: linear-gradient(135deg, #f36d24 0%, #e85d1f 100%);
border-radius: 12px;
padding: 3rem;
text-align: center;
color: white;
margin: 3rem 0;
}
.cta-section h3 {
font-size: 2rem;
margin-bottom: 1rem;
}
.cta-section p {
font-size: 1.1rem;
margin-bottom: 2rem;
opacity: 0.95;
}
.btn-white {
background: white;
color: #f36d24;
padding: 1rem 2rem;
border-radius: 8px;
text-decoration: none;
font-weight: 600;
display: inline-block;
transition: background 0.2s;
}
.btn-white:hover {
background: #f5f5f5;
}
@media (max-width: 768px) {
.hero h1 {
font-size: 2rem;
}
.hero p {
font-size: 1.1rem;
}
.two-column {
grid-template-columns: 1fr;
}
.footer-content {
flex-direction: column;
text-align: center;
}
.footer-info {
text-align: center;
}
.nav {
justify-content: center;
width: 100%;
}
.header-content {
justify-content: center;
}
}
.dropdown {
position: relative;
}
.dropdown-content {
display: none;
position: absolute;
background-color: #f9f9f9;
min-width: 155px;
box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
text-align: left;
color: black;
border-radius: 6px;
}
.dropdown:hover .dropdown-content {
display: block;
}
.dropdown-content > div {
color: black;
border-bottom: solid 1px #e5e5e5;
}
</style>
<!-- Warning Banner -->
<div class="warning-banner">
<strong>⚠️ JavaScript is Disabled</strong>
<span>This is a limited version of the BeamMP website. Please enable JavaScript for the full interactive experience.</span>
</div>
<!-- Header -->
<header class="header">
<div class="header-content">
<img src="/src/assets/BeamMP_blk.png" alt="BeamMP Logo" class="logo">
<nav class="nav">
<a href="https://forum.beammp.com">Forum</a>
<a href="https://docs.beammp.com">Docs</a>
<a href="https://github.com/BeamMP/BeamMP">GitHub</a>
<a href="https://www.patreon.com/BeamMP">Patreon</a>
<a href="https://discord.gg/beammp">Discord</a>
</nav>
</div>
</header>
<!-- Hero Section -->
<section class="hero">
<div class="hero-content">
<h1>Multiplayer Mod for <em>BeamNG.drive</em></h1>
<p>Drive together in the ultimate soft-body physics sandbox</p>
<div class="cta-buttons">
<a href="/installer/BeamMP_Installer.zip" class="btn btn-primary" download>
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-download-icon lucide-download"><path d="M12 15V3"/><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><path d="m7 10 5 5 5-5"/></svg> Download Now
</a>
<a href="https://forum.beammp.com/c/server-list/13" class="btn btn-secondary">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-server-icon lucide-server"><rect width="20" height="8" x="2" y="2" rx="2" ry="2"/><rect width="20" height="8" x="2" y="14" rx="2" ry="2"/><line x1="6" x2="6.01" y1="6" y2="6"/><line x1="6" x2="6.01" y1="18" y2="18"/></svg> Browse Servers
</a>
</div>
<div class="stats">
<div class="stat">
<div class="stat-value">2,000+</div>
<div class="stat-label">Active Players</div>
</div>
<div class="stat">
<div class="stat-value">500+</div>
<div class="stat-label">Public Servers</div>
</div>
<div class="stat">
<div class="stat-value">2M+</div>
<div class="stat-label">All Servers</div>
</div>
</div>
</div>
</section>
<!-- Features Section -->
<section class="section section-alt">
<div class="container">
<h2 class="section-title">Why Choose BeamMP?</h2>
<div class="grid grid-4">
<div class="card">
<div class="card-icon"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-server-icon lucide-server"><rect width="20" height="8" x="2" y="2" rx="2" ry="2"/><rect width="20" height="8" x="2" y="14" rx="2" ry="2"/><line x1="6" x2="6.01" y1="6" y2="6"/><line x1="6" x2="6.01" y1="18" y2="18"/></svg></div>
<h3 class="card-title">Stable Servers</h3>
<p class="card-text">Rock-solid server performance with minimal lag and maximum uptime for the best multiplayer experience.</p>
</div>
<div class="card">
<div class="card-icon"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-package-icon lucide-package"><path d="M11 21.73a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73z"/><path d="M12 22V12"/><polyline points="3.29 7 12 12 20.71 7"/><path d="m7.5 4.27 9 5.15"/></svg></div>
<h3 class="card-title">BeamNG.drive Required</h3>
<p class="card-text">Built specifically for BeamNG.drive, leveraging its incredible soft-body physics engine.</p>
</div>
<div class="card">
<div class="card-icon"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-zap-icon lucide-zap"><path d="M4 14a1 1 0 0 1-.78-1.63l9.9-10.2a.5.5 0 0 1 .86.46l-1.92 6.02A1 1 0 0 0 13 10h7a1 1 0 0 1 .78 1.63l-9.9 10.2a.5.5 0 0 1-.86-.46l1.92-6.02A1 1 0 0 0 11 14z"/></svg></div>
<h3 class="card-title">Standalone Client</h3>
<p class="card-text">Easy-to-use launcher that manages everything for you - just install and play.</p>
</div>
<div class="card">
<div class="card-icon"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-globe-icon lucide-globe"><circle cx="12" cy="12" r="10"/><path d="M12 2a14.5 14.5 0 0 0 0 20 14.5 14.5 0 0 0 0-20"/><path d="M2 12h20"/></svg></div>
<h3 class="card-title">Real-time Sync</h3>
<p class="card-text">Advanced synchronization technology ensures smooth gameplay with players around the world.</p>
</div>
</div>
</div>
</section>
<!-- Communities Section -->
<section class="section">
<div class="container">
<h2 class="section-title">Join Vibrant Communities</h2>
<p style="text-align: center; color: #666; margin-bottom: 3rem; font-size: 1.1rem;">
From casual cruising to competitive racing, find your perfect server
</p>
<div class="grid grid-4">
<div class="card">
<div class="card-icon"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-rocket-icon lucide-rocket"><path d="M4.5 16.5c-1.5 1.26-2 5-2 5s3.74-.5 5-2c.71-.84.7-2.13-.09-2.91a2.18 2.18 0 0 0-2.91-.09z"/><path d="m12 15-3-3a22 22 0 0 1 2-3.95A12.88 12.88 0 0 1 22 2c0 2.72-.78 7.5-6 11a22.35 22.35 0 0 1-4 2z"/><path d="M9 12H4s.55-3.03 2-4c1.62-1.08 5 0 5 0"/><path d="M12 15v5s3.03-.55 4-2c1.08-1.62 0-5 0-5"/></svg></div>
<h3 class="card-title">Racing</h3>
<p class="card-text">Compete in high-speed races with custom tracks and competitive leaderboards.</p>
</div>
<div class="card">
<div class="card-icon"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-gamepad2-icon lucide-gamepad-2"><line x1="6" x2="10" y1="11" y2="11"/><line x1="8" x2="8" y1="9" y2="13"/><line x1="15" x2="15.01" y1="12" y2="12"/><line x1="18" x2="18.01" y1="10" y2="10"/><path d="M17.32 5H6.68a4 4 0 0 0-3.978 3.59c-.006.052-.01.101-.017.152C2.604 9.416 2 14.456 2 16a3 3 0 0 0 3 3c1 0 1.5-.5 2-1l1.414-1.414A2 2 0 0 1 9.828 16h4.344a2 2 0 0 1 1.414.586L17 18c.5.5 1 1 2 1a3 3 0 0 0 3-3c0-1.545-.604-6.584-.685-7.258-.007-.05-.011-.1-.017-.151A4 4 0 0 0 17.32 5z"/></svg></div>
<h3 class="card-title">Roleplay</h3>
<p class="card-text">Immerse yourself in realistic roleplay scenarios with dedicated communities.</p>
</div>
<div class="card">
<div class="card-icon"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-shield-icon lucide-shield"><path d="M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z"/></svg></div>
<h3 class="card-title">Crash & Derby</h3>
<p class="card-text">Destruction enthusiasts unite! Experience epic demolition derby events.</p>
</div>
<div class="card">
<div class="card-icon"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-globe-icon lucide-globe"><circle cx="12" cy="12" r="10"/><path d="M12 2a14.5 14.5 0 0 0 0 20 14.5 14.5 0 0 0 0-20"/><path d="M2 12h20"/></svg></div>
<h3 class="card-title">Freeroam</h3>
<p class="card-text">Explore vast maps with friends in relaxed freeroam servers.</p>
</div>
</div>
</div>
</section>
<!-- Server Browser Section -->
<section class="section section-alt">
<div class="container">
<div class="two-column">
<div>
<h2 style="font-size: 2.5rem; font-weight: bold; margin-bottom: 1.5rem;">Find Your Perfect Server</h2>
<p style="font-size: 1.1rem; color: #666; margin-bottom: 2rem;">
Browse hundreds of unique servers with different game modes, maps, and communities. There's something for everyone!
</p>
<ul class="feature-list">
<li>
<div class="feature-bullet"></div>
<div>
<div class="feature-title">Custom Game Modes</div>
<div class="card-text">From racing leagues to roleplay servers</div>
</div>
</li>
<li>
<div class="feature-bullet"></div>
<div>
<div class="feature-title">Active Moderation</div>
<div class="card-text">Safe and welcoming communities</div>
</div>
</li>
<li>
<div class="feature-bullet"></div>
<div>
<div class="feature-title">Global Network</div>
<div class="card-text">Servers worldwide for the best connection</div>
</div>
</li>
</ul>
<a href="https://forum.beammp.com/c/server-list/13" class="btn btn-primary">
Browse All Servers →
</a>
</div>
<div>
<img src="/beammpservers.png" alt="BeamMP Server Browser" class="screenshot">
</div>
</div>
</div>
</section>
<!-- Developer Section -->
<section class="section">
<div class="container">
<h2 class="section-title">Built for Developers</h2>
<p style="text-align: center; color: #666; margin-bottom: 3rem; font-size: 1.1rem;">
Powerful tools and extensive documentation to create your own server experiences
</p>
<div class="grid grid-4">
<div class="card">
<div class="card-icon"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-code-icon lucide-code"><path d="m16 18 6-6-6-6"/><path d="m8 6-6 6 6 6"/></svg></div>
<h3 class="card-title">Lua Scripting</h3>
<p class="card-text">Create custom game modes and server-side mods with our powerful Lua API.</p>
<a href="https://docs.beammp.com/scripting/mod-reference/" style="color: #4470b6; font-weight: 600; text-decoration: none;">Learn More →</a>
</div>
<div class="card">
<div class="card-icon"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-book-open-icon lucide-book-open"><path d="M12 7v14"/><path d="M3 18a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1h5a4 4 0 0 1 4 4 4 4 0 0 1 4-4h5a1 1 0 0 1 1 1v13a1 1 0 0 1-1 1h-6a3 3 0 0 0-3 3 3 3 0 0 0-3-3z"/></svg></div>
<h3 class="card-title">Comprehensive Docs</h3>
<p class="card-text">Detailed guides and API references to help you get started quickly.</p>
<a href="https://docs.beammp.com" style="color: #4470b6; font-weight: 600; text-decoration: none;">Learn More →</a>
</div>
<div class="card">
<div class="card-icon"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-wrench-icon lucide-wrench"><path d="M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.106-3.105c.32-.322.863-.22.983.218a6 6 0 0 1-8.259 7.057l-7.91 7.91a1 1 0 0 1-2.999-3l7.91-7.91a6 6 0 0 1 7.057-8.259c.438.12.54.662.219.984z"/></svg></div>
<h3 class="card-title">Open Source</h3>
<p class="card-text">Contribute to the project or learn from our codebase on GitHub.</p>
<a href="https://github.com/BeamMP" style="color: #4470b6; font-weight: 600; text-decoration: none;">Learn More →</a>
</div>
</div>
<!-- Hosting CTA -->
<div class="cta-section">
<h3>Ready to Host Your Own Server?</h3>
<p>Check out our trusted hosting partners or download the server software to host it yourself.</p>
<div class="flex flex-col sm:flex-row gap-4 justify-center pt-4">
<a
href="https://github.com/BeamMP/BeamMP-Server/releases/latest/download/BeamMP-Server.exe"
class="btn-white flex items-center justify-center gap-3 bg-neutral-800 hover:bg-neutral-700 dark:bg-neutral-700 dark:hover:bg-neutral-600 text-white border border-neutral-600 dark:border-neutral-600 px-6 py-3 rounded-lg font-semibold transition-all"
>
Windows
<svg xmlns="http://www.w3.org/2000/svg" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-download-icon lucide-download"><path d="M12 15V3"/><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><path d="m7 10 5 5 5-5"/></svg>
</a>
<span
class="dropdown btn-white flex items-center justify-center gap-3 bg-neutral-800 hover:bg-neutral-700 dark:bg-neutral-700 dark:hover:bg-neutral-600 text-white border border-neutral-600 dark:border-neutral-600 px-6 py-3 rounded-lg font-semibold transition-all"
>
Linux Builds
<div class="dropdown-content">
<div>
<span style="color: #666; font-size: 0.85rem; padding: 0.5rem 1rem; display: block; font-weight: 600;">x86_64</span>
</div>
<div style="padding: 0.5rem 1rem;">
<a href="https://github.com/BeamMP/BeamMP-Server/releases/latest/download/BeamMP-Server.debian.11.x86_64" style="color: #333; text-decoration: none; display: flex; align-items: center; gap: 0.5rem; padding: 0.25rem 0;">
Debian 11
<svg xmlns="http://www.w3.org/2000/svg" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-download-icon lucide-download"><path d="M12 15V3"/><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><path d="m7 10 5 5 5-5"/></svg>
</a>
</div>
<div style="padding: 0.5rem 1rem;">
<a href="https://github.com/BeamMP/BeamMP-Server/releases/latest/download/BeamMP-Server.debian.12.x86_64" style="color: #333; text-decoration: none; display: flex; align-items: center; gap: 0.5rem; padding: 0.25rem 0;">
Debian 12
<svg xmlns="http://www.w3.org/2000/svg" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-download-icon lucide-download"><path d="M12 15V3"/><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><path d="m7 10 5 5 5-5"/></svg>
</a>
</div>
<div style="padding: 0.5rem 1rem;">
<a href="https://github.com/BeamMP/BeamMP-Server/releases/latest/download/BeamMP-Server.ubuntu.22.04.x86_64" style="color: #333; text-decoration: none; display: flex; align-items: center; gap: 0.5rem; padding: 0.25rem 0;">
Ubuntu 22.04
<svg xmlns="http://www.w3.org/2000/svg" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-download-icon lucide-download"><path d="M12 15V3"/><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><path d="m7 10 5 5 5-5"/></svg>
</a>
</div>
<div style="padding: 0.5rem 1rem;">
<a href="https://github.com/BeamMP/BeamMP-Server/releases/latest/download/BeamMP-Server.ubuntu.24.04.x86_64" style="color: #333; text-decoration: none; display: flex; align-items: center; gap: 0.5rem; padding: 0.25rem 0;">
Ubuntu 24.04
<svg xmlns="http://www.w3.org/2000/svg" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-download-icon lucide-download"><path d="M12 15V3"/><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><path d="m7 10 5 5 5-5"/></svg>
</a>
</div>
<div>
<span style="color: #666; font-size: 0.85rem; padding: 0.5rem 1rem; display: block; font-weight: 600;">arm64</span>
</div>
<div style="padding: 0.5rem 1rem;">
<a href="https://github.com/BeamMP/BeamMP-Server/releases/latest/download/BeamMP-Server.debian.11.arm64" style="color: #333; text-decoration: none; display: flex; align-items: center; gap: 0.5rem; padding: 0.25rem 0;">
Debian 11
<svg xmlns="http://www.w3.org/2000/svg" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-download-icon lucide-download"><path d="M12 15V3"/><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><path d="m7 10 5 5 5-5"/></svg>
</a>
</div>
<div style="padding: 0.5rem 1rem;">
<a href="https://github.com/BeamMP/BeamMP-Server/releases/latest/download/BeamMP-Server.debian.12.arm64" style="color: #333; text-decoration: none; display: flex; align-items: center; gap: 0.5rem; padding: 0.25rem 0;">
Debian 12
<svg xmlns="http://www.w3.org/2000/svg" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-download-icon lucide-download"><path d="M12 15V3"/><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><path d="m7 10 5 5 5-5"/></svg>
</a>
</div>
<div style="padding: 0.5rem 1rem;">
<a href="https://github.com/BeamMP/BeamMP-Server/releases/latest/download/BeamMP-Server.ubuntu.22.04.arm64" style="color: #333; text-decoration: none; display: flex; align-items: center; gap: 0.5rem; padding: 0.25rem 0;">
Ubuntu 22.04
<svg xmlns="http://www.w3.org/2000/svg" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-download-icon lucide-download"><path d="M12 15V3"/><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><path d="m7 10 5 5 5-5"/></svg>
</a>
</div>
<div style="padding: 0.5rem 1rem;">
<a href="https://github.com/BeamMP/BeamMP-Server/releases/latest/download/BeamMP-Server.ubuntu.24.04.arm64" style="color: #333; text-decoration: none; display: flex; align-items: center; gap: 0.5rem; padding: 0.25rem 0;">
Ubuntu 24.04
<svg xmlns="http://www.w3.org/2000/svg" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-download-icon lucide-download"><path d="M12 15V3"/><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><path d="m7 10 5 5 5-5"/></svg>
</a>
</div>
</div>
<span/>
</div>
</div>
</div>
</section>
<!-- Footer -->
<footer class="footer">
<div class="footer-content">
<div class="social-links">
<a href="https://github.com/BeamMP" aria-label="GitHub">
<svg width="20" height="20" fill="currentColor" viewBox="0 0 24 24"><path d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z"/></svg>
</a>
<a href="https://discord.gg/beammp" aria-label="Discord">
<svg width="20" height="20" fill="currentColor" viewBox="0 0 24 24"><path d="M20.317 4.37a19.791 19.791 0 0 0-4.885-1.515.074.074 0 0 0-.079.037c-.21.375-.444.864-.608 1.25a18.27 18.27 0 0 0-5.487 0 12.64 12.64 0 0 0-.617-1.25.077.077 0 0 0-.079-.037A19.736 19.736 0 0 0 3.677 4.37a.07.07 0 0 0-.032.027C.533 9.046-.32 13.58.099 18.057a.082.082 0 0 0 .031.057 19.9 19.9 0 0 0 5.993 3.03.078.078 0 0 0 .084-.028 14.09 14.09 0 0 0 1.226-1.994.076.076 0 0 0-.041-.106 13.107 13.107 0 0 1-1.872-.892.077.077 0 0 1-.008-.128 10.2 10.2 0 0 0 .372-.292.074.074 0 0 1 .077-.01c3.928 1.793 8.18 1.793 12.062 0a.074.074 0 0 1 .078.01c.12.098.246.198.373.292a.077.077 0 0 1-.006.127 12.299 12.299 0 0 1-1.873.892.077.077 0 0 0-.041.107c.36.698.772 1.362 1.225 1.993a.076.076 0 0 0 .084.028 19.839 19.839 0 0 0 6.002-3.03.077.077 0 0 0 .032-.054c.5-5.177-.838-9.674-3.549-13.66a.061.061 0 0 0-.031-.03zM8.02 15.33c-1.183 0-2.157-1.085-2.157-2.419 0-1.333.956-2.419 2.157-2.419 1.21 0 2.176 1.096 2.157 2.42 0 1.333-.956 2.418-2.157 2.418zm7.975 0c-1.183 0-2.157-1.085-2.157-2.419 0-1.333.955-2.419 2.157-2.419 1.21 0 2.176 1.096 2.157 2.42 0 1.333-.946 2.418-2.157 2.418z"/></svg>
</a>
<a href="https://www.youtube.com/@beammpofficial" aria-label="YouTube">
<svg width="20" height="20" fill="currentColor" viewBox="0 0 24 24"><path d="M23.498 6.186a3.016 3.016 0 0 0-2.122-2.136C19.505 3.545 12 3.545 12 3.545s-7.505 0-9.377.505A3.017 3.017 0 0 0 .502 6.186C0 8.07 0 12 0 12s0 3.93.502 5.814a3.016 3.016 0 0 0 2.122 2.136c1.871.505 9.376.505 9.376.505s7.505 0 9.377-.505a3.015 3.015 0 0 0 2.122-2.136C24 15.93 24 12 24 12s0-3.93-.502-5.814zM9.545 15.568V8.432L15.818 12l-6.273 3.568z"/></svg>
</a>
<a href="https://x.com/beammpofficial" aria-label="X (Twitter)">
<svg width="20" height="20" fill="currentColor" viewBox="0 0 24 24"><path d="M18.901 1.153h3.68l-8.04 9.19L24 22.846h-7.406l-5.8-7.584-6.638 7.584H.474l8.6-9.83L0 1.154h7.594l5.243 6.932ZM17.61 20.644h2.039L6.486 3.24H4.298Z"/></svg>
</a>
<a href="https://www.reddit.com/r/BeamMP" aria-label="Reddit">
<svg width="20" height="20" fill="currentColor" viewBox="0 0 24 24"><path d="M12 0A12 12 0 0 0 0 12a12 12 0 0 0 12 12 12 12 0 0 0 12-12A12 12 0 0 0 12 0zm5.01 4.744c.688 0 1.25.561 1.25 1.249a1.25 1.25 0 0 1-2.498.056l-2.597-.547-.8 3.747c1.824.07 3.48.632 4.674 1.488.308-.309.73-.491 1.207-.491.968 0 1.754.786 1.754 1.754 0 .716-.435 1.333-1.01 1.614a3.111 3.111 0 0 1 .042.52c0 2.694-3.13 4.87-7.004 4.87-3.874 0-7.004-2.176-7.004-4.87 0-.183.015-.366.043-.534A1.748 1.748 0 0 1 4.028 12c0-.968.786-1.754 1.754-1.754.463 0 .898.196 1.207.49 1.207-.883 2.878-1.43 4.744-1.487l.885-4.182a.342.342 0 0 1 .14-.197.35.35 0 0 1 .238-.042l2.906.617a1.214 1.214 0 0 1 1.108-.701zM9.25 12C8.561 12 8 12.562 8 13.25c0 .687.561 1.248 1.25 1.248.687 0 1.248-.561 1.248-1.249 0-.688-.561-1.249-1.249-1.249zm5.5 0c-.687 0-1.248.561-1.248 1.25 0 .687.561 1.248 1.249 1.248.688 0 1.249-.561 1.249-1.249 0-.687-.562-1.249-1.25-1.249zm-5.466 3.99a.327.327 0 0 0-.231.094.33.33 0 0 0 0 .463c.842.842 2.484.913 2.961.913.477 0 2.105-.056 2.961-.913a.361.361 0 0 0 .029-.463.33.33 0 0 0-.464 0c-.547.533-1.684.73-2.512.73-.828 0-1.979-.196-2.512-.73a.326.326 0 0 0-.232-.095z"/></svg>
</a>
<span style="color: #ccc;">|</span>
<a href="https://www.patreon.com/BeamMP" style="color: #f96854; font-size: 0.85rem; text-decoration: underline;">
Support on Patreon
</a>
</div>
<div class="footer-info">
<p>&copy; 2019 - 2025 | BeamMP Mod Team All Rights Reserved</p>
<div class="footer-links">
<a href="https://forum.beammp.com/topic/95/privacy-policy-v1-0">Privacy Policy</a>
<span>·</span>
<a href="https://forum.beammp.com/topic/94/terms-of-use-v1-0">Terms of Use</a>
</div>
</div>
</div>
</footer>
</noscript>
</body>
</html>
-93
View File
@@ -1,93 +0,0 @@
#!/usr/bin/env node
/*
* oooooooooo. ooo ooooo ooooooooo.
* `888' `Y8b `88. .888' `888 `Y88.
* 888 888 .ooooo. .oooo. ooo. .oo. .oo. 888b d'888 888 .d88'
* 888oooo888' d88' `88b `P )88b `888P"Y88bP"Y88b 8 Y88. .P 888 888ooo88P'
* 888 `88b 888ooo888 .oP"888 888 888 888 8 `888' 888 888
* 888 .88P 888 .o d8( 888 888 888 888 8 Y 888 888
* o888bood8P' `Y8bod8P' `Y888""8o o888o o888o o888o o8o o888o o888o
* ========================================================================
* Copyright (c) 2019-2023 BeamMP Ltd. All rights reserved.
*/
require('dotenv').config()
const pkg = require('./package.json')
const chalk = require('chalk');
const cluster = require('cluster');
const error = chalk.bold.keyword('red');
const warn = chalk.keyword('orange');
const good = chalk.keyword('lime');
process.on('warning', (warning) => {
console.log(warning.stack);
});
if (cluster.isMaster) {
const env = process.env.NODE_ENV || 'development'
console.log('oooooooooo. ooo ooooo ooooooooo. ')
console.log('`888\' `Y8b `88. .888\' `888 `Y88. ')
console.log(' 888 888 .ooooo. .oooo. ooo. .oo. .oo. 888b d\'888 888 .d88\' ')
console.log(' 888oooo888\' d88\' `88b `P )88b `888P"Y88bP"Y88b 8 Y88. .P 888 888ooo88P\' ')
console.log(' 888 `88b 888ooo888 .oP"888 888 888 888 8 `888\' 888 888 ')
console.log(' 888 .88P 888 .o d8( 888 888 888 888 8 Y 888 888 ')
console.log('o888bood8P\' `Y8bod8P\' `Y888""8o o888o o888o o888o o8o o888o o888o ')
console.log('=================================================================================')
console.log('Website v' + pkg.version + ' Copyright (C) 2019-2024 BeamMP Ltd')
console.log('')
console.log('Running in: ' + env)
console.log('Server Time: ' + new Date())
function start() {
process.title = pkg.name + "@" + pkg.version;
if (cluster.isMaster) {
console.log(`Master PID: ${process.pid}`)
console.log(`Creating ${process.env.INSTANCES} Instances of the Website Backend`)
for (let i = 0; i < process.env.INSTANCES; i++) {
cluster.fork();
}
// set console's directory so we can see output from workers
console.dir(cluster.workers, { depth: 0 });
cluster.on('exit', (worker, code) => {
// Good exit code is 0 :))
// exitedAfterDisconnect ensures that it is not killed by master cluster or manually
// if we kill it via .kill or .disconnect it will be set to true
// \x1b[XXm represents a color, and [0m represent the end of this
//color in the console ( 0m sets it to white again )
if (code !== 0 && !worker.exitedAfterDisconnect) {
console.error(`\x1b[34mWorker ${worker.process.pid} crashed... Starting a new worker...\x1b[0m`);
const nw = cluster.fork();
console.error(`\x1b[32mWorker ${nw.process.pid} will replace him \x1b[0m`);
}
});
} else {
console.error('FATAL: This script can only be run as a master process.')
}
}
start()
} else {
const ws = require('./src/webserver')
try {
ws.init(function (err) {
if (err) {
console.error(err)
return
}
ws.listen(function () {
console.info('BeamMP Website Ready')
})
})
} catch (e) {
throw e;
}
}
+8
View File
@@ -0,0 +1,8 @@
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/*": ["./src/*"]
}
}
}
+47
View File
@@ -0,0 +1,47 @@
server {
listen 80;
server_name _;
server_tokens off;
root /usr/share/nginx/html;
index index.html;
# Baseline security hardening for a static SPA.
# NOTE: add_header directives are NOT inherited by child location blocks that
# define their own add_header. To avoid silently dropping security headers,
# use the `expires` directive (not add_header Cache-Control) in location blocks.
add_header X-Frame-Options "DENY" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Permissions-Policy "camera=(), microphone=(), geolocation=()" always;
add_header Content-Security-Policy "default-src 'self'; img-src 'self' data: https:; script-src 'self'; style-src 'self' 'unsafe-inline'; font-src 'self' data:; connect-src 'self' https://backend.beammp.com; object-src 'none'; base-uri 'self'; frame-ancestors 'none'" always;
# Installer directory: serve files directly; return 404 for anything missing.
location ^~ /installer/ {
try_files $uri =404;
}
# Vite-hashed assets (JS, CSS, fonts, images): serve directly with a long cache.
# These files have content hashes in their names so stale cache is never an issue.
# Return 404 if a file is genuinely missing rather than silently serving index.html.
location ~* \.(js|css|woff2?|ttf|eot|svg|webp|avif|png|jpg|jpeg|gif|ico|map)$ {
try_files $uri =404;
expires 1y;
access_log off;
}
# Data / download files: serve directly, no client-side cache, 404 if missing.
location ~* \.(json|txt|exe|zip)$ {
try_files $uri =404;
expires -1;
access_log off;
}
# SPA fallback: all other paths go to index.html so Vue Router can render the
# correct view (including the NotFound page for unknown routes).
location / {
try_files $uri /index.html;
}
}
+27
View File
@@ -0,0 +1,27 @@
worker_processes auto;
pid /tmp/nginx.pid;
error_log /tmp/error.log warn;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
access_log /tmp/access.log;
sendfile on;
keepalive_timeout 65;
server_tokens off;
# Redefine temp paths to writable tmpfs locations
client_body_temp_path /tmp/client_temp;
proxy_temp_path /tmp/proxy_temp;
fastcgi_temp_path /tmp/fastcgi_temp;
uwsgi_temp_path /tmp/uwsgi_temp;
scgi_temp_path /tmp/scgi_temp;
include /etc/nginx/conf.d/*.conf;
}
+3228 -1298
View File
File diff suppressed because it is too large. Load diff
+32 -23
View File
@@ -1,29 +1,38 @@
{ {
"name": "beammp-website", "name": "beammp-website",
"version": "1.0.1", "private": true,
"description": "BeamMP Website", "version": "2.4.17",
"main": "index.js", "type": "module",
"scripts": { "scripts": {
"docker-build": "docker build -t 192.168.100.6:5000/beammp/website:latest -t 192.168.100.6:5000/beammp/website:1.0.1 .", "dev": "vite",
"docker-push": "docker push 192.168.100.6:5000/beammp/website:latest" "build": "vite build",
"preview": "vite preview",
"lint": "eslint . --fix",
"format": "prettier --write \"src/**/*.{js,vue,css,json}\""
}, },
"repository": {
"type": "git",
"url": "git+https://github.com/BeamMP/BeamMP-Website.git"
},
"author": "",
"license": "ISC",
"bugs": {
"url": "https://github.com/BeamMP/BeamMP-Website/issues"
},
"homepage": "https://github.com/BeamMP/BeamMP-Website#readme",
"dependencies": { "dependencies": {
"body-parser": "^1.19.0", "@tailwindcss/vite": "^4.1.17",
"chalk": "^3.0.0", "@vueuse/core": "^14.1.0",
"dotenv": "^16.0.3", "class-variance-authority": "^0.7.1",
"ejs": "^3.0.1", "clsx": "^2.1.1",
"express": "^4.17.1", "lucide-vue-next": "^0.555.0",
"helmet": "^6.1.5", "reka-ui": "^2.7.0",
"morgan": "^1.10.0" "tailwind-merge": "^3.4.0",
"tailwindcss": "^4.1.17",
"tailwindcss-animate": "^1.0.7",
"vue": "^3.5.25",
"vue-i18n": "^11.2.2",
"vue-router": "^4.6.3"
},
"devDependencies": {
"@vitejs/plugin-vue": "^6.0.2",
"@vue/eslint-config-prettier": "^10.2.0",
"eslint": "^9.39.1",
"eslint-config-prettier": "^10.1.8",
"eslint-plugin-prettier": "^5.5.4",
"eslint-plugin-vue": "^10.6.2",
"prettier": "^3.7.3",
"tw-animate-css": "^1.4.0",
"vite": "^7.2.4"
} }
} }
File renamed without changes.
Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 MiB

File renamed without changes.
File renamed without changes.
Binary file not shown.

After

Width:  |  Height:  |  Size: 108 KiB

Binary file not shown.
+86
View File
@@ -0,0 +1,86 @@
[
{
"name": "Horizon Hosting",
"website": "https://hrzn.link/beammp",
"from": "$3.34/mo",
"logo": "https://hrznhosting.com/assets/logo.svg"
},
{
"name": "RackGenius",
"website": "https://rackgeni.us/beammp-plans",
"from": "$0.5/mo",
"logo": "https://rackgenius.com/rackgenius-logo.png"
},
{
"name": "Connect Hosting",
"website": "https://connecthosting.net/beammp",
"from": "$1.49/mo",
"logo": "https://connecthosting.net/img/logo.webp"
},
{
"name": "Assetto Hosting",
"website": "https://assettohosting.com/games/beamng",
"from": "$2.30/mo",
"logo": "https://assettohosting.com/_next/image?url=https%3A%2F%2Fstrapi.assettohosting.com%2Fuploads%2Flogo_2228c8bbfb.png&w=640&q=100"
},
{
"name": "Zap-Hosting",
"website": "https://zap-hosting.com/itsbeammp",
"from": "$6.46/mo",
"logo": "https://wormhole.ifyouwantmorepower.com/online/assets/beammp/zap-logo.png"
},
{
"name": "HostHavoc",
"website": "https://hosthavoc.com",
"from": "$3.75/mo",
"logo": "https://hosthavoc.com/images/logo.svg"
},
{
"name": "PedalHost",
"website": "https://pedal.host",
"from": "$1.31/mo",
"logo": "https://pedal.host/pedalhost_horizontal_light.svg"
},
{
"name": "Vyper Hosting",
"website": "https://vyperhosting.com/r/beammp",
"from": "$2.68/mo",
"logo": "https://vyperhosting.com/assets/logo.png"
},
{
"name": "BisecHosting",
"website": "https://bisecthosting.com/beammp-server-hosting",
"from": "$5.99/mo",
"logo": "https://www.bisecthosting.com/_ipx/q_100&s_140x46/images/logo-dark-theme.svg"
},
{
"name": "Four Season Hosting",
"website": "https://fourseasonshosting.com",
"from": "$3.00/mo",
"logo": "https://fourseasonshosting.com/_next/image?url=%2Flogo.png&w=256&q=75"
},
{
"name": "Vertuo Hosting",
"website": "https://vertuohosting.com",
"from": "$1.99/mo",
"logo": "https://vertuohosting.com/assets/img/logo.png"
},
{
"name": "Winheberg",
"website": "https://winheberg.fr/offres/gaming/beammp",
"from": "$2.99/mo",
"logo": "https://winheberg.fr/img/logo-white.png"
},
{
"name": "Wabbanode",
"website": "https://wabbanode.com/partner/beammp",
"from": "$5.96/mo",
"logo": "https://wabbanode.com/_nuxt/wabba_logo.UPNIVeXa.webp"
},
{
"name": "Iceline Hosting",
"website": "https://iceline-hosting.com/games/beammp",
"from": "$3.64/mo",
"logo": "https://iceline-hosting.com/_astro/logo.DTnWV5zL_157TDr.webp"
}
]
+70418
View File
File diff suppressed because it is too large. Load diff
+7
View File
@@ -0,0 +1,7 @@
<script setup>
import DefaultLayout from './layouts/DefaultLayout.vue'
</script>
<template>
<DefaultLayout />
</template>
Binary file not shown.

After

Width:  |  Height:  |  Size: 87 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 121 KiB

File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Loaded 100 of 386 files, more files were not shown because too many files have changed in this diff. Show more