Add Docker deployment support and PWA enhancements

- Add Dockerfile with multi-stage build (Node.js + Nginx)
- Add docker-compose.yml for Portainer stack deployment on port 7777
- Add nginx.conf with PWA support, gzip compression, and security headers
- Add .dockerignore for optimized Docker builds
- Add DEPLOYMENT.md with comprehensive deployment guide
- Configure Vite PWA plugin with service worker and offline support
- Add PWA manifest.json with app icons and shortcuts
- Enhance logo.svg with iOS-style glass effects (filters, gradients, highlights)
- Add app-icon.svg for PWA installation
- Update mobile nav with glassmorphic active tab styling
- Fix mobile tab bar layout shift issues with flex-1 and consistent sizing
- Update index.html with PWA meta tags and Apple-specific settings
- Add health check endpoint at /health for container monitoring

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Dorian
2026-02-02 23:43:42 +00:00
parent 90c55883f2
commit 3f3849e76f
14 changed files with 5571 additions and 136 deletions

20
.dockerignore Normal file
View File

@@ -0,0 +1,20 @@
node_modules
dist
.git
.gitignore
README.md
.env
.env.local
.env.*.local
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
.DS_Store
*.local
.vscode
.idea
*.swp
*.swo
*~
.cursor

174
DEPLOYMENT.md Normal file
View File

@@ -0,0 +1,174 @@
# IndeedHub - Portainer Deployment Guide
## Quick Deploy with Portainer Stacks
### Method 1: Using Portainer Stacks (Recommended)
1. **Log into Portainer**
2. **Navigate to Stacks**
3. **Click "Add Stack"**
4. **Choose "Git Repository"** or **"Upload"** the `docker-compose.yml`
5. **Configure:**
- Name: `indeedhub-prototype`
- Repository URL: (your git repo)
- Compose path: `docker-compose.yml`
6. **Deploy**
### Method 2: Using Docker Compose Directly
```bash
# Build and run
docker-compose up -d --build
# View logs
docker-compose logs -f
# Stop
docker-compose down
```
## Access
- **Application URL**: `http://your-server:7777`
- **Health Check**: `http://your-server:7777/health`
## Configuration
### Port Configuration
The application runs on port **7777** by default. To change:
```yaml
# In docker-compose.yml
ports:
- "YOUR_PORT:7777"
```
### Environment Variables
Add any required environment variables in `docker-compose.yml`:
```yaml
environment:
- NODE_ENV=production
- VITE_API_URL=https://your-api.com
```
## Build Details
### Multi-stage Docker Build
1. **Builder Stage**: Compiles Vue/TypeScript application
2. **Production Stage**: Serves built files with Nginx
### Features
- ✅ Nginx web server (Alpine Linux)
- ✅ Gzip compression
- ✅ Security headers
- ✅ PWA support with proper MIME types
- ✅ Vue Router SPA fallback
- ✅ Service Worker support
- ✅ Health check endpoint
- ✅ Auto-restart enabled
## Monitoring
### Health Check
```bash
curl http://localhost:7777/health
```
### Container Status
```bash
docker ps | grep indeedhub
```
### View Logs
```bash
docker logs -f indeedhub-app
```
## Updates
### Rebuild and Deploy
```bash
docker-compose down
docker-compose up -d --build
```
### Using Portainer
1. Go to your stack
2. Click "Update"
3. Enable "Pull latest image"
4. Click "Update the stack"
## Troubleshooting
### Container won't start
```bash
# Check logs
docker logs indeedhub-app
# Check if port is available
lsof -i :7777
```
### Build fails
```bash
# Clear Docker cache
docker builder prune
# Rebuild without cache
docker-compose build --no-cache
```
## Production Checklist
- ✅ Port 7777 exposed
- ✅ Health checks configured
- ✅ Auto-restart enabled
- ✅ Gzip compression enabled
- ✅ Security headers set
- ✅ PWA manifest support
- ✅ Service worker caching
- ✅ SPA routing configured
- ✅ Docker networking isolated
## Stack Configuration for Portainer
Copy this into Portainer Stack editor:
```yaml
version: '3.8'
services:
indeedhub:
image: indeedhub-prototype:latest
build:
context: .
dockerfile: Dockerfile
container_name: indeedhub-app
restart: unless-stopped
ports:
- "7777:7777"
environment:
- NODE_ENV=production
networks:
- indeedhub-network
labels:
- "com.centurylinklabs.watchtower.enable=true"
healthcheck:
test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:7777/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
networks:
indeedhub-network:
driver: bridge
```
## Support
For issues, check:
1. Container logs: `docker logs indeedhub-app`
2. Health endpoint: `http://localhost:7777/health`
3. Nginx config: `/etc/nginx/conf.d/default.conf`

35
Dockerfile Normal file
View File

@@ -0,0 +1,35 @@
# Build stage
FROM node:20-alpine AS builder
WORKDIR /app
# Copy package files
COPY package*.json ./
# Install dependencies
RUN npm ci
# Copy source code
COPY . .
# Build the application
RUN npm run build
# Production stage
FROM nginx:alpine
# Copy custom nginx config
COPY nginx.conf /etc/nginx/conf.d/default.conf
# Copy built assets from builder stage
COPY --from=builder /app/dist /usr/share/nginx/html
# Expose port 7777
EXPOSE 7777
# Health check
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
CMD wget --no-verbose --tries=1 --spider http://localhost:7777/ || exit 1
# Start nginx
CMD ["nginx", "-g", "daemon off;"]

View File

@@ -0,0 +1,53 @@
<svg width="2480" height="2480" viewBox="0 0 2480 2480" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect width="2480" height="2480" fill="#0A0A0A"/>
<path d="M876 958V786.777V701.903V540H553V958H876Z" fill="url(#paint0_linear_548_33)"/>
<path d="M1927 957V785.777V700.903V539H1604V957H1927Z" fill="url(#paint1_linear_548_33)"/>
<path d="M876 1940V1768.78V1683.9V1522H553V1940H876Z" fill="url(#paint2_linear_548_33)"/>
<path d="M1927 1939V1767.78V1682.9V1521H1604V1939H1927Z" fill="url(#paint3_linear_548_33)"/>
<path d="M1186.03 1382H1021.83L856.707 1096H1020.91L1186.03 1382Z" fill="url(#paint4_linear_548_33)"/>
<path d="M1551.5 1382H1387.23L1222.1 1096H1386.37L1551.5 1382Z" fill="url(#paint5_linear_548_33)"/>
<path d="M1927 1382H1752.69L1587.57 1096H1927V1382Z" fill="url(#paint6_linear_548_33)"/>
<path d="M820.634 1382H553V1096H655.512L820.634 1382Z" fill="url(#paint7_linear_548_33)"/>
<defs>
<linearGradient id="paint0_linear_548_33" x1="677.804" y1="241.431" x2="1904.77" y2="352.601" gradientUnits="userSpaceOnUse">
<stop stop-color="#F0003D"/>
<stop offset="0.369792" stop-color="#FA4727"/>
<stop offset="0.776042" stop-color="#6B90F4"/>
</linearGradient>
<linearGradient id="paint1_linear_548_33" x1="1398.41" y1="314.849" x2="2774.82" y2="432.214" gradientUnits="userSpaceOnUse">
<stop stop-color="#F0003D"/>
<stop offset="0.369792" stop-color="#FA4727"/>
<stop offset="0.776042" stop-color="#6B90F4"/>
</linearGradient>
<linearGradient id="paint2_linear_548_33" x1="56.3747" y1="1427.64" x2="1421.18" y2="1543.04" gradientUnits="userSpaceOnUse">
<stop stop-color="#F0003D"/>
<stop offset="0.369792" stop-color="#FA4727"/>
<stop offset="0.776042" stop-color="#6B90F4"/>
</linearGradient>
<linearGradient id="paint3_linear_548_33" x1="1728.8" y1="1222.43" x2="2955.77" y2="1333.6" gradientUnits="userSpaceOnUse">
<stop stop-color="#F0003D"/>
<stop offset="0.369792" stop-color="#FA4727"/>
<stop offset="0.776042" stop-color="#6B90F4"/>
</linearGradient>
<linearGradient id="paint4_linear_548_33" x1="647.097" y1="942.634" x2="2038.19" y2="1119.39" gradientUnits="userSpaceOnUse">
<stop stop-color="#F0003D"/>
<stop offset="0.369792" stop-color="#FA4727"/>
<stop offset="0.776042" stop-color="#6B90F4"/>
</linearGradient>
<linearGradient id="paint5_linear_548_33" x1="715.651" y1="1031.44" x2="2095.49" y2="1205.34" gradientUnits="userSpaceOnUse">
<stop stop-color="#F0003D"/>
<stop offset="0.369792" stop-color="#FA4727"/>
<stop offset="0.776042" stop-color="#6B90F4"/>
</linearGradient>
<linearGradient id="paint6_linear_548_33" x1="1718.72" y1="891.716" x2="2993.99" y2="1069.18" gradientUnits="userSpaceOnUse">
<stop stop-color="#F0003D"/>
<stop offset="0.369792" stop-color="#FA4727"/>
<stop offset="0.776042" stop-color="#6B90F4"/>
</linearGradient>
<linearGradient id="paint7_linear_548_33" x1="656.411" y1="891.716" x2="1669.21" y2="1002.85" gradientUnits="userSpaceOnUse">
<stop stop-color="#F0003D"/>
<stop offset="0.369792" stop-color="#FA4727"/>
<stop offset="0.776042" stop-color="#6B90F4"/>
</linearGradient>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 3.0 KiB

