<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: The Apostrophe Team</title>
    <description>The latest articles on Forem by The Apostrophe Team (@apostrophetechnologies).</description>
    <link>https://forem.com/apostrophetechnologies</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F478278%2F1e7d222d-875f-49f9-8801-3508ab3d62f3.png</url>
      <title>Forem: The Apostrophe Team</title>
      <link>https://forem.com/apostrophetechnologies</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/apostrophetechnologies"/>
    <language>en</language>
    <item>
      <title>Apostrophe 4.21.0: Effortless Image Uploads and Strategic Platform Enhancements</title>
      <dc:creator>The Apostrophe Team</dc:creator>
      <pubDate>Wed, 03 Sep 2025 15:13:04 +0000</pubDate>
      <link>https://forem.com/apostrophetechnologies/apostrophe-4210-effortless-image-uploads-and-strategic-platform-enhancements-33m5</link>
      <guid>https://forem.com/apostrophetechnologies/apostrophe-4210-effortless-image-uploads-and-strategic-platform-enhancements-33m5</guid>
      <description>&lt;p&gt;Hello Apostrophe Community!&lt;/p&gt;

&lt;p&gt;Apostrophe 4.21.0 delivers immediate improvements to the content editing experience while laying important groundwork for next-generation features. This release centers on quick image uploads that eliminate friction for editors, plus platform enhancements that will enable exciting new capabilities in upcoming releases.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Important&lt;/strong&gt;: Before updating, ensure your Node.js version is 20 or higher, as this release requires a supported version of Node.js.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://apostrophecms.com/blog/apostrophecms-4-21-0-effortless-image-uploads-and-strategic-platform-enhancements" rel="noopener noreferrer"&gt;Full write-up on the blog&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/tdyB9mr58f4"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Quick Image Upload: Smoothing the Content Creation Flow
&lt;/h2&gt;

&lt;p&gt;Content editors can now upload images exactly the way they expect to—with zero extra steps. Our new quick image upload transforms what was previously a multistep media library workflow into an instant, intuitive experience.&lt;/p&gt;

&lt;p&gt;Content managers can now:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Drag images directly&lt;/strong&gt; from their desktop onto any image widget&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Click to upload&lt;/strong&gt; from the file picker without leaving your editing context&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;See images automatically cropped&lt;/strong&gt; and ready to use immediately&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stay in the flow&lt;/strong&gt; of content creation without context switching&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This enhancement eliminates the cognitive overhead that comes with bouncing between the media library and content editing interfaces. For editorial teams working with image-heavy content—whether blog posts, product pages, or marketing materials—this translates to measurably faster content creation and a much more natural editing experience.&lt;/p&gt;

&lt;p&gt;The implementation works seamlessly with all existing image widget functionality, including focal point adjustment and alternative text, ensuring that accessibility and design control remain intact while dramatically improving usability.&lt;/p&gt;

&lt;h2&gt;
  
  
  Foundation for Next-Generation Editing Features
&lt;/h2&gt;

&lt;p&gt;While the quick image upload delivers immediate value, this release also includes strategic platform enhancements that will enable powerful new capabilities in upcoming versions. We've built new infrastructure for custom widget creation workflows and enhanced modal interactions to support features like reusable section templates and AI-powered layouts.&lt;/p&gt;

&lt;p&gt;These behind-the-scenes improvements include new APIs for extending the "add widget" experience, transformer pipelines for processing content before insertion, and enhanced modal flexibility. While these changes immediately benefit developers building advanced editorial interfaces, the groundwork being laid will soon enable editors to work with pre-built layout templates, leverage AI for content suggestions, and access other productivity-enhancing tools.&lt;/p&gt;

&lt;p&gt;The groundwork being laid here will soon enable editors to work with pre-built layout templates, leverage AI for content suggestions, and access other productivity-enhancing tools that build on these foundational improvements.&lt;/p&gt;

&lt;h2&gt;
  
  
  Relationship Field Refinements: Responsive to Community Feedback
&lt;/h2&gt;

&lt;p&gt;Based on developer feedback, we've adjusted relationship field validation to be less restrictive in practice. The strict server-side enforcement introduced in 4.16.0 was causing unexpected errors when related content changed, so we've returned to a more practical approach that balances data integrity with real-world content management workflows.&lt;/p&gt;

&lt;h2&gt;
  
  
  Quality Improvements Across the Platform
&lt;/h2&gt;

&lt;p&gt;This release includes several important fixes that improve the stability and usability of core features:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;API Rendering&lt;/strong&gt;: The &lt;code&gt;?render-areas=1&lt;/code&gt; API feature now correctly disregards areas in related documents, rather than failing the call&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Conditional Fields&lt;/strong&gt;: Now work as expected in the Image Editor interface&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Widget Data Processing&lt;/strong&gt;: Fixed an issue where widget data was being cloned before post-processing, which could cause data loss&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Relationship Updates&lt;/strong&gt;: Improved live preview performance by only post-processing updated relationships&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;These improvements are ready for you to explore! Remember to update your Node.js version to 20 or higher before running &lt;code&gt;npm update&lt;/code&gt;. Let us know what you think on our &lt;a href="https://roadmap.apostrophecms.com/roadmap/" rel="noopener noreferrer"&gt;roadmap&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;🚀 Happy coding!&lt;/p&gt;

</description>
      <category>apostrophecms</category>
      <category>vue</category>
      <category>cms</category>
      <category>node</category>
    </item>
    <item>
      <title>Creation of the ApostropheCMS Documentation Chatbot</title>
      <dc:creator>The Apostrophe Team</dc:creator>
      <pubDate>Thu, 29 Aug 2024 15:17:08 +0000</pubDate>
      <link>https://forem.com/apostrophecms/creation-of-the-apostrophecms-documentation-chatbot-1j7f</link>
      <guid>https://forem.com/apostrophecms/creation-of-the-apostrophecms-documentation-chatbot-1j7f</guid>
      <description>&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Falqkxk2constwrvvam55.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Falqkxk2constwrvvam55.png" alt="Detailed steps in the processing of a user query in our LLM-powered docbot." width="800" height="467"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Chatbots have evolved significantly since their inception in the 1960s with simple programs like ELIZA, which could mimic human conversation through predefined scripts. Initially limited to basic interactions, typically in customer service roles, advancements in artificial intelligence have transformed chatbots into essential tools for businesses, enhancing user engagement and providing 24/7 customer support. Recently, the shift from rule-based systems to the utilization of large language models (LLMs) has enabled chatbots to understand and respond with greater comprehension and context awareness.&lt;/p&gt;

&lt;p&gt;AI-powered assistants are now revolutionizing the developer tools landscape, offering more efficient ways to interact with documentation. When they are at their best, these intelligent search assistants provide accurate, contextual, and efficient navigation through complex information, significantly boosting productivity and saving valuable time.&lt;/p&gt;

&lt;p&gt;Our decision to build an AI-powered documentation assistant was driven by the desire to provide rapid and customized responses to engineers developing with ApostropheCMS. While we remain committed to providing guidance and fostering community in Discord, support via this channel is limited by personnel availability. Implementing an AI-driven chatbot enables developers to receive instant, customized answers anytime, even outside of regular support hours, and expands accessibility by providing support in multiple languages. Our assistant aims to transform the documentation experience by moving beyond simple scripts, offering a seamless and intelligent solution tailored to developers' needs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Technical Design Highlights
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--qJD7s9xM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://apos-website-prod.s3.us-east-1.amazonaws.com/attachments/cm054wohy0bv10bt04ugtw88q-doc-question-smaller.full.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--qJD7s9xM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://apos-website-prod.s3.us-east-1.amazonaws.com/attachments/cm054wohy0bv10bt04ugtw88q-doc-question-smaller.full.gif" alt="Asking a question of the new ApostropheCMS documentation chatbot." width="728" height="480"&gt;&lt;/a&gt;&lt;br&gt;Asking a question of the new ApostropheCMS Documentation chatbot is easy!
  &lt;/p&gt;

&lt;p&gt;Building an AI-powered chatbot is more than just connecting a user’s query to an LLM. While commercial options often bundle everything—natural language processing, conversational memory, knowledge retrieval—into a neat package, they tend to be a black box, leaving us with little control over the finer details. When we set out to create our documentation chatbot, we knew we wanted more than just an out-of-the-box solution. We leveraged the power of an LLM, but also took steps to refine the process, enhancing accuracy and overall user experience by making thoughtful design choices along the way. In this section, we will highlight some of those key design decisions.&lt;/p&gt;

&lt;h3&gt;
  
  
  Retrieval-Augmented Generation (RAG) with Vector Database
&lt;/h3&gt;

&lt;p&gt;When designing our documentation chatbot, we knew from using commercial offerings that there were significant issues with hallucination, where AI generates confident but incorrect or irrelevant information, and references to outdated information about older versions of Apostrophe in answers. Hallucination occurs because large language models (LLMs) are designed to generate the most likely response based on their training data, even if the data doesn't contain relevant or up-to-date information.&lt;/p&gt;

&lt;p&gt;We toyed with “prompt engineering”, essentially adding extra information to guide the AI’s response to enhance the accuracy of answers. For example, for each query we added language like, “&lt;em&gt;Using only information about the latest version of Apostrophe, answer the following query: `{{ user_query }}.&lt;/em&gt;`” But as many of you have probably found in your own experiments, this approach on its own has its limits. The AI would still go off track, lacking the real-time knowledge to separate fact from fiction.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv7kk2guae98x669abcne.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv7kk2guae98x669abcne.png" alt="Simplified Retrievel-Augmented Generation (RAG) workflow." width="800" height="467"&gt;&lt;/a&gt;&lt;/p&gt;
Simplified Retrieval-Augmented Generation (RAG) workflow.



&lt;p&gt;So rather than relying solely on prompt engineering, we chose a Retrieval-Augmented Generation (RAG) approach for our chatbot. Without diving too deep into the technicalities (there is a great &lt;a href="https://medium.com/@bijit211987/rag-vs-vectordb-2c8cb3e0ee52" rel="noopener noreferrer"&gt;article&lt;/a&gt; here for a more comprehensive explanation), RAG is fundamentally about enhancing an LLM's responses by providing it with additional, real-time info. At its simplest, RAG involves three main steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Retrieval: Using the user's query to find relevant information from a knowledge base.&lt;/li&gt;
&lt;li&gt;Augmentation: Adding this retrieved information to context provided along with the query to the LLM.&lt;/li&gt;
&lt;li&gt;Generation: Having the LLM generate a response based on both the original query and the augmented context.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This approach lets us feed the LLM current knowledge that wasn't part of its original training, leading to more accurate and up-to-date answers. The retrieval part can be done in various ways, from simple keyword matching to fancier semantic search techniques. For us, it was a game-changer in helping to reduce hallucination and outdated info problems.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu7zg0karg59ym3afr29e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu7zg0karg59ym3afr29e.png" alt="Simple workflow for the creating of vector embeddings for a RAG DB." width="800" height="467"&gt;&lt;/a&gt;&lt;/p&gt;
Steps in the creation of a RAG vector database.



&lt;h3&gt;
  
  
  Vector Embedding
&lt;/h3&gt;

&lt;p&gt;We settled on using a vector database mechanism for our RAG implementation. This approach allows us to efficiently store and retrieve relevant information based on the semantic meaning of queries. Here's how we built our vector database:&lt;/p&gt;

&lt;p&gt;First, we gathered all of our documentation and extension README files into a collection of about 150 documents. We then split these documents into smaller chunks of 1000 characters each, with an overlap of 200 characters between chunks. This chunking process helps maintain context while allowing for more precise retrieval of relevant information.&lt;/p&gt;

&lt;p&gt;Next, we created embeddings for each of these chunks. Embeddings are numerical representations that capture the semantic meaning of the text, allowing for similarity comparisons. We used the OpenAI text-embedding-3-small model to convert each text chunk into a high-dimensional vector. This is a decision that we may re-think moving forward, based on a number of factors such as whether more context is worth the cost. We'll touch on this briefly in the last section of this article.&lt;/p&gt;

&lt;p&gt;Finally, we stored these vectors in our chosen database: the &lt;a href="https://github.com/activeloopai/deeplake" rel="noopener noreferrer"&gt;activeloop DeepLake database&lt;/a&gt;. This database is open source, something near and dear to our own open-source hearts. We will cover some additional details in a further section, but it is specifically designed to handle vector data and perform efficient similarity searches, which is crucial for quick and accurate retrieval during the RAG process.&lt;/p&gt;

&lt;p&gt;One of the key advantages of this approach is its flexibility and cost-effectiveness. Updating our RAG database is a straightforward process that costs only about five cents per update. This allows us to continuously expand and refine our knowledge base as our documentation evolves, ensuring that our chatbot always has access to the most up-to-date information.&lt;/p&gt;

