diff --git a/_posts/2022-07-24-custom-widgets.md b/_posts/2022-07-24-custom-widgets.md new file mode 100644 index 0000000..d80d279 --- /dev/null +++ b/_posts/2022-07-24-custom-widgets.md @@ -0,0 +1,117 @@ +--- +title: Creating Your Own Custom Widgets for Renewed Tab +author: rubenwardy +layout: post +description: >- + Renewed Tab allows you to create custom widgets with your own UI and code, + isolated from the rest of the extension to improve user privacy. +images: + cover: + path: howto-custom/cover.png + edit_iframe: + path: howto-custom/edit_iframe.png + caption: The Edit Widget modal dialog + widget: + path: howto-custom/widget.png + caption: The Custom Widget +--- + +Renewed Tab intends to be highly customisable whilst having a good user +experience. Taken to the extreme, these two things are in conflict; the more +features you add, the harder it is to provide a good user experience. Renewed +Tab can't support every use case by itself - there's so much you could want to +support, and so little time. It would also make the download huge. + +The solution to this is to allow custom user content. By making it easy for +users and third-party developers to create their own widgets and functionality, +it becomes possible to support a lot more without increasing complexity. + +Renewed Tab allows you to create custom widgets using the IFrame widget. IFrames +isolate third-party code and UIs, protecting the user's privileged information +such as bookmarks and recent sites. Most browser extension stores prohibit +remote code, so using an IFrame is a requirement. This does impose some limits +on what is possible in custom widgets - you are limited to your widgets, and +can't change the UI elsewhere. + +Please note that this is still **experimental** and a bit manual. In the future, +we plan to improve support for third-party widgets, making it easier for users +to use them and allowing more integration with the built-in UI. + + + +- [Hello World widget](#hello-world-widget) + - [Get the repository](#get-the-repository) + - [Serving on localhost](#serving-on-localhost) + - [Adding to Renewed Tab](#adding-to-renewed-tab) +- [Distributing the Widget](#distributing-the-widget) +- [Conclusion](#conclusion) + +## Hello World widget + +Renewed Tab uses the React framework, but you're free to use whatever framework +you like. We will be using React in this tutorial. We recommend using Renewed +Tab's CSS as a basis, however, to keep a consistent theme. + +### Get the repository + +Clone or download [our React widget template](https://gitlab.com/renewedtab/custom_widget_template): + + git clone https://gitlab.com/renewedtab/custom_widget_template + +Run `npm install` to install the dependencies. + +### Serving on localhost + +Renewed Tab can't access files on your computer. In order to add your custom +widget to Renewed Tab, you'll need to make it available using a server of some +kind. The best way to do this locally for testing is using something called a +live HTTP server. Our example template uses webpack-dev-server for this purpose. + +Run `npm start` to build the app and start the live server at +. Once this is done, open it in your browser to check +that it works. + +### Adding to Renewed Tab + +Now that you have a working live server, you can add your widget to your Renewed +Tab install. If you don't want to change your browser's New Tab for this, you +can use the [online version](https://web.renewedtab.com/). + +Enter edit mode by clicking the pencil in the bottom right, click "+ Add +Widget", then click "IFrame". Find the new IFrame, hover over it, and click the +pencil to open the Edit IFrame model. + +{% include figure.html img=page.images.edit_iframe %} + +Set the URL to `http://localhost:8080`. You'll also probably also want to check +"Show panel background". + +Press OK, you should now see the widget. Try resizing and moving the widget, +it should adapt to the available space. + +{% include figure.html img=page.images.widget %} + + +## Distributing the Widget + +Run `npm run build` to build the widget. Share the `dist/` folder publicly to +distribute your widget. A good way to do this is using GitLab pages, as it +supports updating a static website using CI. + +See the `.gitlab-ci.yml` of the template. It deploys the widget to +. + + + +## Conclusion + +Whilst support for custom widgets is in its early days, it's still possible to +do a lot of cool things with it. + +In the future, we'll be adding an official plugins API which will make it super +easy to add custom widgets to Renewed Tab. Users will be able to find plugins in +the settings menu or add them by URL. Plugins will be able to add widgets to the +"Add Widgets" menu. + +Make sure to share any creations you make on Twitter (#renewedtab), Discord, or +Matrix. See [Get Involved](/get_involved). diff --git a/_sass/_syntax.scss b/_sass/_syntax.scss new file mode 100644 index 0000000..2dd88f2 --- /dev/null +++ b/_sass/_syntax.scss @@ -0,0 +1,94 @@ + +code { + padding: .2em .4em; + margin: 0; + font-size: 85%; + background-color: rgba(110,118,129,0.4); + border-radius: 6px; + color: #fff; +} + +.highlight { + margin: 0 0 1em 0; +} + +.highlight code { + padding: unset; + background-color: unset; + border-radius: unset; +} + + +/*! Darcula theme; https://github.com/alem0lars/vim-colorscheme-darcula */ + + +.highlight .hll { background-color: #ffffcc !important; } +.highlight { color: #a9b7c6 !important; } +.highlight .c { color: #808080 !important; font-style: italic !important; } /* Comment */ +.highlight .err { color: #a9b7c6 !important; } /* Error */ +.highlight .g { color: #a9b7c6 !important; } /* Generic */ +.highlight .k { color: #cc7832 !important; } /* Keyword */ +.highlight .l { color: #a9b7c6 !important; } /* Literal */ +.highlight .n, .highlight .h { color: #a9b7c6 !important; } /* Name */ +.highlight .o { color: #a9b7c6 !important; } /* Operator */ +.highlight .x { color: #a9b7c6 !important; } /* Other */ +.highlight .p { color: #a9b7c6 !important; } /* Punctuation */ +.highlight .cm { color: #808080 !important; font-style: italic !important; } /* Comment.Multiline */ +.highlight .cp { color: #cc7832 !important; } /* Comment.Preproc */ +.highlight .c1 { color: #808080 !important; font-style: italic !important; } /* Comment.Single */ +.highlight .cs { color: #808080 !important; font-style: italic !important; } /* Comment.Special */ +.highlight .gd { color: #8c0909 !important; } /* Generic.Deleted */ +.highlight .ge { color: #a9b7c6 !important; text-decoration: underline !important; } /* Generic.Emph */ +.highlight .gr { color: #a9b7c6 !important; } /* Generic.Error */ +.highlight .gh { color: #a9b7c6 !important; font-weight: bold !important; } /* Generic.Heading */ +.highlight .gi { color: #a9b7c6 !important; font-weight: bold !important; background-color: #47840d !important; } /* Generic.Inserted */ +.highlight .go { color: #bfbfbf !important; background-color: #313233 !important; } /* Generic.Output */ +.highlight .gp { color: #a9b7c6 !important; } /* Generic.Prompt */ +.highlight .gs { color: #a9b7c6 !important; } /* Generic.Strong */ +.highlight .gu { color: #a9b7c6 !important; font-weight: bold !important; } /* Generic.Subheading */ +.highlight .gt { color: #ffffff !important; background-color: #990000 !important; } /* Generic.Traceback */ +.highlight .kc { color: #cc7832 !important; } /* Keyword.Constant */ +.highlight .kd { color: #cc7832 !important; } /* Keyword.Declaration */ +.highlight .kn { color: #cc7832 !important; } /* Keyword.Namespace */ +.highlight .kp { color: #cc7832 !important; } /* Keyword.Pseudo */ +.highlight .kr { color: #cc7832 !important; } /* Keyword.Reserved */ +.highlight .kt { color: #cc7832 !important; } /* Keyword.Type */ +.highlight .ld { color: #a9b7c6 !important; } /* Literal.Date */ +.highlight .m { color: #6897bb !important; } /* Literal.Number */ +.highlight .s { color: #a5c25c !important; } /* Literal.String */ +.highlight .na { color: #ffc66d !important; } /* Name.Attribute */ +.highlight .nb { color: #cc7832 !important; } /* Name.Builtin */ +.highlight .nc { color: #a9b7c6 !important; } /* Name.Class */ +.highlight .no { color: #9876aa !important; } /* Name.Constant */ +.highlight .nd { color: #a9b7c6 !important; } /* Name.Decorator */ +.highlight .ni { color: #a9b7c6 !important; } /* Name.Entity */ +.highlight .ne { color: #a9b7c6 !important; } /* Name.Exception */ +.highlight .nf { color: #ffc66d !important; } /* Name.Function */ +.highlight .nl { color: #a5c25c !important; } /* Name.Label */ +.highlight .nn { color: #a9b7c6 !important; } /* Name.Namespace */ +.highlight .nx { color: #a9b7c6 !important; } /* Name.Other */ +.highlight .py { color: #a9b7c6 !important; } /* Name.Property */ +.highlight .nt { color: #cc7832 !important; } /* Name.Tag */ +.highlight .nv { color: #cc7832 !important; } /* Name.Variable */ +.highlight .ow { color: #cc7832 !important; } /* Operator.Word */ +.highlight .w { color: #a9b7c6 !important; } /* Text.Whitespace */ +.highlight .mf { color: #6897bb !important; } /* Literal.Number.Float */ +.highlight .mh { color: #6897bb !important; } /* Literal.Number.Hex */ +.highlight .mi { color: #6897bb !important; } /* Literal.Number.Integer */ +.highlight .mo { color: #6897bb !important; } /* Literal.Number.Oct */ +.highlight .sb { color: #a5c25c !important; } /* Literal.String.Backtick */ +.highlight .sc { color: #a5c25c !important; } /* Literal.String.Char */ +.highlight .sd { color: #a5c25c !important; } /* Literal.String.Doc */ +.highlight .s2 { color: #a5c25c !important; } /* Literal.String.Double */ +.highlight .se { color: #a5c25c !important; } /* Literal.String.Escape */ +.highlight .sh { color: #a5c25c !important; } /* Literal.String.Heredoc */ +.highlight .si { color: #a5c25c !important; } /* Literal.String.Interpol */ +.highlight .sx { color: #a5c25c !important; } /* Literal.String.Other */ +.highlight .sr { color: #a5c25c !important; } /* Literal.String.Regex */ +.highlight .s1 { color: #a5c25c !important; } /* Literal.String.Single */ +.highlight .ss { color: #a5c25c !important; } /* Literal.String.Symbol */ +.highlight .bp { color: #a9b7c6 !important; } /* Name.Builtin.Pseudo */ +.highlight .vc { color: #cc7832 !important; } /* Name.Variable.Class */ +.highlight .vg { color: #cc7832 !important; } /* Name.Variable.Global */ +.highlight .vi { color: #cc7832 !important; } /* Name.Variable.Instance */ +.highlight .il { color: #6897bb !important; } /* Literal.Number.Integer.Long */ diff --git a/en/help/faq.md b/en/help/faq.md index 1e364ae..5d5290d 100644 --- a/en/help/faq.md +++ b/en/help/faq.md @@ -156,16 +156,7 @@ _wrong_. Please report it below. ## How do I add custom widgets? -We would really like to support custom widgets. But unfortunately, it's not -possible due to the developer terms that Firefox and Chrome enforce on extension -developers. We're not allowed to let users upload code which runs in the -extension context. - -GreaseMonkey is allowed because it runs on websites, not as an extension webpage. -We'll continue to look for alternatives for this, as we'd really like to allow it. - -What you can do is use an IFrame widget to show a webpage as if it were a widget. -You can use this to create custom widgets. +See [Creating Your Own Custom Widgets for Renewed Tab](/blog/2022/07/24/custom-widgets/). ## How can I get in contact? diff --git a/es/help/faq.md b/es/help/faq.md index d98c669..52693c6 100644 --- a/es/help/faq.md +++ b/es/help/faq.md @@ -16,6 +16,7 @@ redirect_from: - [¿Por qué no admite sincronización de navegador?](#por-qué-no-admite-sincronización-de-navegador) - [¿Por qué no está disponible para X navegador?](#por-qué-no-está-disponible-para-x-navegador) - [¿Por qué me sale un error al ingresar una URL personalizada en la versión web?](#por-qué-me-sale-un-error-al-ingresar-una-url-personalizada-en-la-versión-web) +- [How do I add custom widgets?](#how-do-i-add-custom-widgets) - [Solicitudes de Funciones, Informe de Errores, y Asistencia](#solicitudes-de-funciones-informe-de-errores-y-asistencia) @@ -142,6 +143,11 @@ Nota: Si obtiene el error mientras usa la extensión del navegador, hay algo _incorrecto_. Por favor repórtelo a continuación. +## How do I add custom widgets? + +See [Creating Your Own Custom Widgets for Renewed Tab](/blog/2022/07/24/custom-widgets/). + + ## Solicitudes de Funciones, Informe de Errores, y Asistencia Publicar un issue en el rastreador de problemas es la forma preferida de discutir diff --git a/fr/help/faq.md b/fr/help/faq.md index 83211a9..8a74e22 100644 --- a/fr/help/faq.md +++ b/fr/help/faq.md @@ -158,16 +158,8 @@ _wrong_. Please report it below. ## How do I add custom widgets? -We would really like to support custom widgets. But unfortunately, it's not -possible due to the developer terms that Firefox and Chrome enforce on extension -developers. We're not allowed to let users upload code which runs in the -extension context. +See [Creating Your Own Custom Widgets for Renewed Tab](/blog/2022/07/24/custom-widgets/). -GreaseMonkey is allowed because it runs on websites, not as an extension webpage. -We'll continue to look for alternatives for this, as we'd really like to allow it. - -What you can do is use an IFrame widget to show a webpage as if it were a widget. -You can use this to create custom widgets. ## How can I get in contact? diff --git a/ms/help/faq.md b/ms/help/faq.md index 2f8f88b..e7f59c2 100644 --- a/ms/help/faq.md +++ b/ms/help/faq.md @@ -158,16 +158,7 @@ _wrong_. Please report it below. ## How do I add custom widgets? -We would really like to support custom widgets. But unfortunately, it's not -possible due to the developer terms that Firefox and Chrome enforce on extension -developers. We're not allowed to let users upload code which runs in the -extension context. - -GreaseMonkey is allowed because it runs on websites, not as an extension webpage. -We'll continue to look for alternatives for this, as we'd really like to allow it. - -What you can do is use an IFrame widget to show a webpage as if it were a widget. -You can use this to create custom widgets. +See [Creating Your Own Custom Widgets for Renewed Tab](/blog/2022/07/24/custom-widgets/). ## How can I get in contact? diff --git a/static/blog/howto-custom/cover.png b/static/blog/howto-custom/cover.png new file mode 100644 index 0000000..16eed2a Binary files /dev/null and b/static/blog/howto-custom/cover.png differ diff --git a/static/blog/howto-custom/cover_full.png b/static/blog/howto-custom/cover_full.png new file mode 100644 index 0000000..244b918 Binary files /dev/null and b/static/blog/howto-custom/cover_full.png differ diff --git a/static/blog/howto-custom/edit_iframe.png b/static/blog/howto-custom/edit_iframe.png new file mode 100644 index 0000000..0b55546 Binary files /dev/null and b/static/blog/howto-custom/edit_iframe.png differ diff --git a/static/blog/howto-custom/widget.png b/static/blog/howto-custom/widget.png new file mode 100644 index 0000000..42e42a6 Binary files /dev/null and b/static/blog/howto-custom/widget.png differ diff --git a/static/style.scss b/static/style.scss index 0fac955..dbdb1a0 100644 --- a/static/style.scss +++ b/static/style.scss @@ -4,3 +4,4 @@ @import "bulma"; @import "buttons"; @import "main"; +@import "syntax";