View File

@@ -0,0 +1,36 @@
<svg width="2051" height="1099" viewBox="0 0 2051 1099" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M48.7775 647.241L0.239258 364.582L350.626 304.395L634.938 546.554L48.7775 647.241Z" fill="url(#paint0_linear_548_13)"/>
<path d="M605.933 260.538L895.592 501.778L1172.25 454.254L877.513 213.887L605.933 260.538Z" fill="url(#paint1_linear_548_13)"/>
<path d="M1123.72 171.595L1415.65 412.445L1694.92 364.474L1397.86 124.504L1123.72 171.595Z" fill="url(#paint2_linear_548_13)"/>
<path d="M1978.53 24.7578L1646.37 81.8147L1943.39 321.789L2027.06 307.417L1978.53 24.7578Z" fill="url(#paint3_linear_548_13)"/>
<path d="M48.9072 1093.3V779.537H121.443V1093.3H48.9072Z" fill="white"/>
<path d="M399.801 1093.29H329.106V965.131C329.106 950.034 326.161 938.984 319.901 932.356C314.011 925.36 306.278 922.044 297.073 922.044C290.446 922.044 283.818 923.887 277.19 927.2C270.563 930.516 264.303 935.301 258.78 941.195C253.257 947.085 249.207 954.085 246.261 961.815V1092.92H175.566V863.489H239.266V902.525C245.157 893.319 252.521 885.218 261.358 878.956C270.195 872.698 280.504 867.91 291.919 864.594C303.333 861.281 315.851 859.809 329.106 859.809C344.571 859.809 356.724 862.387 365.929 867.542C375.134 872.698 382.129 879.694 387.284 888.163C392.068 896.635 395.384 906.209 397.223 916.153C399.066 926.465 399.801 936.039 399.801 945.98V1093.29Z" fill="white"/>
<path d="M432.951 978.757C432.951 956.663 437.368 936.775 446.206 918.732C455.044 900.686 467.194 886.691 482.288 876.379C497.386 866.071 515.429 860.544 535.311 860.544C551.511 860.544 566.239 864.228 579.497 871.961C592.752 879.695 602.691 889.637 609.689 902.526V770.689H680.384V1014.48C680.384 1021.48 681.486 1026.63 683.697 1029.58C685.907 1032.53 689.957 1034 695.846 1034.37V1093.29C683.329 1095.5 673.019 1096.97 665.287 1096.97C652.766 1096.97 643.194 1094.39 635.832 1088.87C628.467 1083.71 624.049 1076.35 622.206 1066.77L621.472 1054.99C613.001 1069.35 601.586 1080.03 587.597 1087.39C573.604 1094.39 558.509 1098.08 543.044 1098.08C527.579 1098.08 512.481 1095.13 499.226 1089.24C485.971 1083.34 474.189 1074.88 464.249 1064.2C454.306 1053.52 446.941 1040.99 441.418 1026.63C436.263 1012.27 433.319 996.435 433.319 979.127L432.951 978.757ZM610.057 1006.75V959.241C607.112 951.507 603.062 944.879 597.536 938.985C592.014 933.094 585.754 928.673 579.126 924.99C572.499 921.31 565.504 919.467 558.509 919.467C550.406 919.467 543.411 921.31 536.784 924.623C530.156 927.938 524.634 932.357 520.214 937.88C515.796 943.406 512.114 949.664 509.536 956.663C506.959 963.659 505.854 971.761 505.854 979.862C505.854 987.966 507.329 995.697 509.907 1002.7C512.851 1009.69 516.534 1015.59 521.319 1020.74C526.106 1025.89 531.996 1029.95 538.994 1032.89C545.989 1035.84 553.354 1037.31 561.454 1037.31C566.609 1037.31 571.394 1036.58 576.181 1035.1C580.969 1033.63 585.386 1031.42 589.804 1028.47C594.224 1025.53 597.907 1022.21 601.586 1018.53C605.269 1014.85 608.217 1010.43 610.424 1005.64L610.057 1006.75Z" fill="white"/>
<path d="M846.059 1097.72C826.176 1097.72 808.868 1094.4 793.406 1088.51C777.941 1082.25 765.053 1073.78 754.376 1063.1C743.698 1052.42 735.595 1039.9 729.706 1025.9C724.183 1011.91 721.235 996.811 721.235 981.71C721.235 959.617 726.023 939.361 735.966 921.315C745.905 903.272 759.898 888.54 778.676 877.493C797.456 866.443 819.546 860.92 845.688 860.92C871.831 860.92 894.294 866.443 912.704 877.126C931.114 888.172 945.474 902.535 955.046 920.58C964.619 938.623 969.406 957.774 969.406 978.765C969.406 982.815 969.406 986.866 968.669 990.917C968.301 994.967 967.934 998.283 967.564 1001.23H795.981C796.718 1011.17 799.296 1019.64 804.451 1026.64C809.606 1033.64 815.866 1038.79 823.599 1042.11C831.328 1045.42 839.061 1047.26 847.531 1047.26C858.576 1047.26 868.519 1044.68 877.724 1039.9C886.929 1034.74 893.189 1028.11 896.501 1020.01L956.519 1037.32C950.626 1049.47 942.526 1059.78 931.849 1068.99C921.171 1078.2 908.651 1085.19 893.923 1090.72C879.196 1096.24 863.364 1098.82 845.688 1098.82L846.059 1097.72ZM895.396 957.039C894.661 947.832 891.716 939.361 886.929 932.732C882.141 925.736 876.251 920.21 869.253 916.53C862.258 912.846 853.791 910.636 844.586 910.636C836.116 910.636 828.016 912.479 820.651 916.53C813.289 920.21 807.396 925.736 802.978 932.365C798.558 938.993 795.984 947.462 794.878 957.039H895.396Z" fill="white"/>
<path d="M1113.02 1097.72C1093.13 1097.72 1075.83 1094.4 1060.36 1088.51C1044.9 1082.25 1032.01 1073.78 1021.33 1063.1C1010.66 1052.42 1002.55 1039.9 996.664 1025.9C991.141 1011.91 988.196 996.811 988.196 981.71C988.196 959.617 992.981 939.361 1002.92 921.315C1012.86 903.272 1026.86 888.54 1045.63 877.493C1064.41 866.443 1086.51 860.92 1112.65 860.92C1138.79 860.92 1161.25 866.443 1179.66 877.126C1198.07 888.172 1212.43 902.535 1222 920.58C1231.58 938.623 1236.36 957.774 1236.36 978.765C1236.36 982.815 1236.36 986.866 1235.63 990.917C1235.26 994.967 1234.89 998.283 1234.52 1001.23H1062.94C1063.68 1011.17 1066.25 1019.64 1071.41 1026.64C1076.56 1033.64 1082.82 1038.79 1090.56 1042.11C1098.29 1045.42 1106.02 1047.26 1114.49 1047.26C1125.53 1047.26 1135.48 1044.68 1144.68 1039.9C1153.89 1034.74 1160.15 1028.11 1163.46 1020.01L1223.48 1037.32C1217.59 1049.47 1209.48 1059.78 1198.81 1068.99C1188.13 1078.2 1175.61 1085.19 1160.88 1090.72C1146.15 1096.24 1130.32 1098.82 1112.65 1098.82L1113.02 1097.72ZM1162.35 957.039C1161.62 947.832 1158.67 939.361 1153.89 932.732C1149.1 925.736 1143.21 920.21 1136.21 916.53C1129.22 912.846 1120.75 910.636 1111.54 910.636C1103.07 910.636 1094.97 912.479 1087.61 916.53C1080.25 920.21 1074.35 925.736 1069.94 932.365C1065.52 938.993 1062.94 947.462 1061.84 957.039H1162.35Z" fill="white"/>
<path d="M1472.01 779.537V1093.3H1399.48V964.773H1274.29V1093.3H1201.75V779.537H1274.29V901.065H1399.48V779.537H1472.01Z" fill="white"/>
<path d="M1523.57 863.854H1594.26V995.323C1594.26 1008.95 1597.21 1019.63 1602.73 1026.99C1608.62 1034.36 1616.35 1038.04 1626.66 1038.04C1633.29 1038.04 1639.18 1036.94 1645.07 1034.73C1650.96 1032.52 1656.85 1029.2 1662.38 1024.42C1667.9 1019.63 1673.06 1013 1677.47 1005.26V864.221H1748.17V1015.21C1748.17 1022.2 1749.27 1026.99 1751.48 1029.94C1753.69 1032.89 1757.74 1034.36 1763.27 1034.73V1093.65C1756.64 1095.12 1751.11 1096.23 1746.33 1096.59C1741.54 1096.96 1737.12 1096.96 1733.44 1096.59C1720.92 1096.59 1711.35 1094.38 1703.98 1089.6C1696.62 1084.81 1692.2 1077.45 1690.36 1067.87L1688.89 1053.88C1678.21 1068.98 1665.32 1080.02 1649.49 1087.39C1634.03 1094.38 1616.35 1098.07 1596.47 1098.07C1572.9 1098.07 1554.86 1090.7 1542.34 1075.97C1529.83 1061.24 1523.57 1039.88 1523.57 1011.53V863.854Z" fill="white"/>
<path d="M1942.58 1097.71C1924.91 1097.71 1909.44 1094.02 1896.56 1086.66C1883.3 1079.29 1872.99 1068.61 1864.89 1054.99V1093.29H1803.4V770.689H1874.1V902.526C1881.83 889.269 1892.14 878.957 1904.66 871.594C1917.54 864.228 1932.64 860.544 1950.31 860.544C1964.67 860.544 1977.93 863.493 1990.45 869.383C2002.97 875.277 2013.28 883.746 2022.11 894.792C2030.95 905.842 2037.95 918.732 2043.1 933.094C2048.26 947.457 2050.47 963.292 2050.47 979.862C2050.47 996.435 2047.89 1011.53 2042.36 1026.27C2036.84 1040.99 2029.48 1053.52 2019.54 1064.2C2009.96 1074.88 1998.55 1083.34 1985.29 1089.24C1972.04 1095.13 1957.68 1098.08 1942.21 1098.08L1942.58 1097.71ZM1922.7 1038.05C1930.8 1038.05 1938.53 1036.58 1945.16 1033.63C1951.79 1030.68 1957.68 1026.63 1962.46 1021.48C1967.62 1016.32 1971.3 1010.06 1974.25 1003.06C1977.19 996.067 1978.3 988.334 1978.3 980.6C1978.3 969.55 1976.09 959.609 1971.67 950.402C1967.25 941.196 1960.99 933.829 1953.26 928.306C1945.53 922.783 1936.32 919.837 1926.38 919.837C1919.02 919.837 1912.02 921.677 1905.03 925.361C1898.4 929.044 1892.14 933.829 1886.98 939.723C1881.83 945.614 1877.41 952.242 1874.1 959.609V1007.48C1876.31 1011.9 1879.25 1016.32 1882.93 1020.37C1886.61 1024.42 1890.3 1027.37 1894.72 1030.32C1899.13 1032.89 1903.55 1035.1 1908.34 1036.58C1913.13 1038.05 1917.91 1038.78 1922.7 1038.78V1038.05Z" fill="white"/>
<defs>
<linearGradient id="paint0_linear_548_13" x1="245.48" y1="59.5055" x2="2566.89" y2="563.412" gradientUnits="userSpaceOnUse">
<stop stop-color="#F0003D"/>
<stop offset="0.369792" stop-color="#FA4727"/>
<stop offset="0.776042" stop-color="#6B90F4"/>
</linearGradient>
<linearGradient id="paint1_linear_548_13" x1="245.48" y1="59.5063" x2="2566.89" y2="563.412" gradientUnits="userSpaceOnUse">
<stop stop-color="#F0003D"/>
<stop offset="0.369792" stop-color="#FA4727"/>
<stop offset="0.776042" stop-color="#6B90F4"/>
</linearGradient>
<linearGradient id="paint2_linear_548_13" x1="245.48" y1="59.5046" x2="2566.89" y2="563.411" gradientUnits="userSpaceOnUse">
<stop stop-color="#F0003D"/>
<stop offset="0.369792" stop-color="#FA4727"/>
<stop offset="0.776042" stop-color="#6B90F4"/>
</linearGradient>
<linearGradient id="paint3_linear_548_13" x1="1793.47" y1="-187.406" x2="3219.26" y2="26.8634" gradientUnits="userSpaceOnUse">
<stop stop-color="#F0003D"/>
<stop offset="0.369792" stop-color="#FA4727"/>
<stop offset="0.776042" stop-color="#6B90F4"/>
</linearGradient>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 8.9 KiB

View File

@@ -1,131 +1,107 @@
<svg
width="67"
height="47"
viewBox="0 0 67 47"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M1.59341 21.1399L0.00781255 11.9078L11.4539 9.94198L20.7415 17.8513L1.59341 21.1399Z"
fill="url(#paint0_linear_5685_136275)"
/>
<path
d="M19.794 8.50952L29.2563 16.3888L38.2938 14.8366L28.6657 6.98583L19.794 8.50952Z"
fill="url(#paint1_linear_5685_136275)"
/>
<path
d="M36.7085 5.60456L46.2451 13.4711L55.3678 11.9043L45.6638 4.0665L36.7085 5.60456Z"
fill="url(#paint2_linear_5685_136275)"
/>
<path
d="M64.6325 0.808593L53.782 2.67216L63.4848 10.5101L66.2181 10.0407L64.6325 0.808593Z"
fill="url(#paint3_linear_5685_136275)"
/>
<path d="M1.59766 35.7088V25.4609H3.96719V35.7088H1.59766Z" fill="white" />
<path
d="M13.0603 35.7085H10.7509V31.5227C10.7509 31.0296 10.6547 30.6687 10.4502 30.4522C10.2578 30.2237 10.0052 30.1154 9.7045 30.1154C9.488 30.1154 9.27149 30.1756 9.05498 30.2838C8.83848 30.3921 8.634 30.5484 8.45358 30.7409C8.27316 30.9333 8.14085 31.1619 8.04462 31.4144V35.6965H5.73523V28.2029H7.81609V29.4779C8.00854 29.1772 8.2491 28.9126 8.53778 28.7081C8.82645 28.5037 9.16324 28.3473 9.53611 28.239C9.90898 28.1308 10.3179 28.0827 10.7509 28.0827C11.2561 28.0827 11.6531 28.1669 11.9538 28.3353C12.2545 28.5037 12.483 28.7322 12.6514 29.0088C12.8077 29.2855 12.916 29.5982 12.9761 29.923C13.0363 30.2598 13.0603 30.5725 13.0603 30.8972V35.7085Z"
fill="white"
/>
<path
d="M14.1432 31.9677C14.1432 31.2461 14.2875 30.5965 14.5762 30.0072C14.8649 29.4178 15.2618 28.9607 15.7549 28.6239C16.2481 28.2872 16.8375 28.1067 17.487 28.1067C18.0162 28.1067 18.4973 28.227 18.9304 28.4796C19.3634 28.7322 19.6881 29.0569 19.9167 29.4779V25.1719H22.2261V33.1345C22.2261 33.363 22.2621 33.5314 22.3343 33.6276C22.4065 33.7239 22.5388 33.772 22.7312 33.784V35.7085C22.3223 35.7807 21.9855 35.8288 21.7329 35.8288C21.3239 35.8288 21.0112 35.7446 20.7707 35.5641C20.5301 35.3958 20.3858 35.1552 20.3256 34.8425L20.3016 34.4576C20.0249 34.9267 19.652 35.2755 19.195 35.516C18.7379 35.7446 18.2448 35.8649 17.7396 35.8649C17.2344 35.8649 16.7412 35.7686 16.3082 35.5762C15.8752 35.3837 15.4903 35.1071 15.1656 34.7583C14.8408 34.4095 14.6002 34.0005 14.4198 33.5314C14.2514 33.0623 14.1552 32.5451 14.1552 31.9798L14.1432 31.9677ZM19.9287 32.8819V31.3303C19.8325 31.0777 19.7002 30.8612 19.5197 30.6687C19.3393 30.4763 19.1348 30.3319 18.9183 30.2116C18.7018 30.0914 18.4733 30.0312 18.2448 30.0312C17.9801 30.0312 17.7516 30.0914 17.5351 30.1996C17.3186 30.3079 17.1382 30.4522 16.9938 30.6326C16.8495 30.8131 16.7292 31.0175 16.645 31.2461C16.5608 31.4746 16.5247 31.7392 16.5247 32.0038C16.5247 32.2685 16.5729 32.521 16.6571 32.7496C16.7533 32.9781 16.8736 33.1706 17.0299 33.339C17.1863 33.5073 17.3787 33.6397 17.6073 33.7359C17.8358 33.8321 18.0764 33.8802 18.341 33.8802C18.5094 33.8802 18.6657 33.8562 18.8221 33.808C18.9785 33.7599 19.1228 33.6878 19.2671 33.5915C19.4115 33.4953 19.5318 33.3871 19.652 33.2668C19.7723 33.1465 19.8686 33.0022 19.9407 32.8458L19.9287 32.8819Z"
fill="white"
/>
<path
d="M27.6382 35.8531C26.9887 35.8531 26.4233 35.7448 25.9182 35.5524C25.413 35.3479 24.992 35.0713 24.6432 34.7224C24.2944 34.3736 24.0297 33.9647 23.8373 33.5076C23.6569 33.0505 23.5606 32.5574 23.5606 32.0642C23.5606 31.3426 23.717 30.681 24.0418 30.0916C24.3665 29.5023 24.8236 29.0211 25.437 28.6603C26.0505 28.2994 26.7721 28.119 27.6261 28.119C28.4801 28.119 29.2139 28.2994 29.8153 28.6483C30.4167 29.0091 30.8858 29.4782 31.1985 30.0676C31.5112 30.6569 31.6676 31.2824 31.6676 31.968C31.6676 32.1003 31.6676 32.2326 31.6435 32.3649C31.6315 32.4972 31.6195 32.6055 31.6074 32.7017H26.0023C26.0264 33.0265 26.1106 33.3031 26.279 33.5317C26.4474 33.7602 26.6519 33.9286 26.9045 34.0368C27.157 34.1451 27.4096 34.2052 27.6863 34.2052C28.0471 34.2052 28.3719 34.121 28.6726 33.9647C28.9733 33.7963 29.1778 33.5798 29.286 33.3152L31.2466 33.8805C31.0541 34.2774 30.7895 34.6142 30.4407 34.9149C30.0919 35.2156 29.6829 35.4441 29.2018 35.6246C28.7207 35.805 28.2035 35.8892 27.6261 35.8892L27.6382 35.8531ZM29.2499 31.2584C29.2259 30.9577 29.1297 30.681 28.9733 30.4645C28.8169 30.236 28.6245 30.0555 28.3959 29.9353C28.1674 29.815 27.8908 29.7428 27.5901 29.7428C27.3134 29.7428 27.0488 29.803 26.8082 29.9353C26.5677 30.0555 26.3752 30.236 26.2309 30.4525C26.0865 30.669 26.0024 30.9456 25.9663 31.2584H29.2499Z"
fill="white"
/>
<path
d="M36.3589 35.8531C35.7094 35.8531 35.144 35.7448 34.6389 35.5524C34.1337 35.3479 33.7127 35.0713 33.3639 34.7224C33.0151 34.3736 32.7504 33.9647 32.558 33.5076C32.3776 33.0505 32.2814 32.5574 32.2814 32.0642C32.2814 31.3426 32.4377 30.681 32.7625 30.0916C33.0872 29.5023 33.5443 29.0211 34.1577 28.6603C34.7712 28.2994 35.4929 28.119 36.3468 28.119C37.2008 28.119 37.9346 28.2994 38.536 28.6483C39.1374 29.0091 39.6065 29.4782 39.9192 30.0676C40.2319 30.6569 40.3883 31.2824 40.3883 31.968C40.3883 32.1003 40.3883 32.2326 40.3642 32.3649C40.3522 32.4972 40.3402 32.6055 40.3281 32.7017H34.7231C34.7471 33.0265 34.8313 33.3031 34.9997 33.5317C35.1681 33.7602 35.3726 33.9286 35.6252 34.0368C35.8778 34.1451 36.1303 34.2052 36.407 34.2052C36.7678 34.2052 37.0926 34.121 37.3933 33.9647C37.694 33.7963 37.8985 33.5798 38.0067 33.3152L39.9673 33.8805C39.7749 34.2774 39.5102 34.6142 39.1614 34.9149C38.8126 35.2156 38.4037 35.4441 37.9225 35.6246C37.4414 35.805 36.9242 35.8892 36.3468 35.8892L36.3589 35.8531ZM37.9706 31.2584C37.9466 30.9577 37.8504 30.681 37.694 30.4645C37.5376 30.236 37.3452 30.0555 37.1166 29.9353C36.8881 29.815 36.6115 29.7428 36.3108 29.7428C36.0341 29.7428 35.7695 29.803 35.5289 29.9353C35.2884 30.0555 35.0959 30.236 34.9516 30.4525C34.8073 30.669 34.7231 30.9456 34.687 31.2584H37.9706Z"
fill="white"
/>
<path
d="M48.0863 25.4609V35.7088H45.7168V31.511H41.6273V35.7088H39.2577V25.4609H41.6273V29.4302H45.7168V25.4609H48.0863Z"
fill="white"
/>
<path
d="M49.7703 28.2148H52.0797V32.5088C52.0797 32.9538 52.1759 33.3026 52.3563 33.5432C52.5488 33.7838 52.8014 33.904 53.1381 33.904C53.3546 33.904 53.5471 33.868 53.7395 33.7958C53.932 33.7236 54.1244 33.6154 54.3049 33.459C54.4853 33.3026 54.6537 33.0861 54.798 32.8335V28.2268H57.1074V33.1583C57.1074 33.3868 57.1435 33.5432 57.2157 33.6394C57.2878 33.7357 57.4201 33.7838 57.6006 33.7958V35.7203C57.3841 35.7684 57.2036 35.8045 57.0473 35.8165C56.8909 35.8285 56.7466 35.8285 56.6263 35.8165C56.2173 35.8165 55.9046 35.7443 55.664 35.588C55.4235 35.4316 55.2791 35.1911 55.219 34.8783L55.1709 34.4213C54.8221 34.9144 54.4011 35.2752 53.8839 35.5158C53.3787 35.7443 52.8014 35.8646 52.1518 35.8646C51.382 35.8646 50.7927 35.6241 50.3837 35.1429C49.9748 34.6618 49.7703 33.9642 49.7703 33.038V28.2148Z"
fill="white"
/>
<path
d="M63.4583 35.8528C62.881 35.8528 62.3758 35.7325 61.9548 35.492C61.5218 35.2514 61.185 34.9026 60.9204 34.4576V35.7085H58.9117V25.1719H61.2211V29.4779C61.4737 29.0449 61.8105 28.7081 62.2194 28.4676C62.6404 28.227 63.1336 28.1067 63.7109 28.1067C64.18 28.1067 64.613 28.203 65.022 28.3954C65.4309 28.5879 65.7677 28.8645 66.0564 29.2253C66.3451 29.5862 66.5736 30.0072 66.742 30.4763C66.9104 30.9454 66.9826 31.4626 66.9826 32.0038C66.9826 32.5451 66.8984 33.0382 66.7179 33.5194C66.5375 34.0005 66.297 34.4095 65.9722 34.7583C65.6595 35.1071 65.2866 35.3837 64.8536 35.5762C64.4206 35.7686 63.9515 35.8649 63.4463 35.8649L63.4583 35.8528ZM62.8088 33.9043C63.0734 33.9043 63.326 33.8562 63.5425 33.7599C63.759 33.6637 63.9515 33.5314 64.1078 33.363C64.2762 33.1946 64.3965 32.9901 64.4927 32.7616C64.589 32.5331 64.625 32.2805 64.625 32.0279C64.625 31.667 64.5529 31.3423 64.4085 31.0416C64.2642 30.7409 64.0597 30.5003 63.8071 30.3199C63.5545 30.1395 63.2538 30.0433 62.9291 30.0433C62.6885 30.0433 62.46 30.1034 62.2315 30.2237C62.0149 30.344 61.8105 30.5003 61.6421 30.6928C61.4737 30.8852 61.3293 31.1017 61.2211 31.3423V32.9059C61.2933 33.0503 61.3895 33.1946 61.5098 33.3269C61.63 33.4592 61.7503 33.5555 61.8947 33.6517C62.039 33.7359 62.1833 33.808 62.3397 33.8562C62.4961 33.9043 62.6524 33.9283 62.8088 33.9283V33.9043Z"
fill="white"
/>
<path
d="M35.4844 46.1875C36.1553 46.1875 36.6992 45.6436 36.6992 44.9726C36.6992 44.3017 36.1553 43.7578 35.4844 43.7578C34.8134 43.7578 34.2695 44.3017 34.2695 44.9726C34.2695 45.6436 34.8134 46.1875 35.4844 46.1875Z"
fill="#F70D37"
/>
<path
d="M39.7671 46.1628C39.3221 46.1628 38.9011 46.0906 38.5162 45.9343C38.1313 45.7779 37.7945 45.5494 37.5059 45.2366L37.7584 44.8518C38.0712 45.1525 38.3839 45.3569 38.6966 45.5013C39.0094 45.6336 39.3582 45.7057 39.7311 45.7057C40.2122 45.7057 40.6091 45.6095 40.9098 45.405C41.2105 45.2006 41.3548 44.9239 41.3548 44.5631C41.3548 44.3225 41.2827 44.1301 41.1383 43.9978C40.994 43.8654 40.7895 43.7572 40.5369 43.673C40.2723 43.5888 39.9596 43.5046 39.5747 43.4084C39.1898 43.3122 38.865 43.2039 38.6004 43.0956C38.3358 42.9874 38.1433 42.8431 38.011 42.6747C37.8787 42.5063 37.8186 42.2657 37.8186 41.977C37.8186 41.6162 37.9148 41.3035 38.0952 41.0629C38.2757 40.8223 38.5282 40.6419 38.841 40.5216C39.1537 40.4014 39.5025 40.3412 39.8874 40.3412C40.3325 40.3412 40.7174 40.4134 41.0421 40.5577C41.3669 40.7021 41.6195 40.8945 41.7999 41.1351L41.5112 41.4839C41.3308 41.2553 41.1023 41.087 40.8136 40.9667C40.5249 40.8584 40.2122 40.7983 39.8634 40.7983C39.5987 40.7983 39.3582 40.8344 39.1297 40.9065C38.9011 40.9787 38.7087 41.099 38.5764 41.2553C38.432 41.4117 38.3599 41.6282 38.3599 41.9049C38.3599 42.1214 38.408 42.2898 38.5162 42.41C38.6245 42.5303 38.7808 42.6266 38.9853 42.7107C39.1898 42.7829 39.4544 42.8671 39.7671 42.9513C40.2122 43.0596 40.5851 43.1678 40.9098 43.2881C41.2225 43.4084 41.4751 43.5527 41.6435 43.7331C41.8119 43.9136 41.9081 44.1782 41.9081 44.5029C41.9081 45.0081 41.7157 45.4171 41.3188 45.7057C40.9339 45.9944 40.4167 46.1508 39.7671 46.1508V46.1628Z"
fill="white"
/>
<path
d="M45.6849 45.8383C45.6849 45.8383 45.5767 45.8864 45.4684 45.9466C45.3602 46.0067 45.2279 46.0548 45.0595 46.1029C44.8911 46.151 44.7106 46.1751 44.5062 46.1751C44.3017 46.1751 44.1333 46.139 43.9529 46.0668C43.7845 45.9947 43.6522 45.8744 43.5439 45.718C43.4477 45.5617 43.3876 45.3812 43.3876 45.1647V40.8948H42.5937V40.4497H43.3876V38.5252H43.9288V40.4497H45.2399V40.8948H43.9288V45.0324C43.9408 45.2489 44.025 45.4053 44.1574 45.5015C44.2897 45.5977 44.4581 45.6579 44.6385 45.6579C44.867 45.6579 45.0595 45.6218 45.2279 45.5496C45.3962 45.4775 45.4925 45.4294 45.5165 45.4053L45.6729 45.8383H45.6849Z"
fill="white"
/>
<path
d="M46.5871 43.6855V40.4499H47.1284V43.6133C47.1284 44.3109 47.2486 44.8281 47.4772 45.1769C47.7177 45.5137 48.0665 45.6941 48.5477 45.6941C48.8604 45.6941 49.1731 45.622 49.4618 45.4776C49.7505 45.3333 50.0151 45.1409 50.2316 44.8883C50.4601 44.6357 50.6165 44.335 50.7248 43.9982V40.4499H51.266V45.3574C51.266 45.4416 51.2901 45.5137 51.3262 45.5498C51.3622 45.5979 51.4224 45.622 51.4946 45.622V46.067C51.4224 46.067 51.3622 46.067 51.3262 46.067C51.2901 46.067 51.254 46.067 51.2299 46.067C51.1097 46.055 51.0014 45.9948 50.9292 45.9106C50.845 45.8265 50.809 45.7062 50.7969 45.5859V44.7439C50.5443 45.189 50.2076 45.5378 49.7745 45.8024C49.3415 46.055 48.8845 46.1873 48.3793 46.1873C47.7899 46.1873 47.3449 45.9828 47.0321 45.5618C46.7314 45.1409 46.5751 44.5274 46.5751 43.7095L46.5871 43.6855Z"
fill="white"
/>
<path
d="M52.6012 43.2643C52.6012 42.735 52.7094 42.2539 52.938 41.8209C53.1665 41.3879 53.4672 41.0271 53.8521 40.7624C54.237 40.4978 54.682 40.3535 55.1872 40.3535C55.6924 40.3535 56.1134 40.4858 56.4862 40.7384C56.8711 41.003 57.1598 41.3037 57.3763 41.6645V38.1523H57.9176V45.3451C57.9176 45.4293 57.9416 45.5015 57.9777 45.5376C58.0138 45.5857 58.0739 45.6098 58.1461 45.6098V46.0548C58.0258 46.0668 57.9416 46.0789 57.8815 46.0548C57.7492 46.0307 57.6409 45.9706 57.5567 45.8744C57.4725 45.7782 57.4244 45.6699 57.4244 45.5496V44.9242C57.1959 45.297 56.8832 45.5977 56.4862 45.8263C56.0893 46.0548 55.6924 46.1631 55.2834 46.1631C54.8985 46.1631 54.5377 46.0789 54.2009 45.9225C53.8641 45.7661 53.5875 45.5496 53.3469 45.273C53.1063 44.9963 52.9139 44.6956 52.7816 44.3468C52.6493 43.998 52.5771 43.6372 52.5771 43.2643H52.6012ZM57.3883 44.1664V42.3261C57.2801 42.0494 57.1237 41.8089 56.8952 41.5804C56.6667 41.3518 56.4141 41.1714 56.1374 41.0391C55.8608 40.9068 55.5721 40.8346 55.3075 40.8346C54.9827 40.8346 54.682 40.9068 54.4294 41.0391C54.1648 41.1714 53.9363 41.3638 53.7438 41.5924C53.5514 41.8209 53.407 42.0855 53.3108 42.3742C53.2146 42.6629 53.1545 42.9636 53.1545 43.2763C53.1545 43.589 53.2146 43.9018 53.3229 44.1904C53.4431 44.4791 53.5995 44.7437 53.804 44.9723C54.0084 45.2008 54.249 45.3692 54.5136 45.5015C54.7782 45.6218 55.079 45.694 55.3917 45.694C55.5841 45.694 55.7886 45.6579 56.0171 45.5737C56.2457 45.4895 56.4502 45.3812 56.6426 45.2489C56.8471 45.1046 57.0034 44.9482 57.1358 44.7678C57.2681 44.5874 57.3523 44.3949 57.3763 44.1904L57.3883 44.1664Z"
fill="white"
/>
<path
d="M59.6494 39.1507V38.1523H60.1907V39.1507H59.6494ZM59.6494 46.0548V40.4257H60.1907V46.0548H59.6494Z"
fill="white"
/>
<path
d="M64.2442 46.1631C63.8473 46.1631 63.4865 46.091 63.1497 45.9346C62.8129 45.7782 62.5242 45.5738 62.2837 45.3091C62.0431 45.0445 61.8506 44.7318 61.7063 44.383C61.562 44.0342 61.5018 43.6613 61.5018 43.2764C61.5018 42.8915 61.574 42.4946 61.7063 42.1458C61.8386 41.7969 62.0311 41.4842 62.2837 41.2196C62.5362 40.955 62.8249 40.7385 63.1617 40.5821C63.4985 40.4257 63.8593 40.3536 64.2442 40.3536C64.6291 40.3536 64.99 40.4257 65.3268 40.5821C65.6635 40.7385 65.9522 40.955 66.2048 41.2196C66.4574 41.4842 66.6499 41.7969 66.7942 42.1458C66.9265 42.4946 66.9987 42.8674 66.9987 43.2764C66.9987 43.6854 66.9265 44.0342 66.7942 44.383C66.6619 44.7318 66.4694 45.0445 66.2168 45.3091C65.9643 45.5738 65.6756 45.7903 65.3388 45.9346C65.002 46.0789 64.6412 46.1631 64.2563 46.1631H64.2442ZM62.0311 43.2764C62.0311 43.7214 62.1273 44.1304 62.3318 44.4912C62.5362 44.8521 62.8009 45.1407 63.1256 45.3573C63.4624 45.5738 63.8232 45.682 64.2322 45.682C64.6412 45.682 65.002 45.5738 65.3388 45.3573C65.6756 45.1407 65.9402 44.84 66.1447 44.4792C66.3491 44.1063 66.4454 43.7094 66.4454 43.2644C66.4454 42.8193 66.3491 42.4224 66.1447 42.0616C65.9402 41.7007 65.6756 41.4 65.3508 41.1835C65.014 40.967 64.6532 40.8587 64.2442 40.8587C63.8353 40.8587 63.4744 40.967 63.1376 41.1955C62.8009 41.4241 62.5362 41.7127 62.3318 42.0736C62.1273 42.4344 62.0311 42.8434 62.0311 43.2884V43.2764Z"
fill="white"
/>
<svg width="1374" height="1401" viewBox="0 0 1374 1401" fill="none" xmlns="http://www.w3.org/2000/svg">
<!-- Add glass effect filters -->
<defs>
<linearGradient
id="paint0_linear_5685_136275"
x1="8.01909"
y1="1.94352"
x2="83.8513"
y2="18.4071"
gradientUnits="userSpaceOnUse"
>
<!-- Glass highlight effect -->
<filter id="glass-effect" x="-50%" y="-50%" width="200%" height="200%">
<feGaussianBlur in="SourceAlpha" stdDeviation="8"/>
<feOffset dx="0" dy="-2" result="offsetblur"/>
<feComponentTransfer>
<feFuncA type="linear" slope="0.3"/>
</feComponentTransfer>
<feMerge>
<feMergeNode/>
<feMergeNode in="SourceGraphic"/>
</feMerge>
</filter>
<!-- Inner glow -->
<filter id="inner-glow">
<feGaussianBlur stdDeviation="4" result="blur"/>
<feComposite in="blur" in2="SourceGraphic" operator="atop"/>
</filter>
<!-- Gradients -->
<linearGradient id="paint0_linear_548_65" x1="124.804" y1="-297.569" x2="1351.77" y2="-186.399" gradientUnits="userSpaceOnUse">
<stop stop-color="#F0003D"/>
<stop offset="0.369792" stop-color="#FA4727"/>
<stop offset="0.776042" stop-color="#6B90F4"/>
</linearGradient>
<linearGradient
id="paint1_linear_5685_136275"
x1="8.01909"
y1="1.94352"
x2="83.8513"
y2="18.4071"
gradientUnits="userSpaceOnUse"
>
<linearGradient id="paint1_linear_548_65" x1="1175.8" y1="-298.569" x2="2402.77" y2="-187.399" gradientUnits="userSpaceOnUse">
<stop stop-color="#F0003D"/>
<stop offset="0.369792" stop-color="#FA4727"/>
<stop offset="0.776042" stop-color="#6B90F4"/>
</linearGradient>
<linearGradient
id="paint2_linear_5685_136275"
x1="8.01909"
y1="1.94352"
x2="83.8513"
y2="18.4071"
gradientUnits="userSpaceOnUse"
>
<linearGradient id="paint2_linear_548_65" x1="124.804" y1="684.431" x2="1351.77" y2="795.601" gradientUnits="userSpaceOnUse">
<stop stop-color="#F0003D"/>
<stop offset="0.369792" stop-color="#FA4727"/>
<stop offset="0.776042" stop-color="#6B90F4"/>
</linearGradient>
<linearGradient
id="paint3_linear_5685_136275"
x1="8.01909"
y1="1.94352"
x2="83.8513"
y2="18.4071"
gradientUnits="userSpaceOnUse"
>
<linearGradient id="paint3_linear_548_65" x1="1175.8" y1="683.431" x2="2402.77" y2="794.601" gradientUnits="userSpaceOnUse">
<stop stop-color="#F0003D"/>
<stop offset="0.369792" stop-color="#FA4727"/>
<stop offset="0.776042" stop-color="#6B90F4"/>
</linearGradient>
<linearGradient id="paint4_linear_548_65" x1="-202.64" y1="492.439" x2="1176.93" y2="666.265" gradientUnits="userSpaceOnUse">
<stop stop-color="#F0003D"/>
<stop offset="0.369792" stop-color="#FA4727"/>
<stop offset="0.776042" stop-color="#6B90F4"/>
</linearGradient>
<linearGradient id="paint5_linear_548_65" x1="162.651" y1="492.439" x2="1542.49" y2="666.336" gradientUnits="userSpaceOnUse">
<stop stop-color="#F0003D"/>
<stop offset="0.369792" stop-color="#FA4727"/>
<stop offset="0.776042" stop-color="#6B90F4"/>
</linearGradient>
<linearGradient id="paint6_linear_548_65" x1="512.679" y1="492.439" x2="1933.21" y2="676.92" gradientUnits="userSpaceOnUse">
<stop stop-color="#F0003D"/>
<stop offset="0.369792" stop-color="#FA4727"/>
<stop offset="0.776042" stop-color="#6B90F4"/>
</linearGradient>
<linearGradient id="paint7_linear_548_65" x1="-411.498" y1="492.439" x2="715.627" y2="607.854" gradientUnits="userSpaceOnUse">
<stop stop-color="#F0003D"/>
<stop offset="0.369792" stop-color="#FA4727"/>
<stop offset="0.776042" stop-color="#6B90F4"/>
</linearGradient>
</defs>
<!-- Logo paths with glass effects -->
<g filter="url(#glass-effect)">
<path d="M323 419V247.777V162.903V1H0V419H323Z" fill="url(#paint0_linear_548_65)" opacity="0.95"/>
<path d="M1374 418V246.777V161.903V0H1051V418H1374Z" fill="url(#paint1_linear_548_65)" opacity="0.95"/>
<path d="M323 1401V1229.78V1144.9V983H0V1401H323Z" fill="url(#paint2_linear_548_65)" opacity="0.95"/>
<path d="M911 1401V1229.78V1144.9V983H463V1401H911Z" fill="#1D1D1D" opacity="0.9"/>
<path d="M911 419V247.777V162.903V1H463V419H911Z" fill="#1D1D1D" opacity="0.9"/>
<path d="M1374 1400V1228.78V1143.9V982H1051V1400H1374Z" fill="url(#paint3_linear_548_65)" opacity="0.95"/>
<path d="M633.03 843H468.829L303.707 557H467.908L633.03 843Z" fill="url(#paint4_linear_548_65)"/>
<path d="M998.495 843H834.226L669.104 557H833.373L998.495 843Z" fill="url(#paint5_linear_548_65)"/>
<path d="M1374 843H1199.69L1034.57 557H1374V843Z" fill="url(#paint6_linear_548_65)"/>
<path d="M267.634 843H0V557H102.512L267.634 843Z" fill="url(#paint7_linear_548_65)"/>
</g>
<!-- Glass highlights on top -->
<g opacity="0.4">
<path d="M323 419V247.777V162.903V1H0V150" fill="url(#glass-highlight-1)"/>
<path d="M1374 418V246.777V161.903V0H1051V150" fill="url(#glass-highlight-2)"/>
<path d="M323 1401V1229.78V1144.9V983H0V1100" fill="url(#glass-highlight-3)"/>
<path d="M1374 1400V1228.78V1143.9V982H1051V1100" fill="url(#glass-highlight-4)"/>
</g>
<!-- Glass highlight gradients -->
<defs>
<linearGradient id="glass-highlight-1" x1="161.5" y1="1" x2="161.5" y2="150" gradientUnits="userSpaceOnUse">
<stop stop-color="white" stop-opacity="0.3"/>
<stop offset="1" stop-color="white" stop-opacity="0"/>
</linearGradient>
<linearGradient id="glass-highlight-2" x1="1212.5" y1="0" x2="1212.5" y2="150" gradientUnits="userSpaceOnUse">
<stop stop-color="white" stop-opacity="0.3"/>
<stop offset="1" stop-color="white" stop-opacity="0"/>
</linearGradient>
<linearGradient id="glass-highlight-3" x1="161.5" y1="983" x2="161.5" y2="1100" gradientUnits="userSpaceOnUse">
<stop stop-color="white" stop-opacity="0.3"/>
<stop offset="1" stop-color="white" stop-opacity="0"/>
</linearGradient>
<linearGradient id="glass-highlight-4" x1="1212.5" y1="982" x2="1212.5" y2="1100" gradientUnits="userSpaceOnUse">
<stop stop-color="white" stop-opacity="0.3"/>
<stop offset="1" stop-color="white" stop-opacity="0"/>
</linearGradient>
</defs>
</svg>

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 5.6 KiB

28
docker-compose.yml Normal file
View File

@@ -0,0 +1,28 @@
version: '3.8'
services:
indeedhub:
image: indeedhub-prototype:latest
build:
context: .
dockerfile: Dockerfile
container_name: indeedhub-app
restart: unless-stopped
ports:
- "7777:7777"
environment:
- NODE_ENV=production
networks:
- indeedhub-network
labels:
- "com.centurylinklabs.watchtower.enable=true"
healthcheck:
test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:7777/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
networks:
indeedhub-network:
driver: bridge

View File

@@ -2,10 +2,18 @@
<html lang="en">
<head>
<meta charset="UTF-8">
<link rel="icon" type="image/svg+xml" href="/assets/images/logo.svg">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="icon" type="image/svg+xml" href="/assets/images/app-icon.svg">
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover">
<title>IndeedHub - Decentralized Media Streaming</title>
<meta name="description" content="Stream films and content on the decentralized web powered by Nostr and Bitcoin">
<!-- PWA Meta Tags -->
<meta name="theme-color" content="#0a0a0a">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
<meta name="apple-mobile-web-app-title" content="IndeedHub">
<link rel="apple-touch-icon" href="/assets/images/app-icon.svg">
<link rel="manifest" href="/manifest.json">
</head>
<body>
<div id="app"></div>

58
nginx.conf Normal file
View File

@@ -0,0 +1,58 @@
server {
listen 7777;
server_name _;
root /usr/share/nginx/html;
index index.html;
# Gzip compression
gzip on;
gzip_vary on;
gzip_min_length 1024;
gzip_types text/plain text/css text/xml text/javascript application/javascript application/xml+rss application/json;
# Security headers
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "no-referrer-when-downgrade" always;
# PWA Support - proper MIME types
location ~* \.(?:manifest|webmanifest|json)$ {
add_header Cache-Control "public, max-age=3600";
add_header Content-Type application/manifest+json;
}
location ~* \.(?:js|css|woff2|woff|ttf|otf|eot|svg|png|jpg|jpeg|gif|ico)$ {
expires 1y;
add_header Cache-Control "public, immutable";
}
# Vue Router - SPA fallback
location / {
try_files $uri $uri/ /index.html;
}
# Service Worker
location /sw.js {
add_header Cache-Control "no-cache";
proxy_cache_bypass $http_pragma;
proxy_cache_revalidate on;
expires off;
access_log off;
}
location /workbox-*.js {
add_header Cache-Control "no-cache";
proxy_cache_bypass $http_pragma;
proxy_cache_revalidate on;
expires off;
access_log off;
}
# Health check endpoint
location /health {
access_log off;
return 200 "healthy\n";
add_header Content-Type text/plain;
}
}

4914
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -24,6 +24,7 @@
"tailwindcss": "^3.4.18",
"typescript": "~5.9.3",
"vite": "^7.2.2",
"vite-plugin-pwa": "^1.2.0",
"vue-tsc": "^3.1.3"
}
}