&lt;p&gt;Compared to alternatives like fine-tuning an entire LLM, which can be time-consuming and expensive, especially with frequently changing content, our vector database approach for RAG is more accurate and cost-effective for maintaining current and constantly changing knowledge in our chatbot.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fprpnww8e0aons2bd1aq5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fprpnww8e0aons2bd1aq5.png" alt="Flowchart of a generalized RAG flow." width="800" height="467"&gt;&lt;/a&gt;&lt;/p&gt;
Steps in responding to a user-submitted query.



&lt;h3&gt;
  
  
  Document Retrieval with Nearest Neighbor
&lt;/h3&gt;

&lt;p&gt;When a user submits a query to our docbot, we employ a process known as nearest neighbor search to find the most relevant information:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Vector Conversion: The query is first converted into a vector, representing its semantic meaning in a multi-dimensional space. This is done with the same embedding model as was used to create the database.&lt;/li&gt;
&lt;li&gt;Nearest Neighbor Search: We use a nearest neighbor algorithm to find the most similar document chunks in our knowledge base. This technique efficiently identifies the 'closest' vectors to our query vector in the high-dimensional space.&lt;/li&gt;
&lt;li&gt;Initial Retrieval: Our system retrieves the top 75 nearest neighbors (fetch_k = 75). In essence, we're finding the 75 document chunks that are most semantically similar to the query.&lt;/li&gt;
&lt;li&gt;Refinement: From these 75 chunks, we further refine our selection to the 12 most relevant (k = 12). This two-step process helps balance between broad coverage and focused relevance.&lt;/li&gt;
&lt;li&gt;Prompt Creation: The selected chunks, along with the original query, are formatted into a prompt for the LLM.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Nearest neighbor search is a fundamental concept in information retrieval and machine learning. It's particularly useful in our context because it allows us to quickly find the most similar documents without having to compare the query to every single document in our database. We use cosine similarity as our distance metric to determine how 'close' or similar two vectors are.&lt;/p&gt;

&lt;p&gt;This approach ensures that the model's answers are grounded in the most relevant and up-to-date information available in our documentation. Our initial parameter choices to fetch 75 document chunks and narrow it to 12 can likely be further optimized to balance between response accuracy and processing speed.&lt;/p&gt;

&lt;h3&gt;
  
  
  LangChain Framework
&lt;/h3&gt;

&lt;p&gt;Any commercial or open-source LLM model is going to have some type of API that allows you to interact with the model, but using these APIs directly can lead to model-specific implementations and require significant custom development for advanced features. To enhance flexibility and streamline development, we chose to use the​ &lt;a href="https://www.langchain.com/langchain" rel="noopener noreferrer"&gt;LangChain framework&lt;/a&gt;. LangChain offers a layer of abstraction that allows us to create model-agnostic chains of processes, easily switch between different LLMs, and leverage pre-built components for common tasks like memory management and prompt engineering.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Falqkxk2constwrvvam55.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Falqkxk2constwrvvam55.png" alt="Detailed steps in the processing of a user query in our LLM-powered docbot." width="800" height="467"&gt;&lt;/a&gt;&lt;/p&gt;
Detailed steps in the processing of a user query in our LLM-powered docbot.



&lt;p&gt;As the name suggests, the LangChain framework allows for queries and retrieved documents to be passed down a chain of processes. Here's how we've implemented it:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Query Reformulation&lt;/strong&gt;: We first combine the user's query with the current user’s chat history from that same session to create a new, stand-alone query. This process, using LangChain's ConversationBufferMemory, improves clarity by providing context from previous interactions. For example, if a user asks, "&lt;em&gt;How do I modify it?&lt;/em&gt;" the reformulated query might be, "&lt;em&gt;How do I modify the page template in ApostropheCMS?&lt;/em&gt;" based on the context of the previous conversation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Document Retrieval and Prompt Engineering&lt;/strong&gt;: The reformulated query is used to retrieve relevant documents from our RAG database. We then apply prompt engineering using LangChain's PromptTemplate before querying the LLM.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;u&gt;Other Useful Features&lt;/u&gt;:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Model Flexibility&lt;/strong&gt;: LangChain's model-agnostic design allows for easy A/B testing between different LLMs. This means that you can easily switch between different LLMs or even fine-tuned versions of the same model to compare performance and outcomes. We've been comparing OpenAI's GPT-4 and Anthropic's Claude Sonnet. This flexibility allows for continuous optimization of the chatbot's responses and ensures that you can choose the best model for your specific needs without significant re-engineering.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F51p9gr3076csfx4jenoj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F51p9gr3076csfx4jenoj.png" alt="A screenshot of an example query chain in LangSmith." width="800" height="352"&gt;&lt;/a&gt;&lt;/p&gt;
LangSmith provides a (highly) detailed dashboard that lets you monitor all of the aspects of your query chain.



&lt;p&gt;&lt;strong&gt;Performance Monitoring&lt;/strong&gt;: LangChain integrates with &lt;a href="https://www.langchain.com/langsmith" rel="noopener noreferrer"&gt;LangSmith&lt;/a&gt;, offering advanced tools for debugging and monitoring. Using LangSmith, we identified that the amount of chat history we were passing with our queries is likely creating excessive and unnecessary token usage. This is an area we can actively investigate to see if we can reduce costs without impacting response quality.&lt;/p&gt;

&lt;p&gt;This integrated suite of tools makes LangChain a powerful choice for building and optimizing AI-powered chatbots. It allows us to continually refine our implementation, ensuring we deliver the best possible user experience while managing resources efficiently.&lt;/p&gt;

&lt;h3&gt;
  
  
  DeepLake Database
&lt;/h3&gt;

&lt;p&gt;While we've already discussed the basics of our vector database implementation, it's worth diving deeper into why we chose activeloop DeepLake and how it enhances our chatbot's performance.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Memory-Resident Capability&lt;/strong&gt;: DeepLake offers the ability to create a memory-resident database. This feature significantly reduces latency by keeping the data in RAM, close to where it's processed. For our current dataset of about 150 documents, this in-memory approach provides very rapid retrieval times.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Versioning System&lt;/strong&gt;: DeepLake's built-in versioning system is a powerful tool for managing our knowledge base. It allows us to track changes over time, making it easy to update our documentation or roll back to previous versions if needed. This is particularly valuable as our product evolves and documentation is frequently updated.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Efficient Querying and Compression&lt;/strong&gt;: The database supports efficient data querying, allowing us to quickly retrieve relevant information. Additionally, its data compression features help optimize memory usage, which is crucial for maintaining high performance as our dataset grows.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Scalability&lt;/strong&gt;: While we currently use DeepLake in-memory due to our relatively small dataset, we have a clear path for scaling. If we expand our dataset to include a large codebase, for example, we can easily transition to DeepLake's cloud offering. However, this would come at the cost of increased latency in document retrieval and hosting costs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Future Optimizations&lt;/strong&gt;: As our dataset grows and we potentially move to cloud storage, we're already considering optimizations. For instance, we may need to implement increased caching of the first document retrieval in our chain of processes to mitigate latency issues. Our current setup, with document retrieval occurring twice in our process flow, may need adjustment to maintain optimal performance.&lt;/p&gt;

&lt;p&gt;By leveraging DeepLake's features, we've created a flexible, efficient foundation for our RAG system. This allows us to focus on improving the chatbot's responses and user experience, knowing that our data retrieval system can scale and adapt as our needs evolve.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reflection from Early Adoption
&lt;/h2&gt;

&lt;p&gt;Our experience with the chatbot in production is still in the early stages, but we’ve already seen some promising results.  For instance, there have been strong examples where the chatbot has effectively guided users through building features like custom widgets from scratch. This includes the main index.js file, Nunjucks template, and player code. As user adoption increases, we hope these positive outcomes will continue. While we've only touched on the key design highlights, there are several other noteworthy takeaways from our early experiences.&lt;/p&gt;

&lt;p&gt;One observation is that users often ask a series of highly similar questions sequentially. This behavior can increase hallucinations, as the LLM may attempt to modify its responses each time. Fortunately, since we control the chain of processes, we were able to introduce a step that evaluates new queries against previous ones in the chat history to mitigate this issue. Unless the two queries have a low similarity (&amp;lt;0.85), they are rejected as being the same questions.  Although this change has occasionally led to user frustration when they perceive their queries as different, it has generally reduced hallucinations.&lt;/p&gt;

&lt;p&gt;Similarly, we noticed that users sometimes ask questions using terminology that is absent in our documentation but appears in our codebase. Because the LLM is primarily limited to our documentation, it tends to hallucinate answers for these unfamiliar terms. By adjusting the process chain to examine the vector scores of the retrieved documents and ensuring that the returned documents have significant (0.85) semantic similarity with the query, we've also been able to reduce this type of hallucination.&lt;/p&gt;

&lt;p&gt;Another unexpected benefit of monitoring user interactions is that it has highlighted areas for improving our documentation. When the LLM struggles to find information, it's often a sign that the content is either not in the right context or not prominently featured. In one case, this led us to discover an incorrectly documented feature, allowing us to rectify the error and enhance our overall documentation quality.&lt;/p&gt;

&lt;p&gt;These early reflections have not only helped us refine our chatbot but have also provided valuable insights into our documentation strategy and user behavior. As we continue to learn and adapt, we're excited about the potential for further improvements and the positive impact on our users' experience.&lt;/p&gt;

&lt;h2&gt;
  
  
  Looking Ahead
&lt;/h2&gt;

&lt;p&gt;When originally designing the chatbot, we opted to build it in Python, despite being a heavily JavaScript-oriented shop. This decision was driven by the availability of more mature analytic tools for objectively testing chatbot hallucination and accuracy in Python. So far, we've been evaluating answers qualitatively, but we plan to incorporate a tool like &lt;a href="https://github.com/Giskard-AI/giskard" rel="noopener noreferrer"&gt;Giskard&lt;/a&gt; to bring a more quantitative approach to our evaluations. This step is crucial and one that, anecdotally, is often overlooked in many production chatbots.&lt;/p&gt;

&lt;p&gt;Another goal on the horizon is optimizing how we manage passed history to reduce token usage. However, with the decreasing cost of most LLM models and the increasing token limits, this concern has become less pressing. These advancements allow us to pass more context for less money without the worry of truncated answers due to token constraints.&lt;/p&gt;

&lt;p&gt;We’re also exploring the idea of supplementing our RAG database with several codebases, including the core Apostrophe repository and potentially some of our &lt;a href="https://apostrophecms.com/starter-kits" rel="noopener noreferrer"&gt;starter kits&lt;/a&gt;. However, this would complicate the embedding process and might challenge the LLM’s primary goal of guiding users to the most relevant documentation for further reading. However, along with this, we have also thought about changing to the text-embedding-3-large model. This would provide more context for our documentation and might also be better suited for large amounts of code. We’re carefully weighing the best way forward, aiming to balance the richness of our database with the clarity and utility of the chatbot’s responses.&lt;/p&gt;

&lt;p&gt;As we continue refining our chatbot, our primary focus remains on providing developers with precise, actionable information. Every enhancement is a step toward that goal, and we're excited to see how these improvements will further elevate the user experience. One key item under discussion is how to best collect user feedback and ensure that when answers have a degree of hallucination and are not effective solutions for the end developer, we can help remedy this.&lt;/p&gt;

&lt;p&gt;We invite you to experience our AI-powered documentation assistant firsthand and explore how it can enhance your development workflow. Try it out &lt;a href="https://www.notion.so/Creation-of-the-ApostropheCMS-Documentation-Chatbot-11343dae468b45a9b0244e0794884e9f?pvs=21" rel="noopener noreferrer"&gt;here&lt;/a&gt;, and let us know your thoughts! Join our &lt;a href="https://discord.com/invite/HwntQpADJr" rel="noopener noreferrer"&gt;Discord community&lt;/a&gt; to share feedback, ask questions, and collaborate with other developers. Together, we can continue to refine and improve this tool to better serve the ApostropheCMS community.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>opensource</category>
      <category>softwaredevelopment</category>
      <category>openai</category>
    </item>
    <item>
      <title>Introducing the Apostrophe / Astro Integration</title>
      <dc:creator>The Apostrophe Team</dc:creator>
      <pubDate>Fri, 16 Feb 2024 18:57:25 +0000</pubDate>
      <link>https://forem.com/apostrophecms/introducing-the-apostrophe-astro-integration-4ifc</link>
      <guid>https://forem.com/apostrophecms/introducing-the-apostrophe-astro-integration-4ifc</guid>
      <description>&lt;h2&gt;
  
  
  What’s the big news?
