Labs

{{svg-jar "idea"}}This is a testing ground for experimental features which aren't quite ready for primetime. They may change, break or inexplicably disappear at any time.

Migration options
Import content
Import posts from another Ghost installation
{{gh-file-upload id="importfile" classNames="flex" uploadButtonText=uploadButtonText onUpload=(action "onUpload") acceptEncoding=importMimeType data-test-file-input="import"}}
{{#if importErrors}}
{{#if importSuccessful}} Import successful with warnings {{else}} Import failed {{/if}}
{{#each importErrors as |error|}}

{{#if error.help}}{{error.help}}: {{/if}}{{error.message}}

{{#if error.context}}
{{error.context}}
{{/if}}
{{/each}}
{{/if}}
Export your content
Download all of your posts and settings in a single, glorious JSON file
Delete all content
Permanently delete all posts and tags from the database, a hard reset
Testing tools
Test email configuration
Send yourself a test email to make sure everything is working
{{gh-task-button "Send" successText="Sent" task=sendTestEmail class="gh-btn gh-btn-hover-blue gh-btn-icon"}}
Beta features
{{#if (not-eq feature.labs.publicAPI undefined)}}
Public API (deprecated)
⚠️ Please use the Content API instead, more info in the docs
{{gh-feature-flag "publicAPI"}}
{{/if}}
Night shift
Swap Ghost admin's colours to a dark background which is easy on the eyes
{{gh-feature-flag "nightShift"}}
Subscribers
Collect email addresses from your readers, more info in the docs
{{#if feature.members}}
{{gh-feature-flag "subscribers" "disabled"}}
{{else}}
{{gh-feature-flag "subscribers" }}
{{/if}}
{{#if config.enableDeveloperExperiments}}
Members
Enable free or paid member registration. Restrict content by using #members hashtag on posts
{{#liquid-if feature.labs.members class="nr20"}} {{#liquid-if showMemberConfig}}
Free
Access to members-only posts require free user registration
Paid
Set up paid subscriptions using Stripe
{{#liquid-if (eq subscriptionSettings.isPaid true)}}
{{gh-text-input value=(readonly subscriptionSettings.stripeConfig.public_token) input=(action "setSubscriptionSettings" "public_token") class="mt1" placeholder="pk_..." }}
{{gh-text-input value=(readonly subscriptionSettings.stripeConfig.secret_token) input=(action "setSubscriptionSettings" "secret_token") class="mt1" placeholder="sk_..." }}
How to find Stripe API keys
{{#gh-form-group}}
{{gh-text-input value=(readonly subscriptionSettings.stripeConfig.plans.monthly.dollarAmount) type="number" input=(action "setSubscriptionSettings" "month") }}
{{/gh-form-group}}
{{#gh-form-group class="description-container"}}
{{gh-text-input value=(readonly subscriptionSettings.stripeConfig.plans.yearly.dollarAmount) type="number" input=(action "setSubscriptionSettings" "year") }}
{{/gh-form-group}}
{{/liquid-if}}
{{gh-task-button "Save" task=saveSettings successText="Saved" runningText="Saving" class="gh-btn gh-btn-blue gh-btn-icon" }}
{{/liquid-if}} {{/liquid-if}}
{{gh-feature-flag "members"}}
{{/if}}
{{#gh-uploader extensions=jsonExtension uploadUrl="/redirects/json/" paramName="redirects" onUploadSuccess=(perform redirectUploadResult true) onUploadFailure=(perform redirectUploadResult false) as |uploader| }}
Redirects
Configure redirects for old or moved content, more info in the docs
{{#each uploader.errors as |error|}}
{{or error.context error.message}}
{{/each}}
{{#if uploader.isUploading}} {{uploader.progressBar}} {{else}} Download current redirects {{/if}}
{{gh-file-input multiple=false action=uploader.setFiles accept=jsonMimeType data-test-file-input="redirects"}}
{{/gh-uploader}}
{{#gh-uploader extensions=yamlExtension uploadUrl="/settings/routes/yaml/" paramName="routes" onUploadSuccess=(perform routesUploadResult true) onUploadFailure=(perform routesUploadResult false) as |uploader| }}
Routes
Configure dynamic routing by modifying the routes.yaml file
{{#each uploader.errors as |error|}}
{{or error.context error.message}}
{{/each}}
{{#if uploader.isUploading}} {{uploader.progressBar}} {{else}} Download current routes.yml {{/if}}
{{gh-file-input multiple=false action=uploader.setFiles accept=yamlMimeType data-test-file-input="routes"}}
{{/gh-uploader}}
{{#if showDeleteAllModal}} {{gh-fullscreen-modal "delete-all" close=(action "toggleDeleteAllModal") modifier="action wide"}} {{/if}}