2024-08-15 23:21:30 -07:00
< template >
2025-08-14 21:48:38 +01:00
< PurchaseModal
ref = "purchaseModal"
: product = "midasProduct"
: country = "country"
: publishable - key = "config.public.stripePublishableKey"
: send - billing - request = "
async ( body ) =>
await useBaseFetch ( 'billing/payment' , { internal : true , method : 'POST' , body } )
"
: fetch - payment - data = "fetchPaymentData"
: on - error = "
( err ) =>
addNotification ( {
title : 'An error occurred' ,
type : 'error' ,
text : err . message ? ? ( err . data ? err . data . description : err ) ,
} )
"
: customer = "customer"
: payment - methods = "paymentMethods"
: return - url = "`${config.public.siteUrl}/settings/billing`"
/ >
< div class = "main-hero" >
< div class = "flex max-w-screen-lg flex-col items-center gap-4 text-center" >
< ModrinthPlusIcon class = "h-8 w-max text-contrast" / >
< h1 class = "m-0 text-[4rem]" > Support creators and go ad - free < / h1 >
< p class = "m-0 mb-4 text-[18px] leading-relaxed" >
Subscribe to Modrinth Plus to go ad - free , support Modrinth ' s development , and get an
exclusive profile badge ! Half your subscription goes directly to Modrinth creators . Cancel
anytime .
< / p >
< p class = "m-0 text-[2rem] font-bold text-purple" >
{ { formatPrice ( vintl . locale , price . prices . intervals . monthly , price . currency _code ) } } / mo
< / p >
< p class = "m-0 mb-4 text-secondary" >
or save
{ { calculateSavings ( price . prices . intervals . monthly , price . prices . intervals . yearly ) } } % with
annual billing !
< / p >
< nuxt-link
v - if = "auth.user && isPermission(auth.user.badges, 1 << 0)"
to = "/settings/billing"
class = "btn btn-purple btn-large"
>
< SettingsIcon aria -hidden = " true " / >
Manage subscription
< / nuxt-link >
< button v-else-if = "auth.user" class="btn btn-purple btn-large" @click="purchaseModal.show()" >
Subscribe
< / button >
< nuxt-link
v - else
: to = "`/auth/sign-in?redirect=${encodeURIComponent('/plus?showModal=true')}`"
class = "btn btn-purple btn-large"
>
Subscribe
< / nuxt-link >
< / div >
< / div >
< div class = "perks-hero" >
< h2 > What you get with Modrinth Plus ! < / h2 >
< div class = "mt-8 grid max-w-screen-lg gap-8 lg:grid-cols-3" >
< div class = "flex flex-col gap-4 rounded-xl bg-bg-raised p-4" >
< HeartIcon class = "h-8 w-8 text-purple" / >
< span class = "text-lg font-bold" > Support Modrinth creators < / span >
< span class = "leading-5 text-secondary" >
50 % of your subscription goes directly to Modrinth creators .
< / span >
< / div >
< div class = "flex flex-col gap-4 rounded-xl bg-bg-raised p-4" >
< SparklesIcon class = "h-8 w-8 text-purple" / >
< span class = "text-lg font-bold" > Remove all ads < / span >
< span class = "leading-5 text-secondary" >
Never see an advertisement again on the Modrinth app .
< / span >
< / div >
< div class = "flex flex-col gap-4 rounded-xl bg-bg-raised p-4" >
< StarIcon class = "h-8 w-8 text-purple" / >
< span class = "text-lg font-bold" > Profile badge < / span >
< span class = "leading-5 text-secondary" > Get an exclusive badge on your user page . < / span >
< / div >
< / div >
< span class = "mt-4 text-secondary" > ... and much more coming soon ™ ! < / span >
< / div >
2024-08-15 23:21:30 -07:00
< / template >
< script setup >
2025-08-14 21:48:38 +01:00
import { HeartIcon , ModrinthPlusIcon , SettingsIcon , SparklesIcon , StarIcon } from '@modrinth/assets'
import { injectNotificationManager , PurchaseModal } from '@modrinth/ui'
import { calculateSavings , formatPrice , getCurrency } from '@modrinth/utils'
2024-08-15 23:21:30 -07:00
2025-08-14 21:48:38 +01:00
import { products } from '~/generated/state.json'
2025-08-13 21:48:52 +01:00
2025-08-14 21:48:38 +01:00
const { addNotification } = injectNotificationManager ( )
const title = 'Subscribe to Modrinth Plus!'
2024-08-15 23:21:30 -07:00
const description =
2025-08-14 21:48:38 +01:00
"Subscribe to Modrinth Plus to go ad-free, support Modrinth's development, and get an exclusive profile badge! Half your subscription goes directly to Modrinth creators."
2024-08-15 23:21:30 -07:00
useSeoMeta ( {
2025-08-14 21:48:38 +01:00
title ,
description ,
ogTitle : title ,
ogDescription : description ,
} )
2024-08-15 23:21:30 -07:00
2024-08-22 15:37:48 -05:00
useHead ( {
2025-08-14 21:48:38 +01:00
script : [
{
src : 'https://js.stripe.com/v3/' ,
defer : true ,
async : true ,
} ,
] ,
} )
2024-08-22 15:37:48 -05:00
2025-08-14 21:48:38 +01:00
const vintl = useVIntl ( )
2024-08-15 23:21:30 -07:00
2025-08-14 21:48:38 +01:00
const config = useRuntimeConfig ( )
2024-08-15 23:21:30 -07:00
2025-08-14 21:48:38 +01:00
const auth = await useAuth ( )
const purchaseModal = ref ( )
const midasProduct = ref ( products . find ( ( x ) => x . metadata . type === 'midas' ) )
const country = useUserCountry ( )
2024-08-15 23:21:30 -07:00
const price = computed ( ( ) =>
2025-08-14 21:48:38 +01:00
midasProduct . value . prices . find ( ( x ) => x . currency _code === getCurrency ( country . value ) ) ,
)
const customer = ref ( )
const paymentMethods = ref ( [ ] )
2024-08-15 23:21:30 -07:00
async function fetchPaymentData ( ) {
2025-08-14 21:48:38 +01:00
; [ customer . value , paymentMethods . value ] = await Promise . all ( [
useBaseFetch ( 'billing/customer' , { internal : true } ) ,
useBaseFetch ( 'billing/payment_methods' , { internal : true } ) ,
] )
2024-08-15 23:21:30 -07:00
}
2025-08-14 21:48:38 +01:00
const route = useRoute ( )
2024-08-15 23:21:30 -07:00
onMounted ( ( ) => {
2025-08-14 21:48:38 +01:00
if ( route . query . showModal ) {
purchaseModal . value . show ( )
}
} )
2024-08-15 23:21:30 -07:00
< / script >
< style lang = "scss" scoped >
. main - hero {
2025-08-14 21:48:38 +01:00
background :
linear - gradient ( 360 deg , rgba ( 199 , 138 , 255 , 0.2 ) 10.92 % , var ( -- color - bg ) 100 % ) ,
var ( -- color - accent - contrast ) ;
margin - top : - 5 rem ;
padding : 11.25 rem 1 rem 8 rem ;
2024-08-15 23:21:30 -07:00
2025-08-14 21:48:38 +01:00
display : flex ;
align - items : center ;
flex - direction : column ;
2024-08-15 23:21:30 -07:00
}
. perks - hero {
2025-08-14 21:48:38 +01:00
background - color : var ( -- color - accent - contrast ) ;
display : flex ;
align - items : center ;
flex - direction : column ;
padding : 4 rem 1 rem ;
2024-08-15 23:21:30 -07:00
}
< / style >