&lt;/h2&gt;

&lt;p&gt;In another step towards making Apostrophe the most dynamic, feature-rich website ecosystem for building and maintaining your website, our team is pleased to announce the integration for the Astro web framework.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Astro?
&lt;/h2&gt;

&lt;p&gt;Astro is a free, open-source software that enables users to build fast, content-driven websites with an emphasis on ease-of-use. It operates using a BYOF or “Bring Your Own Framework” model that makes it compatible with popular JS frameworks such as React, Svelt, or Vue. Some other key features of Astro’s technology include static site generation, component-based architecture, and built in automations. You can read more on &lt;a href="https://astro.build/"&gt;Astro’s website&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What does the integration mean for Apostrophe users?
&lt;/h2&gt;

&lt;p&gt;With the new integration comes the ability to let Apostrophe manage your content, handle routing of URLs and fetch content, and let Astro take the responsibility for the rendering of pages and any associated logic using your framework(s) of choice. Additionally, you can now bring the ApostropheCMS Admin UI into your Astro application, meaning can manage your site exactly as if you were in a "normal" Apostrophe instance.&lt;/p&gt;

&lt;p&gt;Why is this such a big deal? Apostrophe has always been great for providing a rich live editing experience for marketing teams. When we originally introduced our native REST APIs in A3, we made it easier than ever to use Apostrophe as a headless CMS. However, it’s always been harder than it should be to deliver our standard fully WYSIWYG editing experience when running Apostrophe in headless mode. This new integration is an incredible solution to that puzzle, and we’re thrilled that we can now support such an elegant option for delivering a rich, in-context editing experience within a headless architecture.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to get started…
&lt;/h2&gt;

&lt;p&gt;There’s more information about these exciting new capabilities and instructions on how to use the integration at the &lt;a href="https://docs.astro.build/en/guides/cms/apostrophecms/"&gt;Astro docs&lt;/a&gt; and on our &lt;a href="https://apostrophecms.com/starter-kits"&gt;Extensions page&lt;/a&gt;. Head over there now to get setup and install the module.&lt;/p&gt;

&lt;h2&gt;
  
  
  What’s next?
&lt;/h2&gt;

&lt;p&gt;If you have questions about Astro or how to leverage some of the new features, feel free to reach out to us directly or, better yet, bring your feedback to Apostrophe’s Discord Community so others can benefit as well.&lt;/p&gt;

&lt;p&gt;Lastly, we’d love to see you at our next live Show &amp;amp; Tell event on January 25th! We’ll be hosting an open discussion around some of the more commonly used JS frameworks, including some of the ones mentioned earlier in this announcement, and how to use them with Astro. It’s all going down in the &lt;a href="https://discord.gg/UrNVwb6h"&gt;Discord&lt;/a&gt;, see you there!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>astro</category>
      <category>opensource</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Navigating the Generative AI Downpour</title>
      <dc:creator>The Apostrophe Team</dc:creator>
      <pubDate>Wed, 04 Oct 2023 12:05:00 +0000</pubDate>
      <link>https://forem.com/apostrophecms/navigating-the-generative-ai-downpour-56p2</link>
      <guid>https://forem.com/apostrophecms/navigating-the-generative-ai-downpour-56p2</guid>
      <description>&lt;p&gt;This year we have observed the flow of news around generative AI technologies go from a light trickle to a full on downpour. Today we are saturated, our inboxes full each morning with a deluge of new products, new funding rounds, new excitement about the power of generative AI and its immediate impact and future potential. It can be overwhelming (in both a positive and a negative sense) to observe this surging, turbulent flood of both opportunity and risk – and to try to figure out where to jump in and start swimming. At Apostrophe, we are letting our core principles guide us.&lt;/p&gt;

&lt;p&gt;Like many other tech shops out there, &lt;a href="https://apostrophecms.com/blog/how-ai-is-transforming-the-cms-industry"&gt;our thinking about this started at the beginning of the year&lt;/a&gt; after seeing some of the earliest integrations coming from platforms like OpenAI. Thanks to the flexible architecture of Apostrophe, we were able to easily experiment with some simple integrations between generative AI and our content creation tools. We quickly &lt;a href="https://apostrophecms.com/extensions/ai-helper"&gt;open sourced our first module&lt;/a&gt; to demonstrate this potential and have since shared more &lt;a href="https://apostrophecms.com/blog/how-to-integrate-generative-ai-into-apostrophe"&gt;in depth tutorials on the topic&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;iframe src="https://player.vimeo.com/video/853838055" width="710" height="399"&gt;
&lt;/iframe&gt;
&lt;br&gt;
This first small release served as a foundation for our team to strategize about the future roadmap for Apostrophe and generative AI. With some internal strategy workshops and a hackathon, we explored everything from “create fully baked dynamic page layouts via a text prompt” to “enhance the experience of creating and searching developer documentation” to “provide suggestions to help editors create more SEO friendly sites” to “automatically translate text when localizing content”. We were lucky to share some of this process with some of our closest collaborators and the results have informed the future of our product roadmap.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpnosqudlb5id1o97zhfi.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpnosqudlb5id1o97zhfi.jpg" alt="Apostrophe Team discussing AI during an in-person workshop" width="800" height="369"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As we consider these many possibilities, we look to our guiding principles and core values to help us prioritize the features that we think bring the strongest alignment and most significant value. Over all the years of evolution in our field, our focus has remained:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How can the tools we create help digital teams do their very best work?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This is why we created Apostrophe in the first place. It is what animates all of our decisions, particularly in a moment like this where there are new opportunities to consider and prioritize.&lt;/p&gt;

&lt;p&gt;So what does that look like in practice? How do we apply a focus on helping digital teams do their best work? We think this means helping marketing and editorial teams produce content faster and more efficiently, but in a way that doesn’t risk degrading the quality of that content. It means enabling engineering and DevOps teams to focus more on innovation and less on setup and troubleshooting.&lt;/p&gt;

&lt;p&gt;Ultimately, we think Apostrophe can provide the most value by applying generative AI to automate project scaffolding, rote content tasks, and other busywork, with the goal of facilitating the best possible application of our human creativity to create unique, delightful, and inspiring digital experiences.&lt;/p&gt;

&lt;h3&gt;
  
  
  So what’s next on our roadmap?
&lt;/h3&gt;

&lt;p&gt;The first applications of our principles towards these features is taking the form of the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Automatic SEO and accessibility metadata generation&lt;/strong&gt;: Generating a first draft of simple metadata like page descriptions and alt text for images is one way Apostrophe can streamline the work of content teams, especially teams that need to manage large volumes of documents and media.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Native translation support as part of our localization tools&lt;/strong&gt;: Apostrophe has powerful localization workflows built into the core, but they currently require either manual translation or some integration with a third party translation platform like Smartling. Hooking our native localization workflow into a simple automated translation back end can help accelerate the work of managing a multilingual site when you don’t have the capacity to bring more translation resources to the project.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can find more details about both of these in our &lt;a href="https://portal.productboard.com/apostrophecms/1-product-roadmap/tabs/2-planned"&gt;public roadmap&lt;/a&gt;. Please share any feedback you like there, or submit additional ideas that could be considered for future features.&lt;/p&gt;

&lt;h3&gt;
  
  
  What about the far distant future?
&lt;/h3&gt;

&lt;p&gt;As software engineers and digital creators, are we all just mowing the lawn while a tornado approaches in the background?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5abzjrsk1a70jejurgsa.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5abzjrsk1a70jejurgsa.png" alt="mowing the lawn in tornado" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you were to draw a straight line following the trajectory over just the first half of 2023, it was frighteningly easy to imagine a future where the entire creative economy has been replaced by some form of generative AI. But we know that the path ahead will not follow a straight line, and we know that there is no true replacement for the quality of human vision and creativity when it comes to doing great work. &lt;/p&gt;

&lt;p&gt;As this technology makes its way through various technical and regulatory hurdles, and all of the other stops and starts and twists and turns influenced by the complex factors at play, we think it’s possible to guide it in a humane direction and make good choices as a society. As a company we’ll aim to do our part in that.&lt;/p&gt;

&lt;h3&gt;
  
  
  Let us know what you think!
&lt;/h3&gt;

&lt;p&gt;Once again, please do share your feedback on our roadmap, or better yet join us in &lt;a href="http://chat.apostrophecms.org/"&gt;Discord&lt;/a&gt; and get involved by contributing directly to the project. If you’re a company working with Apostrophe and looking to collaborate more directly with us on any of these features, we love rolling up our sleeves in this way with our partners so definitely reach out.&lt;/p&gt;

&lt;p&gt;There are so many more opportunities for what Apostrophe can do when paired with generative AI than we will ever be able to unlock just with our team alone - we look forward to hearing from you as we dive deeper into this work.&lt;/p&gt;

&lt;p&gt;This post was written by Apostrophe's leading conversation starter, CEO, and staunch board game advocate. We also call him &lt;a href="https://medium.com/r/?url=https%3A%2F%2Fwww.linkedin.com%2Fin%2Falex-gilbert-a361a152%2F"&gt;Alex&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>opensource</category>
      <category>openai</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Launch Faster with Apostrophe Starter Kits</title>
      <dc:creator>The Apostrophe Team</dc:creator>
      <pubDate>Mon, 21 Aug 2023 12:25:00 +0000</pubDate>
      <link>https://forem.com/apostrophecms/launch-faster-with-apostrophe-starter-kits-1n85</link>
      <guid>https://forem.com/apostrophecms/launch-faster-with-apostrophe-starter-kits-1n85</guid>
      <description>&lt;p&gt;Starter Kits offer the building blocks tailored to specific use cases, enabling developers to launch their websites faster and with enhanced functionality.&lt;/p&gt;

&lt;p&gt;In today's digital landscape, teams are always looking for more efficient solutions to streamline their design and development processes. &lt;a href="https://apostrophecms.com/"&gt;Apostrophe&lt;/a&gt;, the ultimate open source content management system and website builder, has introduced a suite of resources to kick start the upfront development work of new Apostrophe-powered projects. These pre-bundled &lt;a href="https://apostrophecms.com/starter-kits"&gt;Starter Kits&lt;/a&gt; offer the building blocks tailored to specific use cases, enabling developers to launch their websites faster and with enhanced functionality. In this blog post, we'll highlight the benefits of Apostrophe Starter Kits and how they can empower developers to build exceptional websites with ease.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffp7detay1xjz706x8yx5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffp7detay1xjz706x8yx5.png" alt="Ecommerce Starter Kit Example" width="800" height="839"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Effortless Website Development
&lt;/h2&gt;

&lt;p&gt;Building a website from scratch can be a time-consuming process, requiring digital teams to invest effort in both design and functionality. However, Apostrophe’s new Starter Kits simplify this upfront demand by providing pre-bundled projects designed for ecommerce, hospitality, and marketing sites, to go along with our existing minimalist Apostrophe 3 Essentials project. These Starter Kits act as a foundation, allowing developers to jumpstart their projects and reduce the time and effort required for initial setup.&lt;/p&gt;

&lt;h3&gt;
  
  
  Tailored to Specific Industries
&lt;/h3&gt;

&lt;p&gt;Apostrophe Starter Kits are specifically designed to cater to the needs of various industries. The &lt;a href="https://apostrophecms.com/starter-kits/apostrophe-essentials-kit"&gt;Apostrophe Essentials Kit&lt;/a&gt; provides a solid blank canvas for general-purpose websites, allowing developers to start their projects with a robust and flexible base. The &lt;a href="https://apostrophecms.com/starter-kits/ecommerce-starter-kit"&gt;Ecommerce Kit&lt;/a&gt; equips developers with the necessary components and features to set up an online store seamlessly. Whereas the &lt;a href="https://apostrophecms.com/starter-kits/hospitality-and-restaurant-starter-kit"&gt;Hospitality Kit&lt;/a&gt; offers specialized functionality for restaurants, hotels, resorts, and other leisure businesses. Lastly, the &lt;a href="https://apostrophecms.com/starter-kits/marketing-starter-kit"&gt;Marketing Kit&lt;/a&gt; empowers marketers with tools to create simple promotional websites that effectively showcase their products or services. &lt;/p&gt;

&lt;p&gt;In releasing these Starter Kits as open source projects, we also hope to create new opportunities for the community to &lt;a href="https://github.com/apostrophecms/apostrophe/blob/main/CONTRIBUTING.md"&gt;collaborate with us&lt;/a&gt;. And this is just the beginning!  In partnership with our &lt;a href="https://apostrophecms.com/partners"&gt;Partner Network&lt;/a&gt;, additional Starter Kits are planned for the Apostrophe Library. If you would like to contribute a Starter Kit, &lt;a href="https://apostrophecms.com/contact-us"&gt;contact us today&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsbjgozf1ngqakhcbo9a6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsbjgozf1ngqakhcbo9a6.png" alt="Hospitality Starter Kit Example" width="800" height="839"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Accelerated Time-to-Market
&lt;/h3&gt;