65
public/manifest.json Normal file
View File

@@ -0,0 +1,65 @@
{
"name": "IndeedHub - Decentralized Media Streaming",
"short_name": "IndeedHub",
"description": "Stream films and content on the decentralized web powered by Nostr and Bitcoin",
"start_url": "/",
"display": "standalone",
"background_color": "#0a0a0a",
"theme_color": "#0a0a0a",
"orientation": "portrait-primary",
"icons": [
{
"src": "/assets/images/app-icon.svg",
"sizes": "any",
"type": "image/svg+xml",
"purpose": "any maskable"
},
{
"src": "/pwa-192x192.png",
"sizes": "192x192",
"type": "image/png",
"purpose": "any"
},
{
"src": "/pwa-512x512.png",
"sizes": "512x512",
"type": "image/png",
"purpose": "any"
},
{
"src": "/pwa-maskable-192x192.png",
"sizes": "192x192",
"type": "image/png",
"purpose": "maskable"
},
{
"src": "/pwa-maskable-512x512.png",
"sizes": "512x512",
"type": "image/png",
"purpose": "maskable"
},
{
"src": "/apple-touch-icon.png",
"sizes": "180x180",
"type": "image/png",
"purpose": "any"
}
],
"categories": ["entertainment", "video", "streaming"],
"shortcuts": [
{
"name": "Browse Films",
"short_name": "Films",
"description": "Browse all films",
"url": "/films",
"icons": [{ "src": "/assets/images/app-icon.svg", "sizes": "96x96" }]
},
{
"name": "My List",
"short_name": "My List",
"description": "View your saved content",
"url": "/mylist",
"icons": [{ "src": "/assets/images/app-icon.svg", "sizes": "96x96" }]
}
]
}