&lt;p&gt;By leveraging Apostrophe Starter Kits, developers can significantly reduce their time-to-market. The pre-built nature of the components in the kits eliminates the need to start from scratch, enabling developers to focus on customizing and fine-tuning the website to meet their specific requirements. With the Starter Kits' strong foundation and optimized workflows, developers can rapidly iterate and deploy websites, giving businesses a competitive edge in the ever-evolving digital landscape.&lt;/p&gt;

&lt;h3&gt;
  
  
  Unleash Your Creativity
&lt;/h3&gt;

&lt;p&gt;Apostrophe Starter Kits not only offer efficiency but also provide developers with a platform to unleash their creativity. By streamlining the initial setup process, developers have more time and freedom to concentrate on implementing unique and innovative features that set their websites apart from the competition. Whether it's creating interactive elements, integrating third-party APIs, or designing a visually stunning user interface, Apostrophe Starter Kits empower developers to bring their ideas to life without being hindered by repetitive tasks.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxysi6zhacerlpltqg7bk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxysi6zhacerlpltqg7bk.png" alt="Marketing Starter Kit Example" width="800" height="839"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Get Started with a Starter Kit Today
&lt;/h2&gt;

&lt;p&gt;Apostrophe Starter Kits enhance efficiency and streamline the development process, allowing developers to invest more time and effort in the customization of the website. With the accelerated time-to-market and the ability to unleash creativity, developers can build exceptional websites that captivate users and deliver a seamless digital experience. Whether you're a developer or a business owner, Apostrophe Starter Kits provide the tools you need to begin your development journey on the Apostrophe platform. &lt;/p&gt;

&lt;p&gt;To get started, simply navigate to the &lt;a href="https://apostrophecms.com/starter-kits"&gt;Starter Kit Library&lt;/a&gt; and choose the kit that aligns with your goals and objectives. &lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>opensource</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Introducing Apostrophe Pro</title>
      <dc:creator>The Apostrophe Team</dc:creator>
      <pubDate>Mon, 01 May 2023 11:15:00 +0000</pubDate>
      <link>https://forem.com/apostrophecms/introducing-apostrophe-pro-23ak</link>
      <guid>https://forem.com/apostrophecms/introducing-apostrophe-pro-23ak</guid>
      <description>&lt;p&gt;At Apostrophe, we have always been passionate about delivering awesome developer experiences. We are thrilled to launch Apostrophe Pro in that same spirit.&lt;/p&gt;

&lt;h2&gt;
  
  
  Introducing Apostrophe Pro
&lt;/h2&gt;

&lt;p&gt;Get ready to elevate your CMS. We are thrilled to announce the launch of &lt;a href="http://www.apostrophecms.com/pro"&gt;Apostrophe Pro&lt;/a&gt;, a subscription that enhances our offerings in addition to our popular open-source &lt;a href="https://v3.docs.apostrophecms.org/"&gt;ApostropheCMS&lt;/a&gt; and powerful &lt;a href="https://apostrophecms.com/assembly"&gt;Apostrophe Assembly&lt;/a&gt;. As a company committed to delivering exceptional developer experiences, we're been inspired by our &lt;a href="https://apostrophecms.com/get-involved"&gt;ever-growing community&lt;/a&gt; to create Apostrophe Pro. &lt;/p&gt;

&lt;p&gt;Just as our CEO Alex Gilbert mentioned in &lt;a href="https://apostrophecms.com/blog/why-we-are-open-source"&gt;Why We Are Open Source&lt;/a&gt;, “We believe that our commercial solutions will only be successful with continued renewal of our commitment… to the community we are a part of.” That is why we will always aim to build the highest quality product, support the healthiest possible ecosystem of developers and partners, and focus on craft and purpose to attract and retain the best talent. These are the objectives we’ve kept in mind as we rallied the team around the work of Apostrophe Pro. &lt;/p&gt;

&lt;p&gt;Ultimately, we crafted this new platform solution just for you. Our goal is to provide the tools and support necessary for you to level up your own work. With a Pro subscription, you will have the opportunity to take your projects to new heights with the help of premium modules and advanced features.&lt;/p&gt;

&lt;h2&gt;
  
  
  Apostrophe Pro, Explained
&lt;/h2&gt;

&lt;p&gt;Apostrophe Pro originated from the need to offer a professional tool for organizations and businesses who need more than our core ApostropheCMS modules, but were not quite in the market for a multisite configuration. With a simple upgrade to Apostrophe Pro, users can unlock the following closed source, enterprise level modules:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://apostrophecms.com/extensions/advanced-permission"&gt;Advanced Permissions&lt;/a&gt;&lt;/strong&gt; - offers a higher degree of control with more granular level management of permissions for users, custom group creation, individual document level permissions, and permissions per locale.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://apostrophecms.com/extensions/document-version"&gt;Document Versions&lt;/a&gt;&lt;/strong&gt; - gives editors the power to easily restore previous versions of content and revert back to original content with ease. This feature enables teams to collaborate with confidence, knowing that they can always roll back to a previous version if needed, avoiding costly mistakes, improving productivity, and streamlining their workflows.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://apostrophecms.com/extensions/automated-testing-tools"&gt;Automated Testing Tools&lt;/a&gt;&lt;/strong&gt; - tap into a vast library of pre-built, accelerated, and automated functional tests to streamline your testing process. By automating the testing process, you can reduce the time and effort required to manually test software, improve accuracy, and increase testing coverage.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://apostrophecms.com/extensions/palette-3"&gt;Palette Design Editor&lt;/a&gt;&lt;/strong&gt; - empower your team to visually edit CSS properties of your website with ease, all from within Apostrophe. With Palette, you can easily fine-tune your website's visual design by adjusting colors, font styles, margins, and more using a simple, intuitive interface. This feature makes it easy for non-technical users to make design changes without having to write or modify CSS code manually.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Template Library&lt;/strong&gt; (Coming soon!) - A collection of document templates that can help you speed up your content creation process. Quickly and easily create high-quality content, without having to start from scratch, and customize them to your specific needs to maintain your brand identity and unique style.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Be sure to visit our &lt;a href="https://apostrophecms.com/pricing"&gt;pricing page&lt;/a&gt; to check out Pro’s robust features, along with the other plans we offer! We continually add to both our open and closed source capabilities, so we encourage anyone on the platform to visit our &lt;a href="https://portal.productboard.com/apostrophecms/1-product-roadmap/tabs/1-under-consideration"&gt;product roadmap&lt;/a&gt;. &lt;/p&gt;

&lt;h2&gt;
  
  
  Apostrophe Pro Add Ons
&lt;/h2&gt;

&lt;p&gt;With an Apostrophe Pro subscription, we also offer support packages, which build a more direct relationship between your team and the Apostrophe engineers. These packages include personalized account management, along with expert assistance with expedited bug fixes, enhancements, new features, code and performance audits, module configurations and installations, and training. &lt;/p&gt;

&lt;p&gt;Apostrophe Pro subscribers will also be the first to enjoy any new Apostrophe features, in addition to other exclusive benefits such as invitations to town hall meetings, beta testing, premium how-to content, and more.&lt;/p&gt;

&lt;h2&gt;
  
  
  Who Can be a Pro?
&lt;/h2&gt;

&lt;p&gt;As mentioned earlier, Apostrophe Pro was built as an intermediary between ApostropheCMS and Apostrophe Assembly. If you are a hobbyist developer or a non profit looking to keep costs as low as possible, ApostropheCMS remains open source and has a variety of &lt;a href="https://apostrophecms.com/extensions?license=MIT"&gt;open source extensions&lt;/a&gt; that can enhance your project. See our &lt;a href="https://v3.docs.apostrophecms.org/"&gt;developer documentation&lt;/a&gt; to get the CMS installed. If your business is booming and you need to manage multiple sites seamlessly, Apostrophe Assembly has what you need. &lt;a href="https://apostrophecms.com/contact-us"&gt;Contact us&lt;/a&gt; to learn more about our volume pricing and available hosting options. If you are a small to medium sized business or a digital agency that falls under the category of a single site enterprise, then Pro is the way to go. Set up a call to learn how you can &lt;a href="https://meetings.hubspot.com/ashleigh23/pro-discovery-call?__hstc=103731679.2b6b5293e643351c19403d74b44fa37a.1603208838386.1682701630766.1682714572433.1475&amp;amp;__hssc=103731679.11.1682714572433&amp;amp;__hsfp=2014138109"&gt;subscribe to Pro&lt;/a&gt;, or if you are an existing ApostropheCMS user running on &lt;strong&gt;Apostrophe 3&lt;/strong&gt;, provide us with some basic information and we can help &lt;a href="http://www.apostrophecms.com/contact-us/pro"&gt;upgrade your license&lt;/a&gt;!&lt;/p&gt;

&lt;h2&gt;
  
  
  ApostropheCMS vs Pro vs Assembly
&lt;/h2&gt;

&lt;p&gt;Now that we’ve introduced Apostrophe Pro, let’s dive a little deeper into the differences between Apostrophe’s plans. &lt;/p&gt;

&lt;h4&gt;
  
  
  ApostropheCMS
&lt;/h4&gt;

&lt;p&gt;The core of ApostropheCMS is open source and available to the public – it’s free and always will be. You can host ApostropheCMS on your own server and have full control over your CMS environment. It’s readily available for download via npm or GitHub without cost or commitment. Plus, you have access to a large Apostrophe community where you can partake in real-time discussions and contribute to the project. Get more out of your ApostropheCMS experience when you &lt;a href="https://apostrophecms.com/get-involved"&gt;get involved&lt;/a&gt; with our community!&lt;/p&gt;

&lt;h4&gt;
  
  
  Apostrophe Assembly
&lt;/h4&gt;

&lt;p&gt;Apostrophe Assembly is our top level subscription, elevating the core CMS into a website builder platform that allows users to easily manage a fleet of sites from a single dashboard. Ready to scale, starting at $499 a month (includes 5 sites), Assembly enhances your projects without limitations, and it accommodates any Devops or coding requirements. Assembly comes with a powerful tool stack, including cut and paste in-context editing and localization. Additionally, Assembly allows an easy way to spin up new sites. Furthermore, agencies and SaaS companies can utilize these Assembly tools for clients and customers through white-label experiences.&lt;/p&gt;

&lt;h4&gt;
  
  
  Apostrophe Pro
&lt;/h4&gt;

&lt;p&gt;It’s safe to say that Apostrophe Pro is the answer to a specific need - the need for premium features for a single site. It offers all the capabilities of ApostropheCMS along with a lot of the perks of Assembly, all for an affordable price. For only $199 a month, you can upgrade your digital experience and develop sites like a Pro.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;We hope you are just as thrilled about Apostrophe Pro as we are. And we are even more excited about what’s to come. As always, we plan to keep you updated, but for now - &lt;a href="https://apostrophecms.com/pro"&gt;go big, go Pro&lt;/a&gt;! &lt;/p&gt;

</description>
      <category>webdev</category>
      <category>news</category>
      <category>showdev</category>
    </item>
    <item>
      <title>Video Tutorial: Converting an HTML template for use in Apostrophe</title>
      <dc:creator>The Apostrophe Team</dc:creator>
      <pubDate>Tue, 14 Mar 2023 19:09:36 +0000</pubDate>
      <link>https://forem.com/apostrophecms/converting-an-html-template-for-use-in-apostrophe-2fj</link>
      <guid>https://forem.com/apostrophecms/converting-an-html-template-for-use-in-apostrophe-2fj</guid>
      <description>&lt;p&gt;Creating a website from scratch can be a daunting process. Not only do you have to create the HTML markup, but also the styling to make it all look good. One way to get started quickly is to use one of the numerous premade templates available on the internet.&lt;/p&gt;

&lt;p&gt;In this video tutorial, we will walk through the steps to convert the &lt;a href="https://startbootstrap.com/theme/clean-blog"&gt;"Start Bootstrap Clean Blog"&lt;/a&gt; template into an Apostrophe template. While we are starting with a specific template, these steps can be generalized to any template you might download.&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/KqzKrbCv5G4"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  What to Expect
&lt;/h2&gt;

&lt;p&gt;Any pre-made HTML template can be converted for use in Apostrophe through some simple steps. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add the front end assets to your Apostrophe project.&lt;/li&gt;
&lt;li&gt;Create an Apostrophe page type for each of the template pages that substitutes data from the schema fields into each area of the page that you want to edit.&lt;/li&gt;
&lt;li&gt;Add special piece types and piece page types.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In this tutorial, we took extra steps to create reusable navigation, header, and footer fragments. While this makes the overall project more compact it is completely optional.&lt;/p&gt;

&lt;h2&gt;
  
  
  Documentation and Resources
&lt;/h2&gt;

&lt;p&gt;For developers that like to follow along with the written documentation, that can be found &lt;a href="https://v3.docs.apostrophecms.org/cookbook/html-conversion.html"&gt;here in our docs&lt;/a&gt;. Additional resource links include the &lt;a href="https://apostrophecms.com/extensions/form-builder-3-x"&gt;Form Builder Extension&lt;/a&gt; and the &lt;a href="https://v3.docs.apostrophecms.org/cookbook/building-navigation.html"&gt;Cookbook for Building Navigation&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;We hope that this tutorial will help you get your Apostrophe project up and running a little more quickly! Have you converted a template into Apostrophe? Tell us about it in &lt;a href="http://chat.apostrophecms.org/"&gt;Discord&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;This article was originally published on &lt;a href="https://apostrophecms.com/blog/convert-html-template-apostrophe"&gt;ApostropheCMS.com&lt;/a&gt;. &lt;/p&gt;

</description>
      <category>tutorial</category>
      <category>webdev</category>
      <category>opensource</category>
      <category>html</category>
    </item>
    <item>
      <title>Observability - ApostropheCMS, OpenTelemetry, and New Relic</title>
      <dc:creator>The Apostrophe Team</dc:creator>
      <pubDate>Wed, 16 Nov 2022 16:47:37 +0000</pubDate>
      <link>https://forem.com/apostrophecms/observability-apostrophecms-opentelemetry-and-new-relic-1min</link>
      <guid>https://forem.com/apostrophecms/observability-apostrophecms-opentelemetry-and-new-relic-1min</guid>
      <description>&lt;p&gt;In this article, we will look at how to connect your site to New Relic using the OpenTelemetry observability framework.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is OpenTelemetry?
&lt;/h2&gt;

&lt;p&gt;OpenTelemetry, an open-source project, offers a set of vendor-neutral APIs that allow us to collect and transfer data to a location. This enables you to understand what your site is doing without having to worry about the tools or programming language being used. For more information, check out &lt;a href="https://opentelemetry.io/"&gt;Open Telemetry’s website&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is New Relic?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://newrelic.com/"&gt;New Relic&lt;/a&gt; is a monitoring tool that can import data emitted by OpenTelemetry to help analyze and resolve application or website issues. It provides real-time data and shows the analytical performance of your site on the New Relic dashboard. It is designed to help discover unexpected outcomes and help you improve performance based on key metrics.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Observability?
&lt;/h2&gt;

&lt;p&gt;Observability has become more important for sites in recent years. Most people tend to confuse Observability and Monitoring, but the main difference is that Monitoring tells you when something goes wrong, and Observability tells you why it went wrong. Monitoring has to happen before Observability takes place. Observability is one important concept that needs to be considered in complex systems, because if it doesn’t exist, then you can never know why things go wrong. This, in turn, will affect business performance and customer experience.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://v3.docs.apostrophecms.org/cookbook/opentelemetry.html#_1-install-the-required-dependencies"&gt;Profiling ApostropheCMS with OpenTelemetry&lt;/a&gt; already provides instructions for using another tool, &lt;a href="https://www.jaegertracing.io/"&gt;Jaeger&lt;/a&gt;. The reason we are using New Relic in this article is that it provides more features out-of-the-box besides distributed tracing or monitoring. This article will be a quick guide on configuring this tool, which will extract telemetry data and export them to New Relic for monitoring.&lt;/p&gt;

&lt;p&gt;Before moving on with this guide, we recommend you update Apostrophe to version 3.18.0, or preferably the latest &lt;a href="https://apostrophecms.com/blog/apostrophe-3-release"&gt;3.x&lt;/a&gt; version available.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setup OpenTelemetry and NewRelic
&lt;/h2&gt;

&lt;p&gt;Before we begin, there are a few things to note; we will be using an SDK for OpenTelemetry, which basically is used for measurement, and those measurements(data) will be exported to New Relic using an &lt;a href="https://www.npmjs.com/package/@opentelemetry/exporter-trace-otlp-proto"&gt;OTLP/PROTO&lt;/a&gt; Trace Exporter. The reason for using OTLP/PROTO is that New Relic expects its data in Proto format unlike the more familiar JSON format.&lt;/p&gt;

&lt;h4&gt;
  
  
  Step 1: Install the required dependencies for OpenTelemetry
&lt;/h4&gt;

&lt;p&gt;Install the required dependencies in your project:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;$ npm install @opentelemetry/sdk-node@0.27.0 @opentelemetry/auto-instrumentations-node@0.27.4 @opentelemetry/semantic-conventions@1.0.1 @opentelemetry/resources @opentelemetry/exporter-trace-otlp-proto uuid&lt;/code&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Step 2: Login to New Relic
&lt;/h4&gt;

&lt;p&gt;Before working with New Relic, you will need to have an account. So, go ahead and create one if you don't have one.&lt;/p&gt;

&lt;p&gt;While on the dashboard, head over to the &lt;a href="https://login.newrelic.com/login?return_to=https%3A%2F%2Fone.newrelic.com%2Flauncher%2Fapi-keys-ui.launcher"&gt;API Keys page&lt;/a&gt; and copy the INGEST-License key. This is what will provide permission to get data into New Relic.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa1rdgurui4yspzphfptl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa1rdgurui4yspzphfptl.png" alt="Observability OpenTelemetry" width="800" height="362"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;With that complete, there are two ways we can export our data to New Relic; exporting directly to New Relic from our app or exporting to New Relic from a collector. But in this guide, we will be exporting directly from our Apostrophe app.&lt;/p&gt;

&lt;h4&gt;
  
  
  Step 3: Configure OpenTelemetry
&lt;/h4&gt;

&lt;p&gt;At this point, we are about to do the real work where we have to configure OpenTelemetry and export telemetry data to New Relic. Exporting this kind of data relies on a specific protocol; the &lt;a href="https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/protocol/otlp.md"&gt;OpenTelemetry Protocol&lt;/a&gt; or OTLP.&lt;/p&gt;

&lt;p&gt;In your project root directory, create a file telemetry.js:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const { NodeSDK } = require('@opentelemetry/sdk-node');
    const { getNodeAutoInstrumentations } = require('@opentelemetry/auto-instrumentations-node');
    const { SemanticResourceAttributes } = require('@opentelemetry/semantic-conventions');
    const { Resource } = require('@opentelemetry/resources');
    const { OTLPTraceExporter } = require('@opentelemetry/exporter-trace-otlp-proto');
    const { v4: uuidv4 } = require('uuid');
    const pkg = require('./package-lock.json');

    // Resources attributes
    const resource = new Resource({
      [SemanticResourceAttributes.SERVICE_NAME]: pkg.name,
      [SemanticResourceAttributes.SERVICE_VERSION]: pkg.version,
      [SemanticResourceAttributes.INSTANCE]: uuidv4(),
    });

    const instrumentations = [getNodeAutoInstrumentations()];

    const traceExporter = new OTLPTraceExporter({
      url: '&amp;lt;https://otlp.nr-data.net:4317/v1/traces&amp;gt;',
      headers: {
        'api-key': '&amp;lt;your-api-key&amp;gt;', // Your license key from NewRelic account
      },
    });

    const sdk = new NodeSDK({
      resource,
      instrumentations,
      traceExporter,
    });

    const shutdown = () =&amp;gt; {
      sdk
        .shutdown()
        .then(() =&amp;gt; {
          console.log('Shutdown complete');
        })
        .catch((err) =&amp;gt; {
          console.error('Shutdown failed', err);
        });
    };

    module.exports = {
      sdk,
      shutdown,
    };
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This code imports the necessary packages we had installed earlier and provides the resources attributes, which is more information about the service. It also enables &lt;a href="https://opentelemetry.io/docs/concepts/instrumenting/#:~:text=The"&gt;auto-instrumentation&lt;/a&gt; (OpenTelemetry project facilitates the instrumentation or non-core components) before configuring the OTLP/PROTO trace exporter.&lt;/p&gt;

&lt;p&gt;Finally, this code exports both the configured SDK function we will use and a shutdown function.&lt;/p&gt;

&lt;p&gt;With that set, we have to refractor our app.js to make use of the opentelemetry setup:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const apostrophe = require('apostrophe');
    const process = require('process');
    const { sdk, shutdown } = require('./telemetry');

    const config = {
      shortName: 'apos-relic',
      modules: {},
    };

    if (process.env.APOS_OPENTELEMETRY) {
      sdk
        .start()
        .then(() =&amp;gt; console.log('Started OpenTelemetry'))
        .then(() =&amp;gt; apostrophe(config))
        .catch((err) =&amp;gt; console.error('Failed to start OpenTelemetry', err));
    } else {
      apostrophe(config);
    }

    process.on('SIGTERM', () =&amp;gt; {
      shutdown()
        .then(() =&amp;gt; console.log('Tracing terminated'))
        .catch((error) =&amp;gt; console.log('Error terminating tracing', error))
        .finally(() =&amp;gt; process.exit(0));
    });
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The important things to note in the above code is that we start Apostrophe after OpenTelemetry has started, and we shut down the sdk on process exit.&lt;/p&gt;

&lt;h4&gt;
  
  
  Step 4: Start your application
&lt;/h4&gt;

&lt;p&gt;After everything is set and configured, we can then start our application.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;$ APOS_OPENTELEMETRY=1 node app&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Once our app is started, open &lt;a href="http://localhost:3000"&gt;http://localhost:3000&lt;/a&gt; and head over to the New Relic UI to view your data. If you are logged into your account and navigate to the monitoring &lt;a href="https://one.newrelic.com/"&gt;home page&lt;/a&gt;, you should be on the “Explorer” page. This page allows you to select any services that you have running. You site will be under “Services- OpenTelemetry”. Selecting it will bring up a dashboard showing various data about your site, like response time and error rate.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsr1u5u40bwimbm78fgjx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsr1u5u40bwimbm78fgjx.png" alt="composite relic dash" width="800" height="349"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Three important observations you will need to look at on your New Relic UI are the &lt;a href="https://one.newrelic.com/launcher/nr1-core.explorer?overlay=eyJuZXJkbGV0SWQiOiJkYXRhLWV4cGxvcmF0aW9uLnF1ZXJ5LWJ1aWxkZXIiLCJpbml0aWFsQWN0aXZlSW50ZXJmYWNlIjoibnJxbEVkaXRvciIsImluaXRpYWxOcnFsVmFsdWUiOiIiLCJpbml0aWFsUXVlcmllcyI6W3sibnJxbCI6IkZST00gU3BhbiBTRUxFQ1QgY291bnQoKikgd2hlcmUgbmV3cmVsaWMuc291cmNlPSclb3RscCUnIFRJTUVTRVJJRVMifV0sImluaXRpYWxDaGFydFNldHRpbmdzIjp7ImNoYXJ0VHlwZSI6IkNIQVJUX0xJTkUiLCJsaW1pdCI6NzU0MiwibGlua2VkRW50aXR5R3VpZCI6bnVsbCwibGlua2VkRGFzaGJvYXJkSWQiOm51bGwsInlTY2FsZSI6eyJzdGF0aWMiOmZhbHNlLCJkb21haW4iOltudWxsLG51bGxdfSwieVplcm8iOnRydWV9fQo="&gt;traces&lt;/a&gt;, &lt;a href="https://one.newrelic.com/launcher/nr1-core.explorer?overlay=eyJuZXJkbGV0SWQiOiJkYXRhLWV4cGxvcmF0aW9uLnF1ZXJ5LWJ1aWxkZXIiLCJpbml0aWFsQWN0aXZlSW50ZXJmYWNlIjoibnJxbEVkaXRvciIsImluaXRpYWxOcnFsVmFsdWUiOiIiLCJpbml0aWFsUXVlcmllcyI6W3sibnJxbCI6IkZST00gTG9nIFNFTEVDVCBjb3VudCgqKSB3aGVyZSBuZXdyZWxpYy5zb3VyY2U9JyVvdGxwJScgVElNRVNFUklFUyJ9XSwiaW5pdGlhbENoYXJ0U2V0dGluZ3MiOnsiY2hhcnRUeXBlIjoiQ0hBUlRfTElORSIsImxpbWl0Ijo3NTQyLCJsaW5rZWRFbnRpdHlHdWlkIjpudWxsLCJsaW5rZWREYXNoYm9hcmRJZCI6bnVsbCwieVNjYWxlIjp7InN0YXRpYyI6ZmFsc2UsImRvbWFpbiI6W251bGwsbnVsbF19LCJ5WmVybyI6dHJ1ZX19Cg=="&gt;logs&lt;/a&gt; and &lt;a href="https://one.newrelic.com/launcher/nr1-core.explorer?overlay=eyJuZXJkbGV0SWQiOiJkYXRhLWV4cGxvcmF0aW9uLnF1ZXJ5LWJ1aWxkZXIiLCJpbml0aWFsQWN0aXZlSW50ZXJmYWNlIjoibnJxbEVkaXRvciIsImluaXRpYWxOcnFsVmFsdWUiOiIiLCJpbml0aWFsUXVlcmllcyI6W3sibnJxbCI6IkZST00gTWV0cmljIFNFTEVDVCBjb3VudCgqKSB3aGVyZSBuZXdyZWxpYy5zb3VyY2UgTElLRSAnJW90bHAlJyBUSU1FU0VSSUVTIn1dLCJpbml0aWFsQ2hhcnRTZXR0aW5ncyI6eyJjaGFydFR5cGUiOiJDSEFSVF9MSU5FIiwibGltaXQiOjc1NDIsImxpbmtlZEVudGl0eUd1aWQiOm51bGwsImxpbmtlZERhc2hib2FyZElkIjpudWxsLCJ5U2NhbGUiOnsic3RhdGljIjpmYWxzZSwiZG9tYWluIjpbbnVsbCxudWxsXX0sInlaZXJvIjp0cnVlfX0K"&gt;metrics&lt;/a&gt;. Traces, otherwise known as distributed tracing, are basically application requests which are tagged with a unique identifier. Logs, on the other hand, are vital information and trigger alerts as they happen in your application. These may need some setup before any data is logged. Metrics are the core information or better still statistics; viewership statistics, engagement statistics, etc.&lt;/p&gt;