View File

@@ -1,16 +1,16 @@
<template>
<nav class="mobile-nav fixed bottom-0 left-0 right-0 z-50 md:hidden pb-4 px-6">
<div class="floating-glass-nav px-4 py-3 rounded-2xl">
<div class="flex items-center justify-around">
<div class="flex items-center justify-around gap-1">
<button
v-for="item in navItems"
:key="item.name"
@click="navigate(item.path)"
class="flex flex-col items-center gap-1 nav-tab"
class="flex flex-col items-center gap-1 nav-tab flex-1"
:class="{ 'nav-tab-active': isActive(item.path) }"
>
<component :is="item.icon" class="w-6 h-6" />
<span class="text-xs font-medium">{{ item.name }}</span>
<component :is="item.icon" class="w-6 h-6 flex-shrink-0" />
<span class="text-xs font-medium whitespace-nowrap">{{ item.name }}</span>
</button>
</div>
</div>
@@ -97,6 +97,8 @@ const isActive = (path: string) => {
background: transparent;
border: none;
cursor: pointer;
font-weight: 600;
max-width: 80px;
}
.nav-tab:active {
@@ -104,12 +106,37 @@ const isActive = (path: string) => {
}
.nav-tab-active {
color: rgba(255, 255, 255, 1);
text-decoration: none;
transition: all 0.3s ease;
position: relative;
padding: 8px 12px;
border-radius: 12px;
background: rgba(255, 255, 255, 0.15);
font-weight: 600;
border-radius: 12px;
background: rgba(0, 0, 0, 0.35);
color: rgba(255, 255, 255, 1);
box-shadow:
0 8px 24px rgba(0, 0, 0, 0.6),
inset 0 1px 0 rgba(255, 255, 255, 0.25);
backdrop-filter: blur(24px);
-webkit-backdrop-filter: blur(24px);
border: none;
cursor: pointer;
transition: all 0.3s ease;
max-width: 80px;
}
/* Subtle variant with darker grey border for tab bar */
.nav-tab-active::before {
content: '';
position: absolute;
inset: -2px;
border-radius: inherit;
padding: 2px;
background: linear-gradient(135deg, rgba(255, 255, 255, 0.08), rgba(255, 255, 255, 0.02));
-webkit-mask:
linear-gradient(#fff 0 0) content-box,
linear-gradient(#fff 0 0);
-webkit-mask-composite: xor;
mask-composite: exclude;
pointer-events: none;
z-index: -1;
}
</style>

View File

@@ -1,9 +1,49 @@
import { fileURLToPath, URL } from 'node:url'
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import { VitePWA } from 'vite-plugin-pwa'
export default defineConfig({
plugins: [vue()],
plugins: [
vue(),
VitePWA({
registerType: 'autoUpdate',
includeAssets: ['assets/images/app-icon.svg', 'assets/fonts/*.otf'],
manifest: {
name: 'IndeedHub - Decentralized Media Streaming',
short_name: 'IndeedHub',
description: 'Stream films and content on the decentralized web powered by Nostr and Bitcoin',
theme_color: '#0a0a0a',
background_color: '#0a0a0a',
display: 'standalone',
orientation: 'portrait-primary',
icons: [
{
src: '/assets/images/app-icon.svg',
sizes: '512x512',
type: 'image/svg+xml',
purpose: 'any maskable'
}
]
},
workbox: {
globPatterns: ['**/*.{js,css,html,ico,png,svg,jpg,jpeg,woff,woff2,otf}'],
runtimeCaching: [
{
urlPattern: /^https:\/\/images\.unsplash\.com\/.*/i,
handler: 'CacheFirst',
options: {
cacheName: 'unsplash-images-cache',
expiration: {
maxEntries: 50,
maxAgeSeconds: 60 * 60 * 24 * 30 // 30 days
}
}
}
]
}
})
],
resolve: {
alias: {
'@': fileURLToPath(new URL('./src', import.meta.url))