&lt;p&gt;You may decide to trace command line tasks as well.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;$ APOS_OPENTELEMETRY=1 node app @moduleName:taskName&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwzfowes0hqiqubolu8mx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwzfowes0hqiqubolu8mx.png" alt="request image" width="800" height="464"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Observing your application is critical to noticing which part is slow or needs attention. This guide should give you the power to ensure that your site is in perfect health. Good luck!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This post was originally contributed by an Apostrophe Community member, &lt;a href="https://twitter.com/vectormike_"&gt;Victor Jonah&lt;/a&gt;. If you would like to contribute an article to the community, &lt;a href="https://apostrophecms.com/contact-us"&gt;submit your article here&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  We'd love to hear your feedback on this!
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Join our team and other Apostrophe developers from around the world on &lt;a href="http://chat.apostrophecms.org/"&gt;Discord&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Follow product updates and more on &lt;a href="https://github.com/apostrophecms/apostrophe/discussions"&gt;Github Discussions&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>javascript</category>
      <category>tutorial</category>
      <category>webdev</category>
      <category>tooling</category>
    </item>
    <item>
      <title>Using S3 Compatible Storage Solutions with ApostropheCMS</title>
      <dc:creator>The Apostrophe Team</dc:creator>
      <pubDate>Mon, 07 Nov 2022 17:47:45 +0000</pubDate>
      <link>https://forem.com/apostrophecms/using-s3-compatible-storage-solutions-with-apostrophecms-40c1</link>
      <guid>https://forem.com/apostrophecms/using-s3-compatible-storage-solutions-with-apostrophecms-40c1</guid>
      <description>&lt;p&gt;This tutorial details file storage solutions for FileBase, Vultr, Wasabi, and DigitalOcean using S3 API in order to deploy Apostrophe to production.&lt;/p&gt;

&lt;p&gt;Deploying Apostrophe to production requires that you specify hosting for the code base, the MongoDB instance, and storage for any uploaded content. Many hosting services can provide all three, but it is also possible and sometimes desirable to split these between different services. This tutorial looks at file storage solutions using the S3 API.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is the S3 API?
&lt;/h2&gt;

&lt;p&gt;The S3 API is a REST API developed by Amazon as a means of communicating with their Simple Storage Service (S3). Versions of this API have since been adopted by many other providers. These alternative providers can sometimes provide lower cost points or desirable features, like IPFS. The &lt;code&gt;@apostrophecms/uploadfs&lt;/code&gt; module provides an easy way to connect to most S3 API-powered services through environmental variables.&lt;/p&gt;

&lt;p&gt;Depending on the service used for hosting your code base, there are different ways to set these variables. For example, Heroku as we show in our &lt;a href="https://v3.docs.apostrophecms.org/cookbook/deploying-to-heroku.html"&gt;hosting tutorial&lt;/a&gt;, allows you to configure your app either through their CLI or dashboard. For other hosting environments, you may need to set these variables through a &lt;code&gt;.env&lt;/code&gt; or &lt;code&gt;.bashrc&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;Let's start by looking at how to connect with Amazon Web Services (AWS) S3.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using AWS S3 services
&lt;/h2&gt;

&lt;p&gt;For AWS S3 we need to add values for four environment variables: &lt;code&gt;APOS_S3_BUCKET&lt;/code&gt;, &lt;code&gt;APOS_S3_REGION&lt;/code&gt;, &lt;code&gt;APOS_S3_KEY&lt;/code&gt;, and &lt;code&gt;APOS_S3_SECRET&lt;/code&gt;.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create an &lt;a href="https://aws.amazon.com/pm/serv-s3/"&gt;Amazon AWS&lt;/a&gt; account and then log into the management console. From the "Services" menu select "Storage" and then "S3". Note that Amazon offers 12 months free with a fixed data cap.&lt;/li&gt;
&lt;li&gt;This should take you to a dashboard screen where you can create a new bucket. Give your bucket a name. This is what we will use as a value for the &lt;code&gt;APOS_S3_BUCKET&lt;/code&gt; environment variable.&lt;/li&gt;
&lt;li&gt;Select an AWS region - this is the value we will use for the &lt;code&gt;APOS_S3_REGION&lt;/code&gt; variable.&lt;/li&gt;
&lt;li&gt;Leave everything else alone for now. We will come back to security in the next section.&lt;/li&gt;
&lt;li&gt;From your account drop-down, select "Security credentials".&lt;/li&gt;
&lt;li&gt;Open the "Access keys" section.&lt;/li&gt;
&lt;li&gt;Click to "Create New Access Key"&lt;/li&gt;
&lt;li&gt;This will create both our &lt;code&gt;APOS_S3_KEY&lt;/code&gt; and &lt;code&gt;APOS_S3_SECRET&lt;/code&gt; values. Make sure to save your secret value. You will be able to see your key from this page, but not your secret.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Setting these variables will allow for upload into your bucket, but until you change the permissions settings for the bucket your site won't be able to access the resources.&lt;/p&gt;

&lt;h4&gt;
  
  
  Example Amazon S3 permissions
&lt;/h4&gt;

&lt;p&gt;First, select the bucket from the S3 management console and then click on the "Permissions" tab. Click on the "Edit" button to edit your permissions.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgdnaarlym5kx73beoedj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgdnaarlym5kx73beoedj.png" alt="AWS s3 permissions tab" width="800" height="268"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Uncheck the "Block all public access" box and save the changes. You will have to confirm that you want to do this.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fov8qwklq40gbxwwycjlo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fov8qwklq40gbxwwycjlo.png" alt="Amazon s3 public permissions" width="800" height="607"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Scroll down the page to the "Object Ownership" section and click the "Edit" button.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhl7uh84m95fqy6rmtg46.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhl7uh84m95fqy6rmtg46.png" alt="AWS s3 object ownership" width="800" height="110"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Select "ACLs enabled" and "Object writer" then acknowledge the warning and save the changes.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7nhctnejc57rigo8fq7l.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7nhctnejc57rigo8fq7l.png" alt="Amazon s3 object permission" width="800" height="496"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Using FileBase for storage
&lt;/h2&gt;

&lt;p&gt;The FileBase storage service uses a truncated version of the S3 API. However, we can use this service in almost the same manner as the AWS S3 service. In this case, we must pass in one additional environment variable, &lt;code&gt;APOS_S3_ENDPOINT&lt;/code&gt;, and not set the &lt;code&gt;APOS_S3_REGION&lt;/code&gt; variable.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create a &lt;a href="https://filebase.com/"&gt;FileBase account&lt;/a&gt;. While the service does have a free tier, it doesn't allow public access. This means our site won't be able to load resources, so you need to select one of their paid plans.&lt;/li&gt;
&lt;li&gt;From the console switch to the "Buckets" tab and click on "Create Bucket".&lt;/li&gt;
&lt;li&gt;Give the bucket a name. This is the value we will pass to the &lt;code&gt;APOS_S3_BUCKET&lt;/code&gt; variable.&lt;/li&gt;
&lt;li&gt;Leave the storage network as "IPFS" and click "Create Bucket".&lt;/li&gt;
&lt;li&gt;Set the bucket access to public using the toggle next to the bucket name.&lt;/li&gt;
&lt;li&gt;Click the "Access Keys" tab.&lt;/li&gt;
&lt;li&gt;This screen will display the key and secret values we will add to the &lt;code&gt;APOS_S3_KEY&lt;/code&gt; and &lt;code&gt;APOS_S3_SECRET&lt;/code&gt; variables.&lt;/li&gt;
&lt;li&gt;On this screen we can also get the value for the &lt;code&gt;APOS_S3_ENDPOINT&lt;/code&gt; environment variable from the URL listed under 'S3 API Endpoint'. Note: you should not set the &lt;code&gt;APOS_S3_REGION&lt;/code&gt; key.&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  FileBase Security
&lt;/h4&gt;

&lt;p&gt;While FileBase can accept the same type of CORS (cross-origin resource sharing) and ACL (access control list) rules as AWS S3, simply setting the security toggle to "public" on the "Buckets" screen should be enough for most sites.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using Vultr for storage
&lt;/h2&gt;

&lt;p&gt;The Vultr storage service uses a truncated version of the S3 API. However, we can use this service in almost the same manner as the AWS S3 service. In this case, we must pass in one additional environment variable, &lt;code&gt;APOS_S3_ENDPOINT&lt;/code&gt;, and not set the &lt;code&gt;APOS_S3_REGION&lt;/code&gt; variable.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create a &lt;a href="https://www.vultr.com/"&gt;Vultr account&lt;/a&gt;. While the service doesn't have a free tier, you should be able to find a free credit offer if you are a new customer.&lt;/li&gt;
&lt;li&gt;Log in to your account and navigate to "Products".&lt;/li&gt;
&lt;li&gt;Select "Objects" to begin creating a new storage object.&lt;/li&gt;
&lt;li&gt;Select your preferred location.&lt;/li&gt;
&lt;li&gt;Add a label for your object - this object can contain multiple storage buckets.&lt;/li&gt;
&lt;li&gt;Wait for the object to install and then click on the green arrow.&lt;/li&gt;
&lt;li&gt;Under the S3 Credentials you will see your Hostname, Secret Key, and Access Key. These will be used for the &lt;code&gt;APOS_S3_ENDPOINT&lt;/code&gt;, &lt;code&gt;APOS_S3_SECRET&lt;/code&gt;, and &lt;code&gt;APOS_S3_KEY&lt;/code&gt; variables. Note: you should not set the &lt;code&gt;APOS_S3_REGION&lt;/code&gt; key.&lt;/li&gt;
&lt;li&gt;Click the "Buckets" tab.&lt;/li&gt;
&lt;li&gt;Click the "Create Bucket" button.&lt;/li&gt;
&lt;li&gt;Add a bucket name following the noted limitations. This name will be used to set the &lt;code&gt;APOS_S3_BUCKET&lt;/code&gt; variable.&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  Vultr Security
&lt;/h4&gt;

&lt;p&gt;While files uploaded to Vultr are private by default, the &lt;code&gt;@apostrophecms/uploadfs&lt;/code&gt; module sets &lt;code&gt;bucketObjectsACL&lt;/code&gt; to &lt;code&gt;public-read&lt;/code&gt; by default. Therefore, you don't have to perform any further security changes in order for your site to be able to access the stored files.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using Wasabi for storage
&lt;/h2&gt;

&lt;p&gt;The Wasabi storage service has an expanded API that supports some features not found in the AWS S3 REST API, but is compatible with the core S3 API that Apostrophe uses. We can use this service in almost the same manner as the AWS S3 service. In this case, we must pass in one additional environment variable, &lt;code&gt;APOS_S3_ENDPOINT&lt;/code&gt;, and not set the &lt;code&gt;APOS_S3_REGION&lt;/code&gt; variable.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create a &lt;a href="https://www.wasabi.com/"&gt;Wasabi account&lt;/a&gt;. While the service does have a free tier, it doesn't allow public access. This means our site won't be able to load resources, so you need to select one of their paid plans. You may be able to find a credit offer if you are a new customer.&lt;/li&gt;
&lt;li&gt;Once logged in, click on "Create Bucket".&lt;/li&gt;
&lt;li&gt;Add a bucket name. This is the value we need to set for the &lt;code&gt;APOS_S3_BUCKET&lt;/code&gt; variable.&lt;/li&gt;
&lt;li&gt;Select a preferred region. Note the URL to the right of each region. This is the value for the &lt;code&gt;APOS_S3_ENDPOINT&lt;/code&gt; variable. Although each bucket will have a region listed, this should not be added to the &lt;code&gt;APOS_S3_REGION&lt;/code&gt; variable. This variable should not be set.&lt;/li&gt;
&lt;li&gt;Click the "Next" button to step through the settings until the "Create bucket" button comes up. Nothing needs to be changed.&lt;/li&gt;
&lt;li&gt;Click on the "Access Keys" menu item on the left.&lt;/li&gt;
&lt;li&gt;Click the "Create new access key" button.&lt;/li&gt;
&lt;li&gt;Download the credentials. You won't be able to get the secret again.&lt;/li&gt;
&lt;li&gt;Get the &lt;code&gt;APOS_S3_SECRET&lt;/code&gt; and &lt;code&gt;APOS_S3_KEY&lt;/code&gt; values from the file.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you didn't note the endpoint URL you can get it based on the region code (e.g. 'us-east-1') from this &lt;a href="https://wasabi-support.zendesk.com/hc/en-us/articles/360015106031-What-are-the-service-URLs-for-Wasabi-s-different-storage-regions-"&gt;page&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Wasabi security
&lt;/h4&gt;

&lt;p&gt;The files uploaded to the Wasabi bucket are publicly available right away without the need for any changes. However, if you click the menu to the right of the bucket name and select "Setting", it will bring up a page that allows you to alter permissions easily.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using DigitalOcean Spaces for storage
&lt;/h2&gt;

&lt;p&gt;The DigitalOcean Spaces API is a truncated version of the AWS S3 API that supports all the features we need for using it for storage with Apostrophe. We can use this service in almost the same manner as the AWS S3 service. In this case, we must pass in one additional environment variable, &lt;code&gt;APOS_S3_ENDPOINT&lt;/code&gt;, and not set the &lt;code&gt;APOS_S3_REGION&lt;/code&gt; variable.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create a &lt;a href="https://www.digitalocean.com/"&gt;DigitalOcean account&lt;/a&gt;. They don't have a free tier, but do offer a credit to new customers.&lt;/li&gt;
&lt;li&gt;Once logged in, you'll be brought to a project page. Click on "Store static objects". In some cases, you might instead have to click "Start using Spaces".&lt;/li&gt;
&lt;li&gt;Choose a preferred datacenter region.&lt;/li&gt;
&lt;li&gt;Leave "Restrict File Listing" selected.&lt;/li&gt;
&lt;li&gt;Create a name and select a project. If you haven't made one it will assign it to a default called "first-project". The name is the value for the &lt;code&gt;APOS_S3_BUCKET&lt;/code&gt; variable.&lt;/li&gt;
&lt;li&gt;Click on "Create a Space".&lt;/li&gt;
&lt;li&gt;Click on the "Settings" tab.&lt;/li&gt;
&lt;li&gt;Copy the "endpoint" URL. This is the value for the &lt;code&gt;APOS_S3_ENDPOINT&lt;/code&gt; variable.&lt;/li&gt;
&lt;li&gt;Click on the "API" tab in the left menu.&lt;/li&gt;
&lt;li&gt;Scroll down to the "Spaces access keys" section and click "Generate New Key".&lt;/li&gt;
&lt;li&gt;Add a name and hit return. It will take a few seconds to generate the key and secret. Copy them. You will be able to get the key again by returning to this page, but you won't be able to retrieve the secret.&lt;/li&gt;
&lt;li&gt;Assign the key and secret values to the &lt;code&gt;APOS_S3_KEY&lt;/code&gt; and &lt;code&gt;APOS_S3_SECRET&lt;/code&gt; variables, respectively. The &lt;code&gt;APOS_S3_REGION&lt;/code&gt; variable should not be set.&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  DigitalOcean Security
&lt;/h4&gt;

&lt;p&gt;The assets uploaded to the DigitalOcean Spaces are publicly readable by default. No security policy changes are required. If needed, you can configure the CORS (cross-origin resource sharing) through the settings of each space, and you shouldn't need to change anything.&lt;/p&gt;

&lt;h4&gt;
  
  
  Share your Solution
&lt;/h4&gt;

&lt;p&gt;Have you implemented any of the described solutions? Share your experience with the author in &lt;a href="http://chat.apostrophecms.org/"&gt;Discord&lt;/a&gt;. &lt;/p&gt;

</description>
      <category>tutorial</category>
      <category>webdev</category>
      <category>opensource</category>
      <category>aws</category>
    </item>
    <item>
      <title>ApostropheCMS Launches Document Versions Tool</title>
      <dc:creator>The Apostrophe Team</dc:creator>
      <pubDate>Mon, 17 Oct 2022 16:32:55 +0000</pubDate>
      <link>https://forem.com/apostrophecms/apostrophecms-launches-document-versions-tool-1dbl</link>
      <guid>https://forem.com/apostrophecms/apostrophecms-launches-document-versions-tool-1dbl</guid>
      <description>&lt;p&gt;&lt;em&gt;Document versions, Apostrophe's most recent professional module, is available via paid license &amp;amp; allows contributors to work on documents across multiple sites.&lt;/em&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Document Versions: The Ultimate Tool For Multi Site Document Management
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://apostrophecms.com/"&gt;ApostropheCMS&lt;/a&gt; allows multiple content contributors and editors to work on documents across multiple sites. Keeping track of when changes were made to a document and who made those changes is critical. The enterprise edition of ApostropheCMS has an important new tool for managing the content pipeline. The &lt;a href="https://apostrophecms.com/extensions/document-version"&gt;Document Versions&lt;/a&gt; tool facilitates the use and management of multiple versions of a document (page).&lt;/p&gt;

&lt;p&gt;&lt;iframe src="https://player.vimeo.com/video/756910279" width="710" height="399"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Alongside the already powerful core ApostropheCMS functionality, this new tool allows reversion to older versions of any document. This was impossible in A2 because of how documents were auto-saved. Now, we can view a list of all published content on a page, preview them as they exist in the current page, and elect to rollback to a previous version.&lt;/p&gt;

&lt;p&gt;The Documents Versions tool allows us to keep a record of all the changes made to our content, and which editor made the changes. We can also elect to view or roll-back to previous versions of our choice. This provides easier collaboration and editorial control of all our documents.&lt;/p&gt;

&lt;p&gt;The Documents Version module is available with a paid plan. &lt;a href="https://apostrophecms.com/contact-us"&gt;Get in touch&lt;/a&gt; to find out more about our &lt;a href="https://apostrophecms.com/pricing"&gt;pricing&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  How it Works
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Step 1: Add a new version to an existing page
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Open an existing page to be edited&lt;/li&gt;
&lt;li&gt;Click the plus sign to add new content&lt;/li&gt;
&lt;li&gt;'Save' and 'Update' the page&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Step 2: Compare versions
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;In the right hand side bar, find the Edit button to make changes to your page.&lt;/li&gt;
&lt;li&gt;Select the option 'Document Versions' beside the 'Preview' button, as seen below. A new page should appear with 'Document Versions' as the title.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fieeap622wqmgsvs27hva.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fieeap622wqmgsvs27hva.png" alt="CMS Document Version menu access" width="800" height="192"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The Document Versions page contains a list of all changes and previous versions on the right hand side, organized by date modified. It also lists the author of the changes.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fky62bwu7je7y0swoyf5k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fky62bwu7je7y0swoyf5k.png" alt="CMS Document Version fields" width="800" height="161"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Select a version to view the content present in that version.&lt;/li&gt;
&lt;li&gt;Press the 'Restore' button to revert to a previous version of your choice. The list contains Snapshots of every change that was saved. So, you can decide to revert to a Document you had published earlier.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fagcyhn6yo9cv9vq8dyfy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fagcyhn6yo9cv9vq8dyfy.png" alt="CMS Document Version change log" width="800" height="404"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This post was originally contributed by an Apostrophe Community member, &lt;a href="//twitter.com/vectormike_"&gt;Victor Jonah&lt;/a&gt;. If you would like to contribute an article to the community, &lt;a href="//apostrophecms.com/contact-us"&gt;submit your article here&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  We'd love to hear your feedback on this!
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Join our team and other Apostrophe developers from around the world on &lt;a href="http://chat.apostrophecms.org/"&gt;Discord&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Follow product updates and more on &lt;a href="https://github.com/apostrophecms/apostrophe/discussions"&gt;Github Discussions&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Want to learn more about Apostrophe enterprise features?
&lt;/h3&gt;

&lt;p&gt;To learn more about the enterprise edition of ApostropheCMS, &lt;a href="https://meetings.hubspot.com/ashleigh23"&gt;schedule a personalized demo&lt;/a&gt; with an Apostrophe team member, or &lt;a href="//apostrophecms.com/contact-us"&gt;contact us&lt;/a&gt; with questions.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
    </item>
    <item>
      <title>How an Ecommerce Company Improved Onboarding Speed by 10x with Apostrophe Assembly</title>
      <dc:creator>The Apostrophe Team</dc:creator>
      <pubDate>Wed, 21 Sep 2022 15:56:49 +0000</pubDate>
      <link>https://forem.com/apostrophecms/how-an-ecommerce-company-improved-onboarding-speed-by-10x-with-apostrophe-assembly-4fko</link>
      <guid>https://forem.com/apostrophecms/how-an-ecommerce-company-improved-onboarding-speed-by-10x-with-apostrophe-assembly-4fko</guid>
      <description>&lt;p&gt;Thirstie is an ecommerce company connecting alcohol beverage brands directly with consumers. Founded in 2014, &lt;a href="//thirstie.com/"&gt;Thirstie&lt;/a&gt; is a pioneer in the e-commerce market within beverage alcohol. It is the best-in-class white label solution with its proprietary technology, national retailer network, and on-demand delivery options. &lt;/p&gt;

&lt;p&gt;Headquartered in New York, NY, Thirstie helps alcohol beverage brands reach 100 million adult consumers via its fulfillment network in over 40 geographic areas nationwide with compliant branded e-commerce solutions. While other online marketplaces focus on customer acquisition for themselves, Thirstie puts the power of first party consumer data in the hands of the brands they service. Furthermore, Thirstie’s primary goal is to help alcohol suppliers increase consumer engagement and adoption through branded digital storefronts that deliver compliant end-to-end customer experiences in a highly regulated industry. &lt;/p&gt;

&lt;h3&gt;
  
  
  To Buy or To Build?
&lt;/h3&gt;

&lt;p&gt;When Thirstie began the process of looking for a CMS solution to enhance their proprietary e-commerce API, they faced a decision of whether they should build the solution themselves or outsource. &lt;em&gt;“Outsourcing wasn’t the most obvious choice given there are numerous complex regulatory requirements of the beverage alcohol industry that many solutions may not support,”&lt;/em&gt; says co-founder Maxim Razmakhin.&lt;/p&gt;

&lt;p&gt;After testing their own development capabilities and researching alternatives such as Contentful, Wordpress, and Netlify among others, Thirstie identified ApostropheCMS as the perfect match for the problem at hand.&lt;/p&gt;

&lt;p&gt;Apostrophe offered an attractive balance of flexibility and robustness with their CMS solutions. Additionally, the Apostrophe team immediately understood Thirstie’s needs in creating a new ecommerce solution within the constraints of a regulated market. Ultimately, &lt;a href="https://apostrophecms.com/assembly"&gt;Apostrophe Assembly&lt;/a&gt; rose to the top of the pack as Thirstie’s tool of choice, as it provided a cost effective, white label solution for managing over a hundred separate branded storefronts. &lt;/p&gt;

&lt;h3&gt;
  
  
  Powered by Assembly
&lt;/h3&gt;

&lt;p&gt;Apostrophe Assembly is a cloud-hosted, multisite low-code platform that makes managing a collection of websites easy. With Assembly, users can build their own custom CMS components and integrations, turn those into a reusable theme, and use that theme to create new sites in just a few clicks. This can all be accomplished without the hassle of multiple codebases or managing deployment and ops. &lt;a href="https://apostrophecms.com/blog/assembly-on-a3"&gt;Now powered by Apostrophe 3&lt;/a&gt;, Assembly brings speed plus an improved user interface to the process of spinning up and managing fleets of websites.&lt;/p&gt;

&lt;h4&gt;
  
  
  To summarize, Apostrophe Assembly offers users:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;A white label experience for customers&lt;/li&gt;
&lt;li&gt;A low technology barrier&lt;/li&gt;
&lt;li&gt;Speed to market deployment&lt;/li&gt;
&lt;li&gt;Component reusability&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Apostrophe Assembly helped Thirstie create the world’s first turnkey e-commerce platform for beverage alcohol brands, allowing customers to quickly create online stores with customizable themes. With Assembly’s speed to market, design flexibility, and approvals and permissions, Thirstie saw success like never before.&lt;/p&gt;

&lt;h3&gt;
  
  
  Launching Hundreds of Storefronts with Ease
&lt;/h3&gt;

&lt;p&gt;With the power and flexibility of Apostrophe’s open source tech stack, Thirstie launched over a hundred branded storefronts. The entire onboarding process, from conception to having a ready-to-launch product, took less than six months. &lt;/p&gt;

&lt;p&gt;Now, alcohol beverage brand managers, web designers and marketers alike work with the Thirstie team to analyze the customer data generated by Apostrophe Assembly to provide unique consumer experiences.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"If you are looking for a responsive, personable and creative partner to build something innovative, the Apostrophe team will be a match."&lt;br&gt;
&lt;em&gt;Richard Cramer, Director of Engineering, Thirstie&lt;/em&gt;   &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;iframe src="https://player.vimeo.com/video/640014190" width="710" height="399"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h3&gt;
  
  
  Speed to Market + Design Flexibility = Customer Benefits
&lt;/h3&gt;

&lt;p&gt;Thanks to their multiple branded storefronts built with Apostrophe Assembly, Thirstie is able to showcase the range of experiences they offer consumers. Assembly also gives Thirstie the ability to spin a demo site in a matter of hours. Likewise, after securing brand assets and arranging compliant e-commerce retailer relationships, Thirstie can launch a new branded storefront within 1 week vs months.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Apostrophe Assembly allows us to launch new web storefronts for our clients in minutes, with our robust and hyper-compliant API technology pre-built. This has improved our customer onboarding speed by 10x, as we can now get new brands live faster than ever before.  Apostrophe has transformed our sales process and our customer's speed to market."&lt;br&gt;
&lt;em&gt;Devaraj Southworth, CEO &amp;amp; Co-Founder, Thirsite&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;In finding a CMS solution with Apostrophe, Thirstie’s customers have experienced numerous benefits, including:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Multi-tenancy support&lt;/li&gt;
&lt;li&gt;Custom theme development&lt;/li&gt;
&lt;li&gt;Flexible choices for render framework and style palette&lt;/li&gt;
&lt;li&gt;Responsive support and individualized attention&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Over time, Apostrophe has become intertwined with Thirstie’s daily existence. With drag and drop in-context editing, easy to spin up new sites, and one dashboard to oversee it all, Thirstie manages its many websites with ease. Most importantly, ApostropheCMS solutions allow Thirstie more time to focus on other aspects of their business.&lt;/p&gt;

&lt;h3&gt;
  
  
  Leading the Way with Revolutionary Solutions
&lt;/h3&gt;

&lt;p&gt;Thirstie continues to lead the way in building solutions that drive online consumer adoption for alcohol brands. They recently developed the first alcohol-branded gift card product in the industry.&lt;/p&gt;

&lt;p&gt;Thirstie also offers a first-time, innovative solution allowing brands to own their own consumer data. Within an easy-to-use dashboard, this solution helps brands harness the transactional, demographic, and attribution data of their consumers.  &lt;/p&gt;

&lt;p&gt;In just two years of collaborating with Apostrophe’s team and utilizing Apostrophe Assembly, Thirstie experienced explosive growth as a business. They gained the ability to scale quickly and with ease. Moreover, Apostrophe will continue to be a trusted partner in bringing Thirstie’s revolutionary solutions to life.&lt;/p&gt;

&lt;p&gt;If your company manages multiple websites and you want a simplified, easy-to-use site builder that creates beautiful, functional websites, we would love to help you see if Apostrophe Assembly could help. Schedule your free personalized demo of Apostrophe Assembly by &lt;a href="https://apostrophecms.com/contact-us"&gt;contacting us&lt;/a&gt;. We’ll book a time to show you how Apostrophe Assembly can reduce your development timeline and support your company’s growth.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>tutorial</category>
      <category>news</category>
      <category>startup</category>
    </item>
    <item>
      <title>Create Custom Schema Field Types</title>
      <dc:creator>The Apostrophe Team</dc:creator>
      <pubDate>Tue, 11 Jan 2022 14:43:42 +0000</pubDate>
      <link>https://forem.com/apostrophecms/create-custom-schema-field-types-3oe4</link>
      <guid>https://forem.com/apostrophecms/create-custom-schema-field-types-3oe4</guid>
      <description>&lt;p&gt;This guide focuses on how to create custom schema field types in Apostrophe 3.&lt;/p&gt;

&lt;h2&gt;
  
  
  Custom schema field types
&lt;/h2&gt;

&lt;p&gt;Apostrophe's &lt;a href="https://v3.docs.apostrophecms.org/guide/content-schema.html"&gt;schema field types&lt;/a&gt; cover many situations, but we might wish to add a new one.&lt;/p&gt;

&lt;p&gt;A schema field has two parts: a server-side part and a browser-side part. The server-side part is responsible for sanitizing the input received from the browser, while the browser-side part is responsible for providing the admin UI.&lt;/p&gt;

&lt;h2&gt;
  
  
  Implementing the server-side part
&lt;/h2&gt;

&lt;p&gt;Any module can register a schema field type on the server side, like this one, which allows editors to set a "star rating" of 1 to 5 stars, as is often seen in movie and restaurant reviews.&lt;/p&gt;

&lt;p&gt;Note that this code could be in any module. Here we've chosen to create a module just for this new field type, since it might be used in several modules.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;module.exports = {
  init(self) {
    self.addStarRatingFieldType();
  },
  methods(self) {
    return {
      addStarRatingFieldType() {
        self.apos.schema.addFieldType({
          name: 'starRating',
          convert: self.convertInput,
          vueComponent: 'InputStarRating'
        });
      },
      async convertInput(req, field, data, object) {
        const input = data[field.name];
        if ((data[field.name] == null) || (data[field.name] === '')) {
          if (field.required) {
            throw self.apos.error('notfound');
          }
        }
        object[field.name] = self.apos.launder.integer(input, field.def, 1, 5);
      }
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In &lt;code&gt;init&lt;/code&gt;, which runs when the module is initialized, we call our &lt;code&gt;addStarRatingFieldType&lt;/code&gt; method. &lt;code&gt;init&lt;/code&gt; is the right place to invoke code that should run when the Apostrophe process starts up.&lt;/p&gt;

&lt;p&gt;In &lt;code&gt;addStarRatingFieldType&lt;/code&gt;, we invoke &lt;code&gt;self.apos.schema.addFieldType&lt;/code&gt; to add our custom field type on the server side. We provide:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;name&lt;/code&gt;, which can be used as a &lt;code&gt;type&lt;/code&gt; setting when adding the field to a schema.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;convert&lt;/code&gt;, a function to be used to sanitize the input and copy it to a destination. We pass our &lt;code&gt;convertInput&lt;/code&gt; method for this purpose. Methods of our module are available as properties of &lt;code&gt;self&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;component&lt;/code&gt;, the name of a Vue.js component to be displayed when editing the field.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In &lt;code&gt;convertInput&lt;/code&gt;, we sanitize the input and copy it from &lt;code&gt;data[field.name]&lt;/code&gt; to &lt;code&gt;object[field.name]&lt;/code&gt;. Since we must not trust the browser, we take care to sanitize it with &lt;a href="https://npmjs.com/package/launder"&gt;the &lt;code&gt;launder&lt;/code&gt; module&lt;/a&gt;, which is always available as &lt;code&gt;apos.launder&lt;/code&gt;. But we can validate the input any way we like, as long as we never trust the input.&lt;/p&gt;

&lt;h2&gt;
  
  
  Implementing the browser-side part
&lt;/h2&gt;

&lt;p&gt;On the browser side, we'll need a custom Vue.js component. Apostrophe provides a Vue.js mixin, &lt;code&gt;AposInputMixin&lt;/code&gt;, that does much of the work for us.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;template&amp;gt;
  &amp;lt;AposInputWrapper
    :modifiers="modifiers" :field="field"
    :error="effectiveError" :uid="uid"
    :display-options="displayOptions"
  &amp;gt;
    &amp;lt;template #body&amp;gt;
      &amp;lt;div class="apos-input-wrapper"&amp;gt;
        &amp;lt;button v-for="index in 5" :key="index" @click="setValue(index)" class="rating"&amp;gt;{{ isActive(index) ? '☆' : '★' }}&amp;lt;/button&amp;gt;
        &amp;lt;button class="clear" @click="clear"&amp;gt;Clear&amp;lt;/button&amp;gt;
      &amp;lt;/div&amp;gt;
    &amp;lt;/template&amp;gt;
  &amp;lt;/AposInputWrapper&amp;gt;
&amp;lt;/template&amp;gt;

&amp;lt;script&amp;gt;
import AposInputMixin from 'Modules/@apostrophecms/schema/mixins/AposInputMixin';

export default {
  name: 'InputStarRating',
  mixins: [ AposInputMixin ],
  methods: {
    validate(value) {
      if (this.field.required) {
        if (!value) {
          return 'required';
        }
      }
      return false;
    },
    setValue(index) {
      this.next = index;
    },
    clear() {
      this.next = null;
    },
    isActive(index) {
      return index &amp;lt;= this.next;
    }
  }
};
&amp;lt;/script&amp;gt;

&amp;lt;style lang="scss" scoped&amp;gt;
  .rating {
    border: none;
    background-color: inherit;
    color: inherit;
    font-size: inherit;
  }
&amp;lt;/style&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In our template element, &lt;code&gt;AposInputWrapper&lt;/code&gt; takes care of decorating our field with a label, error messages, etc. All we have to do is pass on some standard props that are provided to us. Beyond that, our responsibility is to display the current &lt;code&gt;value&lt;/code&gt; to the user. We also add event handlers to handle user input, as explained below.&lt;/p&gt;

&lt;p&gt;In our script element, we have just two jobs: assigning a new value to &lt;code&gt;this.next&lt;/code&gt; whenever the value changes, and validating the user's input. The &lt;code&gt;AposInputMixin&lt;/code&gt; does the rest of the work for us.&lt;/p&gt;

&lt;p&gt;To update &lt;code&gt;this.next&lt;/code&gt;, we implement methods that respond to click events, like the &lt;code&gt;setValue&lt;/code&gt; and &lt;code&gt;clear&lt;/code&gt; methods in this example. To validate the user's input, we implement a &lt;code&gt;validate&lt;/code&gt; method, which accepts the current value and checks constraints like the &lt;code&gt;required&lt;/code&gt; property of the field. If there is a problem, we return an error code such as &lt;code&gt;required&lt;/code&gt;, &lt;code&gt;min&lt;/code&gt; or &lt;code&gt;max&lt;/code&gt;, otherwise we return &lt;code&gt;false&lt;/code&gt;. The field configuration is available to us as &lt;code&gt;this.field&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;style&lt;/code&gt; element takes care of CSS for this component. Note that SCSS syntax is available. To avoid conflicts, using the &lt;code&gt;scoped&lt;/code&gt; attribute is recommended.&lt;/p&gt;

&lt;h4&gt;
  
  
  WARNING
&lt;/h4&gt;

&lt;p&gt;&lt;em&gt;If it doesn't seem to work at first, make sure you launched &lt;code&gt;npm run dev&lt;/code&gt; with the &lt;code&gt;APOS_DEV=1&lt;/code&gt; environment variable setting as explained earlier. This ensures the Apostrophe admin UI is rebuilt on each code change. You can stop using it when you are finished changing admin UI code.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Putting the new schema field type to work
&lt;/h2&gt;

&lt;p&gt;Now we can use the new schema field type in any piece or widget much as we would use an &lt;code&gt;integer&lt;/code&gt; field:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;fields: {
  add: {
    rating: {
      type: 'starRating',
      label: 'Star Rating',
      required: true
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The resulting value is then available as the &lt;code&gt;stars&lt;/code&gt; property of the piece or widget, with an integer value between &lt;code&gt;1&lt;/code&gt; and &lt;code&gt;5&lt;/code&gt;.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>tutorial</category>
      <category>uiweekly</category>
    </item>
  </channel>
</rss>
